diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 0a2209bf5..39b19fed8 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -14,7 +14,7 @@ "moby": true }, "ghcr.io/devcontainers/features/dotnet:1": { - "version": "6.0.413", + "version": "8.0.100", "installUsingApt": false } }, diff --git a/src/Testcontainers.Azurite/AzuriteBuilder.cs b/src/Testcontainers.Azurite/AzuriteBuilder.cs index ae1a1d162..222d0d346 100644 --- a/src/Testcontainers.Azurite/AzuriteBuilder.cs +++ b/src/Testcontainers.Azurite/AzuriteBuilder.cs @@ -4,7 +4,7 @@ namespace Testcontainers.Azurite; [PublicAPI] public sealed class AzuriteBuilder : ContainerBuilder { - public const string AzuriteImage = "mcr.microsoft.com/azure-storage/azurite:3.24.0"; + public const string AzuriteImage = "mcr.microsoft.com/azure-storage/azurite:3.28.0"; public const ushort BlobPort = 10000; @@ -12,7 +12,14 @@ public sealed class AzuriteBuilder : ContainerBuilder _enabledServices = new HashSet(); + private static readonly ISet EnabledServices = new HashSet(); + + static AzuriteBuilder() + { + EnabledServices.Add(AzuriteService.Blob); + EnabledServices.Add(AzuriteService.Queue); + EnabledServices.Add(AzuriteService.Table); + } /// /// Initializes a new instance of the class. @@ -21,10 +28,6 @@ public AzuriteBuilder() : this(new AzuriteConfiguration()) { DockerResourceConfiguration = Init().DockerResourceConfiguration; - - _enabledServices.Add(AzuriteService.Blob); - _enabledServices.Add(AzuriteService.Queue); - _enabledServices.Add(AzuriteService.Table); } /// @@ -40,6 +43,26 @@ private AzuriteBuilder(AzuriteConfiguration resourceConfiguration) /// protected override AzuriteConfiguration DockerResourceConfiguration { get; } + /// + /// Enables in-memory persistence. + /// + /// + /// By default, the in-memory is limited to 50% of the total memory on the container. + /// + /// An optional in-memory limit in megabytes. + /// A configured instance of . + public AzuriteBuilder WithInMemoryPersistence(float? megabytes = null) + { + if (megabytes.HasValue) + { + return WithCommand("--inMemoryPersistence", "--extentMemoryLimit", megabytes.ToString()); + } + else + { + return WithCommand("--inMemoryPersistence"); + } + } + /// public override AzuriteContainer Build() { @@ -47,17 +70,17 @@ public override AzuriteContainer Build() var waitStrategy = Wait.ForUnixContainer(); - if (_enabledServices.Contains(AzuriteService.Blob)) + if (EnabledServices.Contains(AzuriteService.Blob)) { waitStrategy = waitStrategy.UntilMessageIsLogged("Blob service is successfully listening"); } - if (_enabledServices.Contains(AzuriteService.Queue)) + if (EnabledServices.Contains(AzuriteService.Queue)) { waitStrategy = waitStrategy.UntilMessageIsLogged("Queue service is successfully listening"); } - if (_enabledServices.Contains(AzuriteService.Table)) + if (EnabledServices.Contains(AzuriteService.Table)) { waitStrategy = waitStrategy.UntilMessageIsLogged("Table service is successfully listening"); } @@ -73,7 +96,9 @@ protected override AzuriteBuilder Init() .WithImage(AzuriteImage) .WithPortBinding(BlobPort, true) .WithPortBinding(QueuePort, true) - .WithPortBinding(TablePort, true); + .WithPortBinding(TablePort, true) + .WithEntrypoint("azurite") + .WithCommand("--blobHost", "0.0.0.0", "--queueHost", "0.0.0.0", "--tableHost", "0.0.0.0"); } /// diff --git a/tests/Testcontainers.Azurite.Tests/AzuriteContainerTest.cs b/tests/Testcontainers.Azurite.Tests/AzuriteContainerTest.cs index da57ddf2d..7f99f2d59 100644 --- a/tests/Testcontainers.Azurite.Tests/AzuriteContainerTest.cs +++ b/tests/Testcontainers.Azurite.Tests/AzuriteContainerTest.cs @@ -2,7 +2,12 @@ namespace Testcontainers.Azurite; public abstract class AzuriteContainerTest : IAsyncLifetime { - private readonly AzuriteContainer _azuriteContainer = new AzuriteBuilder().Build(); + private readonly AzuriteContainer _azuriteContainer; + + private AzuriteContainerTest(AzuriteContainer azuriteContainer) + { + _azuriteContainer = azuriteContainer; + } public Task InitializeAsync() { @@ -14,6 +19,51 @@ public Task DisposeAsync() return _azuriteContainer.DisposeAsync().AsTask(); } + [Fact] + [Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))] + public async Task EstablishesBlobServiceConnection() + { + // Give + var client = new BlobServiceClient(_azuriteContainer.GetConnectionString()); + + // When + var properties = await client.GetPropertiesAsync() + .ConfigureAwait(false); + + // Then + Assert.False(HasError(properties)); + } + + [Fact] + [Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))] + public async Task EstablishesQueueServiceConnection() + { + // Give + var client = new QueueServiceClient(_azuriteContainer.GetConnectionString()); + + // When + var properties = await client.GetPropertiesAsync() + .ConfigureAwait(false); + + // Then + Assert.False(HasError(properties)); + } + + [Fact] + [Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))] + public async Task EstablishesTableServiceConnection() + { + // Give + var client = new TableServiceClient(_azuriteContainer.GetConnectionString()); + + // When + var properties = await client.GetPropertiesAsync() + .ConfigureAwait(false); + + // Then + Assert.False(HasError(properties)); + } + private static bool HasError(NullableResponse response) { using (var rawResponse = response.GetRawResponse()) @@ -22,57 +72,48 @@ private static bool HasError(NullableResponse } } - public sealed class BlobService : AzuriteContainerTest + [UsedImplicitly] + public sealed class AzuriteDefaultConfiguration : AzuriteContainerTest { - [Fact] - [Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))] - public async Task EstablishesConnection() + public AzuriteDefaultConfiguration() + : base(new AzuriteBuilder().Build()) { - // Give - var client = new BlobServiceClient(_azuriteContainer.GetConnectionString()); - - // When - var properties = await client.GetPropertiesAsync() - .ConfigureAwait(false); - - // Then - Assert.False(HasError(properties)); } } - public sealed class QueueService : AzuriteContainerTest + [UsedImplicitly] + public sealed class AzuriteInMemoryConfiguration : AzuriteContainerTest { - [Fact] - [Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))] - public async Task EstablishesConnection() + public AzuriteInMemoryConfiguration() + : base(new AzuriteBuilder().WithInMemoryPersistence().Build()) { - // Give - var client = new QueueServiceClient(_azuriteContainer.GetConnectionString()); - - // When - var properties = await client.GetPropertiesAsync() - .ConfigureAwait(false); - - // Then - Assert.False(HasError(properties)); } } - public sealed class TableService : AzuriteContainerTest + [UsedImplicitly] + public sealed class AzuriteMemoryLimitConfiguration : AzuriteContainerTest { + private const int MemoryLimitInMb = 64; + + private static readonly string[] LineEndings = { "\r\n", "\n" }; + + public AzuriteMemoryLimitConfiguration() + : base(new AzuriteBuilder().WithInMemoryPersistence(MemoryLimitInMb).Build()) + { + } + [Fact] - [Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))] - public async Task EstablishesConnection() + public async Task MemoryLimitIsConfigured() { - // Give - var client = new TableServiceClient(_azuriteContainer.GetConnectionString()); + // Given + var (stdout, _) = await _azuriteContainer.GetLogsAsync(timestampsEnabled: false) + .ConfigureAwait(false); // When - var properties = await client.GetPropertiesAsync() - .ConfigureAwait(false); + var firstLine = stdout.Split(LineEndings, StringSplitOptions.RemoveEmptyEntries).First(); // Then - Assert.False(HasError(properties)); + Assert.StartsWith(string.Format(CultureInfo.InvariantCulture, "In-memory extent storage is enabled with a limit of {0:F2} MB", MemoryLimitInMb), firstLine); } } } \ No newline at end of file diff --git a/tests/Testcontainers.Azurite.Tests/Usings.cs b/tests/Testcontainers.Azurite.Tests/Usings.cs index 8a39ce7c2..645e958bd 100644 --- a/tests/Testcontainers.Azurite.Tests/Usings.cs +++ b/tests/Testcontainers.Azurite.Tests/Usings.cs @@ -1,7 +1,11 @@ +global using System; +global using System.Globalization; +global using System.Linq; global using System.Threading.Tasks; global using Azure; global using Azure.Data.Tables; global using Azure.Storage.Blobs; global using Azure.Storage.Queues; global using DotNet.Testcontainers.Commons; +global using JetBrains.Annotations; global using Xunit; \ No newline at end of file