Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Extend the "wait until file exists" API to distinguish between the test host and container filesystem #1009

Merged
merged 3 commits into from
Nov 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions src/Testcontainers/Configurations/FileSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace DotNet.Testcontainers.Configurations
{
using JetBrains.Annotations;

/// <summary>
/// Indicates the file system for file operations.
/// </summary>
[PublicAPI]
public enum FileSystem
{
/// <summary>
/// The test host file system.
/// </summary>
Host = 0,

/// <summary>
/// The container file system.
/// </summary>
Container = 1,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,11 @@ public interface IWaitForContainerOS
/// <summary>
/// Waits until the file exists.
/// </summary>
/// <param name="file">The file to be checked.</param>
/// <param name="filePath">The file path to be checked.</param>
/// <param name="fileSystem">The file system to be checked.</param>
/// <returns>A configured instance of <see cref="IWaitForContainerOS" />.</returns>
[PublicAPI]
IWaitForContainerOS UntilFileExists(string file);
IWaitForContainerOS UntilFileExists(string filePath, FileSystem fileSystem = FileSystem.Host);

/// <summary>
/// Waits until the message is logged.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
namespace DotNet.Testcontainers.Configurations
{
using System.IO;
using System.Threading.Tasks;
using DotNet.Testcontainers.Containers;

internal class UntilFileExistsInContainer : IWaitUntil
{
private readonly string _file;

public UntilFileExistsInContainer(string file)
{
_file = file;
}

public async Task<bool> UntilAsync(IContainer container)
{
try
{
_ = await container.ReadFileAsync(_file)
.ConfigureAwait(false);

return true;
}
catch (FileNotFoundException)
{
return false;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ namespace DotNet.Testcontainers.Configurations
using System.Threading.Tasks;
using DotNet.Testcontainers.Containers;

internal class UntilFilesExists : IWaitUntil
internal class UntilFileExistsOnHost : IWaitUntil
{
private readonly string _file;

public UntilFilesExists(string file)
public UntilFileExistsOnHost(string file)
{
_file = file;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,16 @@ public virtual IWaitForContainerOS AddCustomWaitStrategy(IWaitUntil waitStrategy
}

/// <inheritdoc />
public virtual IWaitForContainerOS UntilFileExists(string file)
public virtual IWaitForContainerOS UntilFileExists(string filePath, FileSystem fileSystem = FileSystem.Host)
{
return AddCustomWaitStrategy(new UntilFilesExists(file));
switch (fileSystem)
{
case FileSystem.Container:
return AddCustomWaitStrategy(new UntilFileExistsInContainer(filePath));
case FileSystem.Host:
default:
return AddCustomWaitStrategy(new UntilFileExistsOnHost(filePath));
}
}

/// <inheritdoc />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
namespace DotNet.Testcontainers.Tests.Unit
{
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using DotNet.Testcontainers.Builders;
using DotNet.Testcontainers.Commons;
using DotNet.Testcontainers.Configurations;
using DotNet.Testcontainers.Containers;
using Xunit;

public sealed class WaitUntilFileExistsInContainerTest : IAsyncLifetime, IDisposable
{
private const string ContainerFilePath = "/tmp/hostname";

private readonly CancellationTokenSource _cts = new CancellationTokenSource(TimeSpan.FromMinutes(1));

private readonly IContainer _container = new ContainerBuilder()
.WithImage(CommonImages.Alpine)
.WithEntrypoint("/bin/sh", "-c")
.WithCommand("hostname > " + ContainerFilePath + "; trap : TERM INT; sleep infinity & wait")
.WithWaitStrategy(Wait.ForUnixContainer().UntilFileExists(ContainerFilePath, FileSystem.Container))
.Build();

public Task InitializeAsync()
{
return _container.StartAsync(_cts.Token);
}

public Task DisposeAsync()
{
return _container.DisposeAsync().AsTask();
}

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

[Fact]
public async Task ContainerIsRunning()
{
var execResult = await _container.ExecAsync(new List<string> { "test", "-f", ContainerFilePath })
.ConfigureAwait(false);

Assert.Equal(0, execResult.ExitCode);
}
}
}