Skip to content

Commit

Permalink
pr-fix: add missing xml code docs
Browse files Browse the repository at this point in the history
  • Loading branch information
stijnmoreels committed Jul 26, 2024
1 parent 37ba635 commit 561a69f
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 28 deletions.
43 changes: 32 additions & 11 deletions src/Arcus.Testing.Storage.Blob/TemporaryBlobContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,9 @@ public class OnSetupBlobContainerOptions
{
private readonly List<BlobNameFilter> _filters = new();

/// <summary>
/// Gets the configurable setup option on what to do with existing Azure Blobs in the Azure Blob container upon the test fixture creation.
/// </summary>
internal OnSetupContainer Blobs { get; private set; } = OnSetupContainer.LeaveExisted;

/// <summary>
Expand Down Expand Up @@ -214,6 +217,11 @@ public OnSetupBlobContainerOptions LeaveAllBlobs()
return this;
}

/// <summary>
/// Determines whether the given <paramref name="blob"/> matches the configured filter.
/// </summary>
/// <param name="blob">The blob to match the filter against.</param>
/// <exception cref="ArgumentNullException">Thrown when the <paramref name="blob"/> is <c>null</c>.</exception>
internal bool IsMatched(BlobItem blob)
{
if (blob is null)
Expand All @@ -238,7 +246,14 @@ public class OnTeardownBlobContainerOptions
{
private readonly List<BlobNameFilter> _filters = new();

/// <summary>
/// Gets the configurable option on what to do with unlinked Azure Blobs in the Azure Blob container upon the disposal of the test fixture.
/// </summary>
internal OnTeardownBlobs Blobs { get; private set; } = OnTeardownBlobs.CleanIfCreated;

/// <summary>
/// Gets the configurable option on what to do with the Azure Blob container upon the disposal of the test fixture.
/// </summary>
internal OnTeardownContainer Container { get; private set; } = OnTeardownContainer.DeleteIfCreated;

/// <summary>
Expand Down Expand Up @@ -310,6 +325,8 @@ public OnTeardownBlobContainerOptions DeleteExistingContainer()
/// <summary>
/// Determines whether the given <paramref name="blob"/> should be deleted upon the disposal of the <see cref="TemporaryBlobContainer"/>.
/// </summary>
/// <param name="blob">The blob to match the filter against.</param>
/// <exception cref="ArgumentNullException">Thrown when the <paramref name="blob"/> is <c>null</c>.</exception>
internal bool IsMatched(BlobItem blob)
{
if (blob is null)
Expand Down Expand Up @@ -347,7 +364,6 @@ public class TemporaryBlobContainerOptions
/// </summary>
public class TemporaryBlobContainer : IAsyncDisposable
{
private readonly BlobContainerClient _containerClient;
private readonly Collection<TemporaryBlobFile> _blobs = new();
private readonly bool _createdByUs;
private readonly TemporaryBlobContainerOptions _options;
Expand All @@ -359,21 +375,22 @@ private TemporaryBlobContainer(
TemporaryBlobContainerOptions options,
ILogger logger)
{
_containerClient = containerClient ?? throw new ArgumentNullException(nameof(containerClient));
_createdByUs = createdByUs;
_options = options ?? new TemporaryBlobContainerOptions();
_logger = logger ?? NullLogger.Instance;

Client = containerClient ?? throw new ArgumentNullException(nameof(containerClient));
}

/// <summary>
/// Gets the name of the temporary Azure Blob container currently in storage.
/// </summary>
public string Name => _containerClient.Name;
public string Name => Client.Name;

/// <summary>
/// Gets the <see cref="BlobContainerClient"/> instance that represents the temporary Azure Blob container.
/// </summary>
public BlobContainerClient Client => _containerClient;
public BlobContainerClient Client { get; }

/// <summary>
/// Creates a new instance of the <see cref="TemporaryBlobContainer"/> which creates a new Azure Blob storage container if it doesn't exist yet.
Expand Down Expand Up @@ -440,9 +457,13 @@ public static async Task<TemporaryBlobContainer> CreateIfNotExistsAsync(
/// </summary>
/// <param name="containerClient">The client to interact with the Azure Blob storage container.</param>
/// <param name="logger">The logger to write diagnostic messages during the creation of the Azure Blob container.</param>
/// <exception cref="ArgumentNullException">Thrown when the <paramref name="containerClient"/> is <c>null</c>.</exception>
public static async Task<TemporaryBlobContainer> CreateIfNotExistsAsync(BlobContainerClient containerClient, ILogger logger)
{
return await CreateIfNotExistsAsync(containerClient, logger, configureOptions: null);
return await CreateIfNotExistsAsync(
containerClient ?? throw new ArgumentNullException(nameof(containerClient)),
logger,
configureOptions: null);
}

/// <summary>
Expand Down Expand Up @@ -523,7 +544,7 @@ public async Task<BlobClient> UploadBlobAsync(string blobName, BinaryData blobCo
throw new ArgumentNullException(nameof(blobContent));
}

BlobClient blobClient = _containerClient.GetBlobClient(blobName);
BlobClient blobClient = Client.GetBlobClient(blobName);
_blobs.Add(await TemporaryBlobFile.UploadIfNotExistsAsync(blobClient, blobContent, _logger, configureOptions));

return blobClient;
Expand All @@ -540,15 +561,15 @@ public async ValueTask DisposeAsync()
disposables.AddRange(_blobs);
disposables.Add(AsyncDisposable.Create(async () =>
{
await CleanBlobContainerUponDeletionAsync(_containerClient, _options, _logger);
await CleanBlobContainerUponDeletionAsync(Client, _options, _logger);
}));

if (_createdByUs || _options.OnTeardown.Container is OnTeardownContainer.DeleteIfExists)
{
disposables.Add(AsyncDisposable.Create(async () =>
{
_logger.LogTrace("Deleting Azure Blob container '{ContainerName}'", _containerClient.Name);
await _containerClient.DeleteIfExistsAsync();
_logger.LogTrace("Deleting Azure Blob container '{ContainerName}'", Client.Name);
await Client.DeleteIfExistsAsync();
}));
}
}
Expand All @@ -560,7 +581,7 @@ private static async Task CleanBlobContainerUponCreationAsync(BlobContainerClien
return;
}

logger.LogDebug("Cleaning Azure Blob container '{ContainerName}'", containerClient.Name);
logger.LogTrace("Cleaning Azure Blob container '{ContainerName}'", containerClient.Name);
await foreach (BlobItem blob in containerClient.GetBlobsAsync())
{
if (options.OnSetup.IsMatched(blob))
Expand All @@ -578,7 +599,7 @@ private static async Task CleanBlobContainerUponDeletionAsync(BlobContainerClien
return;
}

logger.LogDebug("Cleaning Azure Blob container '{ContainerName}'", containerClient.Name);
logger.LogTrace("Cleaning Azure Blob container '{ContainerName}'", containerClient.Name);
await foreach (BlobItem blob in containerClient.GetBlobsAsync())
{
if (options.OnTeardown.IsMatched(blob))
Expand Down
63 changes: 51 additions & 12 deletions src/Arcus.Testing.Storage.Blob/TemporaryBlobFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ namespace Arcus.Testing
/// </summary>
public class OnSetupBlobFileOptions
{
/// <summary>
/// Gets the configured setup option on what to do with an existing Azure Blob file upon creation.
/// </summary>
/// <remarks>
/// [true] overrides the existing Azure Blob file when it already exists;
/// [false] uses the existing Azure Blob file's content instead.
/// </remarks>
internal bool OverrideBlob { get; private set; }

/// <summary>
Expand Down Expand Up @@ -44,6 +51,9 @@ internal enum OnTeardownBlob { DeleteIfCreated, DeleteIfExisted }
/// </summary>
public class OnTeardownBlobFileOptions
{
/// <summary>
/// Gets the configured teardown option on what to do with the Azure Blob content upon disposal.
/// </summary>
internal OnTeardownBlob Content { get; private set; }

/// <summary>
Expand Down Expand Up @@ -87,7 +97,6 @@ public class TemporaryBlobFileOptions
/// </summary>
public class TemporaryBlobFile : IAsyncDisposable
{
private readonly BlobClient _blobClient;
private readonly bool _createdByUs;
private readonly BinaryData _originalData;
private readonly TemporaryBlobFileOptions _options;
Expand All @@ -100,22 +109,28 @@ private TemporaryBlobFile(
TemporaryBlobFileOptions options,
ILogger logger)
{
_blobClient = blobClient ?? throw new ArgumentNullException(nameof(blobClient));
_createdByUs = createdByUs;
_originalData = originalData;
_options = options;
_logger = logger ?? NullLogger.Instance;

Client = blobClient ?? throw new ArgumentNullException(nameof(blobClient));
}

/// <summary>
/// Gets the name of the Azure Blob file currently in storage.
/// </summary>
public string Name => _blobClient.Name;
public string Name => Client.Name;

/// <summary>
/// Gets the name of the Azure Blob container where the Azure Blob file is currently stored.
/// </summary>
public string ContainerName => Client.BlobContainerName;

/// <summary>
/// Gets the client to interact with the temporary stored Azure Blob file currently in storage.
/// </summary>
public BlobClient Client => _blobClient;
public BlobClient Client { get; }

/// <summary>
/// Uploads a temporary blob to the Azure Blob container.
Expand All @@ -134,7 +149,17 @@ private TemporaryBlobFile(
/// <exception cref="ArgumentNullException">Thrown when <paramref name="blobContainerUri"/> or the <paramref name="blobContent"/> is <c>null</c>.</exception>
public static async Task<TemporaryBlobFile> UploadIfNotExistsAsync(Uri blobContainerUri, string blobName, BinaryData blobContent, ILogger logger)
{
return await UploadIfNotExistsAsync(blobContainerUri, blobName, blobContent, logger, configureOptions: null);
if (string.IsNullOrWhiteSpace(blobName))
{
throw new ArgumentException("Requires a non-blank name for the Azure Blob file name for it to be uploaded to Azure Blob storage", nameof(blobName));
}

return await UploadIfNotExistsAsync(
blobContainerUri ?? throw new ArgumentNullException(nameof(blobContainerUri)),
blobName,
blobContent ?? throw new ArgumentNullException(nameof(blobContent)),
logger,
configureOptions: null);
}

/// <summary>
Expand Down Expand Up @@ -165,8 +190,18 @@ public static async Task<TemporaryBlobFile> UploadIfNotExistsAsync(
throw new ArgumentNullException(nameof(blobContainerUri));
}

if (string.IsNullOrWhiteSpace(blobName))
{
throw new ArgumentException("Requires a non-blank name for the Azure Blob file name for it to be uploaded to Azure Blob storage", nameof(blobName));
}

if (blobContent is null)
{
throw new ArgumentNullException(nameof(blobContent));
}

var containerClient = new BlobContainerClient(blobContainerUri, new DefaultAzureCredential());
var blobClient = containerClient.GetBlobClient(blobName);
BlobClient blobClient = containerClient.GetBlobClient(blobName);

return await UploadIfNotExistsAsync(blobClient, blobContent, logger, configureOptions);
}
Expand All @@ -180,7 +215,11 @@ public static async Task<TemporaryBlobFile> UploadIfNotExistsAsync(
/// <exception cref="ArgumentNullException">Thrown when the <paramref name="blobClient"/> or the <paramref name="blobContent"/> is <c>null</c>.</exception>
public static async Task<TemporaryBlobFile> UploadIfNotExistsAsync(BlobClient blobClient, BinaryData blobContent, ILogger logger)
{
return await UploadIfNotExistsAsync(blobClient, blobContent, logger, configureOptions: null);
return await UploadIfNotExistsAsync(
blobClient ?? throw new ArgumentNullException(nameof(blobClient)),
blobContent ?? throw new ArgumentNullException(nameof(blobContent)),
logger,
configureOptions: null);
}

/// <summary>
Expand Down Expand Up @@ -236,7 +275,7 @@ public static async Task<TemporaryBlobFile> UploadIfNotExistsAsync(
return (createdByUs: false, originalContent.Content);
}

logger.LogDebug("Uploading Azure Blob '{BlobName}' to container '{ContainerName}'", client.Name, client.BlobContainerName);
logger.LogTrace("Uploading Azure Blob '{BlobName}' to container '{ContainerName}'", client.Name, client.BlobContainerName);
await client.UploadAsync(newContent);

return (createdByUs: true, originalData: null);
Expand All @@ -250,14 +289,14 @@ public async ValueTask DisposeAsync()
{
if (!_createdByUs && _originalData != null && _options.OnTeardown.Content != OnTeardownBlob.DeleteIfExisted)
{
_logger.LogDebug("Reverting Azure Blob '{BlobName}' original content in container '{ContainerName}'", _blobClient.Name, _blobClient.BlobContainerName);
await _blobClient.UploadAsync(_originalData, overwrite: true);
_logger.LogDebug("Reverting Azure Blob '{BlobName}' original content in container '{ContainerName}'", Client.Name, Client.BlobContainerName);
await Client.UploadAsync(_originalData, overwrite: true);
}

if (_createdByUs || _options.OnTeardown.Content is OnTeardownBlob.DeleteIfExisted)
{
_logger.LogDebug("Deleting Azure Blob '{BlobName}' from container '{ContainerName}'", _blobClient.Name, _blobClient.BlobContainerName);
await _blobClient.DeleteIfExistsAsync();
_logger.LogTrace("Deleting Azure Blob '{BlobName}' from container '{ContainerName}'", Client.Name, Client.BlobContainerName);
await Client.DeleteIfExistsAsync();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,12 @@ private async Task<TemporaryBlobContainer> WhenTempContainerCreatedAsync(
Action<TemporaryBlobContainerOptions> configureOptions = null)
{
TemporaryBlobContainer temp = configureOptions is null
? await TemporaryBlobContainer.CreateIfNotExistsAsync(context.StorageAccount.Name, client.Name, Logger)
: await TemporaryBlobContainer.CreateIfNotExistsAsync(context.StorageAccount.Name, client.Name, Logger, configureOptions);
? Bogus.Random.Bool()
? await TemporaryBlobContainer.CreateIfNotExistsAsync(context.StorageAccount.Name, client.Name, Logger)
: await TemporaryBlobContainer.CreateIfNotExistsAsync(client, Logger)
: Bogus.Random.Bool()
? await TemporaryBlobContainer.CreateIfNotExistsAsync(context.StorageAccount.Name, client.Name, Logger, configureOptions)
: await TemporaryBlobContainer.CreateIfNotExistsAsync(client, Logger, configureOptions);

Assert.Equal(client.Name, temp.Name);
Assert.Equal(client.Name, temp.Client.Name);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,16 @@ private async Task<TemporaryBlobFile> WhenBlobUploadedAsync(
blobName ??= $"test-{Guid.NewGuid():N}";
blobContent ??= BinaryData.FromBytes(Bogus.Random.Bytes(100));

var temp = configureOptions is null
? await TemporaryBlobFile.UploadIfNotExistsAsync(client.Uri, blobName, blobContent, Logger)
: await TemporaryBlobFile.UploadIfNotExistsAsync(client.Uri, blobName, blobContent, Logger, configureOptions);
TemporaryBlobFile temp = configureOptions is null
? Bogus.Random.Bool()
? await TemporaryBlobFile.UploadIfNotExistsAsync(client.Uri, blobName, blobContent, Logger)
: await TemporaryBlobFile.UploadIfNotExistsAsync(client.GetBlobClient(blobName), blobContent, Logger)
: Bogus.Random.Bool()
? await TemporaryBlobFile.UploadIfNotExistsAsync(client.Uri, blobName, blobContent, Logger, configureOptions)
: await TemporaryBlobFile.UploadIfNotExistsAsync(client.GetBlobClient(blobName), blobContent, Logger, configureOptions);

Assert.Equal(blobName, temp.Name);
Assert.Equal(client.Name, temp.ContainerName);
Assert.Equal(blobName, temp.Client.Name);
Assert.Equal(client.Name, temp.Client.BlobContainerName);

Expand Down

0 comments on commit 561a69f

Please sign in to comment.