diff --git a/docs/preview/03-Features/04-Azure/04-Storage/01-storage-account.mdx b/docs/preview/03-Features/04-Azure/04-Storage/01-storage-account.mdx index 6df69635..0c8b0ded 100644 --- a/docs/preview/03-Features/04-Azure/04-Storage/01-storage-account.mdx +++ b/docs/preview/03-Features/04-Azure/04-Storage/01-storage-account.mdx @@ -255,7 +255,7 @@ using Azure.Storage.Files.Shares; var shareClient = new ShareClient(...); await using var directory = await TemporaryShareDirectory.CreateIfNotExistsAsync( - shareClient, " - \ No newline at end of file + diff --git a/src/Arcus.Testing.Storage.File.Share/Arcus.Testing.Storage.File.Share.csproj b/src/Arcus.Testing.Storage.File.Share/Arcus.Testing.Storage.File.Share.csproj index ca21823d..8fbe7c0d 100644 --- a/src/Arcus.Testing.Storage.File.Share/Arcus.Testing.Storage.File.Share.csproj +++ b/src/Arcus.Testing.Storage.File.Share/Arcus.Testing.Storage.File.Share.csproj @@ -22,6 +22,10 @@ All + + + + diff --git a/src/Arcus.Testing.Storage.File.Share/TemporaryShareDirectory.cs b/src/Arcus.Testing.Storage.File.Share/TemporaryShareDirectory.cs index 048a7623..b8ce4a57 100644 --- a/src/Arcus.Testing.Storage.File.Share/TemporaryShareDirectory.cs +++ b/src/Arcus.Testing.Storage.File.Share/TemporaryShareDirectory.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; +using System.Threading; using System.Threading.Tasks; using Azure; using Azure.Storage.Files.Shares; @@ -83,7 +84,7 @@ public class OnTeardownTemporaryShareDirectoryOptions /// /// (default) Configures the to clean only the items (both files and directories) in the directory share - /// that the test fixture was responsible for upserting (via ), upon the deletion of the fixture. + /// that the test fixture was responsible for upserting (via ), upon the deletion of the fixture. /// public OnTeardownTemporaryShareDirectoryOptions CleanUpsertedItems() { @@ -207,6 +208,7 @@ public OnTeardownTemporaryShareDirectoryOptions OnTeardown /// The logger instance to write diagnostic traces during the lifetime of the fixture. /// Thrown when the is null. /// Thrown when the is blank. + [Obsolete("Will be removed in v3, please use the " + nameof(CreateIfNotExistsAsync) + " overload instead that provides cancellation token support", DiagnosticId = ObsoleteDefaults.DiagnosticId)] public static Task CreateIfNotExistsAsync(ShareClient shareClient, string directoryName, ILogger logger) { return CreateIfNotExistsAsync(shareClient, directoryName, logger, configureOptions: null); @@ -221,6 +223,7 @@ public static Task CreateIfNotExistsAsync(ShareClient s /// The additional options to manipulate the behavior of the test fixture during its lifetime. /// Thrown when the is null. /// Thrown when the is blank. + [Obsolete("Will be removed in v3, please use the " + nameof(CreateIfNotExistsAsync) + " overload instead that provides cancellation token support", DiagnosticId = ObsoleteDefaults.DiagnosticId)] public static Task CreateIfNotExistsAsync( ShareClient shareClient, string directoryName, @@ -240,6 +243,7 @@ public static Task CreateIfNotExistsAsync( /// The client to interact with the directory share in the Azure Files share resource. /// The logger instance to write diagnostic traces during the lifetime of the fixture. /// Thrown when the is null. + [Obsolete("Will be removed in v3, please use the " + nameof(CreateIfNotExistsAsync) + " overload instead that provides cancellation token support", DiagnosticId = ObsoleteDefaults.DiagnosticId)] public static Task CreateIfNotExistsAsync(ShareDirectoryClient directoryClient, ILogger logger) { return CreateIfNotExistsAsync(directoryClient, logger, configureOptions: null); @@ -252,21 +256,57 @@ public static Task CreateIfNotExistsAsync(ShareDirector /// The logger instance to write diagnostic traces during the lifetime of the fixture. /// The additional options to manipulate the behavior of the test fixture during its lifetime. /// Thrown when the is null. - public static async Task CreateIfNotExistsAsync( + [Obsolete("Will be removed in v3, please use the " + nameof(CreateIfNotExistsAsync) + " overload instead that provides cancellation token support", DiagnosticId = ObsoleteDefaults.DiagnosticId)] + public static Task CreateIfNotExistsAsync( ShareDirectoryClient directoryClient, ILogger logger, Action configureOptions) + { + return CreateIfNotExistsAsync(directoryClient, logger, configureOptions, CancellationToken.None); + } + + /// + /// Creates a temporary directory share on an Azure Files share resource. + /// + /// The client to interact with the directory share in the Azure Files share resource. + /// The logger instance to write diagnostic traces during the lifetime of the fixture. + /// The optional token to propagate notifications that the operation should be cancelled. + /// Thrown when the is null. + /// Thrown when the interaction with Azure failed. + public static Task CreateIfNotExistsAsync( + ShareDirectoryClient directoryClient, + ILogger logger, + CancellationToken cancellationToken) + { + return CreateIfNotExistsAsync(directoryClient, logger, configureOptions: null, cancellationToken); + } + + /// + /// Creates a temporary directory share on an Azure Files share resource. + /// + /// The client to interact with the directory share in the Azure Files share resource. + /// The logger instance to write diagnostic traces during the lifetime of the fixture. + /// The additional options to manipulate the behavior of the test fixture during its lifetime. + /// The optional token to propagate notifications that the operation should be cancelled. + /// Thrown when the is null. + /// Thrown when the interaction with Azure failed. + public static async Task CreateIfNotExistsAsync( + ShareDirectoryClient directoryClient, + ILogger logger, + Action configureOptions, + CancellationToken cancellationToken) { ArgumentNullException.ThrowIfNull(directoryClient); + cancellationToken.ThrowIfCancellationRequested(); logger ??= NullLogger.Instance; var options = new TemporaryShareDirectoryOptions(); configureOptions?.Invoke(options); - if (await directoryClient.ExistsAsync().ConfigureAwait(false)) + if (await directoryClient.ExistsAsync(cancellationToken: cancellationToken).ConfigureAwait(false)) { logger.LogSetupUseExistingDirectory(directoryClient.Name, directoryClient.AccountName, directoryClient.Path); - await CleanDirectoryOnSetupAsync(directoryClient, options, logger).ConfigureAwait(false); + await CleanDirectoryOnSetupAsync(directoryClient, options, logger, cancellationToken).ConfigureAwait(false); return new TemporaryShareDirectory(directoryClient, createdByUs: false, options, logger); } @@ -274,7 +314,7 @@ public static async Task CreateIfNotExistsAsync( try { logger.LogSetupCreateNewDirectory(directoryClient.Name, directoryClient.AccountName, directoryClient.Path); - await directoryClient.CreateAsync().ConfigureAwait(false); + await directoryClient.CreateAsync(cancellationToken: cancellationToken).ConfigureAwait(false); } catch (RequestFailedException exception) when (exception.ErrorCode == ShareErrorCode.ShareNotFound) { @@ -288,8 +328,13 @@ public static async Task CreateIfNotExistsAsync( return new TemporaryShareDirectory(directoryClient, createdByUs: true, options, logger); } - private static async Task CleanDirectoryOnSetupAsync(ShareDirectoryClient directoryClient, TemporaryShareDirectoryOptions options, ILogger logger) + private static async Task CleanDirectoryOnSetupAsync( + ShareDirectoryClient directoryClient, + TemporaryShareDirectoryOptions options, + ILogger logger, + CancellationToken cancellationToken) { + cancellationToken.ThrowIfCancellationRequested(); if (options.OnSetup.Items is OnSetupDirectoryShare.LeaveExisted) { return; @@ -297,11 +342,11 @@ private static async Task CleanDirectoryOnSetupAsync(ShareDirectoryClient direct if (options.OnSetup.Items is OnSetupDirectoryShare.CleanIfExisted) { - await DeleteAllDirectoryContentsAsync(directoryClient, TestFixture.Setup, logger).ConfigureAwait(false); + await DeleteAllDirectoryContentsAsync(directoryClient, TestFixture.Setup, logger, cancellationToken).ConfigureAwait(false); } else if (options.OnSetup.Items is OnSetupDirectoryShare.CleanIfMatched) { - await DeleteDirectoryContentsAsync(directoryClient, options.OnSetup.IsMatch, TestFixture.Setup, logger).ConfigureAwait(false); + await DeleteDirectoryContentsAsync(directoryClient, options.OnSetup.IsMatch, TestFixture.Setup, logger, cancellationToken).ConfigureAwait(false); } } @@ -316,10 +361,32 @@ private static async Task CleanDirectoryOnSetupAsync(ShareDirectoryClient direct /// Thrown when the test fixture was already teared down. /// Thrown when the is blank. /// Thrown when the is null. - public async Task UpsertFileAsync(string fileName, Stream fileContents) + [Obsolete("Will be removed in v3, please use the " + nameof(UpsertFileAsync) + " overload instead that provides cancellation token support", DiagnosticId = ObsoleteDefaults.DiagnosticId)] + public Task UpsertFileAsync(string fileName, Stream fileContents) + { + return UpsertFileAsync(fileName, fileContents, CancellationToken.None); + } + + /// + /// Creates a new or replaces an existing file in this directory share (a.k.a. UPSERT). + /// + /// + /// Any files uploaded via this call will always be deleted (if new) or reverted (if existing) when this instance is disposed. + /// + /// The name of the file to upload to the share directory. + /// The contents of the file to upload to the share directory. + /// The optional token to propagate notifications that the operation should be cancelled. + /// Thrown when the test fixture was already teared down. + /// Thrown when the is blank. + /// Thrown when the is null. + /// Thrown when the interaction with Azure failed. + public async Task UpsertFileAsync(string fileName, Stream fileContents, CancellationToken cancellationToken) { ObjectDisposedException.ThrowIf(_disposables.IsDisposed, this); - _files.Add(await TemporaryShareFile.UpsertFileAsync(Client, fileName, fileContents, _logger).ConfigureAwait(false)); + cancellationToken.ThrowIfCancellationRequested(); + + ShareFileClient fileClient = Client.GetFileClient(fileName); + _files.Add(await TemporaryShareFile.UpsertFileAsync(fileClient, fileContents, _logger, cancellationToken).ConfigureAwait(false)); } /// @@ -339,7 +406,7 @@ public async ValueTask DisposeAsync() if (_createdByUs) { - await DeleteAllDirectoryContentsAsync(_client, TestFixture.Teardown, _logger).ConfigureAwait(false); + await DeleteAllDirectoryContentsAsync(_client, TestFixture.Teardown, _logger, CancellationToken.None).ConfigureAwait(false); _disposables.Add(AsyncDisposable.Create(async () => { @@ -365,7 +432,7 @@ private async Task CleanDirectoryOnTeardownAsync() if (_options.OnTeardown.Items is OnTeardownDirectoryShare.CleanAll) { - await DeleteAllDirectoryContentsAsync(_client, TestFixture.Teardown, _logger).ConfigureAwait(false); + await DeleteAllDirectoryContentsAsync(_client, TestFixture.Teardown, _logger, CancellationToken.None).ConfigureAwait(false); } else if (_options.OnTeardown.Items is OnTeardownDirectoryShare.CleanIfMatched) { @@ -379,25 +446,27 @@ private static async Task DeleteDirectoryContentsAsync( ShareDirectoryClient current, Func shouldDeleteItem, TestFixture state, - ILogger logger) + ILogger logger, + CancellationToken cancellationToken = default) { - await current.ForceCloseAllHandlesAsync(recursive: true).ConfigureAwait(false); + cancellationToken.ThrowIfCancellationRequested(); + await current.ForceCloseAllHandlesAsync(recursive: true, cancellationToken: cancellationToken).ConfigureAwait(false); - await foreach (ShareFileItem item in current.GetFilesAndDirectoriesAsync().ConfigureAwait(false)) + await foreach (ShareFileItem item in current.GetFilesAndDirectoriesAsync(cancellationToken: cancellationToken).ConfigureAwait(false)) { if (item.IsDirectory) { ShareDirectoryClient sub = current.GetSubdirectoryClient(item.Name); if (shouldDeleteItem(item)) { - await DeleteAllDirectoryContentsAsync(sub, state, logger).ConfigureAwait(false); + await DeleteAllDirectoryContentsAsync(sub, state, logger, cancellationToken).ConfigureAwait(false); LogDeleteDirectory(logger, state, sub.Name, sub.AccountName, sub.Path); - await sub.DeleteIfExistsAsync().ConfigureAwait(false); + await sub.DeleteIfExistsAsync(cancellationToken: cancellationToken).ConfigureAwait(false); } else { - await DeleteDirectoryContentsAsync(sub, shouldDeleteItem, state, logger).ConfigureAwait(false); + await DeleteDirectoryContentsAsync(sub, shouldDeleteItem, state, logger, cancellationToken).ConfigureAwait(false); } } else if (shouldDeleteItem(item)) @@ -405,7 +474,7 @@ private static async Task DeleteDirectoryContentsAsync( ShareFileClient file = current.GetFileClient(item.Name); LogDeleteFile(logger, state, file.Name, file.AccountName, file.Path); - await file.DeleteIfExistsAsync().ConfigureAwait(false); + await file.DeleteIfExistsAsync(cancellationToken: cancellationToken).ConfigureAwait(false); } } } @@ -438,9 +507,10 @@ private static void LogDeleteFile(ILogger logger, TestFixture state, string file } } - private static async Task DeleteAllDirectoryContentsAsync(ShareDirectoryClient current, TestFixture state, ILogger logger) + private static async Task DeleteAllDirectoryContentsAsync(ShareDirectoryClient current, TestFixture state, ILogger logger, CancellationToken cancellationToken) { - await DeleteDirectoryContentsAsync(current, shouldDeleteItem: _ => true, state, logger).ConfigureAwait(false); + cancellationToken.ThrowIfCancellationRequested(); + await DeleteDirectoryContentsAsync(current, shouldDeleteItem: _ => true, state: state, logger: logger, cancellationToken).ConfigureAwait(false); } } diff --git a/src/Arcus.Testing.Storage.File.Share/TemporaryShareFile.cs b/src/Arcus.Testing.Storage.File.Share/TemporaryShareFile.cs index f84b7784..202ca3c3 100644 --- a/src/Arcus.Testing.Storage.File.Share/TemporaryShareFile.cs +++ b/src/Arcus.Testing.Storage.File.Share/TemporaryShareFile.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Threading; using System.Threading.Tasks; using Azure; using Azure.Storage.Files.Shares; @@ -59,13 +60,30 @@ public ShareFileClient Client /// The instance to log diagnostic traces during the lifetime of the fixture. /// Thrown when the or the is null. /// Thrown when the is blank. + [Obsolete("Will be removed in v3, please use the " + nameof(UpsertFileAsync) + " overload instead that provides cancellation token support", DiagnosticId = ObsoleteDefaults.DiagnosticId)] public static Task UpsertFileAsync(ShareDirectoryClient directoryClient, string fileName, Stream fileContents, ILogger logger) { ArgumentNullException.ThrowIfNull(directoryClient); - ArgumentException.ThrowIfNullOrWhiteSpace(fileName); - ShareFileClient fileClient = directoryClient.GetFileClient(fileName); - return UpsertFileAsync(fileClient, fileContents, logger); + + return UpsertFileAsync(fileClient, fileContents, logger, CancellationToken.None); + } + + /// + /// Creates a new or replaces an existing file on an Azure Files share directory. + /// + /// + /// Make sure that the 's is accessible, + /// so the appropriate size can be set on the file share. + /// + /// The client to interact with the share file to upload to file to. + /// The contents of the file to upload to the share directory. + /// The instance to log diagnostic traces during the lifetime of the fixture. + /// Thrown when the or the is null. + [Obsolete("Will be removed in v3, please use the " + nameof(UpsertFileAsync) + " overload instead that provides cancellation token support", DiagnosticId = ObsoleteDefaults.DiagnosticId)] + public static Task UpsertFileAsync(ShareFileClient fileClient, Stream fileStream, ILogger logger) + { + return UpsertFileAsync(fileClient, fileStream, logger, CancellationToken.None); } /// @@ -78,20 +96,29 @@ public static Task UpsertFileAsync(ShareDirectoryClient dire /// The client to interact with the share file to upload to file to. /// The contents of the file to upload to the share directory. /// The instance to log diagnostic traces during the lifetime of the fixture. + /// The optional token to propagate notifications that the operation should be cancelled. /// Thrown when the or the is null. - public static async Task UpsertFileAsync(ShareFileClient fileClient, Stream fileStream, ILogger logger) + /// Thrown when the interaction with Azure failed. + /// Thrown when the refers to a non-existing Azure Files share directory. + /// Thrown when the refers to a non-existing Azure Files share. + public static async Task UpsertFileAsync( + ShareFileClient fileClient, + Stream fileStream, + ILogger logger, + CancellationToken cancellationToken) { ArgumentNullException.ThrowIfNull(fileClient); ArgumentNullException.ThrowIfNull(fileStream); + cancellationToken.ThrowIfCancellationRequested(); logger ??= NullLogger.Instance; - if (await fileClient.ExistsAsync().ConfigureAwait(false)) + if (await fileClient.ExistsAsync(cancellationToken).ConfigureAwait(false)) { logger.LogSetupReplaceExistingFile(fileClient.Name, fileClient.AccountName, fileClient.Path); - ShareFileDownloadInfo result = await fileClient.DownloadAsync().ConfigureAwait(false); - await fileClient.CreateAsync(fileStream.Length).ConfigureAwait(false); - await fileClient.UploadAsync(fileStream).ConfigureAwait(false); + ShareFileDownloadInfo result = await fileClient.DownloadAsync(cancellationToken: cancellationToken).ConfigureAwait(false); + await fileClient.CreateAsync(fileStream.Length, cancellationToken: cancellationToken).ConfigureAwait(false); + await fileClient.UploadAsync(fileStream, cancellationToken: cancellationToken).ConfigureAwait(false); return new TemporaryShareFile(fileClient, (result.Content, result.ContentLength), logger); } @@ -100,8 +127,8 @@ public static async Task UpsertFileAsync(ShareFileClient fil { logger.LogSetupUploadNewFile(fileClient.Name, fileClient.AccountName, fileClient.Path); - await fileClient.CreateAsync(fileStream.Length).ConfigureAwait(false); - await fileClient.UploadAsync(fileStream).ConfigureAwait(false); + await fileClient.CreateAsync(fileStream.Length, cancellationToken: cancellationToken).ConfigureAwait(false); + await fileClient.UploadAsync(fileStream, cancellationToken: cancellationToken).ConfigureAwait(false); } catch (RequestFailedException exception) when (exception.ErrorCode == ShareErrorCode.ShareNotFound) { diff --git a/src/Arcus.Testing.Tests.Integration/Storage/TemporaryShareDirectoryTests.cs b/src/Arcus.Testing.Tests.Integration/Storage/TemporaryShareDirectoryTests.cs index ec2a2213..e77dd974 100644 --- a/src/Arcus.Testing.Tests.Integration/Storage/TemporaryShareDirectoryTests.cs +++ b/src/Arcus.Testing.Tests.Integration/Storage/TemporaryShareDirectoryTests.cs @@ -1,11 +1,11 @@ using System; using System.IO; using System.Text; +using System.Threading; using System.Threading.Tasks; using Arcus.Testing.Tests.Integration.Storage.Configuration; using Azure.Storage.Files.Shares; using Azure.Storage.Files.Shares.Models; -using Azure.Storage.Files.Shares.Specialized; using Bogus; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; @@ -197,20 +197,9 @@ await Assert.ThrowsAsync( private async Task WhenTempDirCreatedAsync(DirClient dir, Action configureOptions = null) { - TemporaryShareDirectory temp; - if (Bogus.Random.Bool()) - { - ShareClient shareClient = dir.GetParentShareClient(); - temp = configureOptions is null - ? await TemporaryShareDirectory.CreateIfNotExistsAsync(shareClient, dir.Name, Logger) - : await TemporaryShareDirectory.CreateIfNotExistsAsync(shareClient, dir.Name, Logger, configureOptions); - } - else - { - temp = configureOptions is null - ? await TemporaryShareDirectory.CreateIfNotExistsAsync(dir, Logger) - : await TemporaryShareDirectory.CreateIfNotExistsAsync(dir, Logger, configureOptions); - } + TemporaryShareDirectory temp = configureOptions is null + ? await TemporaryShareDirectory.CreateIfNotExistsAsync(dir, Logger, TestContext.Current.CancellationToken) + : await TemporaryShareDirectory.CreateIfNotExistsAsync(dir, Logger, configureOptions, TestContext.Current.CancellationToken); Assert.Equal(dir.Name, temp.Client.Name); Assert.Equal(dir.AccountName, temp.Client.AccountName); @@ -220,7 +209,7 @@ private async Task WhenTempDirCreatedAsync(DirClient di private async Task GivenFileShareAsync() { - return await FileShareTestContext.GivenAvailableAsync(Configuration, Logger); + return await FileShareTestContext.GivenAvailableAsync(Configuration, Logger, TestContext.Current.CancellationToken); } } @@ -231,7 +220,7 @@ internal static class TempShareDirExtensions internal static async Task WhenFileFileUploadAsync(this TemporaryShareDirectory dir, FileClient file) { await using var fileContents = new MemoryStream(Encoding.UTF8.GetBytes(Bogus.Lorem.Sentence())); - await dir.UpsertFileAsync(file.Name, fileContents); + await dir.UpsertFileAsync(file.Name, fileContents, TestContext.Current.CancellationToken); } } @@ -240,21 +229,25 @@ internal class FileShareTestContext : IAsyncDisposable private readonly ShareClient _share; private readonly ShareServiceClient _service; private readonly ILogger _logger; + private readonly CancellationToken _cancellationToken; private static readonly Faker Bogus = new(); private FileShareTestContext( ShareServiceClient service, ShareClient share, - ILogger logger) + ILogger logger, + CancellationToken cancellationToken) { _service = service; _share = share; _logger = logger ?? NullLogger.Instance; + _cancellationToken = cancellationToken; } - public static async Task GivenAvailableAsync(TestConfig configuration, ILogger logger) + public static async Task GivenAvailableAsync(TestConfig configuration, ILogger logger, CancellationToken cancellationToken) { + cancellationToken.ThrowIfCancellationRequested(); StorageAccount account = configuration.GetStorageAccount(); var service = new ShareServiceClient(account.ConnectionString); @@ -263,9 +256,9 @@ public static async Task GivenAvailableAsync(TestConfig co ShareClient share = service.GetShareClient(shareName); logger.LogTrace("[Test:Setup] Create new Azure File share '{ShareName}' in account '{AccountName}'", share.Name, share.AccountName); - await share.CreateIfNotExistsAsync(); + await share.CreateIfNotExistsAsync(cancellationToken: cancellationToken); - return new FileShareTestContext(service, share, logger); + return new FileShareTestContext(service, share, logger, cancellationToken); } public ShareClient WhenShareUnavailable() @@ -280,7 +273,7 @@ public async Task WhenDirectoryAvailableAsync() DirClient sub = WhenDirectoryUnavailable(); _logger.LogTrace("[Test] Create new Azure File share directory '{DirectoryName}' at '{DirectoryPath}'", sub.Name, sub.Path); - await sub.CreateIfNotExistsAsync(); + await sub.CreateIfNotExistsAsync(cancellationToken: _cancellationToken); return sub; } @@ -290,7 +283,7 @@ public async Task WhenDirectoryAvailableAsync(DirClient dirClient) DirClient sub = WhenDirectoryUnavailable(dirClient); _logger.LogTrace("[Test] Create new Azure File share directory '{DirectoryName}' at '{DirectoryPath}'", sub.Name, sub.Path); - await sub.CreateIfNotExistsAsync(); + await sub.CreateIfNotExistsAsync(cancellationToken: _cancellationToken); return sub; } @@ -328,8 +321,8 @@ public async Task WhenFileAvailableAsync(DirClient directoryClient) _logger.LogTrace("[Test] Upload new Azure File share item '{FileName}' in directory '{AccountName}/{DirectoryPath}'", fileName, directoryClient.AccountName, directoryClient.Path); await using var contents = BinaryData.FromString(fileContents).ToStream(); - FileClient fileClient = await directoryClient.CreateFileAsync(fileName, contents.Length); - await fileClient.UploadAsync(contents); + FileClient fileClient = await directoryClient.CreateFileAsync(fileName, contents.Length, cancellationToken: _cancellationToken); + await fileClient.UploadAsync(contents, cancellationToken: _cancellationToken); return fileClient; } @@ -338,7 +331,9 @@ public async Task ShouldHaveDirectoriesAsync(params DirClient[] directories) { foreach (DirClient dir in directories) { - Assert.True(await dir.ExistsAsync(), $"Azure File share directory '{dir.Name}' should be available on share '{dir.ShareName}', but it wasn't"); + Assert.True( + await dir.ExistsAsync(cancellationToken: _cancellationToken), + $"Azure File share directory '{dir.Name}' should be available on share '{dir.ShareName}', but it wasn't"); } } @@ -346,16 +341,18 @@ public async Task ShouldHaveFilesAsync(params FileClient[] files) { foreach (var file in files) { - Assert.True(await file.ExistsAsync(), $"Azure File share file '{file.Name}' should be available on share '{file.ShareName}', but it wasn't"); + Assert.True( + await file.ExistsAsync(cancellationToken: _cancellationToken), + $"Azure File share file '{file.Name}' should be available on share '{file.ShareName}', but it wasn't"); } } public async Task ShouldHaveFileAsync(FileClient file) { await ShouldHaveFilesAsync(file); - using ShareFileDownloadInfo fileInfo = await file.DownloadAsync(); + using ShareFileDownloadInfo fileInfo = await file.DownloadAsync(cancellationToken: _cancellationToken); - var data = await BinaryData.FromStreamAsync(fileInfo.Content); + var data = await BinaryData.FromStreamAsync(fileInfo.Content, _cancellationToken); return data; } @@ -363,7 +360,9 @@ public async Task ShouldNotHaveFilesAsync(params FileClient[] files) { foreach (var file in files) { - Assert.False(await file.ExistsAsync(), $"Azure File share file '{file.Name}' should not be available on share '{file.ShareName}', but it was"); + Assert.False( + await file.ExistsAsync(cancellationToken: _cancellationToken), + $"Azure File share file '{file.Name}' should not be available on share '{file.ShareName}', but it was"); } } @@ -371,7 +370,9 @@ public async Task ShouldNotHaveDirectoriesAsync(params DirClient[] directories) { foreach (var dir in directories) { - Assert.False(await dir.ExistsAsync(), $"Azure File share directory '{dir.Name}' should not be available on share '{dir.ShareName}', but it was"); + Assert.False( + await dir.ExistsAsync(cancellationToken: _cancellationToken), + $"Azure File share directory '{dir.Name}' should not be available on share '{dir.ShareName}', but it was"); } } @@ -386,6 +387,8 @@ public async ValueTask DisposeAsync() disposables.Add(AsyncDisposable.Create(async () => { _logger.LogTrace("[Test:Teardown] Fallback remove Azure File share '{ShareName}' in account '{AccountName}'", _share.Name, _share.AccountName); + + // ReSharper disable once MethodSupportsCancellation -- We want to ensure the share is deleted, even if the cancellation token is triggered. await _share.DeleteIfExistsAsync(); })); } diff --git a/src/Arcus.Testing.Tests.Integration/Storage/TemporaryShareFileTests.cs b/src/Arcus.Testing.Tests.Integration/Storage/TemporaryShareFileTests.cs index c7664ab2..5932f935 100644 --- a/src/Arcus.Testing.Tests.Integration/Storage/TemporaryShareFileTests.cs +++ b/src/Arcus.Testing.Tests.Integration/Storage/TemporaryShareFileTests.cs @@ -125,7 +125,7 @@ private static Stream CreateFileContents() private async Task WhenFileCreatedAsync(FileClient client, Stream fileStream) { - var temp = await TemporaryShareFile.UpsertFileAsync(client, fileStream, Logger); + var temp = await TemporaryShareFile.UpsertFileAsync(client, fileStream, Logger, TestContext.Current.CancellationToken); Assert.Equal(client.Name, temp.Client.Name); return temp; @@ -133,7 +133,7 @@ private async Task WhenFileCreatedAsync(FileClient client, S private async Task GivenFileShareAsync() { - return await FileShareTestContext.GivenAvailableAsync(Configuration, Logger); + return await FileShareTestContext.GivenAvailableAsync(Configuration, Logger, TestContext.Current.CancellationToken); } } }