From 3aec7d95edf0b9c8e933f3ee02e4ccdb26813947 Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Thu, 16 Feb 2023 13:34:22 -0800 Subject: [PATCH 1/5] Add more blob e2e binding tests --- .../E2EApp/Blob/BlobInputBindingFunctions.cs | 122 +++++++++++ .../E2EApps/E2EApp/Blob/BlobTestFunctions.cs | 57 ------ .../Blob/BlobTriggerBindingFunctions.cs | 94 +++++++++ test/E2ETests/E2EApps/E2EApp/Blob/Book.cs | 11 + test/E2ETests/E2ETests/Constants.cs | 18 +- .../{ => Cosmos}/CosmosDBEndToEndTests.cs | 4 +- .../E2ETests/Storage/BlobEndToEndTests.cs | 192 ++++++++++++++++++ .../QueueEndToEndTests.cs} | 73 +------ 8 files changed, 441 insertions(+), 130 deletions(-) create mode 100644 test/E2ETests/E2EApps/E2EApp/Blob/BlobInputBindingFunctions.cs delete mode 100644 test/E2ETests/E2EApps/E2EApp/Blob/BlobTestFunctions.cs create mode 100644 test/E2ETests/E2EApps/E2EApp/Blob/BlobTriggerBindingFunctions.cs create mode 100644 test/E2ETests/E2EApps/E2EApp/Blob/Book.cs rename test/E2ETests/E2ETests/{ => Cosmos}/CosmosDBEndToEndTests.cs (93%) create mode 100644 test/E2ETests/E2ETests/Storage/BlobEndToEndTests.cs rename test/E2ETests/E2ETests/{StorageEndToEndTests.cs => Storage/QueueEndToEndTests.cs} (76%) diff --git a/test/E2ETests/E2EApps/E2EApp/Blob/BlobInputBindingFunctions.cs b/test/E2ETests/E2EApps/E2EApp/Blob/BlobInputBindingFunctions.cs new file mode 100644 index 000000000..6490cfcb1 --- /dev/null +++ b/test/E2ETests/E2EApps/E2EApp/Blob/BlobInputBindingFunctions.cs @@ -0,0 +1,122 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Text; +using System.Threading.Tasks; +using Azure.Storage.Blobs; +using Microsoft.Azure.Functions.Worker.Http; +using Microsoft.Extensions.Logging; + +namespace Microsoft.Azure.Functions.Worker.E2EApp.Blob +{ + public class BlobInputBindingFunctions + { + private readonly ILogger _logger; + + public BlobInputBindingFunctions(ILogger logger) + { + _logger = logger; + } + + [Function(nameof(BlobInputClientTest))] + public async Task BlobInputClientTest( + [HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req, + [BlobInput("test-input-dotnet-isolated/testFile")] BlobClient client) + { + var response = req.CreateResponse(HttpStatusCode.OK); + var downloadResult = await client.DownloadContentAsync(); + await response.Body.WriteAsync(downloadResult.Value.Content); + return response; + } + + [Function(nameof(BlobInputStreamTest))] + public async Task BlobInputStreamTest( + [HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req, + [BlobInput("test-input-dotnet-isolated/testFile")] Stream stream) + { + var response = req.CreateResponse(HttpStatusCode.OK); + using var blobStreamReader = new StreamReader(stream); + await response.WriteStringAsync(blobStreamReader.ReadToEnd()); + return response; + } + + [Function(nameof(BlobInputByteTest))] + public async Task BlobInputByteTest( + [HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req, + [BlobInput("test-input-dotnet-isolated/testFile")] Byte[] data) + { + var response = req.CreateResponse(HttpStatusCode.OK); + await response.WriteStringAsync(Encoding.Default.GetString(data)); + return response; + } + + [Function(nameof(BlobInputStringTest))] + public async Task BlobInputStringTest( + [HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req, + [BlobInput("test-input-dotnet-isolated/testFile")] string data) + { + var response = req.CreateResponse(HttpStatusCode.OK); + await response.WriteStringAsync(data); + return response; + } + + [Function(nameof(BlobInputPocoTest))] + public async Task BlobInputPocoTest( + [HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req, + [BlobInput("test-input-dotnet-isolated/testFile")] Book data) + { + var response = req.CreateResponse(HttpStatusCode.OK); + await response.WriteStringAsync(data.Name); + return response; + } + + [Function(nameof(BlobInputCollectionTest))] + public async Task BlobInputCollectionTest( + [HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req, + [BlobInput("test-input-dotnet-isolated", IsBatched = true)] IEnumerable blobs) + { + List blobList = new(); + + foreach (BlobClient blob in blobs) + { + _logger.LogInformation("Blob name: {blobName}, Container name: {containerName}", blob.Name, blob.BlobContainerName); + blobList.Add(blob.Name); + } + + var response = req.CreateResponse(HttpStatusCode.OK); + await response.WriteStringAsync(blobList.ToString()); + return response; + } + + [Function(nameof(BlobInputStringArrayTest))] + public async Task BlobInputStringArrayTest( + [HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req, + [BlobInput("test-input-dotnet-isolated", IsBatched = true)] string[] blobContent) + { + var response = req.CreateResponse(HttpStatusCode.OK); + await response.WriteStringAsync(blobContent.ToString()); + return response; + } + + [Function(nameof(BlobInputPocoArrayTest))] + public async Task BlobInputPocoArrayTest( + [HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req, + [BlobInput("test-input-dotnet-isolated", IsBatched = true)] Book[] books) + { + List bookNames = new(); + + foreach (var item in books) + { + bookNames.Add(item.Name); + } + + var response = req.CreateResponse(HttpStatusCode.OK); + await response.WriteStringAsync(bookNames.ToString()); + return response; + } + } +} \ No newline at end of file diff --git a/test/E2ETests/E2EApps/E2EApp/Blob/BlobTestFunctions.cs b/test/E2ETests/E2EApps/E2EApp/Blob/BlobTestFunctions.cs deleted file mode 100644 index b375e044a..000000000 --- a/test/E2ETests/E2EApps/E2EApp/Blob/BlobTestFunctions.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. - -using System.Text.Json.Serialization; -using Microsoft.Azure.Functions.Worker; -using Microsoft.Extensions.Logging; - -namespace Microsoft.Azure.Functions.Worker.E2EApp.Blob -{ - public class BlobTestFunctions - { - private readonly ILogger _logger; - - public BlobTestFunctions(ILogger logger) - { - _logger = logger; - } - - [Function(nameof(BlobTriggerToBlobTest))] - [BlobOutput("test-output-dotnet-isolated/{name}")] - public byte[] BlobTriggerToBlobTest( - [BlobTrigger("test-triggerinput-dotnet-isolated/{name}")] byte[] triggerBlob, string name, - [BlobInput("test-input-dotnet-isolated/{name}")] byte[] inputBlob, - FunctionContext context) - { - _logger.LogInformation("Trigger:\n Name: " + name + "\n Size: " + triggerBlob.Length + " Bytes"); - _logger.LogInformation("Input:\n Name: " + name + "\n Size: " + inputBlob.Length + " Bytes"); - return inputBlob; - } - - [Function(nameof(BlobTriggerPocoTest))] - [BlobOutput("test-outputpoco-dotnet-isolated/{name}")] - public TestBlobData BlobTriggerPocoTest( - [BlobTrigger("test-triggerinputpoco-dotnet-isolated/{name}")] TestBlobData triggerBlob, string name, - FunctionContext context) - { - _logger.LogInformation(".NET Blob trigger function processed a blob.\n Name: " + name + "\n Content: " + triggerBlob.BlobText); - return triggerBlob; - } - - [Function(nameof(BlobTriggerStringTest))] - [BlobOutput("test-outputstring-dotnet-isolated/{name}")] - public string BlobTriggerStringTest( - [BlobTrigger("test-triggerinputstring-dotnet-isolated/{name}")] string triggerBlobText, string name, - FunctionContext context) - { - _logger.LogInformation(".NET Blob trigger function processed a blob.\n Name: " + name + "\n Content: " + triggerBlobText); - return triggerBlobText; - } - - public class TestBlobData - { - [JsonPropertyName("text")] - public string BlobText { get; set; } - } - } -} diff --git a/test/E2ETests/E2EApps/E2EApp/Blob/BlobTriggerBindingFunctions.cs b/test/E2ETests/E2EApps/E2EApp/Blob/BlobTriggerBindingFunctions.cs new file mode 100644 index 000000000..4783a3f6c --- /dev/null +++ b/test/E2ETests/E2EApps/E2EApp/Blob/BlobTriggerBindingFunctions.cs @@ -0,0 +1,94 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +using System.IO; +using System.Text.Json.Serialization; +using System.Threading.Tasks; +using Azure.Storage.Blobs; +using Microsoft.Extensions.Logging; + +namespace Microsoft.Azure.Functions.Worker.E2EApp.Blob +{ + public class BlobTriggerBindingFunctions + { + private readonly ILogger _logger; + + public BlobTriggerBindingFunctions(ILogger logger) + { + _logger = logger; + } + + [Function(nameof(BlobTriggerToBlobTest))] + [BlobOutput("test-output-dotnet-isolated/{name}")] + public byte[] BlobTriggerToBlobTest( + [BlobTrigger("test-trigger-dotnet-isolated/{name}")] byte[] triggerBlob, string name, + [BlobInput("test-input-dotnet-isolated/{name}")] byte[] inputBlob, + FunctionContext context) + { + _logger.LogInformation("Trigger:\n Name: " + name + "\n Size: " + triggerBlob.Length + " Bytes"); + _logger.LogInformation("Input:\n Name: " + name + "\n Size: " + inputBlob.Length + " Bytes"); + return inputBlob; + } + + [Function(nameof(BlobTriggerPocoTest))] + [BlobOutput("test-output-poco-dotnet-isolated/{name}")] + public TestBlobData BlobTriggerPocoTest( + [BlobTrigger("test-trigger-poco-dotnet-isolated/{name}")] TestBlobData triggerBlob, string name, + FunctionContext context) + { + _logger.LogInformation(".NET Blob trigger function processed a blob.\n Name: " + name + "\n Content: " + triggerBlob.BlobText); + return triggerBlob; + } + + [Function(nameof(BlobTriggerStringTest))] + [BlobOutput("test-output-string-dotnet-isolated/{name}")] + public string BlobTriggerStringTest( + [BlobTrigger("test-trigger-string-dotnet-isolated/{name}")] string triggerBlobText, string name, + FunctionContext context) + { + _logger.LogInformation(".NET Blob trigger function processed a blob.\n Name: " + name + "\n Content: " + triggerBlobText); + return triggerBlobText; + } + + [Function(nameof(BlobTriggerStreamTest))] + [BlobOutput("test-output-stream-dotnet-isolated/{name}")] + public async Task BlobTriggerStreamTest( + [BlobTrigger("test-trigger-stream-dotnet-isolated/{name}")] Stream stream, string name) + { + using var blobStreamReader = new StreamReader(stream); + var content = await blobStreamReader.ReadToEndAsync(); + _logger.LogInformation(".NET Blob trigger function processed a blob.\n Name: " + name + "\n Content: " + content); + return stream; + + } + + [Function(nameof(BlobTriggerBlobClientTest))] + [BlobOutput("test-output-blobclient-dotnet-isolated/{name}")] + public async Task BlobTriggerBlobClientTest( + [BlobTrigger("test-trigger-blobclient-dotnet-isolated/{name}")] BlobClient client, string name) + { + var downloadResult = await client.DownloadContentAsync(); + var content = downloadResult.Value.Content.ToString(); + _logger.LogInformation(".NET Blob trigger function processed a blob.\n Name: " + name + "\n Content: " + content); + return content; + } + + [Function(nameof(BlobTriggerBlobContainerClientTest))] + [BlobOutput("test-output-containerclient-dotnet-isolated/{name}")] + public async Task BlobTriggerBlobContainerClientTest( + [BlobTrigger("test-trigger-containerclient-dotnet-isolated/{name}")] BlobContainerClient client, string name) + { + var blobClient = client.GetBlobClient(name); + var downloadResult = await blobClient.DownloadContentAsync(); + var content = downloadResult.Value.Content.ToString(); + _logger.LogInformation(".NET Blob trigger function processed a blob.\n Name: " + name + "\n Content: " + content); + return content; + } + + public class TestBlobData + { + [JsonPropertyName("text")] + public string BlobText { get; set; } + } + } +} diff --git a/test/E2ETests/E2EApps/E2EApp/Blob/Book.cs b/test/E2ETests/E2EApps/E2EApp/Blob/Book.cs new file mode 100644 index 000000000..2cea88356 --- /dev/null +++ b/test/E2ETests/E2EApps/E2EApp/Blob/Book.cs @@ -0,0 +1,11 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +namespace Microsoft.Azure.Functions.Worker.E2EApp.Blob +{ + public class Book + { + public string Id { get; set; } + public string Name { get; set; } + } +} \ No newline at end of file diff --git a/test/E2ETests/E2ETests/Constants.cs b/test/E2ETests/E2ETests/Constants.cs index 70256b28a..f9cd316f0 100644 --- a/test/E2ETests/E2ETests/Constants.cs +++ b/test/E2ETests/E2ETests/Constants.cs @@ -34,15 +34,19 @@ public static class Queue //Blob tests public static class Blob { - public const string TriggerInputBindingContainer = "test-triggerinput-dotnet-isolated"; + public const string TriggerInputBindingContainer = "test-trigger-dotnet-isolated"; public const string InputBindingContainer = "test-input-dotnet-isolated"; public const string OutputBindingContainer = "test-output-dotnet-isolated"; - - public const string TriggerPocoContainer = "test-triggerinputpoco-dotnet-isolated"; - public const string OutputPocoContainer = "test-outputpoco-dotnet-isolated"; - - public const string TriggerStringContainer = "test-triggerinputstring-dotnet-isolated"; - public const string OutputStringContainer = "test-outputstring-dotnet-isolated"; + public const string TriggerPocoContainer = "test-trigger-poco-dotnet-isolated"; + public const string OutputPocoContainer = "test-output-poco-dotnet-isolated"; + public const string TriggerStringContainer = "test-trigger-string-dotnet-isolated"; + public const string OutputStringContainer = "test-output-string-dotnet-isolated"; + public const string TriggerStreamContainer = "test-trigger-stream-dotnet-isolated"; + public const string OutputStreamContainer = "test-output-stream-dotnet-isolated"; + public const string TriggerBlobClientContainer = "test-trigger-blobclient-dotnet-isolated"; + public const string OutputBlobClientContainer = "test-output-blobclient-dotnet-isolated"; + public const string TriggerBlobContainerClientContainer = "test-trigger-containerclient-dotnet-isolated"; + public const string OutputBlobContainerClientContainer = "test-output-containerclient-dotnet-isolated"; } // CosmosDB tests diff --git a/test/E2ETests/E2ETests/CosmosDBEndToEndTests.cs b/test/E2ETests/E2ETests/Cosmos/CosmosDBEndToEndTests.cs similarity index 93% rename from test/E2ETests/E2ETests/CosmosDBEndToEndTests.cs rename to test/E2ETests/E2ETests/Cosmos/CosmosDBEndToEndTests.cs index e44d215eb..71fb75934 100644 --- a/test/E2ETests/E2ETests/CosmosDBEndToEndTests.cs +++ b/test/E2ETests/E2ETests/Cosmos/CosmosDBEndToEndTests.cs @@ -6,7 +6,7 @@ using Xunit; using Xunit.Abstractions; -namespace Microsoft.Azure.Functions.Tests.E2ETests +namespace Microsoft.Azure.Functions.Tests.E2ETests.Cosmos { [Collection(Constants.FunctionAppCollectionName)] public class CosmosDBEndToEndTests : IDisposable @@ -26,7 +26,7 @@ public async Task CosmosDBTriggerAndOutput_Succeeds() string expectedDocId = Guid.NewGuid().ToString(); try { - //Trigger + //Trigger await CosmosDBHelpers.CreateDocument(expectedDocId); //Read diff --git a/test/E2ETests/E2ETests/Storage/BlobEndToEndTests.cs b/test/E2ETests/E2ETests/Storage/BlobEndToEndTests.cs new file mode 100644 index 000000000..ae47d62a1 --- /dev/null +++ b/test/E2ETests/E2ETests/Storage/BlobEndToEndTests.cs @@ -0,0 +1,192 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +using System; +using System.Net; +using System.Net.Http; +using System.Text.Json; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Azure.Functions.Tests.E2ETests.Storage +{ + [Collection(Constants.FunctionAppCollectionName)] + public class BlobEndToEndTests + { + private FunctionAppFixture _fixture; + + public BlobEndToEndTests(FunctionAppFixture fixture) + { + _fixture = fixture; + } + + [Fact] + public async Task BlobTriggerToBlob_Succeeds() + { + string fileName = Guid.NewGuid().ToString(); + + //Cleanup + await StorageHelpers.ClearBlobContainers(); + + //Setup + await StorageHelpers.UploadFileToContainer(Constants.Blob.InputBindingContainer, fileName); + + //Trigger + await StorageHelpers.UploadFileToContainer(Constants.Blob.TriggerInputBindingContainer, fileName); + + //Verify + string result = await StorageHelpers.DownloadFileFromContainer(Constants.Blob.OutputBindingContainer, fileName); + + Assert.Equal("Hello World", result); + } + + [Theory] + [InlineData(Constants.Blob.TriggerBlobContainerClientContainer, Constants.Blob.OutputBlobContainerClientContainer)] + [InlineData(Constants.Blob.TriggerBlobContainerClientContainer, Constants.Blob.OutputBlobContainerClientContainer)] + [InlineData(Constants.Blob.TriggerBlobClientContainer, Constants.Blob.OutputBlobClientContainer)] + [InlineData(Constants.Blob.TriggerStreamContainer, Constants.Blob.OutputStreamContainer)] + [InlineData(Constants.Blob.TriggerStringContainer, Constants.Blob.OutputStringContainer)] + [InlineData(Constants.Blob.TriggerPocoContainer, Constants.Blob.OutputPocoContainer)] + [InlineData()] + public async Task BlobTrigger_Succeeds(string triggerContainer, string outputContainer) + { + string fileName = Guid.NewGuid().ToString(); + + //Cleanup + await StorageHelpers.ClearBlobContainers(); + + //Trigger + await StorageHelpers.UploadFileToContainer(triggerContainer, fileName); + + //Verify + string result = await StorageHelpers.DownloadFileFromContainer(outputContainer, fileName); + + Assert.Equal("Hello World", result); + } + + [Theory] + [InlineData("BlobInputClientTest")] + [InlineData("BlobInputStreamTest")] + [InlineData("BlobInputByteTest")] + [InlineData("BlobInputStringTest")] + [InlineData("BlobInputBookArrayTest")] + [InlineData("BlobInputCollectionTest")] + [InlineData("BlobInputStringArrayTest")] + public async Task BlobInput_Succeeds(string functionName) + { + string fileName = "testFile"; + string expectedMessage = "Hello World"; + HttpStatusCode expectedStatusCode = HttpStatusCode.OK; + + //Cleanup + await StorageHelpers.ClearBlobContainers(); + + //Setup + await StorageHelpers.UploadFileToContainer(Constants.Blob.InputBindingContainer, fileName, expectedMessage); + + //Trigger + HttpResponseMessage response = await HttpHelpers.InvokeHttpTrigger(functionName); + string actualMessage = await response.Content.ReadAsStringAsync(); + + //Verify + Assert.Equal(expectedStatusCode, response.StatusCode); + Assert.Contains(expectedMessage, actualMessage); + } + + [Fact] + public async Task BlobInput_Poco_Succeeds() + { + string fileContent = $@"{{ ""id"": ""1"", ""name"": ""To Kill a Mockingbird""}}"; + string expectedMessage = "To Kill a Mockingbird"; + HttpStatusCode expectedStatusCode = HttpStatusCode.OK; + + //Cleanup + await StorageHelpers.ClearBlobContainers(); + + //Setup + await StorageHelpers.UploadFileToContainer(Constants.Blob.InputBindingContainer, "testFile", fileContent); + + //Trigger + HttpResponseMessage response = await HttpHelpers.InvokeHttpTrigger("BlobInputPocoTest"); + string actualMessage = await response.Content.ReadAsStringAsync(); + + //Verify + Assert.Equal(expectedStatusCode, response.StatusCode); + Assert.Contains(expectedMessage, actualMessage); + } + + [Fact] + public async Task BlobInput_BlobClientCollection_Succeeds() + { + string expectedMessage = "testFile1, testFile2, testFile3"; + HttpStatusCode expectedStatusCode = HttpStatusCode.OK; + + //Cleanup + await StorageHelpers.ClearBlobContainers(); + + //Setup + await StorageHelpers.UploadFileToContainer(Constants.Blob.InputBindingContainer, "testFile1"); + await StorageHelpers.UploadFileToContainer(Constants.Blob.InputBindingContainer, "testFile2"); + await StorageHelpers.UploadFileToContainer(Constants.Blob.InputBindingContainer, "testFile3"); + + //Trigger + HttpResponseMessage response = await HttpHelpers.InvokeHttpTrigger("BlobInputCollectionTest"); + string actualMessage = await response.Content.ReadAsStringAsync(); + + //Verify + Assert.Equal(expectedStatusCode, response.StatusCode); + Assert.Contains(expectedMessage, actualMessage); + } + + [Fact] + public async Task BlobInput_StringCollection_Succeeds() + { + string expectedMessage = "ABC, DEF, GHI"; + HttpStatusCode expectedStatusCode = HttpStatusCode.OK; + + //Cleanup + await StorageHelpers.ClearBlobContainers(); + + //Setup + await StorageHelpers.UploadFileToContainer(Constants.Blob.InputBindingContainer, "testFile1", "ABC"); + await StorageHelpers.UploadFileToContainer(Constants.Blob.InputBindingContainer, "testFile2", "DEF"); + await StorageHelpers.UploadFileToContainer(Constants.Blob.InputBindingContainer, "testFile3", "GHI"); + + //Trigger + HttpResponseMessage response = await HttpHelpers.InvokeHttpTrigger("BlobInputCollectionTest"); + string actualMessage = await response.Content.ReadAsStringAsync(); + + //Verify + Assert.Equal(expectedStatusCode, response.StatusCode); + Assert.Contains(expectedMessage, actualMessage); + } + + [Fact] + public async Task BlobInput_PocoCollection_Succeeds() + { + string book1 = $@"{{ ""id"": ""1"", ""name"": ""To Kill a Mockingbird""}}"; + string book2 = $@"{{ ""id"": ""2"", ""name"": ""Of Mice and Men""}}"; + string book3 = $@"{{ ""id"": ""3"", ""name"": ""The Wind in the Willows""}}"; + + string expectedMessage = "To Kill a Mockingbird, Of Mice and Men, The Wind in the Willows"; + HttpStatusCode expectedStatusCode = HttpStatusCode.OK; + + + //Cleanup + await StorageHelpers.ClearBlobContainers(); + + //Setup + await StorageHelpers.UploadFileToContainer(Constants.Blob.InputBindingContainer, "book1", book1); + await StorageHelpers.UploadFileToContainer(Constants.Blob.InputBindingContainer, "book2", book2); + await StorageHelpers.UploadFileToContainer(Constants.Blob.InputBindingContainer, "book3", book3); + + //Trigger + HttpResponseMessage response = await HttpHelpers.InvokeHttpTrigger("BlobInputPocoArrayTest"); + string actualMessage = await response.Content.ReadAsStringAsync(); + + //Verify + Assert.Equal(expectedStatusCode, response.StatusCode); + Assert.Contains(expectedMessage, actualMessage); + } + } +} diff --git a/test/E2ETests/E2ETests/StorageEndToEndTests.cs b/test/E2ETests/E2ETests/Storage/QueueEndToEndTests.cs similarity index 76% rename from test/E2ETests/E2ETests/StorageEndToEndTests.cs rename to test/E2ETests/E2ETests/Storage/QueueEndToEndTests.cs index 8271aad32..ed81d8cfa 100644 --- a/test/E2ETests/E2ETests/StorageEndToEndTests.cs +++ b/test/E2ETests/E2ETests/Storage/QueueEndToEndTests.cs @@ -9,14 +9,14 @@ using System.Threading.Tasks; using Xunit; -namespace Microsoft.Azure.Functions.Tests.E2ETests +namespace Microsoft.Azure.Functions.Tests.E2ETests.Storage { [Collection(Constants.FunctionAppCollectionName)] - public class StorageEndToEndTests + public class QueueEndToEndTests { private FunctionAppFixture _fixture; - public StorageEndToEndTests(FunctionAppFixture fixture) + public QueueEndToEndTests(FunctionAppFixture fixture) { _fixture = fixture; } @@ -29,7 +29,7 @@ public async Task QueueTriggerAndOutput_Succeeds() await StorageHelpers.ClearQueue(Constants.Queue.OutputBindingName); await StorageHelpers.ClearQueue(Constants.Queue.InputBindingName); - //Set up and trigger + //Set up and trigger await StorageHelpers.CreateQueue(Constants.Queue.OutputBindingName); await StorageHelpers.InsertIntoQueue(Constants.Queue.InputBindingName, expectedQueueMessage); @@ -46,7 +46,7 @@ public async Task QueueTriggerAndArrayOutput_Succeeds() await StorageHelpers.ClearQueue(Constants.Queue.InputArrayBindingName); await StorageHelpers.ClearQueue(Constants.Queue.OutputArrayBindingName); - //Set up and trigger + //Set up and trigger await StorageHelpers.CreateQueue(Constants.Queue.OutputArrayBindingName); await StorageHelpers.InsertIntoQueue(Constants.Queue.InputArrayBindingName, expectedQueueMessage); @@ -72,7 +72,7 @@ public async Task QueueTriggerAndListOutput_Succeeds() await StorageHelpers.ClearQueue(Constants.Queue.InputListBindingName); await StorageHelpers.ClearQueue(Constants.Queue.OutputListBindingName); - //Set up and trigger + //Set up and trigger await StorageHelpers.CreateQueue(Constants.Queue.OutputListBindingName); await StorageHelpers.InsertIntoQueue(Constants.Queue.InputListBindingName, expectedQueueMessage); @@ -98,7 +98,7 @@ public async Task QueueTriggerAndBindingDataOutput_Succeeds() await StorageHelpers.ClearQueue(Constants.Queue.InputBindingDataName); await StorageHelpers.ClearQueue(Constants.Queue.OutputBindingDataName); - //Set up and trigger + //Set up and trigger await StorageHelpers.CreateQueue(Constants.Queue.OutputBindingDataName); await StorageHelpers.InsertIntoQueue(Constants.Queue.InputBindingDataName, expectedQueueMessage); @@ -122,7 +122,7 @@ public async Task QueueTrigger_BindToTriggerMetadata_Succeeds() await StorageHelpers.ClearQueue(Constants.Queue.OutputBindingNameMetadata); await StorageHelpers.ClearQueue(Constants.Queue.InputBindingNameMetadata); - //Set up and trigger + //Set up and trigger await StorageHelpers.CreateQueue(Constants.Queue.OutputBindingNameMetadata); string expectedQueueMessage = await StorageHelpers.InsertIntoQueue(Constants.Queue.InputBindingNameMetadata, inputQueueMessage); @@ -139,7 +139,7 @@ public async Task QueueTrigger_QueueOutput_Poco_Succeeds() await StorageHelpers.ClearQueue(Constants.Queue.OutputBindingNamePOCO); await StorageHelpers.ClearQueue(Constants.Queue.InputBindingNamePOCO); - //Set up and trigger + //Set up and trigger await StorageHelpers.CreateQueue(Constants.Queue.OutputBindingNamePOCO); string json = JsonSerializer.Serialize(new { id = expectedQueueMessage }); @@ -166,60 +166,5 @@ public async Task QueueOutput_PocoList_Succeeds() IEnumerable queueMessages = await StorageHelpers.ReadMessagesFromQueue(Constants.Queue.OutputBindingNamePOCO); Assert.True(queueMessages.All(msg => msg.Contains(expectedQueueMessage))); } - - [Fact] - public async Task BlobTriggerToBlob_Succeeds() - { - string fileName = Guid.NewGuid().ToString(); - - //cleanup - await StorageHelpers.ClearBlobContainers(); - - //Setup - await StorageHelpers.UploadFileToContainer(Constants.Blob.InputBindingContainer, fileName); - - //Trigger - await StorageHelpers.UploadFileToContainer(Constants.Blob.TriggerInputBindingContainer, fileName); - - //Verify - string result = await StorageHelpers.DownloadFileFromContainer(Constants.Blob.OutputBindingContainer, fileName); - - Assert.Equal("Hello World", result); - } - - [Fact] - public async Task BlobTriggerPoco_Succeeds() - { - string fileName = Guid.NewGuid().ToString(); - - //cleanup - await StorageHelpers.ClearBlobContainers(); - - //Trigger - var json = JsonSerializer.Serialize(new { text = "Hello World" }); - await StorageHelpers.UploadFileToContainer(Constants.Blob.TriggerPocoContainer, fileName, json); - - //Verify - string result = await StorageHelpers.DownloadFileFromContainer(Constants.Blob.OutputPocoContainer, fileName); - - Assert.Equal(json, result); - } - - [Fact] - public async Task BlobTriggerString_Succeeds() - { - string fileName = Guid.NewGuid().ToString(); - - //cleanup - await StorageHelpers.ClearBlobContainers(); - - //Trigger - await StorageHelpers.UploadFileToContainer(Constants.Blob.TriggerStringContainer, fileName); - - //Verify - string result = await StorageHelpers.DownloadFileFromContainer(Constants.Blob.OutputStringContainer, fileName); - - Assert.Equal("Hello World", result); - } } } From 799e0fefcf36017174df7f6acc08e9a586dfe3bc Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Thu, 16 Feb 2023 17:56:19 -0800 Subject: [PATCH 2/5] update tests --- .../E2EApp/Blob/BlobInputBindingFunctions.cs | 26 +++- .../Blob/BlobTriggerBindingFunctions.cs | 34 ++-- test/E2ETests/E2EApps/E2EApp/E2EApp.csproj | 4 +- .../E2ETests/Helpers/StorageHelpers.cs | 6 + .../E2ETests/Storage/BlobEndToEndTests.cs | 147 ++++++++++++++---- 5 files changed, 163 insertions(+), 54 deletions(-) diff --git a/test/E2ETests/E2EApps/E2EApp/Blob/BlobInputBindingFunctions.cs b/test/E2ETests/E2EApps/E2EApp/Blob/BlobInputBindingFunctions.cs index 6490cfcb1..4e6798c90 100644 --- a/test/E2ETests/E2EApps/E2EApp/Blob/BlobInputBindingFunctions.cs +++ b/test/E2ETests/E2EApps/E2EApp/Blob/BlobInputBindingFunctions.cs @@ -25,10 +25,22 @@ public BlobInputBindingFunctions(ILogger logger) [Function(nameof(BlobInputClientTest))] public async Task BlobInputClientTest( [HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req, - [BlobInput("test-input-dotnet-isolated/testFile")] BlobClient client) + [BlobInput("test-input-dotnet-isolated/testFile.txt")] BlobClient client) { - var response = req.CreateResponse(HttpStatusCode.OK); var downloadResult = await client.DownloadContentAsync(); + var response = req.CreateResponse(HttpStatusCode.OK); + await response.Body.WriteAsync(downloadResult.Value.Content); + return response; + } + + [Function(nameof(BlobInputContainerClientTest))] + public async Task BlobInputContainerClientTest( + [HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req, + [BlobInput("test-input-dotnet-isolated/testFile.txt")] BlobContainerClient client) + { + var blobClient = client.GetBlobClient("testFile.txt"); + var downloadResult = await blobClient.DownloadContentAsync(); + var response = req.CreateResponse(HttpStatusCode.OK); await response.Body.WriteAsync(downloadResult.Value.Content); return response; } @@ -36,10 +48,10 @@ public async Task BlobInputClientTest( [Function(nameof(BlobInputStreamTest))] public async Task BlobInputStreamTest( [HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req, - [BlobInput("test-input-dotnet-isolated/testFile")] Stream stream) + [BlobInput("test-input-dotnet-isolated/testFile.txt")] Stream stream) { - var response = req.CreateResponse(HttpStatusCode.OK); using var blobStreamReader = new StreamReader(stream); + var response = req.CreateResponse(HttpStatusCode.OK); await response.WriteStringAsync(blobStreamReader.ReadToEnd()); return response; } @@ -47,7 +59,7 @@ public async Task BlobInputStreamTest( [Function(nameof(BlobInputByteTest))] public async Task BlobInputByteTest( [HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req, - [BlobInput("test-input-dotnet-isolated/testFile")] Byte[] data) + [BlobInput("test-input-dotnet-isolated/testFile.txt")] Byte[] data) { var response = req.CreateResponse(HttpStatusCode.OK); await response.WriteStringAsync(Encoding.Default.GetString(data)); @@ -57,7 +69,7 @@ public async Task BlobInputByteTest( [Function(nameof(BlobInputStringTest))] public async Task BlobInputStringTest( [HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req, - [BlobInput("test-input-dotnet-isolated/testFile")] string data) + [BlobInput("test-input-dotnet-isolated/testFile.txt")] string data) { var response = req.CreateResponse(HttpStatusCode.OK); await response.WriteStringAsync(data); @@ -67,7 +79,7 @@ public async Task BlobInputStringTest( [Function(nameof(BlobInputPocoTest))] public async Task BlobInputPocoTest( [HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req, - [BlobInput("test-input-dotnet-isolated/testFile")] Book data) + [BlobInput("test-input-dotnet-isolated/testFile.txt")] Book data) { var response = req.CreateResponse(HttpStatusCode.OK); await response.WriteStringAsync(data.Name); diff --git a/test/E2ETests/E2EApps/E2EApp/Blob/BlobTriggerBindingFunctions.cs b/test/E2ETests/E2EApps/E2EApp/Blob/BlobTriggerBindingFunctions.cs index 4783a3f6c..ecce43f1a 100644 --- a/test/E2ETests/E2EApps/E2EApp/Blob/BlobTriggerBindingFunctions.cs +++ b/test/E2ETests/E2EApps/E2EApp/Blob/BlobTriggerBindingFunctions.cs @@ -51,38 +51,34 @@ public string BlobTriggerStringTest( } [Function(nameof(BlobTriggerStreamTest))] - [BlobOutput("test-output-stream-dotnet-isolated/{name}")] - public async Task BlobTriggerStreamTest( - [BlobTrigger("test-trigger-stream-dotnet-isolated/{name}")] Stream stream, string name) + public async Task BlobTriggerStreamTest( + [BlobTrigger("test-trigger-stream-dotnet-isolated/{name}")] Stream stream, string name, + FunctionContext context) { using var blobStreamReader = new StreamReader(stream); - var content = await blobStreamReader.ReadToEndAsync(); - _logger.LogInformation(".NET Blob trigger function processed a blob.\n Name: " + name + "\n Content: " + content); - return stream; - + string content = await blobStreamReader.ReadToEndAsync(); + _logger.LogInformation("StreamTriggerOutput: {c}", content); } [Function(nameof(BlobTriggerBlobClientTest))] - [BlobOutput("test-output-blobclient-dotnet-isolated/{name}")] - public async Task BlobTriggerBlobClientTest( - [BlobTrigger("test-trigger-blobclient-dotnet-isolated/{name}")] BlobClient client, string name) + public async Task BlobTriggerBlobClientTest( + [BlobTrigger("test-trigger-blobclient-dotnet-isolated/{name}")] BlobClient client, string name, + FunctionContext context) { var downloadResult = await client.DownloadContentAsync(); - var content = downloadResult.Value.Content.ToString(); - _logger.LogInformation(".NET Blob trigger function processed a blob.\n Name: " + name + "\n Content: " + content); - return content; + string content = downloadResult.Value.Content.ToString(); + _logger.LogInformation("BlobClientTriggerOutput: {c}", content); } [Function(nameof(BlobTriggerBlobContainerClientTest))] - [BlobOutput("test-output-containerclient-dotnet-isolated/{name}")] - public async Task BlobTriggerBlobContainerClientTest( - [BlobTrigger("test-trigger-containerclient-dotnet-isolated/{name}")] BlobContainerClient client, string name) + public async Task BlobTriggerBlobContainerClientTest( + [BlobTrigger("test-trigger-containerclient-dotnet-isolated/{name}")] BlobContainerClient client, string name, + FunctionContext context) { var blobClient = client.GetBlobClient(name); var downloadResult = await blobClient.DownloadContentAsync(); - var content = downloadResult.Value.Content.ToString(); - _logger.LogInformation(".NET Blob trigger function processed a blob.\n Name: " + name + "\n Content: " + content); - return content; + string content = downloadResult.Value.Content.ToString(); + _logger.LogInformation("BlobContainerTriggerOutput: {c}", content); } public class TestBlobData diff --git a/test/E2ETests/E2EApps/E2EApp/E2EApp.csproj b/test/E2ETests/E2EApps/E2EApp/E2EApp.csproj index f6fd3de04..2c799e2ef 100644 --- a/test/E2ETests/E2EApps/E2EApp/E2EApp.csproj +++ b/test/E2ETests/E2EApps/E2EApp/E2EApp.csproj @@ -42,8 +42,8 @@ - - + + diff --git a/test/E2ETests/E2ETests/Helpers/StorageHelpers.cs b/test/E2ETests/E2ETests/Helpers/StorageHelpers.cs index 191717b48..f710ebcd7 100644 --- a/test/E2ETests/E2ETests/Helpers/StorageHelpers.cs +++ b/test/E2ETests/E2ETests/Helpers/StorageHelpers.cs @@ -108,6 +108,12 @@ public async static Task ClearBlobContainers() await ClearBlobContainer(Constants.Blob.OutputPocoContainer); await ClearBlobContainer(Constants.Blob.TriggerStringContainer); await ClearBlobContainer(Constants.Blob.OutputStringContainer); + await ClearBlobContainer(Constants.Blob.TriggerStreamContainer); + await ClearBlobContainer(Constants.Blob.OutputStreamContainer); + await ClearBlobContainer(Constants.Blob.TriggerBlobClientContainer); + await ClearBlobContainer(Constants.Blob.OutputBlobClientContainer); + await ClearBlobContainer(Constants.Blob.TriggerBlobContainerClientContainer); + await ClearBlobContainer(Constants.Blob.OutputBlobContainerClientContainer); } public static Task UploadFileToContainer(string containerName, string fileName) diff --git a/test/E2ETests/E2ETests/Storage/BlobEndToEndTests.cs b/test/E2ETests/E2ETests/Storage/BlobEndToEndTests.cs index ae47d62a1..b4be10a78 100644 --- a/test/E2ETests/E2ETests/Storage/BlobEndToEndTests.cs +++ b/test/E2ETests/E2ETests/Storage/BlobEndToEndTests.cs @@ -2,6 +2,8 @@ // Licensed under the MIT License. See License.txt in the project root for license information. using System; +using System.Collections.Generic; +using System.Linq; using System.Net; using System.Net.Http; using System.Text.Json; @@ -40,55 +42,148 @@ public async Task BlobTriggerToBlob_Succeeds() Assert.Equal("Hello World", result); } - [Theory] - [InlineData(Constants.Blob.TriggerBlobContainerClientContainer, Constants.Blob.OutputBlobContainerClientContainer)] - [InlineData(Constants.Blob.TriggerBlobContainerClientContainer, Constants.Blob.OutputBlobContainerClientContainer)] - [InlineData(Constants.Blob.TriggerBlobClientContainer, Constants.Blob.OutputBlobClientContainer)] - [InlineData(Constants.Blob.TriggerStreamContainer, Constants.Blob.OutputStreamContainer)] - [InlineData(Constants.Blob.TriggerStringContainer, Constants.Blob.OutputStringContainer)] - [InlineData(Constants.Blob.TriggerPocoContainer, Constants.Blob.OutputPocoContainer)] - [InlineData()] - public async Task BlobTrigger_Succeeds(string triggerContainer, string outputContainer) + [Fact] + public async Task BlobTrigger_Poco_Succeeds() + { + string fileName = Guid.NewGuid().ToString(); + + //Cleanup + await StorageHelpers.ClearBlobContainers(); + + //Trigger + var json = JsonSerializer.Serialize(new { text = "Hello World" }); + await StorageHelpers.UploadFileToContainer(Constants.Blob.TriggerPocoContainer, fileName, json); + + //Verify + string result = await StorageHelpers.DownloadFileFromContainer(Constants.Blob.OutputPocoContainer, fileName); + + Assert.Equal(json, result); + } + + [Fact] + public async Task BlobTrigger_String_Succeeds() + { + string fileName = Guid.NewGuid().ToString(); + + //Cleanup + await StorageHelpers.ClearBlobContainers(); + + //Trigger + await StorageHelpers.UploadFileToContainer(Constants.Blob.TriggerStringContainer, fileName); + + //Verify + string result = await StorageHelpers.DownloadFileFromContainer(Constants.Blob.OutputStringContainer, fileName); + + Assert.Equal("Hello World", result); + } + + [Fact] + public async Task BlobTrigger_Stream_Succeeds() + { + string key = "StreamTriggerOutput: "; + string fileName = Guid.NewGuid().ToString(); + + IEnumerable logs = null; + await TestUtility.RetryAsync(() => + { + logs = _fixture.TestLogs.CoreToolsLogs.Where(p => p.Contains(key)); + // The "RunOnStartup" log should show, and then a true invocation. + return Task.FromResult(logs.Count() >= 2); + }); + + //Cleanup + await StorageHelpers.ClearBlobContainers(); + + //Trigger + await StorageHelpers.UploadFileToContainer(Constants.Blob.TriggerStreamContainer, fileName); + + //Verify + var lastLog = logs.Last(); + int subStringStart = lastLog.LastIndexOf(key) + key.Length; + var result = lastLog[subStringStart..]; + + Assert.Equal("Hello World", result); + } + + [Fact] + public async Task BlobTrigger_BlobClient_Succeeds() + { + string key = "BlobClientTriggerOutput: "; + string fileName = Guid.NewGuid().ToString(); + + IEnumerable logs = null; + await TestUtility.RetryAsync(() => + { + logs = _fixture.TestLogs.CoreToolsLogs.Where(p => p.Contains(key)); + // The "RunOnStartup" log should show, and then a true invocation. + return Task.FromResult(logs.Count() >= 2); + }); + + //Cleanup + await StorageHelpers.ClearBlobContainers(); + + //Trigger + await StorageHelpers.UploadFileToContainer(Constants.Blob.TriggerBlobClientContainer, fileName); + + //Verify + var lastLog = logs.Last(); + int subStringStart = lastLog.LastIndexOf(key) + key.Length; + var result = lastLog[subStringStart..]; + + Assert.Equal("Hello World", result); + } + + [Fact] + public async Task BlobTrigger_BlobContainerClient_Succeeds() { + string key = "BlobContainerTriggerOutput: "; string fileName = Guid.NewGuid().ToString(); + IEnumerable logs = null; + await TestUtility.RetryAsync(() => + { + logs = _fixture.TestLogs.CoreToolsLogs.Where(p => p.Contains(key)); + // The "RunOnStartup" log should show, and then a true invocation. + return Task.FromResult(logs.Count() >= 2); + }); + //Cleanup await StorageHelpers.ClearBlobContainers(); //Trigger - await StorageHelpers.UploadFileToContainer(triggerContainer, fileName); + await StorageHelpers.UploadFileToContainer(Constants.Blob.TriggerBlobContainerClientContainer, fileName); //Verify - string result = await StorageHelpers.DownloadFileFromContainer(outputContainer, fileName); + var lastLog = logs.Last(); + int subStringStart = lastLog.LastIndexOf(key) + key.Length; + var result = lastLog[subStringStart..]; Assert.Equal("Hello World", result); } [Theory] [InlineData("BlobInputClientTest")] + [InlineData("BlobInputContainerClientTest")] [InlineData("BlobInputStreamTest")] [InlineData("BlobInputByteTest")] [InlineData("BlobInputStringTest")] - [InlineData("BlobInputBookArrayTest")] - [InlineData("BlobInputCollectionTest")] - [InlineData("BlobInputStringArrayTest")] - public async Task BlobInput_Succeeds(string functionName) + public async Task BlobInput_SingleCardinality_Succeeds(string functionName) { - string fileName = "testFile"; string expectedMessage = "Hello World"; - HttpStatusCode expectedStatusCode = HttpStatusCode.OK; //Cleanup await StorageHelpers.ClearBlobContainers(); //Setup - await StorageHelpers.UploadFileToContainer(Constants.Blob.InputBindingContainer, fileName, expectedMessage); + await StorageHelpers.UploadFileToContainer(Constants.Blob.InputBindingContainer, "testFile", expectedMessage); //Trigger HttpResponseMessage response = await HttpHelpers.InvokeHttpTrigger(functionName); string actualMessage = await response.Content.ReadAsStringAsync(); //Verify + HttpStatusCode expectedStatusCode = HttpStatusCode.OK; + Assert.Equal(expectedStatusCode, response.StatusCode); Assert.Contains(expectedMessage, actualMessage); } @@ -96,26 +191,26 @@ public async Task BlobInput_Succeeds(string functionName) [Fact] public async Task BlobInput_Poco_Succeeds() { - string fileContent = $@"{{ ""id"": ""1"", ""name"": ""To Kill a Mockingbird""}}"; - string expectedMessage = "To Kill a Mockingbird"; - HttpStatusCode expectedStatusCode = HttpStatusCode.OK; - //Cleanup await StorageHelpers.ClearBlobContainers(); //Setup - await StorageHelpers.UploadFileToContainer(Constants.Blob.InputBindingContainer, "testFile", fileContent); + var json = JsonSerializer.Serialize(new { id = "1", name = "To Kill a Mockingbird" }); + await StorageHelpers.UploadFileToContainer(Constants.Blob.InputBindingContainer, "testFile", json); //Trigger HttpResponseMessage response = await HttpHelpers.InvokeHttpTrigger("BlobInputPocoTest"); string actualMessage = await response.Content.ReadAsStringAsync(); //Verify + string expectedMessage = "To Kill a Mockingbird"; + HttpStatusCode expectedStatusCode = HttpStatusCode.OK; + Assert.Equal(expectedStatusCode, response.StatusCode); Assert.Contains(expectedMessage, actualMessage); } - [Fact] + [Fact(Skip = "Collection support released in host version 4.16+")] public async Task BlobInput_BlobClientCollection_Succeeds() { string expectedMessage = "testFile1, testFile2, testFile3"; @@ -138,7 +233,7 @@ public async Task BlobInput_BlobClientCollection_Succeeds() Assert.Contains(expectedMessage, actualMessage); } - [Fact] + [Fact(Skip = "Collection support released in host version 4.16+")] public async Task BlobInput_StringCollection_Succeeds() { string expectedMessage = "ABC, DEF, GHI"; @@ -161,7 +256,7 @@ public async Task BlobInput_StringCollection_Succeeds() Assert.Contains(expectedMessage, actualMessage); } - [Fact] + [Fact(Skip = "Collection support released in host version 4.16+")] public async Task BlobInput_PocoCollection_Succeeds() { string book1 = $@"{{ ""id"": ""1"", ""name"": ""To Kill a Mockingbird""}}"; From 31d8e41b7de924706877b7f85e6a47f7b1db70d0 Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Thu, 16 Feb 2023 18:30:25 -0800 Subject: [PATCH 3/5] IDisposable --- test/E2ETests/E2ETests/Storage/BlobEndToEndTests.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/test/E2ETests/E2ETests/Storage/BlobEndToEndTests.cs b/test/E2ETests/E2ETests/Storage/BlobEndToEndTests.cs index b4be10a78..52ed37003 100644 --- a/test/E2ETests/E2ETests/Storage/BlobEndToEndTests.cs +++ b/test/E2ETests/E2ETests/Storage/BlobEndToEndTests.cs @@ -9,17 +9,20 @@ using System.Text.Json; using System.Threading.Tasks; using Xunit; +using Xunit.Abstractions; namespace Microsoft.Azure.Functions.Tests.E2ETests.Storage { [Collection(Constants.FunctionAppCollectionName)] - public class BlobEndToEndTests + public class BlobEndToEndTests : IDisposable { + private readonly IDisposable _disposeLog; private FunctionAppFixture _fixture; - public BlobEndToEndTests(FunctionAppFixture fixture) + public BlobEndToEndTests(FunctionAppFixture fixture, ITestOutputHelper testOutput) { _fixture = fixture; + _disposeLog = _fixture.TestLogs.UseTestLogger(testOutput); } [Fact] @@ -283,5 +286,10 @@ public async Task BlobInput_PocoCollection_Succeeds() Assert.Equal(expectedStatusCode, response.StatusCode); Assert.Contains(expectedMessage, actualMessage); } + + public void Dispose() + { + _disposeLog?.Dispose(); + } } } From f10a4014344dae6d54005a1ad394808a554ec467 Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Fri, 17 Feb 2023 10:18:09 -0800 Subject: [PATCH 4/5] Move log capture --- .../E2ETests/Storage/BlobEndToEndTests.cs | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/test/E2ETests/E2ETests/Storage/BlobEndToEndTests.cs b/test/E2ETests/E2ETests/Storage/BlobEndToEndTests.cs index 52ed37003..2ce999046 100644 --- a/test/E2ETests/E2ETests/Storage/BlobEndToEndTests.cs +++ b/test/E2ETests/E2ETests/Storage/BlobEndToEndTests.cs @@ -86,6 +86,13 @@ public async Task BlobTrigger_Stream_Succeeds() string key = "StreamTriggerOutput: "; string fileName = Guid.NewGuid().ToString(); + //Cleanup + await StorageHelpers.ClearBlobContainers(); + + //Trigger + await StorageHelpers.UploadFileToContainer(Constants.Blob.TriggerStreamContainer, fileName); + + //Verify IEnumerable logs = null; await TestUtility.RetryAsync(() => { @@ -94,13 +101,6 @@ await TestUtility.RetryAsync(() => return Task.FromResult(logs.Count() >= 2); }); - //Cleanup - await StorageHelpers.ClearBlobContainers(); - - //Trigger - await StorageHelpers.UploadFileToContainer(Constants.Blob.TriggerStreamContainer, fileName); - - //Verify var lastLog = logs.Last(); int subStringStart = lastLog.LastIndexOf(key) + key.Length; var result = lastLog[subStringStart..]; @@ -114,6 +114,13 @@ public async Task BlobTrigger_BlobClient_Succeeds() string key = "BlobClientTriggerOutput: "; string fileName = Guid.NewGuid().ToString(); + //Cleanup + await StorageHelpers.ClearBlobContainers(); + + //Trigger + await StorageHelpers.UploadFileToContainer(Constants.Blob.TriggerBlobClientContainer, fileName); + + //Verify IEnumerable logs = null; await TestUtility.RetryAsync(() => { @@ -122,13 +129,6 @@ await TestUtility.RetryAsync(() => return Task.FromResult(logs.Count() >= 2); }); - //Cleanup - await StorageHelpers.ClearBlobContainers(); - - //Trigger - await StorageHelpers.UploadFileToContainer(Constants.Blob.TriggerBlobClientContainer, fileName); - - //Verify var lastLog = logs.Last(); int subStringStart = lastLog.LastIndexOf(key) + key.Length; var result = lastLog[subStringStart..]; @@ -142,6 +142,13 @@ public async Task BlobTrigger_BlobContainerClient_Succeeds() string key = "BlobContainerTriggerOutput: "; string fileName = Guid.NewGuid().ToString(); + //Cleanup + await StorageHelpers.ClearBlobContainers(); + + //Trigger + await StorageHelpers.UploadFileToContainer(Constants.Blob.TriggerBlobContainerClientContainer, fileName); + + //Verify IEnumerable logs = null; await TestUtility.RetryAsync(() => { @@ -150,13 +157,6 @@ await TestUtility.RetryAsync(() => return Task.FromResult(logs.Count() >= 2); }); - //Cleanup - await StorageHelpers.ClearBlobContainers(); - - //Trigger - await StorageHelpers.UploadFileToContainer(Constants.Blob.TriggerBlobContainerClientContainer, fileName); - - //Verify var lastLog = logs.Last(); int subStringStart = lastLog.LastIndexOf(key) + key.Length; var result = lastLog[subStringStart..]; From 5ee2ca85e5d427fe66e5390fdf9d39470091aa26 Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Fri, 17 Feb 2023 11:25:15 -0800 Subject: [PATCH 5/5] Only expecting one log for trigger func --- test/E2ETests/E2ETests/Storage/BlobEndToEndTests.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/test/E2ETests/E2ETests/Storage/BlobEndToEndTests.cs b/test/E2ETests/E2ETests/Storage/BlobEndToEndTests.cs index 2ce999046..a3f41d63c 100644 --- a/test/E2ETests/E2ETests/Storage/BlobEndToEndTests.cs +++ b/test/E2ETests/E2ETests/Storage/BlobEndToEndTests.cs @@ -97,8 +97,7 @@ public async Task BlobTrigger_Stream_Succeeds() await TestUtility.RetryAsync(() => { logs = _fixture.TestLogs.CoreToolsLogs.Where(p => p.Contains(key)); - // The "RunOnStartup" log should show, and then a true invocation. - return Task.FromResult(logs.Count() >= 2); + return Task.FromResult(logs.Count() >= 1); }); var lastLog = logs.Last(); @@ -125,8 +124,7 @@ public async Task BlobTrigger_BlobClient_Succeeds() await TestUtility.RetryAsync(() => { logs = _fixture.TestLogs.CoreToolsLogs.Where(p => p.Contains(key)); - // The "RunOnStartup" log should show, and then a true invocation. - return Task.FromResult(logs.Count() >= 2); + return Task.FromResult(logs.Count() >= 1); }); var lastLog = logs.Last(); @@ -153,8 +151,7 @@ public async Task BlobTrigger_BlobContainerClient_Succeeds() await TestUtility.RetryAsync(() => { logs = _fixture.TestLogs.CoreToolsLogs.Where(p => p.Contains(key)); - // The "RunOnStartup" log should show, and then a true invocation. - return Task.FromResult(logs.Count() >= 2); + return Task.FromResult(logs.Count() >= 1); }); var lastLog = logs.Last();