public void TestSdkMarkerIsWrittenWhenInAzureWebSites()
        {
            // Arrange
            string tempDir = Path.GetTempPath();
            const string filename = "WebJobsSdk.marker";

            var path = Path.Combine(tempDir, filename);

            File.Delete(path);

            IServiceProvider configuration = CreateConfiguration();

            using (JobHost host = new JobHost(configuration))
            {
                try
                {
                    Environment.SetEnvironmentVariable(WebSitesKnownKeyNames.JobDataPath, tempDir);

                    // Act
                    host.Start();

                    // Assert
                    Assert.True(File.Exists(path), "SDK marker file should have been written");
                }
                finally
                {
                    Environment.SetEnvironmentVariable(WebSitesKnownKeyNames.JobDataPath, null);
                    File.Delete(path);
                }
            }
        }
        public void BlobGetsProcessedOnlyOnce_SingleHost()
        {
            TextWriter hold = Console.Out;
            StringWriter consoleOutput = new StringWriter();
            Console.SetOut(consoleOutput);

            CloudBlockBlob blob = _testContainer.GetBlockBlobReference(BlobName);
            blob.UploadText("0");

            int timeToProcess;

            // Process the blob first
            using (_blobProcessedEvent = new ManualResetEvent(initialState: false))
            using (JobHost host = new JobHost(_hostConfiguration))
            {
                DateTime startTime = DateTime.Now;

                host.Start();
                Assert.True(_blobProcessedEvent.WaitOne(TimeSpan.FromSeconds(60)));

                timeToProcess = (int)(DateTime.Now - startTime).TotalMilliseconds;

                host.Stop();

                Console.SetOut(hold);

                string[] consoleOutputLines = consoleOutput.ToString().Trim().Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
                string[] expectedOutputLines = new string[]
                {
                    "Found the following functions:",
                    "Microsoft.Azure.WebJobs.Host.EndToEndTests.BlobTriggerTests.SingleBlobTrigger",
                    "Job host started",
                    string.Format("Executing: 'BlobTriggerTests.SingleBlobTrigger' - Reason: 'New blob detected: {0}/{1}'", blob.Container.Name, blob.Name),
                    "Executed: 'BlobTriggerTests.SingleBlobTrigger' (Succeeded)",
                    "Job host stopped",
                };
                Assert.True(consoleOutputLines.SequenceEqual(expectedOutputLines));
            }

            // Then start again and make sure the blob doesn't get reprocessed
            // wait twice the amount of time required to process first before 
            // deciding that it doesn't get reprocessed
            using (_blobProcessedEvent = new ManualResetEvent(initialState: false))
            using (JobHost host = new JobHost(_hostConfiguration))
            {
                host.Start();

                bool blobReprocessed = _blobProcessedEvent.WaitOne(2 * timeToProcess);

                host.Stop();

                Assert.False(blobReprocessed);
            }
        }
        public void StartAsync_WhenStarted_Throws()
        {
            // Arrange
            using (JobHost host = new JobHost(CreateConfiguration()))
            {
                host.Start();

                // Act & Assert
                ExceptionAssert.ThrowsInvalidOperation(() => host.StartAsync(), "Start has already been called.");
            }
        }
Beispiel #4
0
        public void BlobChainTest()
        {
            // write the initial trigger blob to start the chain
            var blobClient = _storageAccount.CreateCloudBlobClient();
            var container  = blobClient.GetContainerReference(_nameResolver.ResolveInString(BlobChainContainerName));

            container.CreateIfNotExists();
            CloudBlockBlob blob = container.GetBlockBlobReference(BlobChainTriggerBlobName);

            blob.UploadText("0");

            using (_completedEvent = new ManualResetEvent(initialState: false))
                using (JobHost host = new JobHost(_hostConfiguration))
                {
                    host.Start();
                    Assert.True(_completedEvent.WaitOne(TimeSpan.FromSeconds(60)));
                }
        }
Beispiel #5
0
        protected void RunTestHost(JobHostConfiguration config)
        {
            using (JobHost host = new JobHost(config))
                using (DoneNotificationFunction._doneEvent = new ManualResetEvent(initialState: false))
                {
                    host.Start();
                    DoneNotificationFunction._doneEvent.WaitOne();

                    try
                    {
                        host.Stop();
                    }
                    catch
                    {
                        // We don't care about errors here
                    }
                }
        }
        private void EndToEndTestInternal(bool uploadBlobBeforeHostStart)
        {
            // Reinitialize the name resolver to avoid conflicts
            _resolver = new RandomNameResolver();

            JobHostConfiguration hostConfig = new JobHostConfiguration()
            {
                NameResolver = _resolver,
                TypeLocator  = new FakeTypeLocator(
                    this.GetType(),
                    typeof(BlobToCustomObjectBinder))
            };

            _storageAccount = CloudStorageAccount.Parse(hostConfig.StorageConnectionString);

            if (uploadBlobBeforeHostStart)
            {
                // The function will be triggered fast because the blob is already there
                UploadTestObject();
            }

            // The jobs host is started
            JobHost host = new JobHost(hostConfig);

            _functionChainWaitHandle = new ManualResetEvent(initialState: false);

            host.Start();

            if (!uploadBlobBeforeHostStart)
            {
                WaitForTestFunctionsToStart();
                UploadTestObject();
            }

            bool signaled = _functionChainWaitHandle.WaitOne(15 * 60 * 1000);

            // Stop the host and wait for it to finish
            host.Stop();

            Assert.True(signaled);

            // Verify
            VerifyTableResults();
        }
        private async Task EndToEndTest(bool uploadBlobBeforeHostStart)
        {
            // Reinitialize the name resolver to avoid conflicts
            _resolver = new RandomNameResolver();

            JobHostConfiguration hostConfig = new JobHostConfiguration()
            {
                NameResolver = _resolver,
                TypeLocator  = new FakeTypeLocator(
                    this.GetType(),
                    typeof(BlobToCustomObjectBinder))
            };

            hostConfig.AddService <IWebJobsExceptionHandler>(new TestExceptionHandler());

            if (uploadBlobBeforeHostStart)
            {
                // The function will be triggered fast because the blob is already there
                await UploadTestObject();
            }

            // The jobs host is started
            JobHost host = new JobHost(hostConfig);

            _functionChainWaitHandle = new ManualResetEvent(initialState: false);

            host.Start();

            if (!uploadBlobBeforeHostStart)
            {
                await WaitForTestFunctionsToStart();
                await UploadTestObject();
            }

            bool signaled = _functionChainWaitHandle.WaitOne(15 * 1000);

            // Stop the host and wait for it to finish
            host.Stop();

            Assert.True(signaled);

            // Verify
            await VerifyTableResultsAsync();
        }
