Skip to content

Commit

Permalink
feat(testcontainers#421) Added AzuriteTestcontainer - basic implement…
Browse files Browse the repository at this point in the history
…ation
  • Loading branch information
vlaskal committed Aug 7, 2022
1 parent 477776a commit 8bf5136
Show file tree
Hide file tree
Showing 8 changed files with 309 additions and 0 deletions.
1 change: 1 addition & 0 deletions Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<GlobalPackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="6.0.0" />
<GlobalPackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" />
<GlobalPackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" />
<PackageReference Update="Azure.Data.Tables" Version="12.6.1" />
<PackageReference Update="JetBrains.Annotations" Version="2022.1.0" PrivateAssets="all" />
<PackageReference Update="Docker.DotNet" Version="3.125.10" />
<PackageReference Update="Microsoft.Bcl.AsyncInterfaces" Version="1.1.1" />
Expand Down
6 changes: 6 additions & 0 deletions Testcontainers.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeStyle/CSharpUsing/PreferQualifiedReference/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CSharpUsing/QualifiedUsingAtNestedScope/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Azurite/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Testcontainer/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Testcontainers/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
namespace DotNet.Testcontainers.Builders
{
using System.Collections.ObjectModel;
using DotNet.Testcontainers.Configurations.Modules.Databases;
using DotNet.Testcontainers.Containers;
using JetBrains.Annotations;

/// <summary>
/// This class applies the extended Testcontainer configurations for Azurite.
/// </summary>
[PublicAPI]
public static class TestcontainersBuilderAzuriteExtension
{
public static ITestcontainersBuilder<AzuriteTestcontainer> WithAzurite(this ITestcontainersBuilder<AzuriteTestcontainer> builder, AzuriteTestcontainerConfiguration configuration)
{
return builder
.WithImage(configuration.Image)
.WithEnvironment(new ReadOnlyDictionary<string, string>(configuration.Environments))
.WithPortBinding(configuration.BlobPort, AzuriteTestcontainerConfiguration.DefaultBlobPort)
.WithPortBinding(configuration.QueuePort, AzuriteTestcontainerConfiguration.DefaultQueuePort)
.WithPortBinding(configuration.TablePort, AzuriteTestcontainerConfiguration.DefaultTablePort)
.WithOutputConsumer(configuration.OutputConsumer)
.WithWaitStrategy(configuration.WaitStrategy)
.ConfigureContainer(container =>
{
container.ContainerBlobPort = AzuriteTestcontainerConfiguration.DefaultBlobPort;
container.ContainerQueuePort = AzuriteTestcontainerConfiguration.DefaultQueuePort;
container.ContainerTablePort = AzuriteTestcontainerConfiguration.DefaultTablePort;
});
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
namespace DotNet.Testcontainers.Configurations.Modules.Databases
{
using System;
using System.Collections.Generic;
using DotNet.Testcontainers.Builders;
using JetBrains.Annotations;

public class AzuriteTestcontainerConfiguration : IDisposable
{
/// <summary>
/// Default Azurite docker image.
/// </summary>
public const string DefaultAzuriteImage = "mcr.microsoft.com/azure-storage/azurite:3.18.0";

/// <summary>
/// Default Blob service listening port. Default is 10000.
/// </summary>
public const int DefaultBlobPort = 10000;

/// <summary>
/// Default Queue service listening port. Default is 10001.
/// </summary>
public const int DefaultQueuePort = 10001;

/// <summary>
/// Default Table service listening port. Default 10002.
/// </summary>
public const int DefaultTablePort = 10002;

/// <summary>
/// Initializes a new instance of the <see cref="AzuriteTestcontainerConfiguration" /> class with default Azurite image.
/// </summary>
/// <param name="image">The Docker image.</param>
public AzuriteTestcontainerConfiguration()
: this(DefaultAzuriteImage)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="AzuriteTestcontainerConfiguration" /> class.
/// </summary>
/// <param name="image">The Docker image.</param>
protected AzuriteTestcontainerConfiguration(string image)
{
this.Image = image;
this.Environments = new Dictionary<string, string>();
this.OutputConsumer = Consume.DoNotConsumeStdoutAndStderr();
}

/// <summary>
/// Gets the Docker image.
/// </summary>
[PublicAPI]
public string Image { get; }

/// <summary>
/// Gets or sets the host Blob port.
/// </summary>
/// <remarks>
/// Corresponds to the default port of the hosted service.
/// </remarks>
[PublicAPI]
public int BlobPort { get; set; }

/// <summary>
/// Gets or sets the host Queue port.
/// </summary>
/// <remarks>
/// Corresponds to the default port of the hosted service.
/// </remarks>
[PublicAPI]
public int QueuePort { get; set; }

/// <summary>
/// Gets or sets the host Table port.
/// </summary>
/// <remarks>
/// Corresponds to the default port of the hosted service.
/// </remarks>
[PublicAPI]
public int TablePort { get; set; }

/// <summary>
/// Gets the environment configuration.
/// </summary>
[PublicAPI]
public IDictionary<string, string> Environments { get; }

/// <summary>
/// Gets or sets the output consumer.
/// </summary>
/// <remarks>
/// Uses <see cref="Consume.DoNotConsumeStdoutAndStderr" /> as default value.
/// </remarks>
[PublicAPI]
[CanBeNull]
public IOutputConsumer OutputConsumer { get; set; }

/// <summary>
/// Gets the wait strategy.
/// </summary>
/// <remarks>
/// Uses <see cref="Wait.ForUnixContainer" /> and waits for Azurite ports.
/// </remarks>
[PublicAPI]
public IWaitForContainerOS WaitStrategy => Wait.ForUnixContainer()
.UntilPortIsAvailable(DefaultBlobPort)
.UntilPortIsAvailable(DefaultQueuePort)
.UntilPortIsAvailable(DefaultTablePort);

/// <inheritdoc />
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}

/// <summary>
/// Releases all resources used by the <see cref="HostedServiceConfiguration" />.
/// </summary>
/// <param name="disposing">True if managed resources should be disposed, otherwise false..</param>
[PublicAPI]
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
this.OutputConsumer?.Dispose();
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
namespace DotNet.Testcontainers.Containers
{
using DotNet.Testcontainers.Configurations;
using JetBrains.Annotations;
using Microsoft.Extensions.Logging;

[PublicAPI]
public class AzuriteTestcontainer : TestcontainersContainer
{
internal AzuriteTestcontainer(ITestcontainersConfiguration configuration, ILogger logger)
: base(configuration, logger)
{
}

/// <summary>
/// Gets the host Blob port.
/// </summary>
[PublicAPI]
public int BlobPort => this.GetMappedPublicPort(this.ContainerBlobPort);

/// <summary>
/// Gets the host Queue port.
/// </summary>
[PublicAPI]
public int QueuePort => this.GetMappedPublicPort(this.ContainerQueuePort);

/// <summary>
/// Gets the host Table port.
/// </summary>
[PublicAPI]
public int TablePort => this.GetMappedPublicPort(this.ContainerTablePort);

/// <summary>
/// Gets or sets the container Blob port.
/// </summary>
[PublicAPI]
public int ContainerBlobPort { get; set; }

/// <summary>
/// Gets or sets the container Queue port.
/// </summary>
[PublicAPI]
public int ContainerQueuePort { get; set; }

/// <summary>
/// Gets or sets the container Table port.
/// </summary>
[PublicAPI]
public int ContainerTablePort { get; set; }

/// <summary>
/// Gets the Storage connection string.
/// </summary>
[PublicAPI]
public string ConnectionString =>
$"DefaultEndpointsProtocol=http;" +
$"AccountName=devstoreaccount1;" +
$"AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;" +
$"BlobEndpoint=http://{this.Hostname}:{this.BlobPort}/devstoreaccount1;" +
$"QueueEndpoint=http://{this.Hostname}:{this.QueuePort}/devstoreaccount1;" +
$"TableEndpoint=http://{this.Hostname}:{this.TablePort}/devstoreaccount1;";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
namespace DotNet.Testcontainers.Tests.Fixtures
{
using System;
using System.Threading.Tasks;
using Azure.Data.Tables;
using DotNet.Testcontainers.Builders;
using DotNet.Testcontainers.Configurations.Modules.Databases;
using DotNet.Testcontainers.Containers;
using Xunit;

public sealed class AzuriteFixture : IAsyncLifetime, IDisposable
{
private readonly AzuriteTestcontainerConfiguration configuration = new();

public AzuriteFixture()
{
this.Container = new TestcontainersBuilder<AzuriteTestcontainer>()
.WithAzurite(this.configuration)
.Build();
}

public AzuriteTestcontainer Container { get; }

public TableServiceClient Connection { get; private set; }

public async Task InitializeAsync()
{
await this.Container.StartAsync()
.ConfigureAwait(false);

this.Connection = new TableServiceClient(this.Container.ConnectionString);
}

public async Task DisposeAsync()
{
await this.Container.DisposeAsync()
.ConfigureAwait(false);
}

public void Dispose()
{
this.configuration.Dispose();
}
}
}
1 change: 1 addition & 0 deletions tests/Testcontainers.Tests/Testcontainers.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<RootNamespace>DotNet.Testcontainers.Tests</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Azure.Data.Tables" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="Microsoft.Extensions.Hosting" />
<PackageReference Include="coverlet.msbuild" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
namespace DotNet.Testcontainers.Tests.Unit
{
using System.Threading.Tasks;
using DotNet.Testcontainers.Tests.Fixtures;
using Xunit;

[Collection(nameof(Testcontainers))]
public sealed class AzuriteTestcontainerTest : IClassFixture<AzuriteFixture>
{
private readonly AzuriteFixture azuriteFixture;

public AzuriteTestcontainerTest(AzuriteFixture azuriteFixture)
{
this.azuriteFixture = azuriteFixture;
}

[Fact]
public async Task ConnectionEstablished()
{
// Given
var connection = this.azuriteFixture.Connection;

// When
var properties = await connection.GetPropertiesAsync().ConfigureAwait(false);

// Then
Assert.True(properties.GetRawResponse().Status is >= 200 and <= 299);
}
}
}

0 comments on commit 8bf5136

Please sign in to comment.