Skip to content

Commit

Permalink
Merge branch 'develop' into update-azurite-version-to-3.32.0
Browse files Browse the repository at this point in the history
  • Loading branch information
michalchecinski authored Sep 26, 2024
2 parents f15695a + 1cc56ea commit 3bbe7c6
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 69 deletions.
20 changes: 11 additions & 9 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,22 @@
"ghcr.io/devcontainers/features/docker-in-docker:2": {
"moby": true
},
"ghcr.io/devcontainers/features/dotnet:2.0.5": {
"version": "8.0.200",
"ghcr.io/devcontainers/features/dotnet:2.1.3": {
"version": "8.0",
"installUsingApt": false
}
},
"customizations": {
"extensions": [
"ms-azuretools.vscode-docker",
"ms-dotnettools.csdevkit"
],
"settings": {
"omnisharp.path": "latest" // https://github.com/OmniSharp/omnisharp-vscode/issues/5410#issuecomment-1284531542.
"vscode": {
"extensions": [
"ms-azuretools.vscode-docker",
"ms-dotnettools.csdevkit"
],
"settings": {
"dotnet.defaultSolution": "${containerWorkspaceFolder}/Testcontainers.sln"
}
}
},
"postCreateCommand": "git config --global --add safe.directory ${containerWorkspaceFolder} && git lfs checkout",
"postStartCommand": ["dotnet", "build"]
"postStartCommand": ["dotnet", "build", "${containerWorkspaceFolder}/Testcontainers.sln", "/consoleLoggerParameters:NoSummary", "/property:GenerateFullPaths=true", "/property:Configuration=Debug", "/property:Platform=Any CPU"]
}
10 changes: 5 additions & 5 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
<PackageVersion Include="SSH.NET" Version="2023.0.0"/>
<PackageVersion Include="System.Text.Json" Version="6.0.9"/>
<!-- Unit and integration test dependencies: -->
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/>
<PackageVersion Include="Microsoft.Extensions.Diagnostics.Testing" Version="8.2.0"/>
<PackageVersion Include="coverlet.collector" Version="6.0.1"/>
<PackageVersion Include="xunit.runner.visualstudio" Version="2.5.7"/>
<PackageVersion Include="xunit" Version="2.7.0"/>
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.11.1"/>
<PackageVersion Include="Microsoft.Extensions.Diagnostics.Testing" Version="8.9.1"/>
<PackageVersion Include="coverlet.collector" Version="6.0.2"/>
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2"/>
<PackageVersion Include="xunit" Version="2.9.0"/>
<!-- Third-party client dependencies to connect and interact with the containers: -->
<PackageVersion Include="Apache.NMS.ActiveMQ" Version="2.1.0"/>
<PackageVersion Include="ArangoDBNetStandard" Version="2.0.1"/>
Expand Down
1 change: 1 addition & 0 deletions build.cake
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ Task("Tests")
Filter = param.TestFilter,
ResultsDirectory = param.Paths.Directories.TestResultsDirectoryPath,
ArgumentCustomization = args => args
.AppendSwitchQuoted("--blame-hang-timeout", "5m")
});
});

Expand Down
11 changes: 4 additions & 7 deletions src/Testcontainers/Clients/DockerApiClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ namespace DotNet.Testcontainers.Clients
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
Expand Down Expand Up @@ -107,18 +108,14 @@ await RuntimeInitialized.WaitAsync(ct)
runtimeInfo.AppendLine(dockerInfo.OperatingSystem);

runtimeInfo.Append(" Total Memory: ");
runtimeInfo.AppendLine(string.Format(CultureInfo.InvariantCulture, "{0:F} {1}", dockerInfo.MemTotal / Math.Pow(1024, byteUnits.Length), byteUnits[byteUnits.Length - 1]));
runtimeInfo.AppendFormat(CultureInfo.InvariantCulture, "{0:F} {1}", dockerInfo.MemTotal / Math.Pow(1024, byteUnits.Length), byteUnits[byteUnits.Length - 1]);