Beispiel #8
0
        private void RunTest(Type testType, string testName, INotificationHubClientServiceFactory factory, TraceWriter testTrace, object argument = null, string configConnectionString = ConfigConnStr, string configHubName = ConfigHubName, bool includeDefaultConnectionString = true, bool includeDefaultHubName = true)
        {
            ExplicitTypeLocator  locator = new ExplicitTypeLocator(testType);
            JobHostConfiguration config  = new JobHostConfiguration
            {
                TypeLocator = locator,
            };

            config.Tracing.Tracers.Add(testTrace);

            var arguments = new Dictionary <string, object>();

            arguments.Add("triggerData", argument);

            var notificationHubConfig = new NotificationHubsConfiguration()
            {
                ConnectionString = configConnectionString,
                HubName          = configHubName,
                NotificationHubClientServiceFactory = factory
            };

            var resolver = new TestNameResolver();

            resolver.Values.Add("HubName", "ResolvedHubName");
            resolver.Values.Add("MyConnectionString", AttributeConnStr);
            if (includeDefaultConnectionString)
            {
                resolver.Values.Add(NotificationHubsConfiguration.NotificationHubConnectionStringName, DefaultConnStr);
            }
            if (includeDefaultHubName)
            {
                resolver.Values.Add(NotificationHubsConfiguration.NotificationHubSettingName, DefaultHubName);
            }

            config.NameResolver = resolver;

            config.UseNotificationHubs(notificationHubConfig);

            JobHost host = new JobHost(config);

            host.Start();
            host.Call(testType.GetMethod(testName), arguments);
            host.Stop();
        }
Beispiel #9
0
        static void Main()
        {
            CreateDemoData();

            JobHost host = new JobHost();

            host.Start();

            // Stop the host if Ctrl + C/Ctrl + Break is pressed
            Console.CancelKeyPress += (sender, args) =>
            {
                host.Stop();
            };

            while (true)
            {
                Thread.Sleep(500);
            }
        }
        public async Task SingletonTriggerFunction_MultipleConcurrentInvocations_InvocationsAreSerialized()
        {
            JobHost host = CreateTestJobHost(1);

            host.Start();

            // trigger a bunch of parallel invocations
            int            numMessages = 20;
            List <Task>    invokeTasks = new List <Task>();
            JsonSerializer serializer  = new JsonSerializer();

            for (int i = 0; i < numMessages; i++)
            {
                int zone = _rand.Next(3) + 1;

                JObject workItem = new JObject
                {
                    { "ID", i + 1 },
                    { "Region", "Central" },
                    { "Zone", zone },
                    { "Category", 3 },
                    { "Description", "Test Work Item " + i }
                };
                await host.CallAsync(typeof(TestJobs).GetMethod("EnqueueQueue2TestMessage"), new { message = workItem.ToString() });
            }

            // wait for all the messages to be processed by the job
            await TestHelpers.Await(() =>
            {
                return((TestJobs.Queue2MessageCount == numMessages &&
                        TestJobs.JobInvocations.Select(p => p.Value).Sum() == numMessages) || TestJobs.FailureDetected);
            }, pollingInterval : 500);

            Assert.False(TestJobs.FailureDetected);
            Assert.Equal(numMessages, TestJobs.JobInvocations[1]);

            await VerifyLeaseState(typeof(TestJobs).GetMethod("SingletonTriggerJob"), SingletonScope.Function, "Central/1", LeaseState.Available, LeaseStatus.Unlocked);
            await VerifyLeaseState(typeof(TestJobs).GetMethod("SingletonTriggerJob"), SingletonScope.Function, "Central/2", LeaseState.Available, LeaseStatus.Unlocked);
            await VerifyLeaseState(typeof(TestJobs).GetMethod("SingletonTriggerJob"), SingletonScope.Function, "Central/3", LeaseState.Available, LeaseStatus.Unlocked);

            host.Stop();
            host.Dispose();
        }
Beispiel #11
0
        public void GlobalErrorHandler_ManualSubscriberFails_NoInfiniteLoop()
        {
            JobHostConfiguration config = new JobHostConfiguration()
            {
                TypeLocator = new ExplicitTypeLocator(typeof(ErrorProgram))
            };

            config.UseCore();

            int notificationCount = 0;
            var traceMonitor      = new TraceMonitor()
                                    .Filter(p => { return(true); })
                                    .Subscribe(p =>
            {
                notificationCount++;
                throw new Exception("Kaboom");
            });

            config.Tracing.Tracers.Add(traceMonitor);

            JobHost host = new JobHost(config);

            host.Start();

            TestTraceWriter traceWriter = new TestTraceWriter();

            config.Tracing.Tracers.Add(traceWriter);

            MethodInfo method = typeof(ErrorProgram).GetMethod("Throw");

            CallSafe(host, method);

            Assert.Equal(1, notificationCount);

            var events = traceWriter.Events;

            Assert.Equal(4, events.Count);
            Assert.True(events[0].Message.StartsWith("Executing: 'ErrorProgram.Throw'"));
            Assert.True(events[1].Message.StartsWith("Exception while executing function: ErrorProgram.Throw"));
            Assert.True(events[2].Message.StartsWith("Executed: 'ErrorProgram.Throw' (Failed)"));
            Assert.True(events[3].Message.StartsWith("  Function had errors. See Azure WebJobs SDK dashboard for details."));
        }
