diff --git a/src/Testcontainers/Builders/ContainerBuilder`3.cs b/src/Testcontainers/Builders/ContainerBuilder`3.cs
index 468c894c9..ccdaf2d7d 100644
--- a/src/Testcontainers/Builders/ContainerBuilder`3.cs
+++ b/src/Testcontainers/Builders/ContainerBuilder`3.cs
@@ -206,6 +206,12 @@ public TBuilderEntity WithResourceMapping(byte[] resourceContent, string filePat
return WithResourceMapping(new BinaryResourceMapping(resourceContent, filePath, fileMode));
}
+ ///
+ public TBuilderEntity WithResourceMapping(byte[] resourceContent, FileInfo filePath, UnixFileModes fileMode = Unix.FileMode644)
+ {
+ return WithResourceMapping(new BinaryResourceMapping(resourceContent, filePath.FullName, fileMode));
+ }
+
///
public TBuilderEntity WithResourceMapping(string source, string target, UnixFileModes fileMode = Unix.FileMode644)
{
@@ -232,12 +238,24 @@ public TBuilderEntity WithResourceMapping(DirectoryInfo source, string target, U
return WithResourceMapping(new FileResourceMapping(source.FullName, target, fileMode));
}
+ ///
+ public TBuilderEntity WithResourceMapping(DirectoryInfo source, DirectoryInfo target, UnixFileModes fileMode = Unix.FileMode644)
+ {
+ return WithResourceMapping(new FileResourceMapping(source.FullName, target.FullName, fileMode));
+ }
+
///
public TBuilderEntity WithResourceMapping(FileInfo source, string target, UnixFileModes fileMode = Unix.FileMode644)
{
return WithResourceMapping(new FileResourceMapping(source.FullName, target, fileMode));
}
+ ///
+ public TBuilderEntity WithResourceMapping(FileInfo source, DirectoryInfo target, UnixFileModes fileMode = Unix.FileMode644)
+ {
+ return WithResourceMapping(new FileResourceMapping(source.FullName, target.FullName, fileMode));
+ }
+
///
public TBuilderEntity WithResourceMapping(FileInfo source, FileInfo target, UnixFileModes fileMode = Unix.FileMode644)
{
@@ -253,15 +271,31 @@ public TBuilderEntity WithResourceMapping(FileInfo source, FileInfo target, Unix
///
public TBuilderEntity WithResourceMapping(Uri source, string target, UnixFileModes fileMode = Unix.FileMode644)
+ {
+ return WithResourceMapping(source, new DirectoryInfo(target), fileMode);
+ }
+
+ ///
+ public TBuilderEntity WithResourceMapping(Uri source, DirectoryInfo target,
+ UnixFileModes fileMode = Unix.FileMode644)
{
if (source.IsFile)
{
- return WithResourceMapping(new FileResourceMapping(source.AbsolutePath, target, fileMode));
+ return WithResourceMapping(new FileResourceMapping(source.AbsolutePath, target.FullName, fileMode));
}
- else
+
+ return WithResourceMapping(new UriResourceMapping(source, target.FullName, fileMode));
+ }
+
+ ///
+ public TBuilderEntity WithResourceMapping(Uri source, FileInfo target, UnixFileModes fileMode = Unix.FileMode644)
+ {
+ if (source.IsFile)
{
- return WithResourceMapping(new UriResourceMapping(source, target, fileMode));
+ return WithResourceMapping(new FileInfo(source.AbsolutePath), target, fileMode);
}
+
+ return WithResourceMapping(new UriResourceMapping(source, target.FullName, fileMode));
}
///
diff --git a/src/Testcontainers/Builders/IContainerBuilder`2.cs b/src/Testcontainers/Builders/IContainerBuilder`2.cs
index 0493fcbe5..5e05dcb99 100644
--- a/src/Testcontainers/Builders/IContainerBuilder`2.cs
+++ b/src/Testcontainers/Builders/IContainerBuilder`2.cs
@@ -228,8 +228,19 @@ public interface IContainerBuilder : I
/// The POSIX file mode permission.
/// A configured instance of .
[PublicAPI]
+ [Obsolete("Use WithResourceMapping(byte[], FileInfo, UnixFileModes) instead.")]
TBuilderEntity WithResourceMapping(byte[] resourceContent, string filePath, UnixFileModes fileMode = Unix.FileMode644);
+ ///
+ /// Copies the byte array content to the created container before it starts.
+ ///
+ /// The byte array content of the resource mapping.
+ /// The target file path to copy the file to.
+ /// The POSIX file mode permission.
+ /// A configured instance of .
+ [PublicAPI]
+ TBuilderEntity WithResourceMapping(byte[] resourceContent, FileInfo filePath, UnixFileModes fileMode = Unix.FileMode644);
+
///
/// Copies the contents of a URL, a test host directory or file to the container before it starts.
///
@@ -246,6 +257,7 @@ public interface IContainerBuilder : I
/// The POSIX file mode permission.
/// A configured instance of .
[PublicAPI]
+ [Obsolete("Use one of the more specific WithResourceMapping(…) methods instead.")]
TBuilderEntity WithResourceMapping(string source, string target, UnixFileModes fileMode = Unix.FileMode644);
///
@@ -256,18 +268,40 @@ public interface IContainerBuilder : I
/// The POSIX file mode permission.
/// A configured instance of .
[PublicAPI]
+ [Obsolete("Use WithResourceMapping(DirectoryInfo, DirectoryInfo, UnixFileModes) instead.")]
TBuilderEntity WithResourceMapping(DirectoryInfo source, string target, UnixFileModes fileMode = Unix.FileMode644);
///
/// Copies a test host directory or file to the container before it starts.
///
+ /// The source directory to be copied.
+ /// The target directory path to copy the files to.
+ /// The POSIX file mode permission.
+ /// A configured instance of .
+ [PublicAPI]
+ TBuilderEntity WithResourceMapping(DirectoryInfo source, DirectoryInfo target, UnixFileModes fileMode = Unix.FileMode644);
+
+ ///
+ /// Copies a test host directory or file to the given directory in the container before it starts.
+ ///
/// The source file to be copied.
/// The target directory path to copy the file to.
/// The POSIX file mode permission.
/// A configured instance of .
[PublicAPI]
+ [Obsolete("Use WithResourceMapping(FileInfo, DirectoryInfo, UnixFileModes) instead.")]
TBuilderEntity WithResourceMapping(FileInfo source, string target, UnixFileModes fileMode = Unix.FileMode644);
+ ///
+ /// Copies a test host directory or file to the given directory in the container before it starts.
+ ///
+ /// The source file to be copied.
+ /// The target directory path to copy the file to.
+ /// The POSIX file mode permission.
+ /// A configured instance of .
+ [PublicAPI]
+ TBuilderEntity WithResourceMapping(FileInfo source, DirectoryInfo target, UnixFileModes fileMode = Unix.FileMode644);
+
///
/// Copies a test host file to the container before it starts.
///
@@ -295,8 +329,47 @@ public interface IContainerBuilder : I
/// The target directory or file path to copy the file to.
/// The POSIX file mode permission.
/// A configured instance of .
+ [PublicAPI]
+ [Obsolete("Use WithResourceMapping(Uri, FileInfo, UnixFileModes) or WithResourceMapping(Uri, DirectoryInfo, UnixFileModes) instead.")]
TBuilderEntity WithResourceMapping(Uri source, string target, UnixFileModes fileMode = Unix.FileMode644);
+ ///
+ /// Copies a file from a URL to the container before it starts.
+ ///
+ ///
+ /// If the Uri scheme corresponds to a file, the content is copied to the target
+ /// directory path. If the Uri scheme corresponds to HTTP or HTTPS, the content is
+ /// copied to the target file path.
+ ///
+ /// The Uri scheme must be either http, https or file.
+ ///
+ /// If you prefer to copy a file to a specific target file path instead of a
+ /// directory, use: .
+ ///
+ /// The source URL of the file to be copied.
+ /// The target directory path to copy the file to.
+ /// The POSIX file mode permission.
+ /// A configured instance of .
+ [PublicAPI]
+ TBuilderEntity WithResourceMapping(Uri source, DirectoryInfo target, UnixFileModes fileMode = Unix.FileMode644);
+
+ ///
+ /// Copies a file from a URL to the container before it starts.
+ ///
+ ///
+ /// If the Uri scheme corresponds to a file, the content is copied to the target
+ /// directory path. If the Uri scheme corresponds to HTTP or HTTPS, the content is
+ /// copied to the target file path.
+ ///
+ /// The Uri scheme must be either http, https or file.
+ ///
+ /// The source URL of the file to be copied.
+ /// The target file path to copy the file to.
+ /// The POSIX file mode permission.
+ /// A configured instance of .
+ [PublicAPI]
+ TBuilderEntity WithResourceMapping(Uri source, FileInfo target, UnixFileModes fileMode = Unix.FileMode644);
+
///
/// Assigns the mount configuration to manage data in the container.
///
diff --git a/tests/Testcontainers.Tests/Fixtures/Configurations/AlpineBuilderFixture.cs b/tests/Testcontainers.Tests/Fixtures/Configurations/AlpineBuilderFixture.cs
new file mode 100644
index 000000000..a1e5f7125
--- /dev/null
+++ b/tests/Testcontainers.Tests/Fixtures/Configurations/AlpineBuilderFixture.cs
@@ -0,0 +1,45 @@
+using System.Collections.Generic;
+
+namespace DotNet.Testcontainers.Tests.Fixtures
+{
+ using System;
+ using System.Threading.Tasks;
+ using DotNet.Testcontainers.Builders;
+ using DotNet.Testcontainers.Commons;
+ using DotNet.Testcontainers.Containers;
+ using JetBrains.Annotations;
+ using Xunit;
+
+ [UsedImplicitly]
+ public sealed class AlpineBuilderFixture : IAsyncLifetime
+ {
+ private readonly List _containers = [];
+
+ public IContainer Container(Func builder)
+ {
+ var containerBuilder = builder(new ContainerBuilder());
+
+ var container = containerBuilder
+ .WithImage(CommonImages.Alpine)
+ .WithCommand(CommonCommands.SleepInfinity)
+ .Build();
+
+ _containers.Add(container);
+
+ return container;
+ }
+
+ public ValueTask InitializeAsync()
+ {
+ return ValueTask.CompletedTask;
+ }
+
+ public async ValueTask DisposeAsync()
+ {
+ foreach (var container in _containers)
+ {
+ await container.DisposeAsync();
+ }
+ }
+ }
+}
diff --git a/tests/Testcontainers.Tests/Unit/Configurations/WithResourceMappingTest.cs b/tests/Testcontainers.Tests/Unit/Configurations/WithResourceMappingTest.cs
new file mode 100644
index 000000000..0ad557dac
--- /dev/null
+++ b/tests/Testcontainers.Tests/Unit/Configurations/WithResourceMappingTest.cs
@@ -0,0 +1,278 @@
+using System;
+using System.IO;
+
+namespace DotNet.Testcontainers.Tests.Unit
+{
+ using System.Threading.Tasks;
+ using DotNet.Testcontainers.Tests.Fixtures;
+ using Xunit;
+
+ public sealed class WithResourceMappingTest(AlpineBuilderFixture image) : IClassFixture
+ {
+ [Fact]
+ public async Task WithResourceMappingUriDirectoryInfo()
+ {
+ // Given
+ var hostDir = new DirectoryInfo(Path.GetTempPath()).CreateSubdirectory("test");
+ var hostFile = new FileInfo(Path.Combine(hostDir.FullName, "test.txt"));
+
+ var expectedContent = new byte[20];
+ Random.Shared.NextBytes(expectedContent);
+ using (var fileStream = hostFile.OpenWrite())
+ {
+ fileStream.Write(expectedContent, 0, expectedContent.Length);
+ }
+
+ // When
+ var container = image.Container(b =>
+ b.WithResourceMapping(new Uri($"file://{hostFile.FullName}"), new DirectoryInfo("/tmp/")));
+ await container.StartAsync(TestContext.Current.CancellationToken)
+ .ConfigureAwait(true);
+
+ // Then
+ var actualContent = await container.ReadFileAsync($"/tmp/{hostFile.Name}", TestContext.Current.CancellationToken)
+ .ConfigureAwait(true);
+ Assert.Equal(expectedContent, actualContent);
+ }
+
+ [Fact]
+ public async Task WithResourceMappingUriFileInfo()
+ {
+ // Given
+ var hostDir = new DirectoryInfo(Path.GetTempPath()).CreateSubdirectory("test");
+ var hostFile = new FileInfo(Path.Combine(hostDir.FullName, "test.txt"));
+
+ var expectedContent = new byte[20];
+ Random.Shared.NextBytes(expectedContent);
+ using (var fileStream = hostFile.OpenWrite())
+ {
+ fileStream.Write(expectedContent, 0, expectedContent.Length);
+ }
+
+ // When
+ var container = image.Container(b =>
+ b.WithResourceMapping(new Uri($"file://{hostFile.FullName}"), new FileInfo("/tmp/test.txt")));
+ await container.StartAsync(TestContext.Current.CancellationToken)
+ .ConfigureAwait(true);
+
+ // Then
+ var actualContent = await container.ReadFileAsync($"/tmp/test.txt", TestContext.Current.CancellationToken)
+ .ConfigureAwait(true);
+ Assert.Equal(expectedContent, actualContent);
+ }
+
+ [Fact]
+ public async Task WithResourceMappingUriString()
+ {
+ // Given
+ var hostDir = new DirectoryInfo(Path.GetTempPath()).CreateSubdirectory("test");
+ var hostFile = new FileInfo(Path.Combine(hostDir.FullName, "test.txt"));
+
+ var expectedContent = new byte[20];
+ Random.Shared.NextBytes(expectedContent);
+ using (var fileStream = hostFile.OpenWrite())
+ {
+ fileStream.Write(expectedContent, 0, expectedContent.Length);
+ }
+
+ // When
+ var container = image.Container(b =>
+ b.WithResourceMapping(new Uri($"file://{hostFile.FullName}"), "/tmp/"));
+ await container.StartAsync(TestContext.Current.CancellationToken)
+ .ConfigureAwait(true);
+
+ // Then
+ var actualContent = await container.ReadFileAsync($"/tmp/{hostFile.Name}", TestContext.Current.CancellationToken)
+ .ConfigureAwait(true);
+ Assert.Equal(expectedContent, actualContent);
+ }
+
+ [Fact]
+ public async Task WithResourceMappingStringString()
+ {
+ // Given
+ var hostDir = new DirectoryInfo(Path.GetTempPath()).CreateSubdirectory("test");
+ var hostFile = new FileInfo(Path.Combine(hostDir.FullName, "test.txt"));
+
+ var expectedContent = new byte[20];
+ Random.Shared.NextBytes(expectedContent);
+ using (var fileStream = hostFile.OpenWrite())
+ {
+ fileStream.Write(expectedContent, 0, expectedContent.Length);
+ }
+
+ // When
+ var container = image.Container(b =>
+ b.WithResourceMapping(hostDir.FullName, "/tmp"));
+ await container.StartAsync(TestContext.Current.CancellationToken)
+ .ConfigureAwait(true);
+
+ // Then
+ var actualContent = await container.ReadFileAsync($"/tmp/{hostFile.Name}", TestContext.Current.CancellationToken)
+ .ConfigureAwait(true);
+ Assert.Equal(expectedContent, actualContent);
+ }
+
+ [Fact]
+ public async Task WithResourceMappingDirectoryInfoDirectoryInfo()
+ {
+ // Given
+ var hostDir = new DirectoryInfo(Path.GetTempPath()).CreateSubdirectory("test");
+ var hostFile = new FileInfo(Path.Combine(hostDir.FullName, "test.txt"));
+
+ var expectedContent = new byte[20];
+ Random.Shared.NextBytes(expectedContent);
+ using (var fileStream = hostFile.OpenWrite())
+ {
+ fileStream.Write(expectedContent, 0, expectedContent.Length);
+ }
+
+ // When
+ var container = image.Container(b =>
+ b.WithResourceMapping(hostDir, new DirectoryInfo("/tmp/")));
+ await container.StartAsync(TestContext.Current.CancellationToken)
+ .ConfigureAwait(true);
+
+ // Then
+ var actualContent = await container.ReadFileAsync($"/tmp/{hostFile.Name}", TestContext.Current.CancellationToken)
+ .ConfigureAwait(true);
+ Assert.Equal(expectedContent, actualContent);
+ }
+
+ [Fact]
+ public async Task WithResourceMappingDirectoryInfoString()
+ {
+ // Given
+ var hostDir = new DirectoryInfo(Path.GetTempPath()).CreateSubdirectory("test");
+ var hostFile = new FileInfo(Path.Combine(hostDir.FullName, "test.txt"));
+
+ var expectedContent = new byte[20];
+ Random.Shared.NextBytes(expectedContent);
+ using (var fileStream = hostFile.OpenWrite())
+ {
+ fileStream.Write(expectedContent, 0, expectedContent.Length);
+ }
+
+ // When
+ var container = image.Container(b =>
+ b.WithResourceMapping(hostDir, "/tmp/"));
+ await container.StartAsync(TestContext.Current.CancellationToken)
+ .ConfigureAwait(true);
+
+ // Then
+ var actualContent = await container.ReadFileAsync($"/tmp/{hostFile.Name}", TestContext.Current.CancellationToken)
+ .ConfigureAwait(true);
+ Assert.Equal(expectedContent, actualContent);
+ }
+
+ [Fact]
+ public async Task WithResourceMappingFileInfoFileInfo()
+ {
+ // Given
+ var hostFile = new FileInfo(Path.GetTempFileName());
+ var expectedContent = new byte[20];
+ Random.Shared.NextBytes(expectedContent);
+ using (var fileStream = hostFile.OpenWrite())
+ {
+ fileStream.Write(expectedContent, 0, expectedContent.Length);
+ }
+
+ // When
+ var container = image.Container(b =>
+ b.WithResourceMapping(hostFile, new FileInfo("/tmp/test.txt")));
+ await container.StartAsync(TestContext.Current.CancellationToken)
+ .ConfigureAwait(true);
+
+ // Then
+ var actualContent = await container.ReadFileAsync("/tmp/test.txt", TestContext.Current.CancellationToken)
+ .ConfigureAwait(true);
+ Assert.Equal(expectedContent, actualContent);
+ }
+
+ [Fact]
+ public async Task WithResourceMappingFileInfoDirectoryInfo()
+ {
+ // Given
+ var hostFile = new FileInfo(Path.GetTempFileName());
+ var expectedContent = new byte[20];
+ Random.Shared.NextBytes(expectedContent);
+ using (var fileStream = hostFile.OpenWrite())
+ {
+ fileStream.Write(expectedContent, 0, expectedContent.Length);
+ }
+
+ // When
+ var container = image.Container(b =>
+ b.WithResourceMapping(hostFile, new DirectoryInfo("/tmp")));
+ await container.StartAsync(TestContext.Current.CancellationToken)
+ .ConfigureAwait(true);
+
+ // Then
+ var actualContent = await container.ReadFileAsync($"/tmp/{hostFile.Name}", TestContext.Current.CancellationToken)
+ .ConfigureAwait(true);
+ Assert.Equal(expectedContent, actualContent);
+ }
+
+ [Fact]
+ public async Task WithResourceMappingFileInfoString()
+ {
+ // Given
+ var hostFile = new FileInfo(Path.GetTempFileName());
+ var expectedContent = new byte[20];
+ Random.Shared.NextBytes(expectedContent);
+ using (var fileStream = hostFile.OpenWrite())
+ {
+ fileStream.Write(expectedContent, 0, expectedContent.Length);
+ }
+
+ // When
+ var container = image.Container(b =>
+ b.WithResourceMapping(hostFile, "/tmp/"));
+ await container.StartAsync(TestContext.Current.CancellationToken)
+ .ConfigureAwait(true);
+
+ // Then
+ var actualContent = await container.ReadFileAsync($"/tmp/{hostFile.Name}", TestContext.Current.CancellationToken)
+ .ConfigureAwait(true);
+ Assert.Equal(expectedContent, actualContent);
+ }
+
+ [Fact]
+ public async Task WithResourceMappingBytesString()
+ {
+ // Given
+ var expectedContent = new byte[100];
+ Random.Shared.NextBytes(expectedContent);
+
+ // When
+ var container = image.Container(b =>
+ b.WithResourceMapping(expectedContent, "/tmp/test.txt"));
+ await container.StartAsync(TestContext.Current.CancellationToken)
+ .ConfigureAwait(true);
+
+ // Then
+ var actualContent = await container.ReadFileAsync("/tmp/test.txt", TestContext.Current.CancellationToken)
+ .ConfigureAwait(true);
+ Assert.Equal(expectedContent, actualContent);
+ }
+
+ [Fact]
+ public async Task WithResourceMappingBytesFileInfo()
+ {
+ // Given
+ var expectedContent = new byte[100];
+ Random.Shared.NextBytes(expectedContent);
+
+ // When
+ var container = image.Container(b =>
+ b.WithResourceMapping(expectedContent, new FileInfo("/test.txt")));
+ await container.StartAsync(TestContext.Current.CancellationToken)
+ .ConfigureAwait(true);
+
+ // Then
+ var actualContent = await container.ReadFileAsync("/test.txt", TestContext.Current.CancellationToken)
+ .ConfigureAwait(true);
+ Assert.Equal(expectedContent, actualContent);
+ }
+ }
+}