public QueueListenerTests() { CloudQueue queue = new CloudQueue(new Uri("https://test.queue.core.windows.net/testqueue")); Mock<IStorageQueue> mockQueue = new Mock<IStorageQueue>(MockBehavior.Strict); mockQueue.Setup(p => p.SdkObject).Returns(queue); _mockTriggerExecutor = new Mock<ITriggerExecutor<IStorageQueueMessage>>(MockBehavior.Strict); Mock<IDelayStrategy> mockDelayStrategy = new Mock<IDelayStrategy>(MockBehavior.Strict); Mock<IBackgroundExceptionDispatcher> mockExceptionDispatcher = new Mock<IBackgroundExceptionDispatcher>(MockBehavior.Strict); TestTraceWriter log = new TestTraceWriter(TraceLevel.Verbose); Mock<IQueueProcessorFactory> mockQueueProcessorFactory = new Mock<IQueueProcessorFactory>(MockBehavior.Strict); JobHostQueuesConfiguration queuesConfig = new JobHostQueuesConfiguration(); QueueProcessorFactoryContext context = new QueueProcessorFactoryContext(queue, log, queuesConfig); _mockQueueProcessor = new Mock<QueueProcessor>(MockBehavior.Strict, context); JobHostQueuesConfiguration queueConfig = new JobHostQueuesConfiguration { MaxDequeueCount = 5, QueueProcessorFactory = mockQueueProcessorFactory.Object }; mockQueueProcessorFactory.Setup(p => p.Create(It.IsAny<QueueProcessorFactoryContext>())).Returns(_mockQueueProcessor.Object); _listener = new QueueListener(mockQueue.Object, null, _mockTriggerExecutor.Object, mockDelayStrategy.Object, mockExceptionDispatcher.Object, log, null, queueConfig); CloudQueueMessage cloudMessage = new CloudQueueMessage("TestMessage"); _storageMessage = new StorageQueueMessage(cloudMessage); }
public async Task CreateAsync_SkipsDisabledFunctions(Type jobType, string methodName) { Environment.SetEnvironmentVariable("EnvironmentSettingTrue", "True"); Mock<IFunctionDefinition> mockFunctionDefinition = new Mock<IFunctionDefinition>(); Mock<IFunctionInstanceFactory> mockInstanceFactory = new Mock<IFunctionInstanceFactory>(MockBehavior.Strict); Mock<IListenerFactory> mockListenerFactory = new Mock<IListenerFactory>(MockBehavior.Strict); SingletonManager singletonManager = new SingletonManager(); TestTraceWriter traceWriter = new TestTraceWriter(TraceLevel.Verbose); // create a bunch of function definitions that are disabled List<FunctionDefinition> functions = new List<FunctionDefinition>(); FunctionDescriptor descriptor = new FunctionDescriptor { Method = jobType.GetMethod(methodName, BindingFlags.Public | BindingFlags.Static), ShortName = string.Format("{0}.{1}", jobType.Name, methodName) }; FunctionDefinition definition = new FunctionDefinition(descriptor, mockInstanceFactory.Object, mockListenerFactory.Object); functions.Add(definition); // Create the composite listener - this will fail if any of the // function definitions indicate that they are not disabled HostListenerFactory factory = new HostListenerFactory(functions, singletonManager, DefaultJobActivator.Instance, null, traceWriter); IListener listener = await factory.CreateAsync(CancellationToken.None); Assert.Equal(1, traceWriter.Traces.Count); Assert.Equal(TraceLevel.Info, traceWriter.Traces[0].Level); Assert.Equal(TraceSource.Host, traceWriter.Traces[0].Source); Assert.Equal(string.Format("Function '{0}' is disabled", descriptor.ShortName), traceWriter.Traces[0].Message); Environment.SetEnvironmentVariable("EnvironmentSettingTrue", null); }
public FunctionExecutorTests() { _descriptor = new FunctionDescriptor(); _mockFunctionInstance = new Mock<IFunctionInstance>(MockBehavior.Strict); _mockFunctionInstance.Setup(p => p.FunctionDescriptor).Returns(_descriptor); _cancellationTokenSource = new CancellationTokenSource(); _traceWriter = new TestTraceWriter(TraceLevel.Verbose); }
public void Constructor_DefaultsValues() { CloudQueue queue = new CloudQueue(new Uri("https://test.queue.core.windows.net/testqueue")); CloudQueue poisonQueue = new CloudQueue(new Uri("https://test.queue.core.windows.net/poisonqueue")); TestTraceWriter log = new TestTraceWriter(TraceLevel.Verbose); JobHostQueuesConfiguration queuesConfig = new JobHostQueuesConfiguration(); QueueProcessorFactoryContext context = new QueueProcessorFactoryContext(queue, log, queuesConfig, poisonQueue); Assert.Same(queue, context.Queue); Assert.Same(log, context.Trace); Assert.Same(poisonQueue, context.PoisonQueue); Assert.Equal(queuesConfig.BatchSize, context.BatchSize); Assert.Equal(queuesConfig.NewBatchThreshold, context.NewBatchThreshold); Assert.Equal(queuesConfig.MaxDequeueCount, context.MaxDequeueCount); }
public static FunctionIndexer Create(CloudStorageAccount account = null, INameResolver nameResolver = null, IExtensionRegistry extensionRegistry = null) { Mock<IServiceProvider> services = new Mock<IServiceProvider>(MockBehavior.Strict); StorageClientFactory clientFactory = new StorageClientFactory(); services.Setup(p => p.GetService(typeof(StorageClientFactory))).Returns(clientFactory); IStorageAccount storageAccount = account != null ? new StorageAccount(account, services.Object) : null; IStorageAccountProvider storageAccountProvider = new SimpleStorageAccountProvider(services.Object) { StorageAccount = account }; IExtensionTypeLocator extensionTypeLocator = new NullExtensionTypeLocator(); ContextAccessor<IMessageEnqueuedWatcher> messageEnqueuedWatcherAccessor = new ContextAccessor<IMessageEnqueuedWatcher>(); ContextAccessor<IBlobWrittenWatcher> blobWrittenWatcherAccessor = new ContextAccessor<IBlobWrittenWatcher>(); ISharedContextProvider sharedContextProvider = new SharedContextProvider(); TestTraceWriter logger = new TestTraceWriter(TraceLevel.Verbose); SingletonManager singletonManager = new SingletonManager(); ITriggerBindingProvider triggerBindingProvider = DefaultTriggerBindingProvider.Create(nameResolver, storageAccountProvider, extensionTypeLocator, new FixedHostIdProvider("test"), new SimpleQueueConfiguration(maxDequeueCount: 5), BackgroundExceptionDispatcher.Instance, messageEnqueuedWatcherAccessor, blobWrittenWatcherAccessor, sharedContextProvider, new DefaultExtensionRegistry(), singletonManager, logger); IBindingProvider bindingProvider = DefaultBindingProvider.Create(nameResolver, storageAccountProvider, extensionTypeLocator, messageEnqueuedWatcherAccessor, blobWrittenWatcherAccessor, new DefaultExtensionRegistry()); TraceWriter trace = new TestTraceWriter(TraceLevel.Verbose); IFunctionOutputLoggerProvider outputLoggerProvider = new NullFunctionOutputLoggerProvider(); IFunctionOutputLogger outputLogger = outputLoggerProvider.GetAsync(CancellationToken.None).Result; IFunctionExecutor executor = new FunctionExecutor(new NullFunctionInstanceLogger(), outputLogger, BackgroundExceptionDispatcher.Instance, trace, null); if (extensionRegistry == null) { extensionRegistry = new DefaultExtensionRegistry(); } return new FunctionIndexer(triggerBindingProvider, bindingProvider, DefaultJobActivator.Instance, executor, extensionRegistry, new SingletonManager(), trace); }
public static FunctionIndexer Create(CloudStorageAccount account = null, INameResolver nameResolver = null, IExtensionRegistry extensionRegistry = null) { IStorageAccount storageAccount = account != null ? new StorageAccount(account) : null; IStorageAccountProvider storageAccountProvider = new SimpleStorageAccountProvider { StorageAccount = account }; IExtensionTypeLocator extensionTypeLocator = new NullExtensionTypeLocator(); ContextAccessor<IMessageEnqueuedWatcher> messageEnqueuedWatcherAccessor = new ContextAccessor<IMessageEnqueuedWatcher>(); ContextAccessor<IBlobWrittenWatcher> blobWrittenWatcherAccessor = new ContextAccessor<IBlobWrittenWatcher>(); ISharedContextProvider sharedContextProvider = new SharedContextProvider(); TestTraceWriter logger = new TestTraceWriter(TraceLevel.Verbose); ITriggerBindingProvider triggerBindingProvider = DefaultTriggerBindingProvider.Create(nameResolver, storageAccountProvider, extensionTypeLocator, new FixedHostIdProvider("test"), new SimpleQueueConfiguration(maxDequeueCount: 5), BackgroundExceptionDispatcher.Instance, messageEnqueuedWatcherAccessor, blobWrittenWatcherAccessor, sharedContextProvider, new DefaultExtensionRegistry(), logger); IBindingProvider bindingProvider = DefaultBindingProvider.Create(nameResolver, storageAccountProvider, extensionTypeLocator, messageEnqueuedWatcherAccessor, blobWrittenWatcherAccessor, new DefaultExtensionRegistry()); IFunctionOutputLoggerProvider outputLoggerProvider = new NullFunctionOutputLoggerProvider(); var task = outputLoggerProvider.GetAsync(CancellationToken.None); task.Wait(); IFunctionOutputLogger outputLogger = task.Result; IFunctionExecutor executor = new FunctionExecutor(new NullFunctionInstanceLogger(), outputLogger, BackgroundExceptionDispatcher.Instance, new TestTraceWriter(TraceLevel.Verbose)); if (extensionRegistry == null) { extensionRegistry = new DefaultExtensionRegistry(); } return new FunctionIndexer(triggerBindingProvider, bindingProvider, DefaultJobActivator.Instance, executor, extensionRegistry, new SingletonManager()); }
public async Task CustomMessageProcessorTest() { try { TestTraceWriter trace = new TestTraceWriter(TraceLevel.Info); _serviceBusConfig = new ServiceBusConfiguration(); _serviceBusConfig.MessagingProvider = new CustomMessagingProvider(_serviceBusConfig, trace); JobHostConfiguration config = new JobHostConfiguration() { NameResolver = _nameResolver, TypeLocator = new FakeTypeLocator(typeof(ServiceBusTestJobs)) }; config.Tracing.Tracers.Add(trace); config.UseServiceBus(_serviceBusConfig); JobHost host = new JobHost(config); await ServiceBusEndToEndInternal(typeof(ServiceBusTestJobs), host: host); // in addition to verifying that our custom processor was called, we're also // verifying here that extensions can log to the TraceWriter Assert.Equal(4, trace.Traces.Count(p => p.Message.Contains("Custom processor Begin called!"))); Assert.Equal(4, trace.Traces.Count(p => p.Message.Contains("Custom processor End called!"))); } finally { Cleanup(); } }
public void IndexingExceptions_CanBeHandledByTraceWriter() { JobHostConfiguration config = new JobHostConfiguration(); TestTraceWriter traceWriter = new TestTraceWriter(TraceLevel.Verbose); config.Tracing.Tracers.Add(traceWriter); config.TypeLocator = new FakeTypeLocator(typeof(BindingErrorsProgram)); FunctionErrorTraceWriter errorTraceWriter = new FunctionErrorTraceWriter(TraceLevel.Error); config.Tracing.Tracers.Add(errorTraceWriter); JobHost host = new JobHost(config); host.Start(); // verify the handled binding error FunctionIndexingException fex = errorTraceWriter.Errors.SingleOrDefault() as FunctionIndexingException; Assert.True(fex.Handled); Assert.Equal("BindingErrorsProgram.Invalid", fex.MethodName); // verify that the binding error was logged Assert.Equal(5, traceWriter.Traces.Count); TraceEvent traceEvent = traceWriter.Traces[0]; Assert.Equal("Error indexing method 'BindingErrorsProgram.Invalid'", traceEvent.Message); Assert.Same(fex, traceEvent.Exception); Assert.Equal("Invalid container name: invalid$=+1", traceEvent.Exception.InnerException.Message); // verify that the valid function was still indexed traceEvent = traceWriter.Traces[1]; Assert.True(traceEvent.Message.Contains("Found the following functions")); Assert.True(traceEvent.Message.Contains("BindingErrorsProgram.Valid")); // verify that the job host was started successfully traceEvent = traceWriter.Traces[4]; Assert.Equal("Job host started", traceEvent.Message); host.Stop(); host.Dispose(); }
public void CreateQueueProcessor_CreatesProcessorCorrectly() { CloudQueue poisonQueue = null; TestTraceWriter log = new TestTraceWriter(TraceLevel.Verbose); bool poisonMessageHandlerInvoked = false; EventHandler poisonMessageEventHandler = (sender, e) => { poisonMessageHandlerInvoked = true; }; Mock<IQueueProcessorFactory> mockQueueProcessorFactory = new Mock<IQueueProcessorFactory>(MockBehavior.Strict); JobHostQueuesConfiguration queueConfig = new JobHostQueuesConfiguration { MaxDequeueCount = 7, QueueProcessorFactory = mockQueueProcessorFactory.Object }; QueueProcessor expectedQueueProcessor = null; bool processorFactoryInvoked = false; // create for a host queue - don't expect custom factory to be invoked CloudQueue queue = new CloudQueue(new Uri(string.Format("https://test.queue.core.windows.net/{0}", HostQueueNames.GetHostQueueName("12345")))); QueueProcessor queueProcessor = QueueListener.CreateQueueProcessor(queue, poisonQueue, log, queueConfig, poisonMessageEventHandler); Assert.False(processorFactoryInvoked); Assert.NotSame(expectedQueueProcessor, queueProcessor); queueProcessor.OnMessageAddedToPoisonQueue(new EventArgs()); Assert.True(poisonMessageHandlerInvoked); QueueProcessorFactoryContext processorFactoryContext = null; mockQueueProcessorFactory.Setup(p => p.Create(It.IsAny<QueueProcessorFactoryContext>())) .Callback<QueueProcessorFactoryContext>((mockProcessorContext) => { processorFactoryInvoked = true; Assert.Same(queue, mockProcessorContext.Queue); Assert.Same(poisonQueue, mockProcessorContext.PoisonQueue); Assert.Equal(queueConfig.MaxDequeueCount, mockProcessorContext.MaxDequeueCount); Assert.Same(log, mockProcessorContext.Trace); processorFactoryContext = mockProcessorContext; }) .Returns(() => { expectedQueueProcessor = new QueueProcessor(processorFactoryContext); return expectedQueueProcessor; }); // when storage host is "localhost" we invoke the processor factory even for // host queues (this enables local test mocking) processorFactoryInvoked = false; queue = new CloudQueue(new Uri(string.Format("https://localhost/{0}", HostQueueNames.GetHostQueueName("12345")))); queueProcessor = QueueListener.CreateQueueProcessor(queue, poisonQueue, log, queueConfig, poisonMessageEventHandler); Assert.True(processorFactoryInvoked); Assert.Same(expectedQueueProcessor, queueProcessor); // create for application queue - expect processor factory to be invoked poisonMessageHandlerInvoked = false; processorFactoryInvoked = false; queue = new CloudQueue(new Uri("https://test.queue.core.windows.net/testqueue")); queueProcessor = QueueListener.CreateQueueProcessor(queue, poisonQueue, log, queueConfig, poisonMessageEventHandler); Assert.True(processorFactoryInvoked); Assert.Same(expectedQueueProcessor, queueProcessor); queueProcessor.OnMessageAddedToPoisonQueue(new EventArgs()); Assert.True(poisonMessageHandlerInvoked); // if poison message watcher not specified, event not subscribed to poisonMessageHandlerInvoked = false; processorFactoryInvoked = false; queueProcessor = QueueListener.CreateQueueProcessor(queue, poisonQueue, log, queueConfig, null); Assert.True(processorFactoryInvoked); Assert.Same(expectedQueueProcessor, queueProcessor); queueProcessor.OnMessageAddedToPoisonQueue(new EventArgs()); Assert.False(poisonMessageHandlerInvoked); }
public TraceWriterFunctionInstanceLoggerTests() { _traceWriter = new TestTraceWriter(TraceLevel.Verbose); _logger = new TraceWriterFunctionInstanceLogger(_traceWriter); }
public async Task MultipleAccountTest() { try { TestTraceWriter trace = new TestTraceWriter(TraceLevel.Info); _serviceBusConfig = new ServiceBusConfiguration(); _serviceBusConfig.MessagingProvider = new CustomMessagingProvider(_serviceBusConfig, trace); JobHostConfiguration config = new JobHostConfiguration() { NameResolver = _nameResolver, TypeLocator = new FakeTypeLocator(typeof(ServiceBusTestJobs)) }; config.Tracing.Tracers.Add(trace); config.UseServiceBus(_serviceBusConfig); JobHost host = new JobHost(config); string queueName = ResolveName(StartQueueName); string queuePrefix = queueName.Replace("-queue-start", ""); string firstTopicName = string.Format("{0}-topic/Subscriptions/{0}-queue-topic-1", queuePrefix); WriteQueueMessage(_secondaryNamespaceManager, _secondaryConnectionString, queueName, "Test"); _topicSubscriptionCalled1 = new ManualResetEvent(initialState: false); await host.StartAsync(); _topicSubscriptionCalled1.WaitOne(SBTimeout); // ensure all logs have had a chance to flush await Task.Delay(3000); // Wait for the host to terminate await host.StopAsync(); host.Dispose(); Assert.Equal("Test-topic-1", _resultMessage1); } finally { Cleanup(); } }