Beispiel #12
0
        public void GlobalErrorHandler_HandlerFails_NoInfiniteLoop()
        {
            ErrorTriggerProgram_GlobalCatchAllHandler instance = new ErrorTriggerProgram_GlobalCatchAllHandler(fail: true);

            JobHostConfiguration config = new JobHostConfiguration()
            {
                TypeLocator  = new ExplicitTypeLocator(instance.GetType()),
                JobActivator = new ExplicitJobActivator(instance)
            };

            config.UseCore();
            JobHost host = new JobHost(config);

            host.Start();

            TestTraceWriter traceWriter = new TestTraceWriter();

            config.Tracing.Tracers.Add(traceWriter);

            MethodInfo method = instance.GetType().GetMethod("Throw");

            CallSafe(host, method);

            Assert.Equal(1, instance.Errors.Count);
            TraceEvent error = instance.Errors.Single();

            Assert.Equal("Exception while executing function: ErrorTriggerProgram_GlobalCatchAllHandler.Throw", error.Message);

            // make sure the error handler failure is still logged
            var events = traceWriter.Events;

            Assert.Equal(8, events.Count);
            Assert.True(events[0].Message.StartsWith("Executing: 'ErrorTriggerProgram_GlobalCatchAllHandler.Throw'"));
            Assert.True(events[1].Message.StartsWith("Executing: 'ErrorTriggerProgram_GlobalCatchAllHandler.ErrorHandler'"));
            Assert.True(events[2].Message.StartsWith("Exception while executing function: ErrorTriggerProgram_GlobalCatchAllHandler.ErrorHandler"));
            Assert.Equal("Kaboom!", events[3].Exception.InnerException.Message);
            Assert.True(events[3].Message.StartsWith("Executed: 'ErrorTriggerProgram_GlobalCatchAllHandler.ErrorHandler' (Failed)"));
            Assert.True(events[4].Message.StartsWith("  Function had errors. See Azure WebJobs SDK dashboard for details."));
            Assert.True(events[5].Message.StartsWith("Exception while executing function: ErrorTriggerProgram_GlobalCatchAllHandler.Throw"));
            Assert.True(events[6].Message.StartsWith("Executed: 'ErrorTriggerProgram_GlobalCatchAllHandler.Throw' (Failed)"));
            Assert.True(events[7].Message.StartsWith("  Function had errors. See Azure WebJobs SDK dashboard for details."));
        }
Beispiel #13
0
        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(3, 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[2];
            Assert.Equal("Job host started", traceEvent.Message);

            host.Stop();
            host.Dispose();
        }
        public void MaxDegreeOfParallelism_Queues(int batchSize, int maxExpectedParallelism)
        {
            _receivedMessages = 0;
            _currentSimultaneouslyRunningFunctions = 0;
            _maxSimultaneouslyRunningFunctions     = 0;
            _numberOfQueueMessages = batchSize * 3;

            RandomNameResolver   nameResolver      = new RandomNameResolver();
            JobHostConfiguration hostConfiguration = new JobHostConfiguration()
            {
                NameResolver = nameResolver,
                TypeLocator  = new FakeTypeLocator(typeof(ParallelExecutionTests)),
            };

            hostConfiguration.Queues.BatchSize = batchSize;
            //hostConfiguration.Queues.NewBatchThreshold = Math.Max(1, batchSize / 2);

            CloudStorageAccount storageAccount = CloudStorageAccount.Parse(hostConfiguration.StorageConnectionString);

            _queueClient = storageAccount.CreateCloudQueueClient();
            CloudQueue queue = _queueClient.GetQueueReference(nameResolver.ResolveInString(TestQueueName));

            queue.CreateIfNotExists();

            for (int i = 0; i < _numberOfQueueMessages; i++)
            {
                int sleepTimeInSeconds = i % 2 == 0 ? 5 : 1;
                queue.AddMessage(new CloudQueueMessage(sleepTimeInSeconds.ToString()));
            }

            using (_allMessagesProcessed = new ManualResetEvent(initialState: false))
                using (JobHost host = new JobHost(hostConfiguration))
                {
                    host.Start();
                    _allMessagesProcessed.WaitOne(TimeSpan.FromSeconds(90));
                    host.Stop();
                }

            Assert.Equal(_numberOfQueueMessages, _receivedMessages);
            Assert.Equal(0, _currentSimultaneouslyRunningFunctions);
            Assert.Equal(maxExpectedParallelism, _maxSimultaneouslyRunningFunctions);
        }
Beispiel #15
0
        private async Task RunTimerJobTest(Type jobClassType, Func <bool> condition)
        {
            ExplicitTypeLocator  locator = new ExplicitTypeLocator(jobClassType);
            JobHostConfiguration config  = new JobHostConfiguration
            {
                TypeLocator = locator
            };

            config.UseTimers();
            JobHost host = new JobHost(config);

            host.Start();

            await TestHelpers.Await(() =>
            {
                return(condition());
            });

            host.Stop();
        }
Beispiel #16
0
        public async Task BlobChainTest()
        {
            // write the initial trigger blob to start the chain
            var blobClient = _storageAccount.CreateCloudBlobClient();
            var container  = blobClient.GetContainerReference(_nameResolver.ResolveInString(BlobChainContainerName));
            await container.CreateIfNotExistsAsync();

            CloudBlockBlob blob = container.GetBlockBlobReference(BlobChainTriggerBlobName);
            await blob.UploadTextAsync("0");

            var prog   = new BlobChainTest_Program();
            var config = NewConfig(prog);

            using (prog._completedEvent = new ManualResetEvent(initialState: false))
                using (JobHost host = new JobHost(config))
                {
                    host.Start();
                    Assert.True(prog._completedEvent.WaitOne(TimeSpan.FromSeconds(60)));
                }
        }
Beispiel #17
0
            public TestFixture()
            {
                int testPort = 43000;

                BaseUrl            = string.Format("http://localhost:{0}/", testPort);
                Client             = new HttpClient();
                Client.BaseAddress = new Uri(BaseUrl);

                JobHostConfiguration config = new JobHostConfiguration
                {
                    TypeLocator = new ExplicitTypeLocator(typeof(WebHookTestFunctions))
                };

                WebHooksConfiguration webHooksConfig = new WebHooksConfiguration(testPort);

                webHooksConfig.UseReceiver <GitHubWebHookReceiver>();
                config.UseWebHooks(webHooksConfig);

                Host = new JobHost(config);
                Host.Start();
            }
        public void BlobGetsProcessedOnlyOnce_MultipleHosts()
        {
            _testContainer
                .GetBlockBlobReference(BlobName)
                .UploadText("10");

            using (_blobProcessedEvent = new ManualResetEvent(initialState: false))
            using (JobHost host1 = new JobHost(_hostConfiguration))
            using (JobHost host2 = new JobHost(_hostConfiguration))
            {
                host1.Start();
                host2.Start();

                Assert.True(_blobProcessedEvent.WaitOne(TimeSpan.FromSeconds(60)));

                host1.Stop();
                host2.Stop();
            }

            Assert.Equal(1, _timesProcessed);
        }
Beispiel #19
0
        public void BlobGetsProcessedOnlyOnce_MultipleHosts()
        {
            _testContainer
            .GetBlockBlobReference(BlobName)
            .UploadText("10");

            using (_blobProcessedEvent = new ManualResetEvent(initialState: false))
                using (JobHost host1 = new JobHost(_hostConfiguration))
                    using (JobHost host2 = new JobHost(_hostConfiguration))
                    {
                        host1.Start();
                        host2.Start();

                        Assert.True(_blobProcessedEvent.WaitOne(TimeSpan.FromSeconds(60)));

                        host1.Stop();
                        host2.Stop();
                    }

            Assert.Equal(1, _timesProcessed);
        }
