From 6c51fbe75ba220b003839d3b19c44e976f3f296e Mon Sep 17 00:00:00 2001 From: Emiliano Quiroga Date: Tue, 26 Apr 2022 09:08:46 -0300 Subject: [PATCH 1/8] Files updated --- .../AzureBlobStorage.cs | 10 +- .../AzureBlobTranscriptStore.cs | 24 +- .../Microsoft.Bot.Builder.Azure.csproj | 2 +- .../AzureBlobStorageTests.cs | 6 +- .../AzureBlobTranscriptStoreTests.cs | 522 +++++++++++++++--- 5 files changed, 485 insertions(+), 79 deletions(-) diff --git a/libraries/Microsoft.Bot.Builder.Azure/AzureBlobStorage.cs b/libraries/Microsoft.Bot.Builder.Azure/AzureBlobStorage.cs index 0b48a904df..4f7cd14835 100644 --- a/libraries/Microsoft.Bot.Builder.Azure/AzureBlobStorage.cs +++ b/libraries/Microsoft.Bot.Builder.Azure/AzureBlobStorage.cs @@ -8,11 +8,11 @@ using System.Threading; using System.Threading.Tasks; using System.Web; -using Microsoft.WindowsAzure.Storage; -using Microsoft.WindowsAzure.Storage.Blob; -using Microsoft.WindowsAzure.Storage.Blob.Protocol; -using Microsoft.WindowsAzure.Storage.Core; -using Microsoft.WindowsAzure.Storage.RetryPolicies; +using Microsoft.Azure.Storage; +using Microsoft.Azure.Storage.Blob; +using Microsoft.Azure.Storage.Blob.Protocol; +using Microsoft.Azure.Storage.Core; +using Microsoft.Azure.Storage.RetryPolicies; using Newtonsoft.Json; namespace Microsoft.Bot.Builder.Azure diff --git a/libraries/Microsoft.Bot.Builder.Azure/AzureBlobTranscriptStore.cs b/libraries/Microsoft.Bot.Builder.Azure/AzureBlobTranscriptStore.cs index 0735a704fb..fc364ba99b 100644 --- a/libraries/Microsoft.Bot.Builder.Azure/AzureBlobTranscriptStore.cs +++ b/libraries/Microsoft.Bot.Builder.Azure/AzureBlobTranscriptStore.cs @@ -5,12 +5,15 @@ using System.Globalization; using System.IO; using System.Linq; +using System.Runtime.CompilerServices; using System.Threading.Tasks; +using Microsoft.Azure.Storage; +using Microsoft.Azure.Storage.Blob; using Microsoft.Bot.Schema; -using Microsoft.WindowsAzure.Storage; -using Microsoft.WindowsAzure.Storage.Blob; using Newtonsoft.Json; +[assembly: InternalsVisibleTo("Microsoft.Bot.Builder.Azure.Tests")] + namespace Microsoft.Bot.Builder.Azure { /// @@ -31,6 +34,8 @@ public class AzureBlobTranscriptStore : ITranscriptStore private static HashSet _checkedContainers = new HashSet(); + private readonly CloudBlobClient _blobClient; + /// /// Initializes a new instance of the class. /// Creates an instance of AzureBlobTranscriptStore. @@ -63,7 +68,7 @@ public AzureBlobTranscriptStore(CloudStorageAccount storageAccount, string conta () => { containerName = containerName.ToLowerInvariant(); - var blobClient = storageAccount.CreateCloudBlobClient(); + var blobClient = _blobClient ?? storageAccount.CreateCloudBlobClient(); NameValidator.ValidateContainerName(containerName); var container = blobClient.GetContainerReference(containerName); if (!_checkedContainers.Contains(containerName)) @@ -76,6 +81,19 @@ public AzureBlobTranscriptStore(CloudStorageAccount storageAccount, string conta }, isThreadSafe: true); } + /// + /// Initializes a new instance of the class. + /// Creates an instance of AzureBlobTranscriptStore. + /// + /// . + /// Name of the container where transcript blobs will be stored. + /// Custom implementation of CloudBlobClient. + internal AzureBlobTranscriptStore(CloudStorageAccount storageAccount, string containerName, CloudBlobClient blobClient) + : this(storageAccount, containerName) + { + _blobClient = blobClient; + } + private Lazy Container { get; set; } /// diff --git a/libraries/Microsoft.Bot.Builder.Azure/Microsoft.Bot.Builder.Azure.csproj b/libraries/Microsoft.Bot.Builder.Azure/Microsoft.Bot.Builder.Azure.csproj index f14d277b8b..2d8f0ad83f 100644 --- a/libraries/Microsoft.Bot.Builder.Azure/Microsoft.Bot.Builder.Azure.csproj +++ b/libraries/Microsoft.Bot.Builder.Azure/Microsoft.Bot.Builder.Azure.csproj @@ -38,7 +38,7 @@ - + diff --git a/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobStorageTests.cs b/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobStorageTests.cs index c489b987fb..389faf130c 100644 --- a/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobStorageTests.cs +++ b/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobStorageTests.cs @@ -4,8 +4,10 @@ using System; using System.Reflection; using System.Threading.Tasks; -using Microsoft.WindowsAzure.Storage; -using Microsoft.WindowsAzure.Storage.Blob; +using Microsoft.Azure.Storage; +using Microsoft.Azure.Storage.Auth; +using Microsoft.Azure.Storage.Blob; +using Microsoft.Azure.Storage.Core; using Newtonsoft.Json; using Xunit; using Xunit.Abstractions; diff --git a/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobTranscriptStoreTests.cs b/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobTranscriptStoreTests.cs index ab3f1d3eea..7b8726910b 100644 --- a/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobTranscriptStoreTests.cs +++ b/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobTranscriptStoreTests.cs @@ -2,116 +2,502 @@ // Licensed under the MIT License. using System; -using System.Reflection; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; using System.Threading.Tasks; -using Microsoft.WindowsAzure.Storage; -using Microsoft.WindowsAzure.Storage.Auth; -using Microsoft.WindowsAzure.Storage.Blob; +using Microsoft.Azure.Storage; +using Microsoft.Azure.Storage.Auth; +using Microsoft.Azure.Storage.Blob; +using Microsoft.Bot.Schema; +using Moq; +using Newtonsoft.Json; using Xunit; -using Xunit.Abstractions; -using Xunit.Sdk; -// These tests require Azure Storage Emulator v5.7 -// The emulator must be installed at this path C:\Program Files (x86)\Microsoft SDKs\Azure\Storage Emulator\AzureStorageEmulator.exe -// More info: https://docs.microsoft.com/azure/storage/common/storage-use-emulator namespace Microsoft.Bot.Builder.Azure.Tests { - [Trait("TestCategory", "Storage")] - [Trait("TestCategory", "Storage - BlobTranscripts")] - public class AzureBlobTranscriptStoreTests : TranscriptStoreBaseTests, IAsyncLifetime + public class AzureBlobTranscriptStoreTests { - private readonly string _testName; + protected const string ConnectionString = @"UseDevelopmentStorage=true"; + protected const string ContainerName = "containername"; - public AzureBlobTranscriptStoreTests(ITestOutputHelper testOutputHelper) + private Mock _stream; + private Mock _mockBlockBlob; + private Mock _mockContainer; + private Mock _mockBlobClient; + private Mock _mockAccount; + private AzureBlobTranscriptStore _blobTranscript; + private BlobResultSegment _segment; + private Mock _mockDirectory; + private Activity _activity; + + [Fact] + public void ConstructorValidation() { - var helper = (TestOutputHelper)testOutputHelper; + var storageAccount = CloudStorageAccount.Parse(ConnectionString); - var test = (ITest)helper.GetType().GetField("test", BindingFlags.NonPublic | BindingFlags.Instance) - .GetValue(helper); + // Should work. + Assert.NotNull(new AzureBlobTranscriptStore(ConnectionString, ContainerName)); + Assert.NotNull(new AzureBlobTranscriptStore(storageAccount, ContainerName)); - _testName = test.TestCase.TestMethod.Method.Name; + // No storageAccount. Should throw. + Assert.Throws(() => new AzureBlobTranscriptStore(storageAccount: null, ContainerName)); - if (StorageEmulatorHelper.CheckEmulator()) - { - CloudStorageAccount.Parse(BlobStorageEmulatorConnectionString) - .CreateCloudBlobClient() - .GetContainerReference(ContainerName) - .DeleteIfExistsAsync().ConfigureAwait(false); - } + // No containerName. Should throw. + Assert.Throws(() => new AzureBlobTranscriptStore(storageAccount, null)); + + // Wrong format. Should throw. + Assert.Throws(() => new AzureBlobTranscriptStore("123", ContainerName)); } - protected override string ContainerName => $"blobtranscript{_testName.ToLower()}"; + [Fact] + public async Task LogActivityAsyncNullActivityFailure() + { + var storageAccount = CloudStorageAccount.Parse(ConnectionString); + var blobTranscript = new AzureBlobTranscriptStore(storageAccount, ContainerName); - protected override ITranscriptStore TranscriptStore => new AzureBlobTranscriptStore(BlobStorageEmulatorConnectionString, ContainerName); + await Assert.ThrowsAsync(() => blobTranscript.LogActivityAsync(null)); + } - public Task InitializeAsync() + [Fact] + public async Task LogActivityAsyncDefault() { - return Task.CompletedTask; + InitStorage(); + + _activity = new Activity + { + Type = ActivityTypes.Message, + Text = "Hello", + Id = "test-id", + ChannelId = "channel-id", + Conversation = new ConversationAccount() { Id = "conversation-id" }, + Timestamp = new DateTimeOffset(), + From = new ChannelAccount() { Id = "account-1" }, + Recipient = new ChannelAccount() { Id = "account-2" } + }; + + await _blobTranscript.LogActivityAsync(_activity); + + _mockBlobClient.Verify(x => x.GetContainerReference(It.IsAny()), Times.Once); + _mockContainer.Verify(x => x.GetBlockBlobReference(It.IsAny()), Times.Once); + _mockBlockBlob.Verify(x => x.OpenWriteAsync(), Times.Once); + _mockBlockBlob.Verify(x => x.SetMetadataAsync(), Times.Once); } - public async Task DisposeAsync() + [Fact] + public async Task LogActivityAsyncMessageUpdate() { - if (StorageEmulatorHelper.CheckEmulator()) + _activity = new Activity { - await CloudStorageAccount.Parse(BlobStorageEmulatorConnectionString) - .CreateCloudBlobClient() - .GetContainerReference(ContainerName) - .DeleteIfExistsAsync().ConfigureAwait(false); - } + Type = ActivityTypes.MessageUpdate, + Text = "Hello", + Id = "test-id", + ChannelId = "channel-id", + Conversation = new ConversationAccount { Id = "conversation-id" }, + Timestamp = new DateTimeOffset(), + From = new ChannelAccount { Id = "account-1" }, + Recipient = new ChannelAccount { Id = "account-2" } + }; + + InitStorage(); + + _mockBlockBlob.Setup(x => x.DownloadTextAsync()).Returns(Task.FromResult(JsonConvert.SerializeObject(_activity))); + + await _blobTranscript.LogActivityAsync(_activity); + + _mockBlobClient.Verify(x => x.GetContainerReference(It.IsAny()), Times.Once); + _mockContainer.Verify(x => x.GetDirectoryReference(It.IsAny()), Times.Once); + _mockBlockBlob.Verify(x => x.DownloadTextAsync(), Times.Exactly(2)); + _mockBlockBlob.Verify(x => x.OpenWriteAsync(), Times.Once); + _mockBlockBlob.Verify(x => x.SetMetadataAsync(), Times.Exactly(2)); + _mockDirectory.Verify( + x => x.ListBlobsSegmentedAsync( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); } - // These tests require Azure Storage Emulator v5.7 [Fact] - public async Task LongIdAddTest() + public async Task LogActivityAsyncMessageUpdateNullBlob() { - if (StorageEmulatorHelper.CheckEmulator()) + _activity = new Activity { - try - { - var a = CreateActivity(0, 0, LongId); + Type = ActivityTypes.MessageUpdate, + Text = "Hello", + Id = "test-id", + ChannelId = "channel-id", + Conversation = new ConversationAccount() { Id = "conversation-id" }, + Timestamp = new DateTimeOffset(), + From = new ChannelAccount() { Id = "account-1" }, + Recipient = new ChannelAccount() { Id = "account-2" } + }; + + InitStorage(); + + var segment = new BlobResultSegment(new List(), null); + + _mockDirectory.Setup(x => x.ListBlobsSegmentedAsync( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).Returns(Task.FromResult(segment)); + + _mockContainer.Setup(x => x.GetDirectoryReference(It.IsAny())).Returns(_mockDirectory.Object); - await TranscriptStore.LogActivityAsync(a); + await _blobTranscript.LogActivityAsync(_activity); - throw new XunitException("Should have thrown an error"); - } - catch (StorageException) - { - return; - } - } + _mockBlobClient.Verify(x => x.GetContainerReference(It.IsAny()), Times.Once); + _mockContainer.Verify(x => x.GetDirectoryReference(It.IsAny()), Times.Once); + _mockContainer.Verify(x => x.GetBlockBlobReference(It.IsAny()), Times.Once); + _mockBlockBlob.Verify(x => x.OpenWriteAsync(), Times.Once); + _mockBlockBlob.Verify(x => x.SetMetadataAsync(), Times.Once); + _mockDirectory.Verify( + x => x.ListBlobsSegmentedAsync( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); } - // These tests require Azure Storage Emulator v5.7 [Fact] - public void BlobTranscriptParamTest() + public async Task LogActivityAsyncMessageDelete() { - if (StorageEmulatorHelper.CheckEmulator()) + _activity = new Activity { - Assert.Throws(() => new AzureBlobTranscriptStore("123", ContainerName)); + Type = ActivityTypes.MessageDelete, + Text = "Hello", + Id = "test-id", + ChannelId = "channel-id", + Conversation = new ConversationAccount { Id = "conversation-id" }, + Timestamp = new DateTimeOffset(), + From = new ChannelAccount { Id = "account-1" }, + Recipient = new ChannelAccount { Id = "account-2" } + }; + + InitStorage(); + + _mockBlockBlob.Setup(x => x.DownloadTextAsync()).Returns(Task.FromResult(JsonConvert.SerializeObject(_activity))); + + await _blobTranscript.LogActivityAsync(_activity); + + _mockBlobClient.Verify(x => x.GetContainerReference(It.IsAny()), Times.Once); + _mockContainer.Verify(x => x.GetDirectoryReference(It.IsAny()), Times.Once); + _mockBlockBlob.Verify(x => x.DownloadTextAsync(), Times.Exactly(2)); + _mockBlockBlob.Verify(x => x.OpenWriteAsync(), Times.Once); + _mockBlockBlob.Verify(x => x.SetMetadataAsync(), Times.Exactly(2)); + _mockDirectory.Verify( + x => x.ListBlobsSegmentedAsync( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + } + + [Fact] + public async Task GetTranscriptActivitiesAsyncValidations() + { + var storageAccount = CloudStorageAccount.Parse(ConnectionString); + var blobTranscript = new AzureBlobTranscriptStore(storageAccount, ContainerName); - Assert.Throws(() => new AzureBlobTranscriptStore(new CloudStorageAccount(new StorageCredentials(), false), string.Empty)); + // No channel id. Should throw. + await Assert.ThrowsAsync(() => blobTranscript.GetTranscriptActivitiesAsync(null, "convo-id")); - Assert.Throws(() => - new AzureBlobTranscriptStore((CloudStorageAccount)null, ContainerName)); + // No conversation id. Should throw. + await Assert.ThrowsAsync(() => blobTranscript.GetTranscriptActivitiesAsync("channel-id", null)); + } - Assert.Throws(() => - new AzureBlobTranscriptStore((string)null, ContainerName)); + [Fact] + public async Task GetTranscriptActivitiesAsync() + { + InitStorage(); + + _mockDirectory.Setup(x => x.ListBlobsSegmentedAsync( + It.IsAny(), + It.IsAny(), + null, + It.IsAny(), + It.IsAny(), + It.IsAny())).Returns(Task.FromResult(_segment)); - Assert.Throws(() => - new AzureBlobTranscriptStore((CloudStorageAccount)null, null)); + await _blobTranscript.GetTranscriptActivitiesAsync("channelId", "conversationId"); - Assert.Throws(() => new AzureBlobTranscriptStore((string)null, null)); - } + _mockBlobClient.Verify(x => x.GetContainerReference(It.IsAny()), Times.Once); + _mockContainer.Verify(x => x.GetDirectoryReference(It.IsAny()), Times.Once); + _mockDirectory.Verify( + x => x.ListBlobsSegmentedAsync( + It.IsAny(), + It.IsAny(), + null, + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); } - // These tests require Azure Storage Emulator v5.7 [Fact] - public async void ListTranscriptsAsyncWithEmptyChannelIdShouldFail() + public async Task GetTranscriptActivitiesAsyncWithMetadata() { - if (StorageEmulatorHelper.CheckEmulator()) + InitStorage(); + + _mockBlockBlob.Object.Metadata["Timestamp"] = DateTime.Now.ToString(CultureInfo.InvariantCulture); + + _mockDirectory.Setup(x => x.ListBlobsSegmentedAsync( + It.IsAny(), + It.IsAny(), + null, + It.IsAny(), + It.IsAny(), + It.IsAny())).Returns(Task.FromResult(_segment)); + + await _blobTranscript.GetTranscriptActivitiesAsync("channelId", "conversationId"); + + _mockBlobClient.Verify(x => x.GetContainerReference(It.IsAny()), Times.Once); + _mockContainer.Verify(x => x.GetDirectoryReference(It.IsAny()), Times.Once); + _mockDirectory.Verify( + x => x.ListBlobsSegmentedAsync( + It.IsAny(), + It.IsAny(), + null, + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + + _mockBlobClient.Verify(x => x.GetContainerReference(It.IsAny()), Times.Once); + } + + [Fact] + public async Task GetTranscriptActivitiesAsyncContinuationToken() + { + InitStorage(); + + _mockBlockBlob.Object.Metadata["Timestamp"] = DateTime.Now.ToString(CultureInfo.InvariantCulture); + _mockBlockBlob.SetupGet(x => x.Name).Returns("token-name"); + + _mockDirectory.Setup(x => x.ListBlobsSegmentedAsync( + It.IsAny(), + It.IsAny(), + null, + It.IsAny(), + It.IsAny(), + It.IsAny())).Returns(Task.FromResult(_segment)); + + await _blobTranscript.GetTranscriptActivitiesAsync("channelId", "conversationId", "token-name"); + + _mockBlobClient.Verify(x => x.GetContainerReference(It.IsAny()), Times.Once); + _mockContainer.Verify(x => x.GetDirectoryReference(It.IsAny()), Times.Once); + _mockDirectory.Verify( + x => x.ListBlobsSegmentedAsync( + It.IsAny(), + It.IsAny(), + null, + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + + _mockBlobClient.Verify(x => x.GetContainerReference(It.IsAny()), Times.Once); + } + + [Fact] + public async Task GetTranscriptActivitiesAsyncMultipleBlobs() + { + InitStorage(); + + var jsonString = JsonConvert.SerializeObject(new Activity()); + _mockBlockBlob.Setup(x => x.DownloadTextAsync()).Returns(Task.FromResult(jsonString)); + _mockBlockBlob.Object.Metadata["Timestamp"] = DateTime.Now.ToString(CultureInfo.InvariantCulture); + _mockBlockBlob.SetupGet(x => x.Name).Returns("token-name"); + + var segment = new BlobResultSegment(CreateSegment(21, _mockBlockBlob.Object).ToList(), null); + + _mockDirectory.Setup(x => x.ListBlobsSegmentedAsync( + It.IsAny(), + It.IsAny(), + null, + It.IsAny(), + It.IsAny(), + It.IsAny())).Returns(Task.FromResult(segment)); + + await _blobTranscript.GetTranscriptActivitiesAsync("channelId", "conversationId", "token-name"); + + _mockBlobClient.Verify(x => x.GetContainerReference(It.IsAny()), Times.Once); + _mockContainer.Verify(x => x.GetDirectoryReference(It.IsAny()), Times.Once); + _mockDirectory.Verify( + x => x.ListBlobsSegmentedAsync( + It.IsAny(), + It.IsAny(), + null, + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + + _mockBlobClient.Verify(x => x.GetContainerReference(It.IsAny()), Times.Once); + } + + [Fact] + public async Task ListTranscriptAsyncValidations() + { + var storageAccount = CloudStorageAccount.Parse(ConnectionString); + var blobTranscript = new AzureBlobTranscriptStore(storageAccount, ContainerName); + + // No channel id. Should throw. + await Assert.ThrowsAsync(() => blobTranscript.ListTranscriptsAsync(null)); + } + + [Fact] + public async Task ListTranscriptAsync() + { + InitStorage(); + + _mockDirectory.Setup(x => x.ListBlobsSegmentedAsync( + It.IsAny(), + It.IsAny(), + null, + It.IsAny(), + It.IsAny(), + It.IsAny())).Returns(Task.FromResult(_segment)); + + _mockContainer.Setup(x => x.GetDirectoryReference(It.IsAny())).Returns(_mockDirectory.Object); + + await _blobTranscript.ListTranscriptsAsync("channelId", null); + + _mockBlobClient.Verify(x => x.GetContainerReference(It.IsAny()), Times.Once); + _mockContainer.Verify(x => x.GetDirectoryReference(It.IsAny()), Times.Once); + _mockDirectory.Verify( + x => x.ListBlobsSegmentedAsync( + It.IsAny(), + It.IsAny(), + null, + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + } + + [Fact] + public async Task DeleteTranscriptAsyncValidations() + { + var storageAccount = CloudStorageAccount.Parse(ConnectionString); + var blobTranscript = new AzureBlobTranscriptStore(storageAccount, ContainerName); + + // No channel id. Should throw. + await Assert.ThrowsAsync(() => blobTranscript.DeleteTranscriptAsync(null, "convo-id")); + + // No conversation id. Should throw. + await Assert.ThrowsAsync(() => blobTranscript.DeleteTranscriptAsync("channel-id", null)); + } + + [Fact] + public async Task DeleteTranscriptAsync() + { + InitStorage(); + + _mockDirectory.Setup(x => x.ListBlobsSegmentedAsync( + It.IsAny(), + It.IsAny(), + null, + It.IsAny(), + It.IsAny(), + It.IsAny())).Returns(Task.FromResult(_segment)); + + await _blobTranscript.DeleteTranscriptAsync("channelId", "convo-id"); + + _mockBlobClient.Verify(x => x.GetContainerReference(It.IsAny()), Times.Once); + _mockContainer.Verify(x => x.GetDirectoryReference(It.IsAny()), Times.Once); + _mockDirectory.Verify( + x => x.ListBlobsSegmentedAsync( + It.IsAny(), + It.IsAny(), + null, + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockBlockBlob.Verify(x => x.DeleteIfExistsAsync(), Times.Once); + } + + [Fact] + public async Task LogActivityAsyncInternalFindActivityBlobAsync() + { + _activity = new Activity { - await Assert.ThrowsAsync(() => TranscriptStore.ListTranscriptsAsync(string.Empty)); - } + Type = ActivityTypes.MessageUpdate, + Text = "Hello", + Id = "test-id", + ChannelId = "channel-id", + Conversation = new ConversationAccount { Id = "conversation-id" }, + Timestamp = new DateTimeOffset(), + From = new ChannelAccount { Id = "account-1" }, + Recipient = new ChannelAccount { Id = "account-2" } + }; + + InitStorage(); + + _mockBlockBlob.Object.Metadata["Id"] = "test-id"; + _mockBlockBlob.Setup(x => x.DownloadTextAsync()).Returns(Task.FromResult(JsonConvert.SerializeObject(_activity))); + + await _blobTranscript.LogActivityAsync(_activity); + + _mockBlobClient.Verify(x => x.GetContainerReference(It.IsAny()), Times.Once); + _mockContainer.Verify(x => x.GetDirectoryReference(It.IsAny()), Times.Once); + + _mockBlockBlob.Verify(x => x.OpenWriteAsync(), Times.Once); + + _mockDirectory.Verify( + x => x.ListBlobsSegmentedAsync( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + } + + private static IEnumerable CreateSegment(int count, CloudBlockBlob blob) + { + return Enumerable.Range(0, count).Select(x => blob); + } + + private void InitStorage() + { + var jsonString = JsonConvert.SerializeObject(new Activity()); + + _stream = new Mock(); + _stream.SetupGet(x => x.CanWrite).Returns(true); + + _mockBlockBlob = new Mock(new Uri("http://test/myaccount/blob")); + _mockBlockBlob.Setup(x => x.OpenWriteAsync()).Returns(Task.FromResult(_stream.Object)); + _mockBlockBlob.Setup(x => x.SetMetadataAsync()); + _mockBlockBlob.Setup(x => x.DownloadTextAsync()).Returns(Task.FromResult(JsonConvert.SerializeObject(_activity))); + _mockBlockBlob.Setup(x => x.DownloadTextAsync()).Returns(Task.FromResult(jsonString)); + + _segment = new BlobResultSegment(new List { _mockBlockBlob.Object }, null); + + _mockDirectory = new Mock(); + _mockDirectory.Setup(x => x.ListBlobsSegmentedAsync( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).Returns(Task.FromResult(_segment)); + + _mockContainer = new Mock(new Uri("https://testuri.com")); + _mockContainer.Setup(x => x.GetBlockBlobReference(It.IsAny())).Returns(_mockBlockBlob.Object); + _mockContainer.Setup(x => x.CreateIfNotExistsAsync()); + _mockContainer.Setup(x => x.GetDirectoryReference(It.IsAny())).Returns(_mockDirectory.Object); + + _mockBlobClient = new Mock(new Uri("https://testuri.com"), null); + _mockBlobClient.Setup(x => x.GetContainerReference(It.IsAny())).Returns(_mockContainer.Object); + + _mockAccount = new Mock(new StorageCredentials("accountName", "S2V5VmFsdWU=", "key"), false); + + _blobTranscript = new AzureBlobTranscriptStore(_mockAccount.Object, ContainerName, _mockBlobClient.Object); } } } From 0d64a5923facc0365b4e5947f56e5b8fa62b1a6c Mon Sep 17 00:00:00 2001 From: Emiliano Quiroga Date: Tue, 26 Apr 2022 09:26:23 -0300 Subject: [PATCH 2/8] Tests order updated --- .../AzureBlobTranscriptStoreTests.cs | 74 +++++++++---------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobTranscriptStoreTests.cs b/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobTranscriptStoreTests.cs index 7b8726910b..48c08cc062 100644 --- a/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobTranscriptStoreTests.cs +++ b/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobTranscriptStoreTests.cs @@ -202,6 +202,43 @@ public async Task LogActivityAsyncMessageDelete() It.IsAny()), Times.Once); } + [Fact] + public async Task LogActivityAsyncInternalFindActivityBlobAsync() + { + _activity = new Activity + { + Type = ActivityTypes.MessageUpdate, + Text = "Hello", + Id = "test-id", + ChannelId = "channel-id", + Conversation = new ConversationAccount { Id = "conversation-id" }, + Timestamp = new DateTimeOffset(), + From = new ChannelAccount { Id = "account-1" }, + Recipient = new ChannelAccount { Id = "account-2" } + }; + + InitStorage(); + + _mockBlockBlob.Object.Metadata["Id"] = "test-id"; + _mockBlockBlob.Setup(x => x.DownloadTextAsync()).Returns(Task.FromResult(JsonConvert.SerializeObject(_activity))); + + await _blobTranscript.LogActivityAsync(_activity); + + _mockBlobClient.Verify(x => x.GetContainerReference(It.IsAny()), Times.Once); + _mockContainer.Verify(x => x.GetDirectoryReference(It.IsAny()), Times.Once); + + _mockBlockBlob.Verify(x => x.OpenWriteAsync(), Times.Once); + + _mockDirectory.Verify( + x => x.ListBlobsSegmentedAsync( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + } + [Fact] public async Task GetTranscriptActivitiesAsyncValidations() { @@ -421,43 +458,6 @@ public async Task DeleteTranscriptAsync() _mockBlockBlob.Verify(x => x.DeleteIfExistsAsync(), Times.Once); } - [Fact] - public async Task LogActivityAsyncInternalFindActivityBlobAsync() - { - _activity = new Activity - { - Type = ActivityTypes.MessageUpdate, - Text = "Hello", - Id = "test-id", - ChannelId = "channel-id", - Conversation = new ConversationAccount { Id = "conversation-id" }, - Timestamp = new DateTimeOffset(), - From = new ChannelAccount { Id = "account-1" }, - Recipient = new ChannelAccount { Id = "account-2" } - }; - - InitStorage(); - - _mockBlockBlob.Object.Metadata["Id"] = "test-id"; - _mockBlockBlob.Setup(x => x.DownloadTextAsync()).Returns(Task.FromResult(JsonConvert.SerializeObject(_activity))); - - await _blobTranscript.LogActivityAsync(_activity); - - _mockBlobClient.Verify(x => x.GetContainerReference(It.IsAny()), Times.Once); - _mockContainer.Verify(x => x.GetDirectoryReference(It.IsAny()), Times.Once); - - _mockBlockBlob.Verify(x => x.OpenWriteAsync(), Times.Once); - - _mockDirectory.Verify( - x => x.ListBlobsSegmentedAsync( - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny()), Times.Once); - } - private static IEnumerable CreateSegment(int count, CloudBlockBlob blob) { return Enumerable.Range(0, count).Select(x => blob); From 6c41dfb71c8361cb1d529b22c88b76e7835adde3 Mon Sep 17 00:00:00 2001 From: Emiliano Quiroga Date: Tue, 26 Apr 2022 12:14:24 -0300 Subject: [PATCH 3/8] Categories restored --- .../AzureBlobTranscriptStoreTests.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobTranscriptStoreTests.cs b/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobTranscriptStoreTests.cs index 48c08cc062..9e6830ddb7 100644 --- a/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobTranscriptStoreTests.cs +++ b/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobTranscriptStoreTests.cs @@ -16,6 +16,8 @@ namespace Microsoft.Bot.Builder.Azure.Tests { + [Trait("TestCategory", "Storage")] + [Trait("TestCategory", "Storage - BlobTranscripts")] public class AzureBlobTranscriptStoreTests { protected const string ConnectionString = @"UseDevelopmentStorage=true"; From d495a15b7a2b6ef4d5fc09107c8aa6fc378cbc32 Mon Sep 17 00:00:00 2001 From: Emiliano Quiroga Date: Wed, 27 Apr 2022 15:57:41 -0300 Subject: [PATCH 4/8] Activity instantiated globally --- .../AzureBlobTranscriptStoreTests.cs | 73 +++++-------------- 1 file changed, 17 insertions(+), 56 deletions(-) diff --git a/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobTranscriptStoreTests.cs b/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobTranscriptStoreTests.cs index 9e6830ddb7..c03152ba5a 100644 --- a/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobTranscriptStoreTests.cs +++ b/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobTranscriptStoreTests.cs @@ -31,7 +31,18 @@ public class AzureBlobTranscriptStoreTests private AzureBlobTranscriptStore _blobTranscript; private BlobResultSegment _segment; private Mock _mockDirectory; - private Activity _activity; + + private Activity _activity = new Activity + { + Type = ActivityTypes.Message, + Text = "Hello", + Id = "test-id", + ChannelId = "channel-id", + Conversation = new ConversationAccount() { Id = "conversation-id" }, + Timestamp = new DateTimeOffset(), + From = new ChannelAccount() { Id = "account-1" }, + Recipient = new ChannelAccount() { Id = "account-2" } + }; [Fact] public void ConstructorValidation() @@ -66,17 +77,7 @@ public async Task LogActivityAsyncDefault() { InitStorage(); - _activity = new Activity - { - Type = ActivityTypes.Message, - Text = "Hello", - Id = "test-id", - ChannelId = "channel-id", - Conversation = new ConversationAccount() { Id = "conversation-id" }, - Timestamp = new DateTimeOffset(), - From = new ChannelAccount() { Id = "account-1" }, - Recipient = new ChannelAccount() { Id = "account-2" } - }; + _activity.Type = ActivityTypes.Message; await _blobTranscript.LogActivityAsync(_activity); @@ -89,17 +90,7 @@ public async Task LogActivityAsyncDefault() [Fact] public async Task LogActivityAsyncMessageUpdate() { - _activity = new Activity - { - Type = ActivityTypes.MessageUpdate, - Text = "Hello", - Id = "test-id", - ChannelId = "channel-id", - Conversation = new ConversationAccount { Id = "conversation-id" }, - Timestamp = new DateTimeOffset(), - From = new ChannelAccount { Id = "account-1" }, - Recipient = new ChannelAccount { Id = "account-2" } - }; + _activity.Type = ActivityTypes.MessageUpdate; InitStorage(); @@ -125,17 +116,7 @@ public async Task LogActivityAsyncMessageUpdate() [Fact] public async Task LogActivityAsyncMessageUpdateNullBlob() { - _activity = new Activity - { - Type = ActivityTypes.MessageUpdate, - Text = "Hello", - Id = "test-id", - ChannelId = "channel-id", - Conversation = new ConversationAccount() { Id = "conversation-id" }, - Timestamp = new DateTimeOffset(), - From = new ChannelAccount() { Id = "account-1" }, - Recipient = new ChannelAccount() { Id = "account-2" } - }; + _activity.Type = ActivityTypes.MessageUpdate; InitStorage(); @@ -171,17 +152,7 @@ public async Task LogActivityAsyncMessageUpdateNullBlob() [Fact] public async Task LogActivityAsyncMessageDelete() { - _activity = new Activity - { - Type = ActivityTypes.MessageDelete, - Text = "Hello", - Id = "test-id", - ChannelId = "channel-id", - Conversation = new ConversationAccount { Id = "conversation-id" }, - Timestamp = new DateTimeOffset(), - From = new ChannelAccount { Id = "account-1" }, - Recipient = new ChannelAccount { Id = "account-2" } - }; + _activity.Type = ActivityTypes.MessageDelete; InitStorage(); @@ -207,17 +178,7 @@ public async Task LogActivityAsyncMessageDelete() [Fact] public async Task LogActivityAsyncInternalFindActivityBlobAsync() { - _activity = new Activity - { - Type = ActivityTypes.MessageUpdate, - Text = "Hello", - Id = "test-id", - ChannelId = "channel-id", - Conversation = new ConversationAccount { Id = "conversation-id" }, - Timestamp = new DateTimeOffset(), - From = new ChannelAccount { Id = "account-1" }, - Recipient = new ChannelAccount { Id = "account-2" } - }; + _activity.Type = ActivityTypes.MessageUpdate; InitStorage(); From a3d723f02185ff6f3eafa6fbac4feee4f685a7f1 Mon Sep 17 00:00:00 2001 From: CeciliaAvila Date: Thu, 28 Apr 2022 14:48:34 -0300 Subject: [PATCH 5/8] Make activity property readonly. --- .../AzureBlobTranscriptStoreTests.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobTranscriptStoreTests.cs b/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobTranscriptStoreTests.cs index c03152ba5a..7b6e0b667b 100644 --- a/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobTranscriptStoreTests.cs +++ b/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobTranscriptStoreTests.cs @@ -32,7 +32,7 @@ public class AzureBlobTranscriptStoreTests private BlobResultSegment _segment; private Mock _mockDirectory; - private Activity _activity = new Activity + private readonly Activity _activity = new Activity { Type = ActivityTypes.Message, Text = "Hello", @@ -77,8 +77,6 @@ public async Task LogActivityAsyncDefault() { InitStorage(); - _activity.Type = ActivityTypes.Message; - await _blobTranscript.LogActivityAsync(_activity); _mockBlobClient.Verify(x => x.GetContainerReference(It.IsAny()), Times.Once); From 4001659d968b63656b83eb6b384568ab429c1252 Mon Sep 17 00:00:00 2001 From: sw-joelmut Date: Fri, 29 Apr 2022 14:33:19 -0300 Subject: [PATCH 6/8] Revert Microsoft.Azure.Storage.Blob bump from 9.4.2 to 10.0.3 --- .../Microsoft.Bot.Builder.Azure/AzureBlobStorage.cs | 10 +++++----- .../AzureBlobTranscriptStore.cs | 4 ++-- .../Microsoft.Bot.Builder.Azure.csproj | 2 +- .../AzureBlobStorageTests.cs | 6 ++---- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/libraries/Microsoft.Bot.Builder.Azure/AzureBlobStorage.cs b/libraries/Microsoft.Bot.Builder.Azure/AzureBlobStorage.cs index 4f7cd14835..0b48a904df 100644 --- a/libraries/Microsoft.Bot.Builder.Azure/AzureBlobStorage.cs +++ b/libraries/Microsoft.Bot.Builder.Azure/AzureBlobStorage.cs @@ -8,11 +8,11 @@ using System.Threading; using System.Threading.Tasks; using System.Web; -using Microsoft.Azure.Storage; -using Microsoft.Azure.Storage.Blob; -using Microsoft.Azure.Storage.Blob.Protocol; -using Microsoft.Azure.Storage.Core; -using Microsoft.Azure.Storage.RetryPolicies; +using Microsoft.WindowsAzure.Storage; +using Microsoft.WindowsAzure.Storage.Blob; +using Microsoft.WindowsAzure.Storage.Blob.Protocol; +using Microsoft.WindowsAzure.Storage.Core; +using Microsoft.WindowsAzure.Storage.RetryPolicies; using Newtonsoft.Json; namespace Microsoft.Bot.Builder.Azure diff --git a/libraries/Microsoft.Bot.Builder.Azure/AzureBlobTranscriptStore.cs b/libraries/Microsoft.Bot.Builder.Azure/AzureBlobTranscriptStore.cs index fc364ba99b..f8d95fe43b 100644 --- a/libraries/Microsoft.Bot.Builder.Azure/AzureBlobTranscriptStore.cs +++ b/libraries/Microsoft.Bot.Builder.Azure/AzureBlobTranscriptStore.cs @@ -7,9 +7,9 @@ using System.Linq; using System.Runtime.CompilerServices; using System.Threading.Tasks; -using Microsoft.Azure.Storage; -using Microsoft.Azure.Storage.Blob; using Microsoft.Bot.Schema; +using Microsoft.WindowsAzure.Storage; +using Microsoft.WindowsAzure.Storage.Blob; using Newtonsoft.Json; [assembly: InternalsVisibleTo("Microsoft.Bot.Builder.Azure.Tests")] diff --git a/libraries/Microsoft.Bot.Builder.Azure/Microsoft.Bot.Builder.Azure.csproj b/libraries/Microsoft.Bot.Builder.Azure/Microsoft.Bot.Builder.Azure.csproj index 2d8f0ad83f..f14d277b8b 100644 --- a/libraries/Microsoft.Bot.Builder.Azure/Microsoft.Bot.Builder.Azure.csproj +++ b/libraries/Microsoft.Bot.Builder.Azure/Microsoft.Bot.Builder.Azure.csproj @@ -38,7 +38,7 @@ - + diff --git a/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobStorageTests.cs b/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobStorageTests.cs index 389faf130c..c489b987fb 100644 --- a/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobStorageTests.cs +++ b/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobStorageTests.cs @@ -4,10 +4,8 @@ using System; using System.Reflection; using System.Threading.Tasks; -using Microsoft.Azure.Storage; -using Microsoft.Azure.Storage.Auth; -using Microsoft.Azure.Storage.Blob; -using Microsoft.Azure.Storage.Core; +using Microsoft.WindowsAzure.Storage; +using Microsoft.WindowsAzure.Storage.Blob; using Newtonsoft.Json; using Xunit; using Xunit.Abstractions; From 48a653cf39d7edf5eab5240288677fadaca9a67e Mon Sep 17 00:00:00 2001 From: sw-joelmut Date: Fri, 29 Apr 2022 14:35:38 -0300 Subject: [PATCH 7/8] Fix and improve unit tests --- .../AzureBlobTranscriptStoreTests.cs | 250 +++++------------- 1 file changed, 69 insertions(+), 181 deletions(-) diff --git a/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobTranscriptStoreTests.cs b/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobTranscriptStoreTests.cs index 7b6e0b667b..a40b6d05f1 100644 --- a/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobTranscriptStoreTests.cs +++ b/tests/Microsoft.Bot.Builder.Azure.Tests/AzureBlobTranscriptStoreTests.cs @@ -5,11 +5,12 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Threading; using System.Threading.Tasks; -using Microsoft.Azure.Storage; -using Microsoft.Azure.Storage.Auth; -using Microsoft.Azure.Storage.Blob; using Microsoft.Bot.Schema; +using Microsoft.WindowsAzure.Storage; +using Microsoft.WindowsAzure.Storage.Auth; +using Microsoft.WindowsAzure.Storage.Blob; using Moq; using Newtonsoft.Json; using Xunit; @@ -30,7 +31,6 @@ public class AzureBlobTranscriptStoreTests private Mock _mockAccount; private AzureBlobTranscriptStore _blobTranscript; private BlobResultSegment _segment; - private Mock _mockDirectory; private readonly Activity _activity = new Activity { @@ -92,23 +92,15 @@ public async Task LogActivityAsyncMessageUpdate() InitStorage(); - _mockBlockBlob.Setup(x => x.DownloadTextAsync()).Returns(Task.FromResult(JsonConvert.SerializeObject(_activity))); + _mockBlockBlob.Setup(x => x.DownloadTextAsync()).ReturnsAsync(JsonConvert.SerializeObject(_activity)); await _blobTranscript.LogActivityAsync(_activity); - _mockBlobClient.Verify(x => x.GetContainerReference(It.IsAny()), Times.Once); - _mockContainer.Verify(x => x.GetDirectoryReference(It.IsAny()), Times.Once); + BaseVerification(); + _mockBlockBlob.Verify(x => x.DownloadTextAsync(), Times.Exactly(2)); _mockBlockBlob.Verify(x => x.OpenWriteAsync(), Times.Once); _mockBlockBlob.Verify(x => x.SetMetadataAsync(), Times.Exactly(2)); - _mockDirectory.Verify( - x => x.ListBlobsSegmentedAsync( - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny()), Times.Once); } [Fact] @@ -120,31 +112,25 @@ public async Task LogActivityAsyncMessageUpdateNullBlob() var segment = new BlobResultSegment(new List(), null); - _mockDirectory.Setup(x => x.ListBlobsSegmentedAsync( - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny())).Returns(Task.FromResult(segment)); - - _mockContainer.Setup(x => x.GetDirectoryReference(It.IsAny())).Returns(_mockDirectory.Object); + _mockContainer.Setup( + x => x.ListBlobsSegmentedAsync( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .ReturnsAsync(segment); await _blobTranscript.LogActivityAsync(_activity); - _mockBlobClient.Verify(x => x.GetContainerReference(It.IsAny()), Times.Once); - _mockContainer.Verify(x => x.GetDirectoryReference(It.IsAny()), Times.Once); + BaseVerification(); + _mockContainer.Verify(x => x.GetBlockBlobReference(It.IsAny()), Times.Once); _mockBlockBlob.Verify(x => x.OpenWriteAsync(), Times.Once); _mockBlockBlob.Verify(x => x.SetMetadataAsync(), Times.Once); - _mockDirectory.Verify( - x => x.ListBlobsSegmentedAsync( - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny()), Times.Once); } [Fact] @@ -154,23 +140,15 @@ public async Task LogActivityAsyncMessageDelete() InitStorage(); - _mockBlockBlob.Setup(x => x.DownloadTextAsync()).Returns(Task.FromResult(JsonConvert.SerializeObject(_activity))); + _mockBlockBlob.Setup(x => x.DownloadTextAsync()).ReturnsAsync(JsonConvert.SerializeObject(_activity)); await _blobTranscript.LogActivityAsync(_activity); - _mockBlobClient.Verify(x => x.GetContainerReference(It.IsAny()), Times.Once); - _mockContainer.Verify(x => x.GetDirectoryReference(It.IsAny()), Times.Once); + BaseVerification(); + _mockBlockBlob.Verify(x => x.DownloadTextAsync(), Times.Exactly(2)); _mockBlockBlob.Verify(x => x.OpenWriteAsync(), Times.Once); _mockBlockBlob.Verify(x => x.SetMetadataAsync(), Times.Exactly(2)); - _mockDirectory.Verify( - x => x.ListBlobsSegmentedAsync( - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny()), Times.Once); } [Fact] @@ -181,23 +159,13 @@ public async Task LogActivityAsyncInternalFindActivityBlobAsync() InitStorage(); _mockBlockBlob.Object.Metadata["Id"] = "test-id"; - _mockBlockBlob.Setup(x => x.DownloadTextAsync()).Returns(Task.FromResult(JsonConvert.SerializeObject(_activity))); + _mockBlockBlob.Setup(x => x.DownloadTextAsync()).ReturnsAsync(JsonConvert.SerializeObject(_activity)); await _blobTranscript.LogActivityAsync(_activity); - _mockBlobClient.Verify(x => x.GetContainerReference(It.IsAny()), Times.Once); - _mockContainer.Verify(x => x.GetDirectoryReference(It.IsAny()), Times.Once); + BaseVerification(); _mockBlockBlob.Verify(x => x.OpenWriteAsync(), Times.Once); - - _mockDirectory.Verify( - x => x.ListBlobsSegmentedAsync( - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny()), Times.Once); } [Fact] @@ -218,26 +186,9 @@ public async Task GetTranscriptActivitiesAsync() { InitStorage(); - _mockDirectory.Setup(x => x.ListBlobsSegmentedAsync( - It.IsAny(), - It.IsAny(), - null, - It.IsAny(), - It.IsAny(), - It.IsAny())).Returns(Task.FromResult(_segment)); - await _blobTranscript.GetTranscriptActivitiesAsync("channelId", "conversationId"); - _mockBlobClient.Verify(x => x.GetContainerReference(It.IsAny()), Times.Once); - _mockContainer.Verify(x => x.GetDirectoryReference(It.IsAny()), Times.Once); - _mockDirectory.Verify( - x => x.ListBlobsSegmentedAsync( - It.IsAny(), - It.IsAny(), - null, - It.IsAny(), - It.IsAny(), - It.IsAny()), Times.Once); + BaseVerification(); } [Fact] @@ -247,28 +198,9 @@ public async Task GetTranscriptActivitiesAsyncWithMetadata() _mockBlockBlob.Object.Metadata["Timestamp"] = DateTime.Now.ToString(CultureInfo.InvariantCulture); - _mockDirectory.Setup(x => x.ListBlobsSegmentedAsync( - It.IsAny(), - It.IsAny(), - null, - It.IsAny(), - It.IsAny(), - It.IsAny())).Returns(Task.FromResult(_segment)); - await _blobTranscript.GetTranscriptActivitiesAsync("channelId", "conversationId"); - _mockBlobClient.Verify(x => x.GetContainerReference(It.IsAny()), Times.Once); - _mockContainer.Verify(x => x.GetDirectoryReference(It.IsAny()), Times.Once); - _mockDirectory.Verify( - x => x.ListBlobsSegmentedAsync( - It.IsAny(), - It.IsAny(), - null, - It.IsAny(), - It.IsAny(), - It.IsAny()), Times.Once); - - _mockBlobClient.Verify(x => x.GetContainerReference(It.IsAny()), Times.Once); + BaseVerification(); } [Fact] @@ -279,28 +211,9 @@ public async Task GetTranscriptActivitiesAsyncContinuationToken() _mockBlockBlob.Object.Metadata["Timestamp"] = DateTime.Now.ToString(CultureInfo.InvariantCulture); _mockBlockBlob.SetupGet(x => x.Name).Returns("token-name"); - _mockDirectory.Setup(x => x.ListBlobsSegmentedAsync( - It.IsAny(), - It.IsAny(), - null, - It.IsAny(), - It.IsAny(), - It.IsAny())).Returns(Task.FromResult(_segment)); - await _blobTranscript.GetTranscriptActivitiesAsync("channelId", "conversationId", "token-name"); - _mockBlobClient.Verify(x => x.GetContainerReference(It.IsAny()), Times.Once); - _mockContainer.Verify(x => x.GetDirectoryReference(It.IsAny()), Times.Once); - _mockDirectory.Verify( - x => x.ListBlobsSegmentedAsync( - It.IsAny(), - It.IsAny(), - null, - It.IsAny(), - It.IsAny(), - It.IsAny()), Times.Once); - - _mockBlobClient.Verify(x => x.GetContainerReference(It.IsAny()), Times.Once); + BaseVerification(); } [Fact] @@ -309,34 +222,27 @@ public async Task GetTranscriptActivitiesAsyncMultipleBlobs() InitStorage(); var jsonString = JsonConvert.SerializeObject(new Activity()); - _mockBlockBlob.Setup(x => x.DownloadTextAsync()).Returns(Task.FromResult(jsonString)); + _mockBlockBlob.Setup(x => x.DownloadTextAsync()).ReturnsAsync(jsonString); _mockBlockBlob.Object.Metadata["Timestamp"] = DateTime.Now.ToString(CultureInfo.InvariantCulture); _mockBlockBlob.SetupGet(x => x.Name).Returns("token-name"); var segment = new BlobResultSegment(CreateSegment(21, _mockBlockBlob.Object).ToList(), null); - _mockDirectory.Setup(x => x.ListBlobsSegmentedAsync( - It.IsAny(), - It.IsAny(), - null, - It.IsAny(), - It.IsAny(), - It.IsAny())).Returns(Task.FromResult(segment)); - - await _blobTranscript.GetTranscriptActivitiesAsync("channelId", "conversationId", "token-name"); - - _mockBlobClient.Verify(x => x.GetContainerReference(It.IsAny()), Times.Once); - _mockContainer.Verify(x => x.GetDirectoryReference(It.IsAny()), Times.Once); - _mockDirectory.Verify( + _mockContainer.Setup( x => x.ListBlobsSegmentedAsync( + It.IsAny(), It.IsAny(), It.IsAny(), - null, + It.IsAny(), It.IsAny(), It.IsAny(), - It.IsAny()), Times.Once); + It.IsAny(), + It.IsAny())) + .ReturnsAsync(segment); - _mockBlobClient.Verify(x => x.GetContainerReference(It.IsAny()), Times.Once); + await _blobTranscript.GetTranscriptActivitiesAsync("channelId", "conversationId", "token-name"); + + BaseVerification(); } [Fact] @@ -354,28 +260,9 @@ public async Task ListTranscriptAsync() { InitStorage(); - _mockDirectory.Setup(x => x.ListBlobsSegmentedAsync( - It.IsAny(), - It.IsAny(), - null, - It.IsAny(), - It.IsAny(), - It.IsAny())).Returns(Task.FromResult(_segment)); - - _mockContainer.Setup(x => x.GetDirectoryReference(It.IsAny())).Returns(_mockDirectory.Object); - await _blobTranscript.ListTranscriptsAsync("channelId", null); - _mockBlobClient.Verify(x => x.GetContainerReference(It.IsAny()), Times.Once); - _mockContainer.Verify(x => x.GetDirectoryReference(It.IsAny()), Times.Once); - _mockDirectory.Verify( - x => x.ListBlobsSegmentedAsync( - It.IsAny(), - It.IsAny(), - null, - It.IsAny(), - It.IsAny(), - It.IsAny()), Times.Once); + BaseVerification(); } [Fact] @@ -396,32 +283,33 @@ public async Task DeleteTranscriptAsync() { InitStorage(); - _mockDirectory.Setup(x => x.ListBlobsSegmentedAsync( - It.IsAny(), - It.IsAny(), - null, - It.IsAny(), - It.IsAny(), - It.IsAny())).Returns(Task.FromResult(_segment)); - await _blobTranscript.DeleteTranscriptAsync("channelId", "convo-id"); + BaseVerification(); + + _mockBlockBlob.Verify(x => x.DeleteIfExistsAsync(), Times.Once); + } + + private static IEnumerable CreateSegment(int count, CloudBlockBlob blob) + { + return Enumerable.Range(0, count).Select(x => blob); + } + + private void BaseVerification() + { _mockBlobClient.Verify(x => x.GetContainerReference(It.IsAny()), Times.Once); _mockContainer.Verify(x => x.GetDirectoryReference(It.IsAny()), Times.Once); - _mockDirectory.Verify( + _mockContainer.Verify( x => x.ListBlobsSegmentedAsync( + It.IsAny(), It.IsAny(), It.IsAny(), - null, + It.IsAny(), It.IsAny(), It.IsAny(), - It.IsAny()), Times.Once); - _mockBlockBlob.Verify(x => x.DeleteIfExistsAsync(), Times.Once); - } - - private static IEnumerable CreateSegment(int count, CloudBlockBlob blob) - { - return Enumerable.Range(0, count).Select(x => blob); + It.IsAny(), + It.IsAny()), + Times.Once); } private void InitStorage() @@ -432,26 +320,26 @@ private void InitStorage() _stream.SetupGet(x => x.CanWrite).Returns(true); _mockBlockBlob = new Mock(new Uri("http://test/myaccount/blob")); - _mockBlockBlob.Setup(x => x.OpenWriteAsync()).Returns(Task.FromResult(_stream.Object)); + _mockBlockBlob.Setup(x => x.OpenWriteAsync()).ReturnsAsync(_stream.Object); _mockBlockBlob.Setup(x => x.SetMetadataAsync()); - _mockBlockBlob.Setup(x => x.DownloadTextAsync()).Returns(Task.FromResult(JsonConvert.SerializeObject(_activity))); - _mockBlockBlob.Setup(x => x.DownloadTextAsync()).Returns(Task.FromResult(jsonString)); + _mockBlockBlob.Setup(x => x.DownloadTextAsync()).ReturnsAsync(JsonConvert.SerializeObject(_activity)); + _mockBlockBlob.Setup(x => x.DownloadTextAsync()).ReturnsAsync(jsonString); _segment = new BlobResultSegment(new List { _mockBlockBlob.Object }, null); - _mockDirectory = new Mock(); - _mockDirectory.Setup(x => x.ListBlobsSegmentedAsync( + _mockContainer = new Mock(new Uri("https://testuri.com")); + _mockContainer.Setup(x => x.GetBlockBlobReference(It.IsAny())).Returns(_mockBlockBlob.Object); + _mockContainer.Setup(x => x.CreateIfNotExistsAsync()); + _mockContainer.Setup(x => x.GetDirectoryReference(It.IsAny())).CallBase(); + _mockContainer.Setup(x => x.ListBlobsSegmentedAsync( + It.IsAny(), It.IsAny(), It.IsAny(), - It.IsAny(), + It.IsAny(), It.IsAny(), It.IsAny(), - It.IsAny())).Returns(Task.FromResult(_segment)); - - _mockContainer = new Mock(new Uri("https://testuri.com")); - _mockContainer.Setup(x => x.GetBlockBlobReference(It.IsAny())).Returns(_mockBlockBlob.Object); - _mockContainer.Setup(x => x.CreateIfNotExistsAsync()); - _mockContainer.Setup(x => x.GetDirectoryReference(It.IsAny())).Returns(_mockDirectory.Object); + It.IsAny(), + It.IsAny())).ReturnsAsync(_segment); _mockBlobClient = new Mock(new Uri("https://testuri.com"), null); _mockBlobClient.Setup(x => x.GetContainerReference(It.IsAny())).Returns(_mockContainer.Object); From dfbf5bbb5bd5813973f5443503218e65d2db3fc6 Mon Sep 17 00:00:00 2001 From: CeciliaAvila Date: Tue, 17 May 2022 15:14:35 -0300 Subject: [PATCH 8/8] Add AssemblyInfo to BotBuilder.Azure --- libraries/Microsoft.Bot.Builder.Azure/AssemblyInfo.cs | 11 +++++++++++ .../AzureBlobTranscriptStore.cs | 3 --- 2 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 libraries/Microsoft.Bot.Builder.Azure/AssemblyInfo.cs diff --git a/libraries/Microsoft.Bot.Builder.Azure/AssemblyInfo.cs b/libraries/Microsoft.Bot.Builder.Azure/AssemblyInfo.cs new file mode 100644 index 0000000000..8634e2460a --- /dev/null +++ b/libraries/Microsoft.Bot.Builder.Azure/AssemblyInfo.cs @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Runtime.CompilerServices; + +// Allows us to access some internal methods from the Microsoft.Bot.Builder.Azure.Tests unit tests so we don't have to use reflection and we get compile checks. +#if SIGNASSEMBLY +[assembly: InternalsVisibleTo("Microsoft.Bot.Builder.Azure.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] +#else +[assembly: InternalsVisibleTo("Microsoft.Bot.Builder.Azure.Tests")] +#endif diff --git a/libraries/Microsoft.Bot.Builder.Azure/AzureBlobTranscriptStore.cs b/libraries/Microsoft.Bot.Builder.Azure/AzureBlobTranscriptStore.cs index f8d95fe43b..24ebff2060 100644 --- a/libraries/Microsoft.Bot.Builder.Azure/AzureBlobTranscriptStore.cs +++ b/libraries/Microsoft.Bot.Builder.Azure/AzureBlobTranscriptStore.cs @@ -5,15 +5,12 @@ using System.Globalization; using System.IO; using System.Linq; -using System.Runtime.CompilerServices; using System.Threading.Tasks; using Microsoft.Bot.Schema; using Microsoft.WindowsAzure.Storage; using Microsoft.WindowsAzure.Storage.Blob; using Newtonsoft.Json; -[assembly: InternalsVisibleTo("Microsoft.Bot.Builder.Azure.Tests")] - namespace Microsoft.Bot.Builder.Azure { ///