var labels = dockerInfo.Labels;
if (labels != null && labels.Count > 0)
{
runtimeInfo.AppendLine();
runtimeInfo.AppendLine(" Labels: ");

foreach (var label in labels)
{
runtimeInfo.Append(" ");
runtimeInfo.AppendLine(label);
}
runtimeInfo.Append(string.Join(Environment.NewLine, labels.Select(label => " " + label)));
}
Logger.LogInformation("{RuntimeInfo}", runtimeInfo);
}
Expand Down
3 changes: 2 additions & 1 deletion src/Testcontainers/Logger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Except
{
if (IsEnabled(logLevel))
{
Console.Out.WriteLine("[testcontainers.org {0:hh\\:mm\\:ss\\.ff}] {1}", _stopwatch.Elapsed, formatter.Invoke(state, exception));
var message = exception == null ? formatter.Invoke(state, null) : string.Join(Environment.NewLine, formatter.Invoke(state, exception), exception);
Console.Out.WriteLine("[testcontainers.org {0:hh\\:mm\\:ss\\.ff}] {1}", _stopwatch.Elapsed, message);
}
}

Expand Down
2 changes: 1 addition & 1 deletion tests/Testcontainers.Commons/CommonImages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ namespace DotNet.Testcontainers.Commons;
[PublicAPI]
public static class CommonImages
{
public static readonly IImage Ryuk = new DockerImage("testcontainers/ryuk:0.6.0");
public static readonly IImage Ryuk = new DockerImage("testcontainers/ryuk:0.9.0");

public static readonly IImage Alpine = new DockerImage("alpine:3.17");

Expand Down
86 changes: 53 additions & 33 deletions tests/Testcontainers.Platform.Linux.Tests/DependsOnTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,57 +2,77 @@ namespace Testcontainers.Tests;

public sealed class DependsOnTest : IAsyncLifetime
{
private const string DependsOnKey = "org.testcontainers.depends-on";
private readonly FilterByProperty _filters = new FilterByProperty();

private const string DependsOnValue = "true";
private readonly IList<IAsyncDisposable> _disposables = new List<IAsyncDisposable>();

private readonly IContainer _container = new ContainerBuilder()
.DependsOn(new ContainerBuilder()
private readonly string _labelKey = Guid.NewGuid().ToString("D");

private readonly string _labelValue = Guid.NewGuid().ToString("D");

public DependsOnTest()
{
_filters.Add("label", string.Join("=", _labelKey, _labelValue));
}

public async Task InitializeAsync()
{
var childContainer1 = new ContainerBuilder()
.WithImage(CommonImages.Alpine)
.WithLabel(DependsOnKey, DependsOnValue)
.Build())
.DependsOn(new ContainerBuilder()
.WithLabel(_labelKey, _labelValue)
.Build();

var childContainer2 = new ContainerBuilder()
.WithImage(CommonImages.Alpine)
.WithLabel(DependsOnKey, DependsOnValue)
.Build())
.DependsOn(new NetworkBuilder()
.WithLabel(DependsOnKey, DependsOnValue)
.Build())
.DependsOn(new VolumeBuilder()
.WithLabel(DependsOnKey, DependsOnValue)
.Build(), "/workdir")
.WithImage(CommonImages.Alpine)
.WithLabel(DependsOnKey, DependsOnValue)
.Build();

public Task InitializeAsync()
{
return _container.StartAsync();
.WithLabel(_labelKey, _labelValue)
.Build();

var network = new NetworkBuilder()
.WithLabel(_labelKey, _labelValue)
.Build();

var volume = new VolumeBuilder()
.WithLabel(_labelKey, _labelValue)
.Build();

var parentContainer = new ContainerBuilder()
.DependsOn(childContainer1)
.DependsOn(childContainer2)
.DependsOn(network)
.DependsOn(volume, "/workdir")
.WithImage(CommonImages.Alpine)
.WithLabel(_labelKey, _labelValue)
.Build();

await parentContainer.StartAsync()
.ConfigureAwait(false);

_disposables.Add(parentContainer);
_disposables.Add(childContainer1);
_disposables.Add(childContainer2);
_disposables.Add(network);
_disposables.Add(volume);
}

public Task DisposeAsync()
{
return _container.DisposeAsync().AsTask();
return Task.WhenAll(_disposables.Select(disposable => disposable.DisposeAsync().AsTask()));
}

[Fact]
[Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))]
public async Task DependsOnCreatesDependentResources()
{
// Given
using var clientConfiguration = TestcontainersSettings.OS.DockerEndpointAuthConfig.GetDockerClientConfiguration(ResourceReaper.DefaultSessionId);
using var clientConfiguration = TestcontainersSettings.OS.DockerEndpointAuthConfig.GetDockerClientConfiguration(Guid.NewGuid());

using var client = clientConfiguration.CreateClient();

var labelFilter = new Dictionary<string, bool> { { string.Join("=", DependsOnKey, DependsOnValue), true } };

var filters = new Dictionary<string, IDictionary<string, bool>> { { "label", labelFilter } };

var containersListParameters = new ContainersListParameters { All = true, Filters = filters };
var containersListParameters = new ContainersListParameters { All = true, Filters = _filters };

var networksListParameters = new NetworksListParameters { Filters = filters };
var networksListParameters = new NetworksListParameters { Filters = _filters };

var volumesListParameters = new VolumesListParameters { Filters = filters };
var volumesListParameters = new VolumesListParameters { Filters = _filters };

// When
var containers = await client.Containers.ListContainersAsync(containersListParameters)
Expand All @@ -61,12 +81,12 @@ public async Task DependsOnCreatesDependentResources()
var networks = await client.Networks.ListNetworksAsync(networksListParameters)
.ConfigureAwait(true);

var volumesListResponse = await client.Volumes.ListAsync(volumesListParameters)
var response = await client.Volumes.ListAsync(volumesListParameters)
.ConfigureAwait(true);

// Then
Assert.Equal(3, containers.Count);
Assert.Single(networks);
Assert.Single(volumesListResponse.Volumes);
Assert.Single(response.Volumes);
}
}
38 changes: 25 additions & 13 deletions tests/Testcontainers.Platform.Linux.Tests/ReusableResourceTest.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
namespace Testcontainers.Tests;