Beispiel #20
0
        static void Main(string[] args)
        {
            using (var listener = new ObservableEventListener())
            {
                listener.LogToConsole(new ConsoleFormatter());
                listener.EnableEvents(EngineEventSource.Log, EventLevel.Verbose, Keywords.All);
                listener.EnableEvents(TableStorageEventSource.Log, EventLevel.Verbose, Keywords.All);

                var eventContext = new TableStorageJobEventContext(
                    CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageAccount")));

                var host = new JobHost(eventContext);
                host.Add(new LogCleanupJob());
                host.Add(new SendNewsletterJob());
                host.Add(new LongRunningJob());
                host.Start();

                Console.WriteLine("Waiting...");
                Console.ReadLine();
            }
        }
        static void Main()
        {
            //CreateDemoData();
            GetNextMessage();
            EnCryptDecrypt.CryptorEngine.Decrypt();

            JobHost host = new JobHost();

            host.Start();

            // Stop the host if Ctrl + C/Ctrl + Break is pressed
            Console.CancelKeyPress += (sender, args) =>
            {
                host.Stop();
            };

            while (true)
            {
                Thread.Sleep(500);
            }
        }
Beispiel #22
0
        private void RunTest(Type testType, string testName, IDocumentDBServiceFactory factory, TraceWriter testTrace, object argument = null, DocumentDBConfiguration documentDBConfig = null)
        {
            ExplicitTypeLocator  locator = new ExplicitTypeLocator(testType);
            JobHostConfiguration config  = new JobHostConfiguration
            {
                TypeLocator = locator,
            };

            config.Tracing.Tracers.Add(testTrace);

            var arguments = new Dictionary <string, object>();

            arguments.Add("triggerData", argument);

            if (documentDBConfig == null)
            {
                documentDBConfig = new DocumentDBConfiguration()
                {
                    ConnectionString         = "AccountEndpoint=https://someuri;AccountKey=some_key",
                    DocumentDBServiceFactory = factory
                };
            }

            var resolver = new TestNameResolver();

            resolver.Values.Add("Database", "ResolvedDatabase");
            resolver.Values.Add("Collection", "ResolvedCollection");

            config.NameResolver = resolver;

            config.UseDocumentDB(documentDBConfig);

            JobHost host = new JobHost(config);

            host.Start();
            host.Call(testType.GetMethod(testName), arguments);
            host.Stop();
        }
Beispiel #23
0
        static void Main(string[] vargStrings)
        {
            var configuration = new JobHostConfiguration();

            configuration.Queues.MaxPollingInterval = TimeSpan.FromSeconds(30);
            configuration.Queues.MaxDequeueCount    = 10;
            configuration.Queues.BatchSize          = 1;

            var host = new JobHost(configuration);

            host.Start();

            // Stop the host if Ctrl + C/Ctrl + Break is pressed
            Console.CancelKeyPress += (sender, args) =>
            {
                host.Stop();
            };

            while (true)
            {
                Thread.Sleep(500);
            }
        }
Beispiel #24
0
        public async Task BlobGetsProcessedOnlyOnce_MultipleHosts()
        {
            await _testContainer
            .GetBlockBlobReference(TestBlobName)
            .UploadTextAsync("10");


            var prog   = new BlobGetsProcessedOnlyOnce_SingleHost_Program();
            var config = NewConfig(prog);


            using (prog._completedEvent = new ManualResetEvent(initialState: false))
                using (JobHost host1 = new JobHost(config))
                    using (JobHost host2 = new JobHost(config))
                    {
                        host1.Start();
                        host2.Start();

                        Assert.True(prog._completedEvent.WaitOne(TimeSpan.FromSeconds(60)));
                    }

            Assert.Equal(1, prog._timesProcessed);
        }
        public void Queue_IfNameIsInvalid_ThrowsDuringIndexing()
        {
            IStorageAccount account = CreateFakeStorageAccount();
            TaskCompletionSource<object> backgroundTaskSource = new TaskCompletionSource<object>();
            IServiceProvider serviceProvider = FunctionalTest.CreateServiceProviderForCallFailure(account,
                typeof(InvalidQueueNameProgram), backgroundTaskSource);

            using (JobHost host = new JobHost(serviceProvider))
            {
                // Act & Assert
                FunctionIndexingException exception = Assert.Throws<FunctionIndexingException>(() => host.Start());
                Assert.Equal("Error indexing method 'InvalidQueueNameProgram.Invalid'", exception.Message);
                Exception innerException = exception.InnerException;
                Assert.IsType<ArgumentException>(innerException);
                ArgumentException argumentException = (ArgumentException)innerException;
                Assert.Equal("name", argumentException.ParamName);
                string expectedMessage = String.Format(CultureInfo.InvariantCulture,
                    "The dash (-) character may not be the first or last letter - \"-illegalname-\"{0}Parameter " +
                    "name: name", Environment.NewLine);
                Assert.Equal(expectedMessage, innerException.Message);
                Assert.Equal(TaskStatus.WaitingForActivation, backgroundTaskSource.Task.Status);
            }
        }
Beispiel #26
0
        public void GlobalErrorHandler_CatchAll_InvokedAsExpected()
        {
            ErrorTriggerProgram_GlobalCatchAllHandler instance = new ErrorTriggerProgram_GlobalCatchAllHandler();

            JobHostConfiguration config = new JobHostConfiguration()
            {
                TypeLocator  = new ExplicitTypeLocator(instance.GetType()),
                JobActivator = new ExplicitJobActivator(instance)
            };

            config.UseCore();
            JobHost host = new JobHost(config);

            host.Start();

            MethodInfo method = instance.GetType().GetMethod("Throw");

            CallSafe(host, method);
            Assert.NotNull(instance.TraceFilter);

            Assert.Equal("One or more WebJob errors have occurred.", instance.TraceFilter.Message);
            Assert.Equal(1, instance.TraceFilter.Events.Count);
        }
Beispiel #27
0
        public void BlobGetsProcessedOnlyOnce_SingleHost()
        {
            _testContainer
            .GetBlockBlobReference(BlobName)
            .UploadText("0");

            int timeToProcess;

            // Process the blob first
            using (_blobProcessedEvent = new ManualResetEvent(initialState: false))
                using (JobHost host = new JobHost(_hostConfiguration))
                {
                    DateTime startTime = DateTime.Now;

                    host.Start();
                    Assert.True(_blobProcessedEvent.WaitOne(TimeSpan.FromSeconds(60)));

                    timeToProcess = (int)(DateTime.Now - startTime).TotalMilliseconds;

                    host.Stop();
                }

            // Then start again and make sure the blob doesn't get reprocessed
            // wait twice the amount of time required to process first before
            // deciding that it doesn't get reprocessed
            using (_blobProcessedEvent = new ManualResetEvent(initialState: false))
                using (JobHost host = new JobHost(_hostConfiguration))
                {
                    host.Start();

                    bool blobReprocessed = _blobProcessedEvent.WaitOne(2 * timeToProcess);

                    host.Stop();

                    Assert.False(blobReprocessed);
                }
        }
        private async Task RunTimerJobTest(Type jobClassType, Func<bool> condition)
        {
            TestTraceWriter testTrace = new TestTraceWriter(TraceLevel.Error);
            ExplicitTypeLocator locator = new ExplicitTypeLocator(jobClassType);
            JobHostConfiguration config = new JobHostConfiguration
            {
                TypeLocator = locator
            };
            config.UseTimers();
            config.Tracing.Tracers.Add(testTrace);
            JobHost host = new JobHost(config);

            host.Start();

            await TestHelpers.Await(() =>
            {
                return condition();
            });

            host.Stop();

            // ensure there were no errors
            Assert.Equal(0, testTrace.Events.Count);
        }
        public async Task SingletonNonTriggeredFunction_MultipleConcurrentInvocations_InvocationsAreSerialized()
        {
            JobHost host = CreateTestJobHost(1);

            host.Start();

            // make a bunch of parallel invocations
            int         numInvocations = 20;
            List <Task> invokeTasks    = new List <Task>();
            MethodInfo  method         = typeof(TestJobs).GetMethod(nameof(TestJobs.SingletonJob));

            for (int i = 0; i < numInvocations; i++)
            {
                int zone = _rand.Next(3) + 1;

                WorkItem workItem = new WorkItem
                {
                    ID          = i + 1,
                    Region      = "Central",
                    Zone        = zone,
                    Category    = 3,
                    Description = "Test Work Item " + i
                };
                invokeTasks.Add(host.CallAsync(method, new { workItem = workItem }));
            }

            await Task.WhenAll(invokeTasks);

            Assert.False(TestJobs.FailureDetected);
            Assert.Equal(numInvocations, TestJobs.JobInvocations[1]);

            await VerifyLeaseState(method, SingletonScope.Function, "TestValue", LeaseState.Available, LeaseStatus.Unlocked);

            host.Stop();
            host.Dispose();
        }
        public void Stop_WhenUsingHostCall_DoesNotTriggerCancellationToken()
        {
            // Run test in multithreaded environment
            var oldContext = SynchronizationContext.Current;

            try
            {
                SynchronizationContext.SetSynchronizationContext(null);
                using (JobHost host = new JobHost(_hostConfiguration))
                {
                    host.Start();

                    Task callTask = InvokeNoAutomaticTriggerFunction(host);

                    host.Stop();

                    EvaluateNoAutomaticTriggerCancellation(callTask, expectedCancellation: false);
                }
            }
            finally
            {
                SynchronizationContext.SetSynchronizationContext(oldContext);
            }
        }
        public void Stop_WhenUsingHostCall_DoesNotTriggerCancellationToken()
        {
            using (JobHost host = new JobHost(_hostConfiguration))
            {
                host.Start();

                Task callTask = InvokeNoAutomaticTriggerFunction(host);

                host.Stop();

                EvaluateNoAutomaticTriggerCancellation(callTask, expectedCancellation: false);
            }
        }
        private void PrepareHostForTrigger(JobHost host, bool startHost)
        {
            host.Call(typeof(AsyncCancellationEndToEndTests).GetMethod("WriteQueueMessage"));

            if (startHost)
            {
                host.Start();
                Assert.True(_functionStarted.WaitOne(DefaultTimeout));
            }
        }
        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 TestFixture()
            {
                RandomNameResolver   nameResolver      = new RandomNameResolver();
                JobHostConfiguration hostConfiguration = new JobHostConfiguration()
                {
                    NameResolver = nameResolver,
                    TypeLocator  = new FakeTypeLocator(typeof(BlobBindingEndToEndTests)),
                };

                Config = hostConfiguration;

                StorageAccount = CloudStorageAccount.Parse(hostConfiguration.StorageConnectionString);
                CloudBlobClient blobClient = StorageAccount.CreateCloudBlobClient();

                BlobContainer = blobClient.GetContainerReference(nameResolver.ResolveInString(ContainerName));
                Assert.False(BlobContainer.Exists());
                BlobContainer.Create();

                OutputBlobContainer = blobClient.GetContainerReference(nameResolver.ResolveInString(OutputContainerName));

                CloudBlobContainer pageBlobContainer = blobClient.GetContainerReference(nameResolver.ResolveInString(PageBlobContainerName));

                Assert.False(pageBlobContainer.Exists());
                pageBlobContainer.Create();

                CloudBlobContainer hierarchicalBlobContainer = blobClient.GetContainerReference(nameResolver.ResolveInString(HierarchicalBlobContainerName));

                Assert.False(hierarchicalBlobContainer.Exists());
                hierarchicalBlobContainer.Create();

                Host = new JobHost(hostConfiguration);
                Host.Start();

                // upload some test blobs
                CloudBlockBlob blob = BlobContainer.GetBlockBlobReference("blob1");

                blob.UploadText(TestData);
                blob = BlobContainer.GetBlockBlobReference("blob2");
                blob.UploadText(TestData);
                blob = BlobContainer.GetBlockBlobReference("blob3");
                blob.UploadText(TestData);
                blob = BlobContainer.GetBlockBlobReference("file1");
                blob.UploadText(TestData);
                blob = BlobContainer.GetBlockBlobReference("file2");
                blob.UploadText(TestData);

                // add a couple hierarchical blob paths
                blob = hierarchicalBlobContainer.GetBlockBlobReference("sub/blob1");
                blob.UploadText(TestData);
                blob = hierarchicalBlobContainer.GetBlockBlobReference("sub/blob2");
                blob.UploadText(TestData);
                blob = hierarchicalBlobContainer.GetBlockBlobReference("sub/sub/blob3");
                blob.UploadText(TestData);
                blob = hierarchicalBlobContainer.GetBlockBlobReference("blob4");
                blob.UploadText(TestData);

                byte[] bytes     = new byte[512];
                byte[] testBytes = Encoding.UTF8.GetBytes(TestData);
                for (int i = 0; i < testBytes.Length; i++)
                {
                    bytes[i] = testBytes[i];
                }
                CloudPageBlob pageBlob = pageBlobContainer.GetPageBlobReference("blob1");

                pageBlob.UploadFromByteArray(bytes, 0, bytes.Length);
                pageBlob = pageBlobContainer.GetPageBlobReference("blob2");
                pageBlob.UploadFromByteArray(bytes, 0, bytes.Length);
            }
Beispiel #35
0
        static void Main()
        {
            Log.Trace();
            // Set the maximum number of concurrent connections
            HttpUtilities.SetServicePointDefaultConnectionLimit();

            var shipHubConfig         = new ShipHubCloudConfiguration();
            var azureWebJobsDashboard = shipHubConfig.AzureWebJobsDashboard;
            var azureWebJobsStorage   = shipHubConfig.AzureWebJobsStorage;

            // Raygun Client
            var          raygunApiKey = shipHubConfig.RaygunApiKey;
            RaygunClient raygunClient = null;

            if (!raygunApiKey.IsNullOrWhiteSpace())
            {
                raygunClient = new RaygunClient(raygunApiKey);
                raygunClient.AddWrapperExceptions(typeof(AggregateException));
            }

            // App Insights Client
            var             applicationInsightsKey = shipHubConfig.ApplicationInsightsKey;
            TelemetryClient telemetryClient        = null;

            if (!applicationInsightsKey.IsNullOrWhiteSpace())
            {
                TelemetryConfiguration.Active.InstrumentationKey = applicationInsightsKey;
                telemetryClient = new TelemetryClient();
            }

            var detailedLogger = new DetailedExceptionLogger(telemetryClient, raygunClient);

            var container = CreateContainer(detailedLogger);

            // Hack to address https://github.com/realartists/shiphub-server/issues/277
            // I suspect that when DI occurs, the AzureBlobTraceListener is registered as a TraceListener
            // but not initialized. To get around this, force Orleans to initialize now, before any
            // TraceListeners get added.
            var timer = new Stopwatch();

            timer.Restart();
            Log.Info("[Orleans Client]: Initializing");
            container.GetInstance <IAsyncGrainFactory>();
            timer.Stop();
            Log.Info($"[Orleans Client]: Initialized in {timer.Elapsed}");

            // Job Host Configuration
            var config = new JobHostConfiguration()
            {
                DashboardConnectionString = azureWebJobsDashboard,
                StorageConnectionString   = azureWebJobsStorage,
                JobActivator = new SimpleInjectorJobActivator(container),
            };

            config.Queues.MaxDequeueCount = 2; // Only try twice

            // Gross manual DI
            ConfigureGlobalLogging(config, telemetryClient, raygunClient);

            var azureWebJobsServiceBus = shipHubConfig.AzureWebJobsServiceBus;
            var sbConfig = new ServiceBusConfiguration()
            {
                ConnectionString = azureWebJobsServiceBus,
            };

            sbConfig.MessageOptions.MaxConcurrentCalls = 128;

#if DEBUG
            config.UseDevelopmentSettings();
            config.DashboardConnectionString           = null;
            sbConfig.MessageOptions.AutoRenewTimeout   = TimeSpan.FromSeconds(10); // Abandon locks quickly
            sbConfig.MessageOptions.MaxConcurrentCalls = 1;
            config.Queues.MaxDequeueCount = 1;
#endif

            // https://azure.microsoft.com/en-us/documentation/articles/service-bus-performance-improvements/ recommends
            // 20x the processing rate/sec
            var ratePerSecond = 1;
            sbConfig.PrefetchCount = sbConfig.MessageOptions.MaxConcurrentCalls * 20 * ratePerSecond;

            Log.Info($"[Service Bus]: Initializing");
            timer.Restart();
            var sbFactory = container.GetInstance <IServiceBusFactory>();
            timer.Stop();
            Log.Info($"[Service Bus]: Initialized in {timer.Elapsed}");

            // Override default messaging provider to use pairing.
            sbConfig.MessagingProvider = new PairedMessagingProvider(sbConfig, sbFactory);

            config.UseServiceBus(sbConfig);
            config.UseTimers();
            config.UseCore(); // For ExecutionContext

            Log.Info("[Job Host]: Starting");
            using (var host = new JobHost(config)) {
#if DEBUG
                host.Start();
                Console.WriteLine("Press Any Key to Exit.");
                Console.ReadLine();
                Console.WriteLine("Stopping job host...");
                host.Stop();
#else
                host.RunAndBlock();
#endif
                Log.Info("[Job Host]: Stopped");
            }
        }
            public TestFixture()
            {
                RandomNameResolver   nameResolver      = new RandomNameResolver();
                JobHostConfiguration hostConfiguration = new JobHostConfiguration()
                {
                    NameResolver = nameResolver,
                    TypeLocator  = new FakeTypeLocator(typeof(MultipleStorageAccountsEndToEndTests)),
                };

                Config = hostConfiguration;

                Account1 = CloudStorageAccount.Parse(hostConfiguration.StorageConnectionString);
                string secondaryConnectionString = AmbientConnectionStringProvider.Instance.GetConnectionString(Secondary);

                Account2 = CloudStorageAccount.Parse(secondaryConnectionString);

                CleanContainers();

                CloudBlobClient    blobClient1     = Account1.CreateCloudBlobClient();
                string             inputName       = nameResolver.ResolveInString(Input);
                CloudBlobContainer inputContainer1 = blobClient1.GetContainerReference(inputName);

                inputContainer1.Create();
                string outputName = nameResolver.ResolveWholeString(Output);

                OutputContainer1 = blobClient1.GetContainerReference(outputName);
                OutputContainer1.CreateIfNotExists();

                CloudBlobClient    blobClient2     = Account2.CreateCloudBlobClient();
                CloudBlobContainer inputContainer2 = blobClient2.GetContainerReference(inputName);

                inputContainer2.Create();
                OutputContainer2 = blobClient2.GetContainerReference(outputName);
                OutputContainer2.CreateIfNotExists();

                CloudQueueClient queueClient1 = Account1.CreateCloudQueueClient();
                CloudQueue       inputQueue1  = queueClient1.GetQueueReference(inputName);

                inputQueue1.CreateIfNotExists();
                OutputQueue1 = queueClient1.GetQueueReference(outputName);
                OutputQueue1.CreateIfNotExists();

                CloudQueueClient queueClient2 = Account2.CreateCloudQueueClient();
                CloudQueue       inputQueue2  = queueClient2.GetQueueReference(inputName);

                inputQueue2.CreateIfNotExists();
                OutputQueue2 = queueClient2.GetQueueReference(outputName);
                OutputQueue2.CreateIfNotExists();

                CloudTableClient tableClient1    = Account1.CreateCloudTableClient();
                string           outputTableName = nameResolver.ResolveWholeString(OutputTableName);

                OutputTable1 = tableClient1.GetTableReference(outputTableName);
                OutputTable2 = Account2.CreateCloudTableClient().GetTableReference(outputTableName);

                // upload some test blobs to the input containers of both storage accounts
                CloudBlockBlob blob = inputContainer1.GetBlockBlobReference("blob1");

                blob.UploadText(TestData);
                blob = inputContainer2.GetBlockBlobReference("blob2");
                blob.UploadText(TestData);

                // upload some test queue messages to the input queues of both storage accounts
                inputQueue1.AddMessage(new CloudQueueMessage(TestData));
                inputQueue2.AddMessage(new CloudQueueMessage(TestData));

                Host = new JobHost(hostConfiguration);
                Host.Start();
            }
Beispiel #37
0
 /// <summary>
 /// <see cref="IJobHost.Start"/>
 /// </summary>
 public void Start()
 {
     _jobHost.Start();
 }
        public void JobHost_NoStorage_Succeeds()
        {
            string prevStorage   = Environment.GetEnvironmentVariable("AzureWebJobsStorage");
            string prevDashboard = Environment.GetEnvironmentVariable("AzureWebJobsDashboard");

            try
            {
                Environment.SetEnvironmentVariable("AzureWebJobsStorage", null);
                Environment.SetEnvironmentVariable("AzureWebJobsDashboard", null);

                JobHostConfiguration config = new JobHostConfiguration()
                {
                    TypeLocator = new FakeTypeLocator(typeof(BasicTest))
                };
                // Explicitly disalbe storage.
                config.HostId = Guid.NewGuid().ToString("n");
                config.DashboardConnectionString = null;
                config.StorageConnectionString   = null;

                var randomValue = Guid.NewGuid().ToString();

                StringBuilder sbLoggingCallbacks = new StringBuilder();
                var           fastLogger         = new FastLogger();
                config.AddService <IAsyncCollector <FunctionInstanceLogEntry> >(fastLogger);

                JobHost host = new JobHost(config);

                // Manually invoked.
                var method = typeof(BasicTest).GetMethod("Method", BindingFlags.Public | BindingFlags.Static);

                host.Call(method, new { value = randomValue });
                Assert.True(BasicTest.Called);

                Assert.Equal(2, fastLogger.List.Count); // We should be batching, so flush not called yet.

                host.Start();                           // required to call stop()
                host.Stop();                            // will ensure flush is called.

                // Verify fast logs
                Assert.Equal(3, fastLogger.List.Count);

                var startMsg = fastLogger.List[0];
                Assert.Equal("BasicTest.Method", startMsg.FunctionName);
                Assert.Equal(null, startMsg.EndTime);
                Assert.NotNull(startMsg.StartTime);

                var endMsg = fastLogger.List[1];
                Assert.Equal(startMsg.FunctionName, endMsg.FunctionName);
                Assert.Equal(startMsg.StartTime, endMsg.StartTime);
                Assert.Equal(startMsg.FunctionInstanceId, endMsg.FunctionInstanceId);
                Assert.NotNull(endMsg.EndTime); // signal completed
                Assert.True(endMsg.StartTime <= endMsg.EndTime);
                Assert.Null(endMsg.ErrorDetails);
                Assert.Null(endMsg.ParentId);

                Assert.Equal(2, endMsg.Arguments.Count);
                Assert.True(endMsg.Arguments.ContainsKey("log"));
                Assert.Equal(randomValue, endMsg.Arguments["value"]);
                Assert.Equal("val=" + randomValue, endMsg.LogOutput.Trim());

                Assert.Same(FastLogger.FlushEntry, fastLogger.List[2]);
            }
            finally
            {
                Environment.SetEnvironmentVariable("AzureWebJobsStorage", prevStorage);
                Environment.SetEnvironmentVariable("AzureWebJobsDashboard", prevDashboard);
            }
        }
        private void ServiceBusEndToEndInternal(Type jobContainerType, bool verifyLogs = true)
        {
            StringWriter consoleOutput = null;
            if (verifyLogs)
            {
                consoleOutput = new StringWriter();
                Console.SetOut(consoleOutput);
            }

            JobHostConfiguration config = new JobHostConfiguration()
            {
                NameResolver = _nameResolver,
                TypeLocator = new FakeTypeLocator(jobContainerType)
            };
            config.UseServiceBus(_serviceBusConfig);

            string startQueueName = ResolveName(StartQueueName);
            string secondQueueName = startQueueName.Replace("start", "1");
            string queuePrefix = startQueueName.Replace("-queue-start", "");
            string firstTopicName = string.Format("{0}-topic/Subscriptions/{0}-queue-topic-1", queuePrefix);
            string secondTopicName = string.Format("{0}-topic/Subscriptions/{0}-queue-topic-2", queuePrefix);
            CreateStartMessage(_serviceBusConfig.ConnectionString, startQueueName);

            _host = new JobHost(config);

            _topicSubscriptionCalled1 = new ManualResetEvent(initialState: false);
            _topicSubscriptionCalled2 = new ManualResetEvent(initialState: false);

            _host.Start();

            int timeout = 1 * 60 * 1000;
            _topicSubscriptionCalled1.WaitOne(timeout);
            _topicSubscriptionCalled2.WaitOne(timeout);

            // Wait for the host to terminate
            _host.Stop();

            Assert.Equal("E2E-SBQueue2SBQueue-SBQueue2SBTopic-topic-1", _resultMessage1);
            Assert.Equal("E2E-SBQueue2SBQueue-SBQueue2SBTopic-topic-2", _resultMessage2);

            if (verifyLogs)
            {
                string[] consoleOutputLines = consoleOutput.ToString().Trim().Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
                string[] expectedOutputLines = new string[]
                {
                    "Found the following functions:",
                    string.Format("{0}.SBQueue2SBQueue", jobContainerType.FullName),
                    string.Format("{0}.SBQueue2SBTopic", jobContainerType.FullName),
                    string.Format("{0}.SBTopicListener1", jobContainerType.FullName),
                    string.Format("{0}.SBTopicListener2", jobContainerType.FullName),
                    "Job host started",
                    string.Format("Executing: '{0}.SBQueue2SBQueue' - Reason: 'New ServiceBus message detected on '{1}'.'", jobContainerType.Name, startQueueName),
                    string.Format("Executing: '{0}.SBQueue2SBTopic' - Reason: 'New ServiceBus message detected on '{1}'.'", jobContainerType.Name, secondQueueName),
                    string.Format("Executing: '{0}.SBTopicListener1' - Reason: 'New ServiceBus message detected on '{1}'.'", jobContainerType.Name, firstTopicName),
                    string.Format("Executing: '{0}.SBTopicListener2' - Reason: 'New ServiceBus message detected on '{1}'.'", jobContainerType.Name, secondTopicName),
                    "Job host stopped"
                };
                Assert.True(expectedOutputLines.OrderBy(p => p).SequenceEqual(consoleOutputLines.OrderBy(p => p)));
            }
        }
        private static TimeBlock RunWebJobsSDKTestInternal(bool disableLogging)
        {
            JobHostConfiguration hostConfig = new JobHostConfiguration(_connectionString);
            hostConfig.Queues.BatchSize = BatchSize;
            hostConfig.NameResolver = _nameResolver;
            hostConfig.TypeLocator = new FakeTypeLocator(typeof(QueueOverheadPerfTest));

            if (disableLogging)
            {
                hostConfig.DashboardConnectionString = null;
            }

            _receivedMessages = 0;

            using (_firstMessagesReceivedEvent = new ManualResetEvent(initialState: false))
            using (_allMessagesReceivedEvent = new ManualResetEvent(initialState: false))
            using (JobHost host = new JobHost(hostConfig))
            {
                host.Start();

                _firstMessagesReceivedEvent.WaitOne();
                TimeBlock block = new TimeBlock();
                _allMessagesReceivedEvent.WaitOne();
                block.End();

                return block;
            }
        }
        public void StopAsync_WhenAlreadyStopping_ReturnsSameTask()
        {
            // Arrange
            using (JobHost host = new JobHost(CreateConfiguration()))
            {
                host.Start();

                // Replace (and cleanup) the existing listener to hook StopAsync.
                IListener oldRunner = host.Listener;
                oldRunner.StopAsync(CancellationToken.None).GetAwaiter().GetResult();

                TaskCompletionSource<object> stopTaskSource = new TaskCompletionSource<object>();
                Mock<IListener> listenerMock = new Mock<IListener>(MockBehavior.Strict);
                listenerMock.Setup(r => r.StopAsync(It.IsAny<CancellationToken>())).Returns(stopTaskSource.Task);
                listenerMock.Setup(r => r.Dispose());
                host.Listener = listenerMock.Object;
                Task alreadyStopping = host.StopAsync();

                // Act
                Task stoppingAgain = host.StopAsync();

                // Assert
                Assert.Same(alreadyStopping, stoppingAgain);

                // Cleanup
                stopTaskSource.SetResult(null);
                alreadyStopping.GetAwaiter().GetResult();
                stoppingAgain.GetAwaiter().GetResult();
            }
        }
        public void StopAsync_WhenStopped_DoesNotThrow()
        {
            // Arrange
            using (JobHost host = new JobHost(CreateConfiguration()))
            {
                host.Start();
                host.Stop();

                // Act & Assert
                host.StopAsync().GetAwaiter().GetResult();
            }
        }
        public void StartAsync_WhenStopping_Throws()
        {
            // Arrange
            using (JobHost host = new JobHost(CreateConfiguration()))
            {
                host.Start();

                // Replace (and cleanup) the exsiting runner to hook StopAsync.
                IListener oldListener = host.Listener;
                oldListener.StopAsync(CancellationToken.None).GetAwaiter().GetResult();

                TaskCompletionSource<object> stopTaskSource = new TaskCompletionSource<object>();
                Mock<IListener> listenerMock = new Mock<IListener>(MockBehavior.Strict);
                listenerMock.Setup(r => r.StopAsync(It.IsAny<CancellationToken>())).Returns(stopTaskSource.Task);
                listenerMock.Setup(r => r.Dispose());
                host.Listener = listenerMock.Object;

                Task stopping = host.StopAsync();

                // Act & Assert
                ExceptionAssert.ThrowsInvalidOperation(() => host.StartAsync(), "Start has already been called.");

                // Cleanup
                stopTaskSource.SetResult(null);
                stopping.GetAwaiter().GetResult();
            }
        }
        public void MaxDegreeOfParallelism_Queues(int batchSize, int maxExpectedParallelism)
        {
            _receivedMessages = 0;
            _currentSimultaneouslyRunningFunctions = 0;
            _maxSimultaneouslyRunningFunctions = 0;
            _numberOfQueueMessages = batchSize * 3;

            RandomNameResolver nameResolver = new RandomNameResolver();
            JobHostConfiguration hostConfiguration = new JobHostConfiguration()
            {
                NameResolver = nameResolver,
                TypeLocator = new FakeTypeLocator(typeof(ParallelExecutionTests)),
            };
            hostConfiguration.Queues.BatchSize = batchSize;

            CloudStorageAccount storageAccount = CloudStorageAccount.Parse(hostConfiguration.StorageConnectionString);
            _queueClient = storageAccount.CreateCloudQueueClient();
            CloudQueue queue = _queueClient.GetQueueReference(nameResolver.ResolveInString(TestQueueName));

            queue.CreateIfNotExists();

            for (int i = 0; i < _numberOfQueueMessages; i++)
            {
                int sleepTimeInSeconds = i % 2 == 0 ? 5 : 1;
                queue.AddMessage(new CloudQueueMessage(sleepTimeInSeconds.ToString()));
            }

            using (_allMessagesProcessed = new ManualResetEvent(initialState: false))
            using (JobHost host = new JobHost(hostConfiguration))
            {
                host.Start();
                _allMessagesProcessed.WaitOne(TimeSpan.FromSeconds(90));
                host.Stop();
            }

            Assert.Equal(_numberOfQueueMessages, _receivedMessages);
            Assert.Equal(0, _currentSimultaneouslyRunningFunctions);

            // the actual value will vary sometimes based on the speed of the machine
            // running the test.
            int delta = _maxSimultaneouslyRunningFunctions - maxExpectedParallelism;
            Assert.True(delta == 0 || delta == 1);
        }
 protected override void OnStart(string[] args)
 {
     jobHost.Start();
 }