// Stops running the host as soon as the program marks the task as completed. public static TResult Call <TResult>(IStorageAccount account, Type programType, MethodInfo method, IDictionary <string, object> arguments, Action <TaskCompletionSource <TResult> > setTaskSource) { // Arrange TaskCompletionSource <TResult> taskSource = new TaskCompletionSource <TResult>(); IServiceProvider serviceProvider = CreateServiceProviderForManualCompletion <TResult>(account, programType, taskSource); Task <TResult> task = taskSource.Task; setTaskSource.Invoke(taskSource); try { using (JobHost host = new JobHost(serviceProvider)) { Task callTask = host.CallAsync(method, arguments); // Act bool completed = Task.WhenAny(task, callTask).WaitUntilCompleted(3 * 1000); // Assert Assert.True(completed); // Give a nicer test failure message for faulted tasks. if (task.Status == TaskStatus.Faulted) { task.GetAwaiter().GetResult(); } if (callTask.Status == TaskStatus.Faulted) { callTask.GetAwaiter().GetResult(); } Assert.Equal(TaskStatus.RanToCompletion, callTask.Status); return(task.Result); } } finally { setTaskSource.Invoke(null); } }
private async Task RunTestAsync(Type testType, string testName, ICosmosDBServiceFactory factory, TraceWriter testTrace, object argument = null, string configConnectionString = ConfigConnStr, bool includeDefaultConnectionString = true) { ExplicitTypeLocator locator = new ExplicitTypeLocator(testType); JobHostConfiguration config = new JobHostConfiguration { TypeLocator = locator, }; config.Tracing.Tracers.Add(testTrace); var arguments = new Dictionary <string, object> { { "triggerData", argument } }; var cosmosDBConfig = new CosmosDBConfiguration() { ConnectionString = configConnectionString, CosmosDBServiceFactory = factory }; var resolver = new TestNameResolver(); resolver.Values.Add("Database", "ResolvedDatabase"); resolver.Values.Add("Collection", "ResolvedCollection"); resolver.Values.Add("MyConnectionString", AttributeConnStr); resolver.Values.Add("Query", "ResolvedQuery"); if (includeDefaultConnectionString) { resolver.Values.Add(CosmosDBConfiguration.AzureWebJobsCosmosDBConnectionStringName, DefaultConnStr); } config.NameResolver = resolver; config.UseCosmosDB(cosmosDBConfig); JobHost host = new JobHost(config); await host.StartAsync(); await host.CallAsync(testType.GetMethod(testName), arguments); await host.StopAsync(); }
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(); }
/// <summary> /// Helper function for the IDurableOrchestrationClientBinding test. Gets an IDurableOrchestrationClient. /// </summary> public static async Task <IDurableOrchestrationClient> GetOrchestrationClientBindingTest( this JobHost host, ITestOutputHelper output) { var startFunction = typeof(ClientFunctions) .GetMethod(nameof(ClientFunctions.GetOrchestrationClientBindingTest)); var clientRef = new IDurableOrchestrationClient[1]; var args = new Dictionary <string, object> { { "clientRef", clientRef }, }; await host.CallAsync(startFunction, args); IDurableOrchestrationClient client = clientRef[0]; return(client); }
// The following code will write a sentence as a message on a queue called textinput. // The SDK will trigger a function called CountAndSplitInWords which is listening on textinput queue. // CountAndSplitInWords will split the sentence into words and store results in Table storage. // static void Main() { if (!VerifyConfiguration()) { Console.ReadLine(); return; } CreateDemoData(); JobHost host = new JobHost(); Task callTask = host.CallAsync(typeof(Functions).GetMethod("ManualTrigger")); Console.WriteLine("Waiting for async operation..."); callTask.Wait(); Console.WriteLine("Task completed: " + callTask.Status); host.RunAndBlock(); }
public async Task TraceWriterLogging() { TextWriter hold = Console.Out; StringWriter consoleOutput = new StringWriter(); Console.SetOut(consoleOutput); using (_functionCompletedEvent = new ManualResetEvent(initialState: false)) { TestTraceWriter trace = new TestTraceWriter(TraceLevel.Verbose); _hostConfig.Tracing.Tracers.Add(trace); JobHost host = new JobHost(_hostConfig); await host.StartAsync(); await host.CallAsync(typeof(AsyncChainEndToEndTests).GetMethod("WriteStartDataMessageToQueue")); _functionCompletedEvent.WaitOne(); // ensure all logs have had a chance to flush await Task.Delay(3000); await host.StopAsync(); bool hasError = string.Join(Environment.NewLine, trace.Traces.Where(p => p.Message.Contains("Error"))).Any(); if (!hasError) { Assert.Equal(18, trace.Traces.Count); Assert.NotNull(trace.Traces.SingleOrDefault(p => p.Message.Contains("User TraceWriter log"))); Assert.NotNull(trace.Traces.SingleOrDefault(p => p.Message.Contains("User TextWriter log (TestParam)"))); Assert.NotNull(trace.Traces.SingleOrDefault(p => p.Message.Contains("Another User TextWriter log"))); ValidateTraceProperties(trace); string[] consoleOutputLines = consoleOutput.ToString().Trim().Split(new string[] { Environment.NewLine }, StringSplitOptions.None); Assert.Equal(27, consoleOutputLines.Length); Assert.NotNull(consoleOutputLines.SingleOrDefault(p => p.Contains("User TraceWriter log"))); Assert.NotNull(consoleOutputLines.SingleOrDefault(p => p.Contains("User TextWriter log (TestParam)"))); Assert.NotNull(consoleOutputLines.SingleOrDefault(p => p.Contains("Another User TextWriter log"))); } } Console.SetOut(hold); }
public async Task Timeout_NoExpiry_CompletesSuccessfully() { TestTraceWriter trace = new TestTraceWriter(TraceLevel.Verbose); _hostConfig.Tracing.Tracers.Add(trace); JobHost host = new JobHost(_hostConfig); _timeoutJobDelay = TimeSpan.FromSeconds(0); MethodInfo methodInfo = GetType().GetMethod("TimeoutJob"); await host.CallAsync(methodInfo); // Validate TraceWriter TraceEvent[] traceErrors = trace.Traces.Where(p => p.Level == TraceLevel.Error).ToArray(); Assert.Equal(0, traceErrors.Length); // Validate Logger LogMessage[] logErrors = _loggerProvider.GetAllLogMessages().Where(l => l.Level == Microsoft.Extensions.Logging.LogLevel.Error).ToArray(); Assert.Equal(0, logErrors.Length); }
private async Task RunTimeoutTest(IHost host, Type expectedExceptionType, string functionName) { JobHost jobHost = host.GetJobHost(); try { await jobHost.StartAsync(); MethodInfo methodInfo = GetType().GetMethod(functionName); Exception ex = await Assert.ThrowsAnyAsync <Exception>(async() => { await jobHost.CallAsync(methodInfo); }); Assert.IsType(expectedExceptionType, ex); } finally { await jobHost.StopAsync(); } string expectedExceptionMessage = $"Timeout value of 00:00:01 exceeded by function 'AsyncChainEndToEndTests.{functionName}'"; string expectedResultMessage = $"Executed 'AsyncChainEndToEndTests.{functionName}' (Failed, Id="; // Validate Logger var loggerProvider = host.GetTestLoggerProvider(); var resultLogger = loggerProvider.CreatedLoggers.Where(l => l.Category == LogCategories.Results).Single(); var executorLogger = loggerProvider.CreatedLoggers.Where(l => l.Category == LogCategories.CreateFunctionCategory(functionName)).Single(); // Results logs the exception with no message Assert.NotNull(resultLogger.GetLogMessages().Single().Exception); Assert.Null(resultLogger.GetLogMessages().Single().FormattedMessage); // It logs Executed/Executing messages and the timeout message. Assert.Equal(3, executorLogger.GetLogMessages().Count()); executorLogger.GetLogMessages().Single(p => p.FormattedMessage != null && p.FormattedMessage.StartsWith(expectedExceptionMessage)); LogMessage resultMessage = executorLogger.GetLogMessages().Single(p => p.FormattedMessage != null && p.FormattedMessage.StartsWith(expectedResultMessage)); Assert.NotNull(resultMessage.Exception); }
public static async Task FromUserToken_CredentialsValid_GetToken() { var config = new AuthTokenExtensionConfig(); var mockClient = GetAadClientMock(); config.AadClient = mockClient.Object; var args = new Dictionary <string, object> { { "token", SampleUserToken }, }; JobHost host = TestHelpers.NewHost <TokenFunctions>(config); await host.CallAsync("TokenFunctions.FromUserToken", args); var expectedResult = AccessTokenFromUserToken; Assert.Equal(expectedResult, finalTokenValue); mockClient.Verify(client => client.GetTokenOnBehalfOfUserAsync(SampleUserToken, GraphResource), Times.Exactly(1)); ResetState(); }
public async Task CanBindExecutionContext() { JobHostConfiguration config = new JobHostConfiguration { TypeLocator = new ExplicitTypeLocator(typeof(CoreTestJobs)) }; config.UseCore(); JobHost host = new JobHost(config); string methodName = nameof(CoreTestJobs.ExecutionContext); await host.CallAsync(typeof(CoreTestJobs).GetMethod(methodName)); ExecutionContext result = CoreTestJobs.Context; Assert.NotNull(result); Assert.NotEqual(Guid.Empty, result.InvocationId); Assert.Equal(methodName, result.FunctionName); Assert.Equal(Environment.CurrentDirectory, result.FunctionDirectory); }
static async Task CallExpectFailureAsync(JobHost host) { bool succeed = false; try { await host.CallAsync(nameof(MyProg3.Method2)); succeed = true; } catch (Exception e) { // Verify exception message comes at _throwAtPhase // Last exception wins. var e2 = e.InnerException ?? e; var lastThrowPhase = _throwAtPhase.Split(';').Reverse().First(); Assert.True(e2.Message.Contains(lastThrowPhase)); } Assert.False(succeed); // Expected method to fail }
public async Task Timeout_TimeoutExpires_TriggersCancellation() { TestTraceWriter trace = new TestTraceWriter(TraceLevel.Verbose); _hostConfig.Tracing.Tracers.Add(trace); JobHost host = new JobHost(_hostConfig); MethodInfo methodInfo = GetType().GetMethod("TimeoutJob"); TaskCanceledException ex = await Assert.ThrowsAsync <TaskCanceledException>(async() => { await host.CallAsync(methodInfo); }); // We expect 3 error messages total TraceEvent[] traceErrors = trace.Traces.Where(p => p.Level == TraceLevel.Error).ToArray(); Assert.Equal(3, traceErrors.Length); Assert.True(traceErrors[0].Message.StartsWith("Timeout value of 00:00:01 exceeded by function 'AsyncChainEndToEndTests.TimeoutJob'")); Assert.True(traceErrors[1].Message.StartsWith("Executed: 'AsyncChainEndToEndTests.TimeoutJob' (Failed)")); Assert.True(traceErrors[2].Message.Trim().StartsWith("Function had errors. See Azure WebJobs SDK dashboard for details.")); }
public async Task SetAppDirectory() { JobHostConfiguration config = new JobHostConfiguration { TypeLocator = new ExplicitTypeLocator(typeof(CoreTestJobs)) }; config.UseCore(@"z:\home"); JobHost host = new JobHost(config); await host.CallAsync("myfunc"); ExecutionContext result = CoreTestJobs.Context; Assert.NotNull(result); Assert.NotEqual(Guid.Empty, result.InvocationId); Assert.Equal("myfunc", result.FunctionName); Assert.Equal(@"z:\home\myfunc", result.FunctionDirectory); Assert.Equal(@"z:\home", result.FunctionAppDirectory); }
private static TResult CallQueueTrigger <TResult>(object message, Type programType, Action <TaskCompletionSource <TResult> > setTaskSource) { // Arrange TaskCompletionSource <TResult> functionTaskSource = new TaskCompletionSource <TResult>(); IServiceProvider serviceProvider = FunctionalTest.CreateServiceProviderForManualCompletion <TResult>( CreateFakeStorageAccount(), programType, functionTaskSource); Task <TResult> functionTask = functionTaskSource.Task; setTaskSource.Invoke(functionTaskSource); Task callTask; bool completed; using (JobHost host = new JobHost(serviceProvider)) { try { callTask = host.CallAsync(programType.GetMethod("Run"), new { message = message }); // Act completed = Task.WhenAll(callTask, functionTask).WaitUntilCompleted(3 * 1000); } finally { setTaskSource.Invoke(null); } } // Assert Assert.True(completed); // Give a nicer test failure message for faulted tasks. if (functionTask.Status == TaskStatus.Faulted) { functionTask.GetAwaiter().GetResult(); } Assert.Equal(TaskStatus.RanToCompletion, functionTask.Status); Assert.Equal(TaskStatus.RanToCompletion, callTask.Status); return(functionTask.Result); }
public static async Task <TestEntityClient> GetEntityClientAsync( this JobHost host, EntityId entityId, ITestOutputHelper output) { var startFunction = typeof(ClientFunctions) .GetMethod(nameof(ClientFunctions.GetEntityClient)); var clientRef = new TestEntityClient[1]; var args = new Dictionary <string, object> { { "entityId", entityId }, { "clientRef", clientRef }, }; await host.CallAsync(startFunction, args); TestEntityClient client = clientRef[0]; return(client); }
private async Task <HttpResponseMessage> TryInvokeNonWebHook(string routeKey, HttpRequestMessage request) { // If no WebHook function is registered, we'll see if there is a job function // that matches based on name, and if so invoke it directly MethodInfo methodInfo = null; if (TryGetMethodInfo(routeKey, out methodInfo)) { // Read the method arguments from the request body // and invoke the function string body = await request.Content.ReadAsStringAsync(); IDictionary <string, JToken> parsed = JObject.Parse(body); IDictionary <string, object> args = parsed.ToDictionary(p => p.Key, q => (object)q.Value.ToString()); await _host.CallAsync(methodInfo, args); return(new HttpResponseMessage(HttpStatusCode.OK)); } return(new HttpResponseMessage(HttpStatusCode.NotFound)); }
public static async Task <TestOrchestratorClient> StartOrchestratorAsync( this JobHost host, string functionName, object input, ITestOutputHelper output) { var startFunction = typeof(ClientFunctions).GetMethod(nameof(ClientFunctions.StartFunction)); var clientRef = new TestOrchestratorClient[1]; var args = new Dictionary <string, object> { { "functionName", functionName }, { "input", input }, { "clientRef", clientRef }, }; await host.CallAsync(startFunction, args); TestOrchestratorClient client = clientRef[0]; output.WriteLine($"Started {functionName}, Instance ID = {client.InstanceId}"); return(client); }
private async Task VerifyInputBinding(JobHost host, MethodInfo method) { string data = Guid.NewGuid().ToString(); string inputFile = Path.Combine(rootPath, ImportTestPath, string.Format("{0}.txt", method.Name)); File.WriteAllText(inputFile, data); await host.CallAsync(method); string outputFile = Path.Combine(rootPath, OutputTestPath, string.Format("{0}.txt", method.Name)); await TestHelpers.Await(() => { return(File.Exists(outputFile)); }); // give time for file to close await Task.Delay(1000); string result = File.ReadAllText(outputFile); Assert.Equal(data, result); }
public static async Task MainAsync() { using (var container = IoC.Initialize()) { var config = new JobHostConfiguration(); var startup = container.GetInstance <IStartup>(); if (container.GetInstance <IEnvironmentService>().IsCurrent(DasEnv.LOCAL)) { config.UseDevelopmentSettings(); } var jobHost = new JobHost(config); await startup.StartAsync(); await jobHost.CallAsync(typeof(Program).GetMethod(nameof(Block))); jobHost.RunAndBlock(); await startup.StopAsync(); } }
// Please set the following connection strings in app.config for this WebJob to run: // AzureWebJobsDashboard and AzureWebJobsStorage static void Main() { var config = new JobHostConfiguration(); if (config.IsDevelopment) { config.UseDevelopmentSettings(); } var host = new JobHost(config); while (true) { host.CallAsync(typeof(Functions).GetMethod("ProcessMethod")); // The following code ensures that the WebJob will be running continuously Console.WriteLine("host.RunAndBlock();"); host.RunAndBlock(); Console.WriteLine("MainThread.Sleep(5000);"); Thread.Sleep(5000); } }
public async Task EventCollectorOnly() { using (_functionCompletedEvent = new ManualResetEvent(initialState: false)) { // aggregator is disabled by default in these tests // add a FunctionEventCollector var eventCollector = new TestFunctionEventCollector(); _hostBuilder.ConfigureServices(services => { services.AddSingleton <IAsyncCollector <FunctionInstanceLogEntry> >(eventCollector); }); IHost host = _hostBuilder.Build(); JobHost jobHost = host.GetJobHost(); await jobHost.StartAsync(); await jobHost.CallAsync(typeof(AsyncChainEndToEndTests).GetMethod("WriteStartDataMessageToQueue")); var loggerProvider = host.GetTestLoggerProvider(); await WaitForFunctionCompleteAsync(loggerProvider); // ensure all logs have had a chance to flush await Task.Delay(3000); await jobHost.StopAsync(); // Make sure the aggregator was logged to var logger = host.GetTestLoggerProvider().CreatedLoggers.Where(l => l.Category == LogCategories.Aggregator).SingleOrDefault(); Assert.Null(logger); // Make sure the eventCollector was logged eventCollector.AssertFunctionCount(4, loggerProvider.GetLogString()); } }
public static void Call(IStorageAccount account, Type programType, MethodInfo method, IDictionary <string, object> arguments, params Type[] cloudBlobStreamBinderTypes) { // Arrange TaskCompletionSource <object> backgroundTaskSource = new TaskCompletionSource <object>(); IServiceProvider serviceProvider = CreateServiceProviderForManualCompletion <object>(account, programType, backgroundTaskSource, cloudBlobStreamBinderTypes: cloudBlobStreamBinderTypes); Task backgroundTask = backgroundTaskSource.Task; using (JobHost host = new JobHost(serviceProvider)) { Task task = host.CallAsync(method, arguments); // Act bool completed = Task.WhenAny(task, backgroundTask).WaitUntilCompleted(3 * 1000); // Assert Assert.True(completed); // Give a nicer test failure message for faulted tasks. if (backgroundTask.Status == TaskStatus.Faulted) { backgroundTask.GetAwaiter().GetResult(); } // The background task should not complete. Assert.Equal(TaskStatus.WaitingForActivation, backgroundTask.Status); // Give a nicer test failure message for faulted tasks. if (task.Status == TaskStatus.Faulted) { task.GetAwaiter().GetResult(); } Assert.Equal(TaskStatus.RanToCompletion, task.Status); } }
public static async Task Main(string[] args) { Console.WriteLine($"{nameof(WebJob)} started"); var cancellationToken = new WebJobsShutdownWatcher().Token; cancellationToken.Register(() => { Console.WriteLine("Cancellation received"); host.Stop(); }); // Assuming you want to get your shitty code up in the cloud ASAP // so I've created this minimalistic config var jobHostConfig = new JobHostConfiguration { HostId = Guid.NewGuid().ToString("N"), StorageConnectionString = string.Empty, DashboardConnectionString = string.Empty }; host = new JobHost(jobHostConfig); await host.CallAsync(nameof(OneTimeTask)); Console.WriteLine($"{nameof(WebJob)} terminated"); }
public async Task AggregatorAndEventCollector() { using (_functionCompletedEvent = new ManualResetEvent(initialState: false)) { _hostConfig.Tracing.ConsoleLevel = TraceLevel.Off; // enable the aggregator _hostConfig.Aggregator.IsEnabled = true; _hostConfig.Aggregator.BatchSize = 1; // add a FunctionEventCollector var eventCollector = new TestFunctionEventCollector(); _hostConfig.AddService <IAsyncCollector <FunctionInstanceLogEntry> >(eventCollector); JobHost host = new JobHost(_hostConfig); await host.StartAsync(); await host.CallAsync(typeof(AsyncChainEndToEndTests).GetMethod("WriteStartDataMessageToQueue")); _functionCompletedEvent.WaitOne(); // ensure all logs have had a chance to flush await Task.Delay(3000); await host.StopAsync(); // Make sure the aggregator was logged to var logger = _loggerProvider.CreatedLoggers.Where(l => l.Category == LogCategories.Aggregator).Single(); Assert.Equal(4, logger.LogMessages.Count); // Make sure the eventCollector was logged to // The aggregator ignores 'start' evetns, so this will be double Assert.Equal(8, eventCollector.LogCount); } }
public async Task FunctionFailures_LogsExpectedMessage() { IHost host = _hostBuilder.Build(); JobHost jobHost = host.GetJobHost(); MethodInfo methodInfo = GetType().GetMethod(nameof(AlwaysFailJob)); try { await jobHost.CallAsync(methodInfo); } catch { } string expectedName = $"{methodInfo.DeclaringType.FullName}.{methodInfo.Name}"; // Validate Logger // Logger only writes out a single log message (which includes the Exception). var logger = host.GetTestLoggerProvider().CreatedLoggers.Where(l => l.Category == LogCategories.Results).Single(); var logMessage = logger.GetLogMessages().Single(); var loggerException = logMessage.Exception as FunctionException; Assert.NotNull(loggerException); Assert.Equal(expectedName, loggerException.MethodName); }
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 static async Task FromId_TokenStillValid_GetStoredToken() { var currentToken = BuildTokenEntry(DateTime.UtcNow.AddDays(1)); var config = new AuthTokenExtensionConfig(); var mockClient = GetEasyAuthClientMock(currentToken); config.EasyAuthClient = mockClient.Object; config.AppSettings = GetNameResolver(new Dictionary <string, string>() { { Constants.AppSettingWebsiteAuthSigningKey, SigningKey } }).Object; var args = new Dictionary <string, object> { { "token", "dummyValue" }, }; JobHost host = TestHelpers.NewHost <TokenFunctions>(config); await host.CallAsync("TokenFunctions.FromId", args); var expectedResult = currentToken.AccessToken; Assert.Equal(expectedResult, finalTokenValue); ResetState(); }
private Task InvokeNoAutomaticTriggerFunction(JobHost host, CancellationToken token) { Task callTask = host.CallAsync( typeof(AsyncCancellationEndToEndTests).GetMethod("InfiniteRunningFunctionUnlessCancelledManual"), token); Assert.True(_functionStarted.WaitOne(DefaultTimeout)); return callTask; }
public async Task Test(JobHost <ConfigConcreteTypeNoConverter> host) { await host.CallAsync("Func", new { k = 1 }); Assert.Equal("AlphaBuilder(1)", _log); }
public static Task CallAsync <T>(this JobHost host, string methodName) { return(host.CallAsync(typeof(T).GetMethod(methodName))); }
public async Task ApplicationInsights_FailedFunction() { string testName = nameof(TestApplicationInsightsFailure); LogCategoryFilter filter = new LogCategoryFilter(); filter.DefaultLevel = LogLevel.Information; var loggerFactory = new LoggerFactory() .AddApplicationInsights( new TestTelemetryClientFactory(filter.Filter, _channel)); JobHostConfiguration config = new JobHostConfiguration { LoggerFactory = loggerFactory, TypeLocator = new FakeTypeLocator(GetType()), }; config.Aggregator.IsEnabled = false; config.AddService <IWebJobsExceptionHandler>(new TestExceptionHandler()); using (JobHost host = new JobHost(config)) { await host.StartAsync(); var methodInfo = GetType().GetMethod(testName, BindingFlags.Public | BindingFlags.Static); await Assert.ThrowsAsync <FunctionInvocationException>(() => host.CallAsync(methodInfo, new { input = "function input" })); await host.StopAsync(); } Assert.Equal(8, _channel.Telemetries.Count); // Validate the traces. Order by message string as the requests may come in // slightly out-of-order or on different threads TraceTelemetry[] telemetries = _channel.Telemetries .OfType <TraceTelemetry>() .OrderBy(t => t.Message) .ToArray(); ValidateTrace(telemetries[0], "Found the following functions:\r\n", LogCategories.Startup); ValidateTrace(telemetries[1], "Job host started", LogCategories.Startup); ValidateTrace(telemetries[2], "Job host stopped", LogCategories.Startup); ValidateTrace(telemetries[3], "Logger", LogCategories.Function, testName, hasCustomScope: true); ValidateTrace(telemetries[4], "Trace", LogCategories.Function, testName); // Validate the exception ExceptionTelemetry[] exceptions = _channel.Telemetries .OfType <ExceptionTelemetry>() .OrderBy(t => t.Timestamp) .ToArray(); Assert.Equal(2, exceptions.Length); ValidateException(exceptions[0], LogCategories.Function, testName); ValidateException(exceptions[1], LogCategories.Results, testName); // Finally, validate the request RequestTelemetry request = _channel.Telemetries .OfType <RequestTelemetry>() .Single(); ValidateRequest(request, testName, false); }