diff --git a/Directory.Packages.props b/Directory.Packages.props index d37617bbf..79222b5b3 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -57,7 +57,7 @@ - + diff --git a/src/Testcontainers/Configurations/WaitStrategies/RetryLimitExceededException.cs b/src/Testcontainers/Configurations/WaitStrategies/RetryLimitExceededException.cs index 17b3621c0..8dd1f8420 100644 --- a/src/Testcontainers/Configurations/WaitStrategies/RetryLimitExceededException.cs +++ b/src/Testcontainers/Configurations/WaitStrategies/RetryLimitExceededException.cs @@ -1,4 +1,4 @@ -namespace DotNet.Testcontainers.Configurations +namespace DotNet.Testcontainers.Configurations { using System; diff --git a/src/Testcontainers/Containers/DockerContainer.cs b/src/Testcontainers/Containers/DockerContainer.cs index d18658eec..3a6fbdffb 100644 --- a/src/Testcontainers/Containers/DockerContainer.cs +++ b/src/Testcontainers/Containers/DockerContainer.cs @@ -261,34 +261,34 @@ public Task GetExitCodeAsync(CancellationToken ct = default) /// public virtual async Task StartAsync(CancellationToken ct = default) { - using (_ = AcquireLock()) - { - var futureResources = Array.Empty() - .Concat(_configuration.Mounts) - .Concat(_configuration.Networks); + using var disposable = await AcquireLockAsync(ct) + .ConfigureAwait(false); - await Task.WhenAll(futureResources.Select(resource => resource.CreateAsync(ct))) - .ConfigureAwait(false); + var futureResources = Array.Empty() + .Concat(_configuration.Mounts) + .Concat(_configuration.Networks); - await Task.WhenAll(_configuration.Containers.Select(resource => resource.StartAsync(ct))) - .ConfigureAwait(false); + await Task.WhenAll(futureResources.Select(resource => resource.CreateAsync(ct))) + .ConfigureAwait(false); - await UnsafeCreateAsync(ct) - .ConfigureAwait(false); + await Task.WhenAll(_configuration.Containers.Select(resource => resource.StartAsync(ct))) + .ConfigureAwait(false); - await UnsafeStartAsync(ct) - .ConfigureAwait(false); - } + await UnsafeCreateAsync(ct) + .ConfigureAwait(false); + + await UnsafeStartAsync(ct) + .ConfigureAwait(false); } /// public virtual async Task StopAsync(CancellationToken ct = default) { - using (_ = AcquireLock()) - { - await UnsafeStopAsync(ct) - .ConfigureAwait(false); - } + using var disposable = await AcquireLockAsync(ct) + .ConfigureAwait(false); + + await UnsafeStopAsync(ct) + .ConfigureAwait(false); } /// @@ -344,7 +344,8 @@ protected override async ValueTask DisposeAsyncCore() return; } - using (_ = AcquireLock()) + using (_ = await AcquireLockAsync() + .ConfigureAwait(false)) { if (Guid.Empty.Equals(_configuration.SessionId)) { diff --git a/src/Testcontainers/Images/FutureDockerImage.cs b/src/Testcontainers/Images/FutureDockerImage.cs index 6a48e787e..02271788b 100644 --- a/src/Testcontainers/Images/FutureDockerImage.cs +++ b/src/Testcontainers/Images/FutureDockerImage.cs @@ -77,21 +77,21 @@ public string GetHostname() /// public async Task CreateAsync(CancellationToken ct = default) { - using (_ = AcquireLock()) - { - await UnsafeCreateAsync(ct) - .ConfigureAwait(false); - } + using var disposable = await AcquireLockAsync(ct) + .ConfigureAwait(false); + + await UnsafeCreateAsync(ct) + .ConfigureAwait(false); } /// public async Task DeleteAsync(CancellationToken ct = default) { - using (_ = AcquireLock()) - { - await UnsafeDeleteAsync(ct) - .ConfigureAwait(false); - } + using var disposable = await AcquireLockAsync(ct) + .ConfigureAwait(false); + + await UnsafeDeleteAsync(ct) + .ConfigureAwait(false); } /// diff --git a/src/Testcontainers/Networks/DockerNetwork.cs b/src/Testcontainers/Networks/DockerNetwork.cs index 9c8086eaf..7db085d82 100644 --- a/src/Testcontainers/Networks/DockerNetwork.cs +++ b/src/Testcontainers/Networks/DockerNetwork.cs @@ -43,21 +43,21 @@ public string Name /// public async Task CreateAsync(CancellationToken ct = default) { - using (_ = AcquireLock()) - { - await UnsafeCreateAsync(ct) - .ConfigureAwait(false); - } + using var disposable = await AcquireLockAsync(ct) + .ConfigureAwait(false); + + await UnsafeCreateAsync(ct) + .ConfigureAwait(false); } /// public async Task DeleteAsync(CancellationToken ct = default) { - using (_ = AcquireLock()) - { - await UnsafeDeleteAsync(ct) - .ConfigureAwait(false); - } + using var disposable = await AcquireLockAsync(ct) + .ConfigureAwait(false); + + await UnsafeDeleteAsync(ct) + .ConfigureAwait(false); } /// diff --git a/src/Testcontainers/Resource.cs b/src/Testcontainers/Resource.cs index 7f5a4795b..d8d0a8c2d 100644 --- a/src/Testcontainers/Resource.cs +++ b/src/Testcontainers/Resource.cs @@ -60,9 +60,12 @@ protected virtual ValueTask DisposeAsyncCore() /// /// Acquires a lock to access the resource thread-safe. /// - /// An that releases the lock on . - protected virtual IDisposable AcquireLock() + /// A that releases the lock on . + protected virtual async Task AcquireLockAsync(CancellationToken ct = default) { + await _semaphoreSlim.WaitAsync(ct) + .ConfigureAwait(false); + return new Lock(_semaphoreSlim); } @@ -102,7 +105,6 @@ private sealed class Lock : IDisposable public Lock(SemaphoreSlim semaphoreSlim) { _semaphoreSlim = semaphoreSlim; - _semaphoreSlim.Wait(); } public void Dispose() diff --git a/src/Testcontainers/Testcontainers.csproj b/src/Testcontainers/Testcontainers.csproj index 7280cbb10..1ee127eba 100644 --- a/src/Testcontainers/Testcontainers.csproj +++ b/src/Testcontainers/Testcontainers.csproj @@ -1,6 +1,7 @@ net6.0;net8.0;netstandard2.0;netstandard2.1 + latest Debug;Release DotNet.Testcontainers diff --git a/src/Testcontainers/Volumes/DockerVolume.cs b/src/Testcontainers/Volumes/DockerVolume.cs index 2f0e44a4b..3062b44b0 100644 --- a/src/Testcontainers/Volumes/DockerVolume.cs +++ b/src/Testcontainers/Volumes/DockerVolume.cs @@ -43,21 +43,21 @@ public string Name /// public async Task CreateAsync(CancellationToken ct = default) { - using (_ = AcquireLock()) - { - await UnsafeCreateAsync(ct) - .ConfigureAwait(false); - } + using var disposable = await AcquireLockAsync(ct) + .ConfigureAwait(false); + + await UnsafeCreateAsync(ct) + .ConfigureAwait(false); } /// public async Task DeleteAsync(CancellationToken ct = default) { - using (_ = AcquireLock()) - { - await UnsafeDeleteAsync(ct) - .ConfigureAwait(false); - } + using var disposable = await AcquireLockAsync(ct) + .ConfigureAwait(false); + + await UnsafeDeleteAsync(ct) + .ConfigureAwait(false); } /// diff --git a/tests/Testcontainers.Platform.Linux.Tests/WaitStrategyTest.cs b/tests/Testcontainers.Platform.Linux.Tests/WaitStrategyTest.cs index 0bcddbb26..ad23a1cc6 100644 --- a/tests/Testcontainers.Platform.Linux.Tests/WaitStrategyTest.cs +++ b/tests/Testcontainers.Platform.Linux.Tests/WaitStrategyTest.cs @@ -1,4 +1,4 @@ -namespace Testcontainers.Tests; +namespace Testcontainers.Tests; public sealed class WaitStrategyTest {