public static ClearFunctionLogs ( string functionName ) : void | ||
functionName | string | |
return | void |
public async Task Scenario_DoneCalledMultipleTimes_ErrorIsLogged() { TestHelpers.ClearFunctionLogs("Scenarios"); JObject input = new JObject { { "scenario", "doubleDone" } }; Dictionary <string, object> arguments = new Dictionary <string, object> { { "input", input.ToString() } }; await Fixture.Host.CallAsync("Scenarios", arguments); var logs = await TestHelpers.GetFunctionLogsAsync("Scenarios"); Assert.Equal(4, logs.Count); Assert.True(logs.Any(p => p.Contains("Function started"))); Assert.True(logs.Any(p => p.Contains("Running scenario 'doubleDone'"))); // verify an error was written Assert.True(logs.Any(p => p.Contains("Error: 'done' has already been called. Please check your script for extraneous calls to 'done'."))); // verify the function completed successfully Assert.True(logs.Any(p => p.Contains("Function completed (Success"))); }
public async Task ListenerError_LogsAndDoesNotStopHost() { string queueName = "samples-input-nonexistent"; bool exists = await Fixture.NamespaceManager.QueueExistsAsync(queueName); Assert.False(exists, $"This test expects the queue '{queueName}' to not exist, but it does."); IList <string> logs = null; await TestHelpers.Await(() => { logs = TestHelpers.GetFunctionLogsAsync("ListenerStartupException", false).Result; string logToFind = "The listener for function 'Functions.ListenerStartupException' was unable to start."; return(logs.Any(l => l.Contains(logToFind))); }); TestHelpers.ClearFunctionLogs("TimerTrigger"); // assert that timer function is still running await TestHelpers.Await(() => { logs = TestHelpers.GetFunctionLogsAsync("TimerTrigger", false).Result; string logToFind = "Timer function ran!"; return(logs.Any(l => l.Contains(logToFind))); }); // assert that Stop does not throw error Fixture.Host.Stop(); }
public async Task QueueTriggerToBlobTest() { TestHelpers.ClearFunctionLogs("QueueTriggerToBlob"); string id = Guid.NewGuid().ToString(); string messageContent = string.Format("{{ \"id\": \"{0}\" }}", id); CloudQueueMessage message = new CloudQueueMessage(messageContent); await Fixture.TestQueue.AddMessageAsync(message); var resultBlob = Fixture.TestOutputContainer.GetBlockBlobReference(id); string result = await TestHelpers.WaitForBlobAndGetStringAsync(resultBlob); Assert.Equal(TestHelpers.RemoveByteOrderMarkAndWhitespace(messageContent), TestHelpers.RemoveByteOrderMarkAndWhitespace(result)); string userCategory = LogCategories.CreateFunctionUserCategory("QueueTriggerToBlob"); LogMessage traceEvent = await WaitForTraceAsync(p => p?.FormattedMessage != null && p.FormattedMessage.Contains(id) && string.Equals(p.Category, userCategory, StringComparison.Ordinal)); Assert.Equal(LogLevel.Information, traceEvent.Level); string trace = traceEvent.FormattedMessage; Assert.Contains("script processed queue message", trace); Assert.Contains(messageContent.Replace(" ", string.Empty), trace.Replace(" ", string.Empty)); }
private async Task RunTimeoutTest(string scriptLang, string functionName) { TestHelpers.ClearFunctionLogs(functionName); TimeSpan testTimeout = TimeSpan.FromSeconds(3); var traceWriter = new TestTraceWriter(TraceLevel.Verbose); using (var manager = await CreateAndStartScriptHostManager(scriptLang, functionName, testTimeout, traceWriter)) { string testData = Guid.NewGuid().ToString(); Dictionary <string, object> arguments = new Dictionary <string, object> { { "inputData", testData }, }; FunctionTimeoutException ex = await Assert.ThrowsAsync <FunctionTimeoutException>(() => manager.Instance.CallAsync(functionName, arguments)); await TestHelpers.Await(() => { // make sure logging from within the function worked // TODO: This doesn't appear to work for Powershell in AppVeyor. Need to investigate. //bool hasTestData = inProgressLogs.Any(l => l.Contains(testData)); var expectedMessage = $"Timeout value of {testTimeout} was exceeded by function: Functions.{functionName}"; var traces = string.Join(Environment.NewLine, traceWriter.Traces); return(traces.Contains(expectedMessage)); }); var exception = GetExceptionHandler(manager).TimeoutExceptionInfos.Single().SourceException; Assert.IsType <FunctionTimeoutException>(exception); } }
public async Task Scenario_Logging() { TestHelpers.ClearFunctionLogs("Scenarios"); string testData = Guid.NewGuid().ToString(); JObject input = new JObject { { "scenario", "logging" }, { "input", testData }, }; Dictionary <string, object> arguments = new Dictionary <string, object> { { "input", input.ToString() } }; await Fixture.Host.CallAsync("Scenarios", arguments); var logs = await TestHelpers.GetFunctionLogsAsync("Scenarios"); // verify use of context.log to log complex objects TraceEvent scriptTrace = Fixture.TraceWriter.Traces.Single(p => p.Message.Contains(testData)); Assert.Equal(TraceLevel.Info, scriptTrace.Level); JObject logEntry = JObject.Parse(scriptTrace.Message); Assert.Equal("This is a test", logEntry["message"]); Assert.Equal("v6.5.0", (string)logEntry["version"]); Assert.Equal(testData, logEntry["input"]); }
public async Task ListenerError_LogsAndDoesNotStopHost() { IList <string> logs = null; await TestHelpers.Await(() => { logs = TestHelpers.GetFunctionLogsAsync("ListenerStartupException", false).Result; return(logs.Count > 0); }); // assert that listener error was captured Assert.Contains(logs, (log) => log.Contains("The listener for function 'Functions.ListenerStartupException' was unable to start.")); TestHelpers.ClearFunctionLogs("TimerTrigger"); await TestHelpers.Await(() => { logs = TestHelpers.GetFunctionLogsAsync("TimerTrigger", false).Result; return(logs.Count > 0); }); // assert that timer function is still running Assert.Contains(logs, (log) => log.Contains("Timer function ran!")); // assert that Stop does not throw error Fixture.Host.Stop(); }
public async Task BlobTriggerToBlobTest() { TestHelpers.ClearFunctionLogs("BlobTriggerToBlob"); // write a binary blob string name = Guid.NewGuid().ToString(); CloudBlockBlob inputBlob = Fixture.TestInputContainer.GetBlockBlobReference(name); byte[] inputBytes = new byte[] { 1, 2, 3, 4, 5 }; using (var stream = inputBlob.OpenWrite()) { stream.Write(inputBytes, 0, inputBytes.Length); } var resultBlob = Fixture.TestOutputContainer.GetBlockBlobReference(name); await TestHelpers.WaitForBlobAsync(resultBlob); byte[] resultBytes; using (var resultStream = resultBlob.OpenRead()) using (var ms = new MemoryStream()) { resultStream.CopyTo(ms); resultBytes = ms.ToArray(); } JObject testResult = await GetFunctionTestResult("BlobTriggerToBlob"); Assert.Equal(inputBytes, resultBytes); Assert.True((bool)testResult["isBuffer"]); Assert.Equal(5, (int)testResult["length"]); }
public async Task PromiseApi_ResolveAfterDone() { TestHelpers.ClearFunctionLogs("Scenarios"); JObject input = new JObject { { "scenario", "promiseApiDone" } }; var arguments = new Dictionary <string, object>() { { "input", input.ToString() } }; // call multiple times to reduce flakiness (function can exit before Promise.resolve executes) for (int i = 0; i < 10; i++) { await Task.WhenAny(Fixture.Host.CallAsync("Scenarios", arguments), Task.Delay(2000)); var logs = await TestHelpers.GetFunctionLogsAsync("Scenarios"); if (logs.Any(p => p.Contains("Error: Choose either to return a promise or call 'done'. Do not use both in your script."))) { // short circuit if we find log return; } } // this should never be reached Assert.True(false, "There was no log found for duplicate calls to done"); }
public async Task HttpTrigger_Post_ByteArray(string contentType) { TestHelpers.ClearFunctionLogs("HttpTriggerByteArray"); IHeaderDictionary headers = new HeaderDictionary(); headers.Add("Content-Type", contentType); byte[] inputBytes = new byte[] { 1, 2, 3, 4, 5 }; var content = inputBytes; HttpRequest request = HttpTestHelpers.CreateHttpRequest("POST", "http://localhost/api/httptriggerbytearray", headers, content); Dictionary <string, object> arguments = new Dictionary <string, object> { { "req", request } }; await Fixture.JobHost.CallAsync("HttpTriggerByteArray", arguments); var result = (IActionResult)request.HttpContext.Items[ScriptConstants.AzureFunctionsHttpResponseKey]; RawScriptResult objectResult = result as RawScriptResult; Assert.NotNull(objectResult); Assert.Equal(200, objectResult.StatusCode); JObject body = (JObject)objectResult.Content; Assert.True((bool)body["isBuffer"]); Assert.Equal(5, body["length"]); var rawBody = Encoding.UTF8.GetBytes((string)body["rawBody"]); Assert.Equal(inputBytes, rawBody); }
public async Task HttpTrigger_CustomRoute_Post_ReturnsExpectedResponse() { TestHelpers.ClearFunctionLogs("HttpTrigger-CustomRoute-Post"); string id = Guid.NewGuid().ToString(); string functionKey = "5u3pyihh8ldfelipm3qdabw69iah0oghgzw8n959"; string uri = $"api/node/products/housewares/{id}?code={functionKey}"; JObject product = new JObject { { "id", id }, { "name", "Waffle Maker Pro" }, { "category", "Housewares" } }; HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uri) { Content = new StringContent(product.ToString()) }; HttpResponseMessage response = await this._fixture.HttpClient.SendAsync(request); Assert.Equal(HttpStatusCode.Created, response.StatusCode); // wait for function to execute and produce its result blob CloudBlobContainer outputContainer = _fixture.BlobClient.GetContainerReference("samples-output"); string path = $"housewares/{id}"; CloudBlockBlob outputBlob = outputContainer.GetBlockBlobReference(path); string result = await TestHelpers.WaitForBlobAndGetStringAsync(outputBlob); JObject resultProduct = JObject.Parse(Utility.RemoveUtf8ByteOrderMark(result)); Assert.Equal(id, (string)resultProduct["id"]); Assert.Equal((string)product["name"], (string)resultProduct["name"]); }
public async Task PromiseApi_ResolveAfterDone() { TestHelpers.ClearFunctionLogs("Scenarios"); JObject input = new JObject { { "scenario", "promiseApiDone" } }; var arguments = new Dictionary <string, object>() { { "input", input.ToString() } }; // call multiple times to reduce flakiness (function can exit before Promise.resolve executes) for (int i = 0; i < 5; i++) { await Task.WhenAny(Fixture.Host.CallAsync("Scenarios", arguments), Task.Delay(3000)); } var logs = await TestHelpers.GetFunctionLogsAsync("Scenarios"); Assert.True(logs.Any(p => p.Contains("Error: Choose either to return a promise or call 'done'. Do not use both in your script."))); Assert.True(logs.Any(p => p.Contains("Function completed (Success"))); }
public async Task Scenario_DoneCalledMultipleTimes_ErrorIsLogged() { TestHelpers.ClearFunctionLogs("Scenarios"); JObject input = new JObject { { "scenario", "doubleDone" } }; Dictionary <string, object> arguments = new Dictionary <string, object> { { "input", input.ToString() } }; // call a few times since this is a timing related error for (int i = 0; i < 3; i++) { await Fixture.Host.CallAsync("Scenarios", arguments); } var logs = await TestHelpers.GetFunctionLogsAsync("Scenarios"); // verify an error was written at least once Assert.True(logs.Any(p => p.Contains("Error: 'done' has already been called. Please check your script for extraneous calls to 'done'."))); // verify the function completed successfully each time Assert.Equal(3, logs.Count(p => p.Contains("Function completed (Success"))); }
public async Task HttpTrigger_Post_ByteArray() { TestHelpers.ClearFunctionLogs("HttpTriggerByteArray"); byte[] inputBytes = new byte[] { 1, 2, 3, 4, 5 }; HttpRequestMessage request = new HttpRequestMessage { RequestUri = new Uri(string.Format("http://localhost/api/httptriggerbytearray")), Method = HttpMethod.Post, Content = new ByteArrayContent(inputBytes) }; request.SetConfiguration(new HttpConfiguration()); request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); Dictionary <string, object> arguments = new Dictionary <string, object> { { "req", request } }; await Fixture.Host.CallAsync("HttpTriggerByteArray", arguments); HttpResponseMessage response = (HttpResponseMessage)request.Properties[ScriptConstants.AzureFunctionsHttpResponseKey]; Assert.Equal(HttpStatusCode.OK, response.StatusCode); JObject testResult = await GetFunctionTestResult("HttpTriggerByteArray"); Assert.True((bool)testResult["isBuffer"]); Assert.Equal(5, (int)testResult["length"]); }
protected EndToEndTestFixture(string rootPath, string testId) { _settingsManager = ScriptSettingsManager.Instance; FixtureId = testId; string connectionString = AmbientConnectionStringProvider.Instance.GetConnectionString(ConnectionStringNames.Storage); CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString); QueueClient = storageAccount.CreateCloudQueueClient(); BlobClient = storageAccount.CreateCloudBlobClient(); TableClient = storageAccount.CreateCloudTableClient(); CreateTestStorageEntities(); TraceWriter = new TestTraceWriter(TraceLevel.Verbose); ApiHubTestHelper.SetDefaultConnectionFactory(); ScriptHostConfiguration config = new ScriptHostConfiguration() { RootScriptPath = rootPath, TraceWriter = TraceWriter, FileLoggingMode = FileLoggingMode.Always }; RequestConfiguration = new HttpConfiguration(); RequestConfiguration.Formatters.Add(new PlaintextMediaTypeFormatter()); ScriptHostEnvironmentMock = new Mock <IScriptHostEnvironment>(); // Reset the timer logs first, since one of the tests will // be checking them TestHelpers.ClearFunctionLogs("TimerTrigger"); Host = ScriptHost.Create(ScriptHostEnvironmentMock.Object, config, _settingsManager); Host.Start(); }
public async Task ApiHubTableEntityIn() { TestHelpers.ClearFunctionLogs("ApiHubTableEntityIn"); // Ensure the test entity exists. await ApiHubTestHelper.EnsureEntityAsync(ApiHubTestHelper.EntityId4); // Test table entity out binding. JObject input = new JObject { { "table", "SampleTable" }, { "id", ApiHubTestHelper.EntityId4 } }; await Fixture.Host.CallAsync("ApiHubTableEntityIn", new Dictionary <string, object>() { { "input", input.ToString() } }); var logs = await TestHelpers.GetFunctionLogsAsync("ApiHubTableEntityIn"); string expectedLog = string.Format("TestResult: {0}", ApiHubTestHelper.EntityId4); Assert.True(logs.Any(p => p.Contains(expectedLog))); }
protected EndToEndTestFixture(string rootPath, string testId) { FixtureId = testId; string connectionString = AmbientConnectionStringProvider.Instance.GetConnectionString(ConnectionStringNames.Storage); CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString); QueueClient = storageAccount.CreateCloudQueueClient(); BlobClient = storageAccount.CreateCloudBlobClient(); TableClient = storageAccount.CreateCloudTableClient(); CreateTestStorageEntities(); TraceWriter = new TestTraceWriter(TraceLevel.Verbose); ApiHubTestHelper.SetDefaultConnectionFactory(); ScriptHostConfiguration config = new ScriptHostConfiguration() { RootScriptPath = rootPath, TraceWriter = TraceWriter, FileLoggingMode = FileLoggingMode.Always }; // Clear the timer logs first, since one of the tests will // be checking them TestHelpers.ClearFunctionLogs("TimerTrigger"); Host = ScriptHost.Create(config); Host.Start(); }
protected ScriptHostEndToEndTestFixture(string rootPath, string testId, ProxyClientExecutor proxyClient = null, bool startHost = true, ICollection <string> functions = null, string functionsWorkerLanguage = null) { if (!string.IsNullOrEmpty(functionsWorkerLanguage)) { Environment.SetEnvironmentVariable(LanguageWorkerConstants.FunctionWorkerRuntimeSettingName, functionsWorkerLanguage); } _settingsManager = ScriptSettingsManager.Instance; FixtureId = testId; string connectionString = AmbientConnectionStringProvider.Instance.GetConnectionString(ConnectionStringNames.Storage); CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString); QueueClient = storageAccount.CreateCloudQueueClient(); BlobClient = storageAccount.CreateCloudBlobClient(); TableClient = storageAccount.CreateCloudTableClient(); CreateTestStorageEntities().Wait(); // ApiHubTestHelper.SetDefaultConnectionFactory(); ScriptHostConfiguration config = new ScriptHostConfiguration() { RootScriptPath = rootPath, FileLoggingMode = FileLoggingMode.Always, }; if (functions != null) { config.OnConfigurationApplied = c => c.Functions = functions; } RequestConfiguration = new HttpConfiguration(); EventManager = new ScriptEventManager(); ScriptHostEnvironmentMock = new Mock <IScriptHostEnvironment>(); LoggerProvider = new TestLoggerProvider(); ILoggerProviderFactory loggerProviderFactory = new TestLoggerProviderFactory(LoggerProvider); // Reset the timer logs first, since one of the tests will // be checking them TestHelpers.ClearFunctionLogs("TimerTrigger"); TestHelpers.ClearFunctionLogs("ListenerStartupException"); InitializeConfig(config); Func <string, FunctionDescriptor> funcLookup = (name) => this.Host.GetFunctionOrNull(name); var fastLogger = new FunctionInstanceLogger(funcLookup, new MetricsLogger()); config.HostConfig.AddService <IAsyncCollector <FunctionInstanceLogEntry> >(fastLogger); Host = new ScriptHost(ScriptHostEnvironmentMock.Object, EventManager, config, _settingsManager, proxyClient: proxyClient, loggerProviderFactory: loggerProviderFactory); Host.Initialize(); if (startHost) { Host.HostStarted += (s, e) => _hostStartedEvent.Set(); Host.Start(); _hostStartedEvent.Wait(TimeSpan.FromSeconds(30)); } }
public async Task Scenario_Logging() { // Sleep to make sure all logs from other "Scenarios" tests have flushed before // we delete the file. await Task.Delay(1000); TestHelpers.ClearFunctionLogs("Scenarios"); string testData = Guid.NewGuid().ToString(); JObject input = new JObject { { "scenario", "logging" }, { "input", testData }, }; Dictionary <string, object> arguments = new Dictionary <string, object> { { "input", input.ToString() } }; await Fixture.Host.CallAsync("Scenarios", arguments); IList <string> logs = null; await TestHelpers.Await(() => { logs = TestHelpers.GetFunctionLogsAsync("Scenarios", throwOnNoLogs: false).Result; return(logs.Count > 0); }); // verify use of context.log to log complex objects TraceEvent scriptTrace = Fixture.TraceWriter.Traces.Single(p => p.Message.Contains(testData)); Assert.Equal(System.Diagnostics.TraceLevel.Info, scriptTrace.Level); JObject logEntry = JObject.Parse(scriptTrace.Message); Assert.Equal("This is a test", logEntry["message"]); Assert.Equal(testData, logEntry["input"]); // verify log levels in traces TraceEvent[] traces = Fixture.TraceWriter.Traces.Where(t => t.Message.Contains("loglevel")).ToArray(); Assert.Equal(System.Diagnostics.TraceLevel.Info, traces[0].Level); Assert.Equal("loglevel default", traces[0].Message); Assert.Equal(System.Diagnostics.TraceLevel.Info, traces[1].Level); Assert.Equal("loglevel info", traces[1].Message); Assert.Equal(System.Diagnostics.TraceLevel.Verbose, traces[2].Level); Assert.Equal("loglevel verbose", traces[2].Message); Assert.Equal(System.Diagnostics.TraceLevel.Warning, traces[3].Level); Assert.Equal("loglevel warn", traces[3].Message); Assert.Equal(System.Diagnostics.TraceLevel.Error, traces[4].Level); Assert.Equal("loglevel error", traces[4].Message); // verify most of the logs look correct Assert.EndsWith("Mathew Charles", logs[4]); Assert.EndsWith("null", logs[5]); Assert.EndsWith("1234", logs[6]); Assert.EndsWith("true", logs[7]); Assert.EndsWith("loglevel default", logs[8]); Assert.EndsWith("loglevel info", logs[9]); }
public async Task HttpTrigger_CustomRoute_Get_ReturnsExpectedResponse() { TestHelpers.ClearFunctionLogs("HttpTrigger-CustomRoute-Get"); var id = Guid.NewGuid().ToString(); string functionKey = "82fprgh77jlbhcma3yr1zen8uv9yb0i7dwze3np2"; string uri = $"api/node/products/electronics/{id}?code={functionKey}"; HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain")); HttpResponseMessage response = await this._fixture.HttpClient.SendAsync(request); Assert.Equal(HttpStatusCode.OK, response.StatusCode); string json = await response.Content.ReadAsStringAsync(); var product = JObject.Parse(json); Assert.Equal("electronics", (string)product["category"]); Assert.Equal(id, (string)product["id"]); // test optional route param (id) uri = $"api/node/products/electronics?code={functionKey}"; request = new HttpRequestMessage(HttpMethod.Get, uri); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain")); response = await this._fixture.HttpClient.SendAsync(request); Assert.Equal(HttpStatusCode.OK, response.StatusCode); json = await response.Content.ReadAsStringAsync(); JArray products = JArray.Parse(json); Assert.Equal(2, products.Count); // test a constraint violation (invalid id) uri = $"api/node/products/electronics/notaguid?code={functionKey}"; request = new HttpRequestMessage(HttpMethod.Get, uri); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain")); response = await this._fixture.HttpClient.SendAsync(request); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); // test a constraint violation (invalid category) uri = $"api/node/products/999/{id}?code={functionKey}"; request = new HttpRequestMessage(HttpMethod.Get, uri); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain")); response = await this._fixture.HttpClient.SendAsync(request); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); // verify route parameters were part of binding data var logs = await TestHelpers.GetFunctionLogsAsync("HttpTrigger-CustomRoute-Get"); var log = logs.Single(p => p.Contains($"category: electronics id: {id}")); Assert.NotNull(log); }
public async Task HttpTrigger_CSharp_CustomRoute_ReturnsExpectedResponse() { TestHelpers.ClearFunctionLogs("HttpTrigger-CSharp-CustomRoute"); string functionKey = "68qkqlughacc6f9n6t4ubk0jq7r5er7pta13yh20"; string uri = $"api/csharp/products/electronics/123?code={functionKey}"; HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri); HttpResponseMessage response = await this._fixture.HttpClient.SendAsync(request); Assert.Equal(HttpStatusCode.OK, response.StatusCode); string json = await response.Content.ReadAsStringAsync(); var product = JObject.Parse(json); Assert.Equal("electronics", (string)product["Category"]); Assert.Equal(123, (int?)product["Id"]); // now try again without specifying optional id parameter uri = $"api/csharp/products/electronics?code={functionKey}"; request = new HttpRequestMessage(HttpMethod.Get, uri); response = await this._fixture.HttpClient.SendAsync(request); Assert.Equal(HttpStatusCode.OK, response.StatusCode); json = await response.Content.ReadAsStringAsync(); product = JObject.Parse(json); Assert.Equal("electronics", (string)product["Category"]); Assert.Null((int?)product["Id"]); // test a constraint violation (invalid id) uri = $"api/csharp/products/electronics/1x3?code={functionKey}"; request = new HttpRequestMessage(HttpMethod.Get, uri); response = await this._fixture.HttpClient.SendAsync(request); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); // test a constraint violation (invalid category) uri = $"api/csharp/products/999/123?code={functionKey}"; request = new HttpRequestMessage(HttpMethod.Get, uri); response = await this._fixture.HttpClient.SendAsync(request); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); // verify route parameters were part of binding data var logs = await TestHelpers.GetFunctionLogsAsync("HttpTrigger-CSharp-CustomRoute"); Assert.True(logs.Any(p => p.Contains("Parameters: category=electronics id=123"))); Assert.True(logs.Any(p => p.Contains("ProductInfo: Category=electronics Id=123"))); }
public async Task SingleNamedExport() { TestHelpers.ClearFunctionLogs("SingleNamedExport"); Dictionary <string, object> arguments = new Dictionary <string, object> { { "input", string.Empty } }; await Fixture.Host.CallAsync("SingleNamedExport", arguments); var logs = await TestHelpers.GetFunctionLogsAsync("SingleNamedExport"); Assert.Contains(logs, log => log.Contains("Exports: IsObject=true, Count=1")); }
public async Task BlobTriggerToBlobTest() { TestHelpers.ClearFunctionLogs("BlobTriggerToBlob"); // write a binary blob string name = Guid.NewGuid().ToString(); CloudBlockBlob inputBlob = Fixture.TestInputContainer.GetBlockBlobReference(name); inputBlob.Metadata.Add("TestMetadataKey", "TestMetadataValue"); byte[] inputBytes = new byte[] { 1, 2, 3, 4, 5 }; using (var stream = inputBlob.OpenWrite()) { stream.Write(inputBytes, 0, inputBytes.Length); } var resultBlob = Fixture.TestOutputContainer.GetBlockBlobReference(name); await TestHelpers.WaitForBlobAsync(resultBlob); byte[] resultBytes; using (var resultStream = resultBlob.OpenRead()) using (var ms = new MemoryStream()) { resultStream.CopyTo(ms); resultBytes = ms.ToArray(); } JObject testResult = await GetFunctionTestResult("BlobTriggerToBlob"); Assert.Equal(inputBytes, resultBytes); Assert.True((bool)testResult["isBuffer"]); Assert.Equal(5, (int)testResult["length"]); var blobMetadata = (JObject)testResult["blobMetadata"]; Assert.Equal($"test-input-node/{name}", (string)blobMetadata["path"]); var metadata = (JObject)blobMetadata["metadata"]; Assert.Equal("TestMetadataValue", (string)metadata["testMetadataKey"]); var properties = (JObject)blobMetadata["properties"]; Assert.Equal("application/octet-stream", (string)properties["contentType"]); Assert.Equal("BlockBlob", (string)properties["blobType"]); Assert.Equal(5, properties["length"]); string invocationId = (string)testResult["invocationId"]; Guid.Parse(invocationId); }
public async Task MultipleExports() { TestHelpers.ClearFunctionLogs("MultipleExports"); Dictionary <string, object> arguments = new Dictionary <string, object> { { "input", string.Empty } }; await Fixture.Host.CallAsync("MultipleExports", arguments); var logs = await TestHelpers.GetFunctionLogsAsync("MultipleExports"); Assert.Equal(3, logs.Count); Assert.True(logs[1].Contains("Exports: IsObject=true, Count=4")); }
public async Task EventHubTrigger() { TestHelpers.ClearFunctionLogs("EventHubTrigger"); // write 3 events List <EventData> events = new List <EventData>(); string[] ids = new string[3]; for (int i = 0; i < 3; i++) { ids[i] = Guid.NewGuid().ToString(); JObject jo = new JObject { { "value", ids[i] } }; events.Add(new EventData(Encoding.UTF8.GetBytes(jo.ToString(Formatting.None)))); } string connectionString = Environment.GetEnvironmentVariable("AzureWebJobsEventHubSender"); ServiceBusConnectionStringBuilder builder = new ServiceBusConnectionStringBuilder(connectionString); EventHubClient eventHubClient; if (!string.IsNullOrWhiteSpace(builder.EntityPath)) { eventHubClient = EventHubClient.CreateFromConnectionString(connectionString); } else { string eventHubPath = _settingsManager.GetSetting("AzureWebJobsEventHubPath"); eventHubClient = EventHubClient.CreateFromConnectionString(connectionString, eventHubPath); } await eventHubClient.SendBatchAsync(events); string logs = null; await TestHelpers.Await(() => { // wait for all 3 of the unique IDs send // above have been processed logs = string.Join("\r\n", TestHelpers.GetFunctionLogsAsync("EventHubTrigger", throwOnNoLogs: false).Result); return(ids.All(p => logs.Contains(p))); }); Assert.True(logs.Contains("IsArray true")); }
public async Task QueueTriggerByteArray() { TestHelpers.ClearFunctionLogs("QueueTriggerByteArray"); // write a binary queue message byte[] inputBytes = new byte[] { 1, 2, 3 }; CloudQueueMessage message = new CloudQueueMessage(inputBytes); var queue = Fixture.QueueClient.GetQueueReference("test-input-byte"); queue.CreateIfNotExists(); queue.Clear(); queue.AddMessage(message); JObject testResult = await GetFunctionTestResult("QueueTriggerByteArray"); Assert.True((bool)testResult["isBuffer"]); Assert.Equal(5, (int)testResult["length"]); }
protected EndToEndTestFixture(string rootPath, string testId) { _settingsManager = ScriptSettingsManager.Instance; FixtureId = testId; string connectionString = AmbientConnectionStringProvider.Instance.GetConnectionString(ConnectionStringNames.Storage); CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString); QueueClient = storageAccount.CreateCloudQueueClient(); BlobClient = storageAccount.CreateCloudBlobClient(); TableClient = storageAccount.CreateCloudTableClient(); CreateTestStorageEntities(); TraceWriter = new TestTraceWriter(TraceLevel.Verbose); ApiHubTestHelper.SetDefaultConnectionFactory(); ScriptHostConfiguration config = new ScriptHostConfiguration() { RootScriptPath = rootPath, TraceWriter = TraceWriter, FileLoggingMode = FileLoggingMode.Always }; RequestConfiguration = new HttpConfiguration(); RequestConfiguration.Formatters.Add(new PlaintextMediaTypeFormatter()); EventManager = new ScriptEventManager(); ScriptHostEnvironmentMock = new Mock <IScriptHostEnvironment>(); // Reset the timer logs first, since one of the tests will // be checking them TestHelpers.ClearFunctionLogs("TimerTrigger"); TestHelpers.ClearFunctionLogs("ListenerStartupException"); InitializeConfig(config); Func <string, FunctionDescriptor> funcLookup = (name) => this.Host.GetFunctionOrNull(name); var fastLogger = new FunctionInstanceLogger(funcLookup, new MetricsLogger()); config.HostConfig.AddService <IAsyncCollector <FunctionInstanceLogEntry> >(fastLogger); Host = ScriptHost.Create(ScriptHostEnvironmentMock.Object, EventManager, config, _settingsManager); Host.Start(); }
protected async Task TwilioReferenceInvokeSucceedsImpl(bool isDotNet) { if (isDotNet) { TestHelpers.ClearFunctionLogs("TwilioReference"); string testData = Guid.NewGuid().ToString(); string inputName = "input"; Dictionary <string, object> arguments = new Dictionary <string, object> { { inputName, testData } }; await Fixture.Host.CallAsync("TwilioReference", arguments); // make sure the input string made it all the way through var logs = await TestHelpers.GetFunctionLogsAsync("TwilioReference"); Assert.True(logs.Any(p => p.Contains(testData))); } }
public async Task HttpTriggerWithError_Get() { string functionName = "HttpTrigger-WithError"; TestHelpers.ClearFunctionLogs(functionName); HttpRequestMessage request = new HttpRequestMessage { RequestUri = new Uri( "http://localhost/api/httptrigger-witherror?code=1388a6b0d05eca2237f10e4a4641260b0a08f3a5&name=testuser"), Method = HttpMethod.Get }; request.SetConfiguration(new HttpConfiguration()); Dictionary <string, object> arguments = new Dictionary <string, object> { { "req", request } }; string innerException = "PowerShell script error"; string errorRecordMessage = "Test Error in Get-DateToday"; Exception ex = await Assert.ThrowsAsync <FunctionInvocationException>(async() => await Fixture.Host.CallAsync(functionName, arguments)); var runtimeException = (RuntimeException)ex.InnerException; Assert.Equal(innerException, runtimeException.Message); Assert.Equal(errorRecordMessage, runtimeException.InnerException.Message); var logs = await TestHelpers.GetFunctionLogsAsync(functionName); Assert.True(logs.Any(p => p.Contains("Function started"))); // verify an error was written Assert.True(logs.Any(p => p.Contains(errorRecordMessage))); // verify the function completed successfully Assert.True(logs.Any(p => p.Contains("Function completed (Failure"))); }
public async Task QueueTriggerPython_Succeeds() { TestHelpers.ClearFunctionLogs("QueueTrigger-Python"); // write the input message CloudQueue inputQueue = _fixture.QueueClient.GetQueueReference("samples-python"); inputQueue.CreateIfNotExists(); string id = Guid.NewGuid().ToString(); JObject jsonObject = new JObject { { "id", id } }; var message = new CloudQueueMessage(jsonObject.ToString(Formatting.None)); await inputQueue.AddMessageAsync(message); // wait for function to execute and produce its result blob CloudBlobContainer outputContainer = _fixture.BlobClient.GetContainerReference("samples-output"); CloudBlockBlob outputBlob = outputContainer.GetBlockBlobReference(id); string result = await TestHelpers.WaitForBlobAndGetStringAsync(outputBlob); jsonObject = JObject.Parse(result); Assert.Equal(id, (string)jsonObject["id"]); // verify the function output var logs = await TestHelpers.GetFunctionLogsAsync("QueueTrigger-Python"); // strip off the timestamps from the beginning of each line logs = logs.Select(l => l.Split(new[] { ' ' }, 2)[1]).ToList(); int idx = logs.IndexOf("Read 5 Table entities"); for (int i = idx + 1; i < 5; i++) { string json = logs[i]; JObject entity = JObject.Parse(json); Assert.Equal("samples-python", entity["PartitionKey"]); Assert.Equal(0, (int)entity["Status"]); } }
protected async Task TableInputTest() { TestHelpers.ClearFunctionLogs("TableIn"); var args = new Dictionary <string, object>() { { "input", "{ \"Region\": \"West\" }" } }; await Fixture.Host.CallAsync("TableIn", args); var logs = await TestHelpers.GetFunctionLogsAsync("TableIn"); string result = logs.Where(p => p.Contains("Result:")).Single(); result = result.Substring(result.IndexOf('{')); // verify singleton binding JObject resultObject = JObject.Parse(result); JObject single = (JObject)resultObject["single"]; Assert.Equal("AAA", (string)single["PartitionKey"]); Assert.Equal("001", (string)single["RowKey"]); // verify partition binding JArray partition = (JArray)resultObject["partition"]; Assert.Equal(3, partition.Count); foreach (var entity in partition) { Assert.Equal("BBB", (string)entity["PartitionKey"]); } // verify query binding JArray query = (JArray)resultObject["query"]; Assert.Equal(2, query.Count); Assert.Equal("003", (string)query[0]["RowKey"]); Assert.Equal("004", (string)query[1]["RowKey"]); }