Skip to content

Commit f7ff14c

Browse files
committed
[#203] #EXTEND 'assemblyName: DotNet.Testcontainers; function WaitForContainerWindows'
{Add UntilCommandIsCompleted and UntilPortIsAvailable for Windows container.}
1 parent a1e7770 commit f7ff14c

17 files changed

+124
-37
lines changed

azure-pipelines.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name: $(date:yyyyMMdd)$(rev:.r)
33
variables:
44
DOTNET_CLI_TELEMETRY_OPTOUT: true
55
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
6-
dotNetCoreVersion3: 3.1.100
6+
dotNetCoreVersion3: 3.1.101
77
dotNetCoreVersion2: 2.2.402
88
cakeVersion: 0.36.0
99

@@ -39,7 +39,6 @@ jobs:
3939
testFilter: FullyQualifiedName~DotNet.Testcontainers
4040

4141
# Run static code analysis and publish artifact.
42-
# Until now, we do not cover Windows only tests.
4342
- ${{ if in(variables['Build.SourceBranch'], 'refs/heads/master', 'refs/heads/develop') }}:
4443
- template: azure/publish.yml
4544
parameters:
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
namespace DotNet.Testcontainers.Tests.Unit.Containers
2+
{
3+
using System.IO;
4+
using System.Linq;
5+
using System.Threading.Tasks;
6+
using DotNet.Testcontainers.Containers.WaitStrategies;
7+
using Xunit;
8+
9+
public class WaitUntilMessageIsLogged
10+
{
11+
[Fact]
12+
public async Task UntilMessageIsLogged()
13+
{
14+
// Given
15+
const string expectedMessage = nameof(this.UntilMessageIsLogged);
16+
17+
// When
18+
// Then
19+
using (var memoryStream = new MemoryStream())
20+
{
21+
using (var streamWriter = new StreamWriter(memoryStream))
22+
{
23+
streamWriter.Write(expectedMessage);
24+
streamWriter.Flush();
25+
26+
var wait = Wait.ForUnixContainer().UntilMessageIsLogged(memoryStream, expectedMessage);
27+
await WaitStrategy.WaitUntil(() => wait.Build().Skip(1).First().Until(null, string.Empty));
28+
}
29+
}
30+
}
31+
}
32+
}

src/DotNet.Testcontainers.Tests/Unit/Containers/WaitUntilOperationSucceededTest.cs renamed to src/DotNet.Testcontainers.Tests/Unit/Containers/WaitUntilOperationIsSucceeded.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
namespace DotNet.Testcontainers.Tests.Unit.Containers
22
{
33
using System;
4+
using System.Linq;
45
using System.Threading.Tasks;
5-
using DotNet.Testcontainers.Clients;
6-
using DotNet.Testcontainers.Containers.WaitStrategies.Common;
7-
using Testcontainers.Containers.WaitStrategies;
6+
using DotNet.Testcontainers.Containers.WaitStrategies;
87
using Xunit;
98

10-
public class WaitUntilOperationSucceededTest
9+
public class WaitUntilOperationIsSucceeded
1110
{
1211
[Theory]
1312
[InlineData(1, 1)]
@@ -24,12 +23,13 @@ public async Task UntilMaxRepeats(int maxCallCount, int expectedCallsCount)
2423
// When
2524
await Assert.ThrowsAsync<TimeoutException>(async () =>
2625
{
27-
var wait = new UntilOperationIsSucceeded(() =>
26+
var wait = Wait.ForUnixContainer().UntilOperationIsSucceeded(() =>
2827
{
2928
callCounter += 1;
3029
return false;
3130
}, maxCallCount);
32-
await WaitStrategy.WaitUntil(() => wait.Until(DockerApiEndpoint.Local, string.Empty));
31+
32+
await WaitStrategy.WaitUntil(() => wait.Build().Skip(1).First().Until(null, string.Empty));
3333
});
3434

3535
// Then
@@ -51,8 +51,8 @@ public async Task UntilSomeRepeats(int maxCallCount, int expectedCallsCount)
5151
var callCounter = 0;
5252

5353
// When
54-
var wait = new UntilOperationIsSucceeded(() => ++callCounter >= expectedCallsCount, maxCallCount);
55-
await WaitStrategy.WaitUntil(() => wait.Until(DockerApiEndpoint.Local, string.Empty));
54+
var wait = Wait.ForUnixContainer().UntilOperationIsSucceeded(() => ++callCounter >= expectedCallsCount, maxCallCount);
55+
await WaitStrategy.WaitUntil(() => wait.Build().Skip(1).First().Until(null, string.Empty));
5656

5757
// Then
5858
Assert.Equal(expectedCallsCount, callCounter);

src/DotNet.Testcontainers.Tests/Unit/Containers/Windows/TestcontainersContainerTest.cs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,30 @@ public async Task IsWindowsEngineEnabled()
1919
}
2020

2121
[IgnoreOnLinuxEngine]
22-
public async Task SafeDisposable()
22+
public async Task UntilCommandIsCompleted()
2323
{
24-
// Given
2524
var testcontainersBuilder = new TestcontainersBuilder<TestcontainersContainer>()
26-
.WithImage("mcr.microsoft.com/windows/nanoserver:1809")
27-
.WithWaitStrategy(Wait.ForWindowsContainer());
25+
.WithImage("mcr.microsoft.com/windows/servercore:1809")
26+
.WithEntrypoint("PowerShell", "-Command", "Start-Sleep -Seconds 3600")
27+
.WithWaitStrategy(Wait.ForWindowsContainer()
28+
.UntilCommandIsCompleted("exit !(Test-Path -Path 'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe')"));
29+
30+
// When
31+
// Then
32+
await using (IDockerContainer testcontainer = testcontainersBuilder.Build())
33+
{
34+
await testcontainer.StartAsync();
35+
}
36+
}
37+
38+
[IgnoreOnLinuxEngine]
39+
public async Task UntilPortIsAvailable()
40+
{
41+
var testcontainersBuilder = new TestcontainersBuilder<TestcontainersContainer>()
42+
.WithImage("mcr.microsoft.com/windows/servercore:1809")
43+
.WithEntrypoint("PowerShell", "-Command", "$tcpListener = [System.Net.Sockets.TcpListener]1337; $tcpListener.Start(); Start-Sleep -Seconds 3600")
44+
.WithWaitStrategy(Wait.ForWindowsContainer()
45+
.UntilPortIsAvailable(1337));
2846

2947
// When
3048
// Then

src/DotNet.Testcontainers/Clients/DockerContainerOperations.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ namespace DotNet.Testcontainers.Clients
99
using Docker.DotNet.Models;
1010
using DotNet.Testcontainers.Containers.Configurations;
1111
using DotNet.Testcontainers.Containers.OutputConsumers;
12-
using DotNet.Testcontainers.Containers.OutputConsumers.Common;
1312
using DotNet.Testcontainers.Internals.Mappers;
1413

1514
internal sealed class DockerContainerOperations : DockerApiClient, IDockerContainerOperations
@@ -84,7 +83,7 @@ public Task RemoveAsync(string id, CancellationToken ct = default)
8483

8584
public async Task AttachAsync(string id, IOutputConsumer outputConsumer, CancellationToken ct = default)
8685
{
87-
if (outputConsumer is null || outputConsumer is DoNotConsumeStdoutOrStderr)
86+
if (outputConsumer is null)
8887
{
8988
return;
9089
}

src/DotNet.Testcontainers/Containers/WaitStrategies/IWaitForContainerOS.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,20 @@ public interface IWaitForContainerOS
2323
/// </summary>
2424
/// <param name="command">Command to be executed</param>
2525
/// <returns>A configured instance of <see cref="IWaitForContainerOS" />.</returns>
26+
/// <remarks>Invokes the operating system command shell. Expects the exit code to be 0.</remarks>
2627
IWaitForContainerOS UntilCommandIsCompleted(string command);
2728

29+
/// <summary>
30+
/// Waits until the command is completed successfully.
31+
/// </summary>
32+
/// <param name="command">Command to be executed</param>
33+
/// <returns>A configured instance of <see cref="IWaitForContainerOS" />.</returns>
34+
/// <remarks>
35+
/// Does not invoke the operating system command shell.
36+
/// Normal shell processing does not happen. Expects the exit code to be 0.
37+
/// </remarks>
38+
IWaitForContainerOS UntilCommandIsCompleted(params string[] command);
39+
2840
/// <summary>
2941
/// Waits until the file exists.
3042
/// </summary>

src/DotNet.Testcontainers/Containers/WaitStrategies/Unix/UntilCommandIsCompleted.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,20 @@ namespace DotNet.Testcontainers.Containers.WaitStrategies.Unix
66

77
internal class UntilCommandIsCompleted : IWaitUntil
88
{
9-
private readonly string command;
9+
private readonly string[] command;
1010

11-
public UntilCommandIsCompleted(string command)
11+
public UntilCommandIsCompleted(string command) : this("/bin/sh", "-c", command)
12+
{
13+
}
14+
15+
public UntilCommandIsCompleted(params string[] command)
1216
{
1317
this.command = command;
1418
}
1519

1620
public virtual async Task<bool> Until(Uri endpoint, string id)
1721
{
18-
var exitCode = await new TestcontainersClient(endpoint).ExecAsync(id, new[] { "/bin/sh", "-c", this.command });
22+
var exitCode = await new TestcontainersClient(endpoint).ExecAsync(id, this.command);
1923
return 0L.Equals(exitCode);
2024
}
2125
}

src/DotNet.Testcontainers/Containers/WaitStrategies/WaitForContainerOS.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ internal abstract class WaitForContainerOS : IWaitForContainerOS
1212

1313
public abstract IWaitForContainerOS UntilCommandIsCompleted(string command);
1414

15+
public abstract IWaitForContainerOS UntilCommandIsCompleted(params string[] command);
16+
1517
public abstract IWaitForContainerOS UntilPortIsAvailable(int port);
1618

1719
protected WaitForContainerOS()

src/DotNet.Testcontainers/Containers/WaitStrategies/WaitForContainerUnix.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ public override IWaitForContainerOS UntilCommandIsCompleted(string command)
1212
return this;
1313
}
1414

15+
/// <inheritdoc />
16+
public override IWaitForContainerOS UntilCommandIsCompleted(params string[] command)
17+
{
18+
this.AddCustomWaitStrategy(new UntilCommandIsCompleted(command));
19+
return this;
20+
}
21+
1522
/// <inheritdoc />
1623
public override IWaitForContainerOS UntilPortIsAvailable(int port)
1724
{

src/DotNet.Testcontainers/Containers/WaitStrategies/WaitForContainerWindows.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ public override IWaitForContainerOS UntilCommandIsCompleted(string command)
1212
return this;
1313
}
1414

15+
/// <inheritdoc />
16+
public override IWaitForContainerOS UntilCommandIsCompleted(params string[] command)
17+
{
18+
this.AddCustomWaitStrategy(new UntilCommandIsCompleted(command));
19+
return this;
20+
}
21+
1522
/// <inheritdoc />
1623
public override IWaitForContainerOS UntilPortIsAvailable(int port)
1724
{

0 commit comments

Comments
 (0)