public sealed class ReusableResourceTest : IAsyncLifetime, IDisposable
// We cannot run these tests in parallel because they interfere with the port
// forwarding tests. When the port forwarding container is running, Testcontainers
// automatically inject the necessary extra hosts into the builder configuration
// using `WithPortForwarding()` internally. Depending on when the test framework
// starts the port forwarding container, these extra hosts can lead to flakiness.
// This happens because the reuse hash changes, resulting in two containers with
// the same labels running instead of one.
[CollectionDefinition(nameof(ReusableResourceTest), DisableParallelization = true)]
[Collection(nameof(ReusableResourceTest))]
public sealed class ReusableResourceTest : IAsyncLifetime
{
private readonly DockerClient _dockerClient = TestcontainersSettings.OS.DockerEndpointAuthConfig.GetDockerClientConfiguration(Guid.NewGuid()).CreateClient();

private readonly FilterByProperty _filters = new FilterByProperty();

private readonly IList<IAsyncDisposable> _disposables = new List<IAsyncDisposable>();
Expand Down Expand Up @@ -63,31 +70,36 @@ public Task DisposeAsync()
}));
}

public void Dispose()
{
_dockerClient.Dispose();
}

[Fact]
public async Task ShouldReuseExistingResource()
{
var containers = await _dockerClient.Containers.ListContainersAsync(new ContainersListParameters { Filters = _filters })
using var clientConfiguration = TestcontainersSettings.OS.DockerEndpointAuthConfig.GetDockerClientConfiguration(Guid.NewGuid());

using var client = clientConfiguration.CreateClient();

var containersListParameters = new ContainersListParameters { All = true, Filters = _filters };

var networksListParameters = new NetworksListParameters { Filters = _filters };

var volumesListParameters = new VolumesListParameters { Filters = _filters };

var containers = await client.Containers.ListContainersAsync(containersListParameters)
.ConfigureAwait(true);

var networks = await _dockerClient.Networks.ListNetworksAsync(new NetworksListParameters { Filters = _filters })
var networks = await client.Networks.ListNetworksAsync(networksListParameters)
.ConfigureAwait(true);

var response = await _dockerClient.Volumes.ListAsync(new VolumesListParameters { Filters = _filters })
var response = await client.Volumes.ListAsync(volumesListParameters)
.ConfigureAwait(true);

Assert.Single(containers);
Assert.Single(networks);
Assert.Single(response.Volumes);
}

public static class ReuseHash
public static class ReuseHashTest
{
public sealed class NotEqual
public sealed class NotEqualTest
{
[Fact]
public void ForDifferentNames()
Expand Down

0 comments on commit 3bbe7c6

Please sign in to comment.