From b07234a060167d2acd163acc40432662cd63b480 Mon Sep 17 00:00:00 2001
From: Andre Hofmeister <9199345+HofmeisterAn@users.noreply.github.com>
Date: Sat, 7 Sep 2024 12:04:15 +0200
Subject: [PATCH 1/4] refactor: Align IImage and DockerImage impl with DSL
---
.../Builders/ContainerBuilder`3.cs | 2 +-
.../DockerRegistryAuthenticationProvider.cs | 1 -
...tlessUnixEndpointAuthenticationProvider.cs | 3 +-
src/Testcontainers/Images/DockerImage.cs | 120 +++++++++++-------
.../Images/FutureDockerImage.cs | 24 +++-
src/Testcontainers/Images/IImage.cs | 21 ++-
src/Testcontainers/Images/MatchImage.cs | 37 ++++--
.../Fixtures/Images/HealthCheckFixture.cs | 6 +-
...ockerRegistryAuthenticationProviderTest.cs | 10 +-
.../Unit/Images/TestcontainersImageTest.cs | 5 +-
10 files changed, 153 insertions(+), 76 deletions(-)
diff --git a/src/Testcontainers/Builders/ContainerBuilder`3.cs b/src/Testcontainers/Builders/ContainerBuilder`3.cs
index a41a049b2..5bc8509eb 100644
--- a/src/Testcontainers/Builders/ContainerBuilder`3.cs
+++ b/src/Testcontainers/Builders/ContainerBuilder`3.cs
@@ -80,7 +80,7 @@ public TBuilderEntity WithImage(IImage image)
return Clone(new ContainerConfiguration(image: image));
}
- return Clone(new ContainerConfiguration(image: new DockerImage(image.Repository, image.Name, image.Tag, TestcontainersSettings.HubImageNamePrefix)));
+ return Clone(new ContainerConfiguration(image: new DockerImage(image.Repository, image.Registry, image.Tag, image.Digest, TestcontainersSettings.HubImageNamePrefix)));
}
///
diff --git a/src/Testcontainers/Builders/DockerRegistryAuthenticationProvider.cs b/src/Testcontainers/Builders/DockerRegistryAuthenticationProvider.cs
index f0fed9f40..73bbfcede 100644
--- a/src/Testcontainers/Builders/DockerRegistryAuthenticationProvider.cs
+++ b/src/Testcontainers/Builders/DockerRegistryAuthenticationProvider.cs
@@ -2,7 +2,6 @@ namespace DotNet.Testcontainers.Builders
{
using System;
using System.Collections.Concurrent;
- using System.IO;
using System.Linq;
using System.Text.Json;
using DotNet.Testcontainers.Configurations;
diff --git a/src/Testcontainers/Builders/RootlessUnixEndpointAuthenticationProvider.cs b/src/Testcontainers/Builders/RootlessUnixEndpointAuthenticationProvider.cs
index ac758ae53..e8e1d6f6d 100644
--- a/src/Testcontainers/Builders/RootlessUnixEndpointAuthenticationProvider.cs
+++ b/src/Testcontainers/Builders/RootlessUnixEndpointAuthenticationProvider.cs
@@ -2,7 +2,6 @@ namespace DotNet.Testcontainers.Builders
{
using System;
using System.IO;
- using System.Linq;
using System.Runtime.InteropServices;
using DotNet.Testcontainers.Configurations;
using JetBrains.Annotations;
@@ -27,7 +26,7 @@ public RootlessUnixEndpointAuthenticationProvider()
/// A list of socket paths.
public RootlessUnixEndpointAuthenticationProvider(params string[] socketPaths)
{
- var socketPath = socketPaths.FirstOrDefault(File.Exists);
+ var socketPath = Array.Find(socketPaths, File.Exists);
DockerEngine = socketPath == null ? null : new Uri("unix://" + socketPath);
}
diff --git a/src/Testcontainers/Images/DockerImage.cs b/src/Testcontainers/Images/DockerImage.cs
index 8347b3fbe..f5f2ba00c 100644
--- a/src/Testcontainers/Images/DockerImage.cs
+++ b/src/Testcontainers/Images/DockerImage.cs
@@ -1,8 +1,7 @@
-namespace DotNet.Testcontainers.Images
+namespace DotNet.Testcontainers.Images
{
using System;
using System.Globalization;
- using System.Linq;
using System.Text.RegularExpressions;
using JetBrains.Annotations;
@@ -14,24 +13,31 @@ public sealed class DockerImage : IImage
private const string NightlyTag = "nightly";
+ private static readonly char[] TrimChars = [' ', ':', '/'];
+
private static readonly Func GetDockerImage = MatchImage.Match;
- private static readonly char[] TrimChars = { ' ', ':', '/' };
+ [NotNull]
+ private readonly string _repository;
- private static readonly char[] HostnameIdentifierChars = { '.', ':' };
+ [CanBeNull]
+ private readonly string _registry;
- private readonly string _hubImageNamePrefix;
+ [CanBeNull]
+ private readonly string _tag;
- private readonly Lazy _lazyFullName;
+ [CanBeNull]
+ private readonly string _digit;
- private readonly Lazy _lazyHostname;
+ [CanBeNull]
+ private readonly string _hubImageNamePrefix;
///
/// Initializes a new instance of the class.
///
/// The image.
public DockerImage(IImage image)
- : this(image.Repository, image.Name, image.Tag)
+ : this(image.Repository, image.Registry, image.Tag, image.Digest)
{
}
@@ -39,8 +45,7 @@ public DockerImage(IImage image)
/// Initializes a new instance of the class.
///
/// The image.
- /// Thrown when any argument is null.
- /// "fedora/httpd:version1.0" where "fedora" is the repository, "httpd" the name and "version1.0" the tag.
+ /// fedora/httpd:version1.0 where fedora/httpd is the repository and version1.0 the tag.
public DockerImage(string image)
: this(GetDockerImage(image))
{
@@ -51,65 +56,78 @@ public DockerImage(string image)
///
/// The repository.
/// The name.
+ [Obsolete("We will remove this construct and replace it with a more efficient implementation. Please use 'DockerImage(string, string = null, string = null, string = null, string = null)' instead. All arguments except for 'repository' (the first) are optional.")]
+ public DockerImage(string repository, string name)
+ : this(string.Join("/", repository, name).Trim('/'))
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The repository.
+ /// The name.
+ /// The tag.
+ [Obsolete("We will remove this construct and replace it with a more efficient implementation. Please use 'DockerImage(string, string = null, string = null, string = null, string = null)' instead. All arguments except for 'repository' (the first) are optional.")]
+ public DockerImage(string repository, string name, string tag)
+ : this(string.Join("/", repository, name).Trim('/') + (":" + tag).TrimEnd(':'))
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The repository.
+ /// The registry.
/// The tag.
+ /// The digest.
/// The Docker Hub image name prefix.
- /// Thrown when any argument is null.
- /// "fedora/httpd:version1.0" where "fedora" is the repository, "httpd" the name and "version1.0" the tag.
+ /// fedora/httpd:version1.0 where fedora/httpd is the repository and version1.0 the tag.
public DockerImage(
string repository,
- string name,
+ string registry = null,
string tag = null,
+ string digest = null,
string hubImageNamePrefix = null)
{
_ = Guard.Argument(repository, nameof(repository))
- .NotNull()
- .NotUppercase();
-
- _ = Guard.Argument(name, nameof(name))
.NotNull()
.NotEmpty()
.NotUppercase();
- _hubImageNamePrefix = TrimOrDefault(hubImageNamePrefix);
+ var defaultTag = tag == null && digest == null ? LatestTag : null;
- Repository = TrimOrDefault(repository, repository);
- Name = TrimOrDefault(name, name);
- Tag = TrimOrDefault(tag, LatestTag);
-
- _lazyFullName = new Lazy(() =>
- {
- var imageComponents = new[] { _hubImageNamePrefix, Repository, Name }
- .Where(imageComponent => !string.IsNullOrEmpty(imageComponent));
+ _repository = TrimOrDefault(repository);
+ _registry = TrimOrDefault(registry);
+ _tag = TrimOrDefault(tag, defaultTag);
+ _digit = TrimOrDefault(digest);
+ _hubImageNamePrefix = TrimOrDefault(hubImageNamePrefix);
+ }
- return string.Join("/", imageComponents) + ":" + Tag;
- });
+ ///
+ public string Repository => _repository;
- _lazyHostname = new Lazy(() =>
- {
- var firstSegmentOfRepository = new[] { _hubImageNamePrefix, Repository }
- .Where(imageComponent => !string.IsNullOrEmpty(imageComponent))
- .DefaultIfEmpty(string.Empty)
- .First()
- .Split('/')[0];
-
- return firstSegmentOfRepository.IndexOfAny(HostnameIdentifierChars) >= 0 ? firstSegmentOfRepository : null;
- });
- }
+ ///
+ public string Registry => string.IsNullOrEmpty(_hubImageNamePrefix) ? _registry : _hubImageNamePrefix;
///
- public string Repository { get; }
+ public string Tag => _tag;
///
- public string Name { get; }
+ public string Digest => _digit;
///
- public string Tag { get; }
+ public string FullName => $"{Registry}/{Repository}:{Tag}".Trim(TrimChars);
///
- public string FullName => _lazyFullName.Value;
+ [Obsolete("We will remove this property, it does not follow the DSL. Use the 'Repository' property instead.")]
+ public string Name => GetBackwardsCompatibleName();
///
- public string GetHostname() => _lazyHostname.Value;
+ public string GetHostname()
+ {
+ return Registry;
+ }
///
public bool MatchLatestOrNightly()
@@ -126,6 +144,11 @@ public bool MatchVersion(Predicate predicate)
///
public bool MatchVersion(Predicate predicate)
{
+ if (Tag == null)
+ {
+ return false;
+ }
+
var versionMatch = Regex.Match(Tag, "^(\\d+)(\\.\\d+)?(\\.\\d+)?", RegexOptions.None, TimeSpan.FromSeconds(1));
if (!versionMatch.Success)
@@ -142,7 +165,14 @@ public bool MatchVersion(Predicate predicate)
return predicate(new Version(int.Parse(versionMatch.Groups[1].Value, NumberStyles.None), 0));
}
- private static string TrimOrDefault(string value, string defaultValue = default)
+ private string GetBackwardsCompatibleName()
+ {
+ // The last index will never be a `/`, we trim it in the constructor.
+ var lastIndex = _repository.LastIndexOf('/');
+ return lastIndex == -1 ? _repository : _repository.Substring(lastIndex + 1);
+ }
+
+ private static string TrimOrDefault(string value, string defaultValue = null)
{
return string.IsNullOrEmpty(value) ? defaultValue : value.Trim(TrimChars);
}
diff --git a/src/Testcontainers/Images/FutureDockerImage.cs b/src/Testcontainers/Images/FutureDockerImage.cs
index 23817169d..9b4f0cd77 100644
--- a/src/Testcontainers/Images/FutureDockerImage.cs
+++ b/src/Testcontainers/Images/FutureDockerImage.cs
@@ -39,12 +39,12 @@ public string Repository
}
///
- public string Name
+ public string Registry
{
get
{
ThrowIfResourceNotFound();
- return _configuration.Image.Name;
+ return _configuration.Image.Registry;
}
}
@@ -58,6 +58,16 @@ public string Tag
}
}
+ ///
+ public string Digest
+ {
+ get
+ {
+ ThrowIfResourceNotFound();
+ return _configuration.Image.Digest;
+ }
+ }
+
///
public string FullName
{
@@ -68,6 +78,16 @@ public string FullName
}
}
+ ///
+ public string Name
+ {
+ get
+ {
+ ThrowIfResourceNotFound();
+ return _configuration.Image.Name;
+ }
+ }
+
///
public string GetHostname()
{
diff --git a/src/Testcontainers/Images/IImage.cs b/src/Testcontainers/Images/IImage.cs
index 307879d23..41cec17ae 100644
--- a/src/Testcontainers/Images/IImage.cs
+++ b/src/Testcontainers/Images/IImage.cs
@@ -16,17 +16,23 @@ public interface IImage
string Repository { get; }
///
- /// Gets the name.
+ /// Gets the registry.
///
- [NotNull]
- string Name { get; }
+ [CanBeNull]
+ string Registry { get; }
///
/// Gets the tag.
///
- [NotNull]
+ [CanBeNull]
string Tag { get; }
+ ///
+ /// Gets the digest.
+ ///
+ [CanBeNull]
+ string Digest { get; }
+
///
/// Gets the full image name.
///
@@ -36,6 +42,13 @@ public interface IImage
[NotNull]
string FullName { get; }
+ ///
+ /// Gets the name.
+ ///
+ [NotNull]
+ [Obsolete("We will remove this property, it does not follow the DSL. Use the 'Repository' property instead.")]
+ string Name { get; }
+
///
/// Gets the registry hostname.
///
diff --git a/src/Testcontainers/Images/MatchImage.cs b/src/Testcontainers/Images/MatchImage.cs
index 58c5d227f..3be5b114b 100644
--- a/src/Testcontainers/Images/MatchImage.cs
+++ b/src/Testcontainers/Images/MatchImage.cs
@@ -1,37 +1,48 @@
namespace DotNet.Testcontainers.Images
{
using System;
- using System.Linq;
+ using System.Text.RegularExpressions;
internal static class MatchImage
{
- private static readonly char[] SlashSeparator = { '/' };
-
- private static readonly char[] ColonSeparator = { ':' };
-
public static IImage Match(string image)
{
_ = Guard.Argument(image, nameof(image))
.NotNull()
.NotEmpty();
- var imageComponents = image.Split(SlashSeparator, StringSplitOptions.RemoveEmptyEntries);
+ var referenceMatch = ReferenceRegex.Instance.Match(image);
+ var remoteName = referenceMatch.Groups["remote_name"].Value;
+ var tag = referenceMatch.Groups["tag"].Value;
+ var digest = referenceMatch.Groups["digest"].Value;
- var registry = string.Join("/", imageComponents.Take(imageComponents.Length - 1));
+ // https://github.com/distribution/reference/blob/8c942b0459dfdcc5b6685581dd0a5a470f615bff/normalize.go#L146-L191
+ var slices = remoteName.Split(['/'], 2);
- imageComponents = imageComponents[imageComponents.Length - 1].Split(ColonSeparator, StringSplitOptions.RemoveEmptyEntries);
+ // The following part does not implement the entire Go implementation. It does
+ // not resolve or set the default domain and repository prefix. This is not
+ // necessary at the moment, and it is something we can address later.
+ var (registry, repository) = slices.Length == 2 && slices[0].LastIndexOfAny(['.', ':']) > -1 ? (slices[0], slices[1]) : (null, remoteName);
+ return new DockerImage(repository, registry, tag, digest);
+ }
+
+ // The regular expression used here is taken from the Go implementation:
+ // https://github.com/distribution/reference/blob/8c942b0459dfdcc5b6685581dd0a5a470f615bff/reference.go.
+ private sealed class ReferenceRegex : Regex
+ {
+ private const string Pattern = "^(?(?:(?:(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])(?:\\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))*|\\[(?:[a-fA-F0-9:]+)\\])(?::[0-9]+)?\\/)?[a-z0-9]+(?:(?:[._]|__|[-]+)[a-z0-9]+)*(?:\\/[a-z0-9]+(?:(?:[._]|__|[-]+)[a-z0-9]+)*)*)(?::(?[\\w][\\w.-]{0,127}))?(?:@(?[A-Za-z][A-Za-z0-9]*(?:[-_+.][A-Za-z][A-Za-z0-9]*)*[:][0-9A-Fa-f]{32,}))?$";
- if (2.Equals(imageComponents.Length))
+ static ReferenceRegex()
{
- return new DockerImage(registry, imageComponents[0], imageComponents[1]);
}
- if (1.Equals(imageComponents.Length))
+ private ReferenceRegex()
+ : base(Pattern, RegexOptions.Compiled, TimeSpan.FromSeconds(1))
{
- return new DockerImage(registry, imageComponents[0], string.Empty);
}
- throw new ArgumentException("Cannot parse image: " + image, nameof(image));
+ public static Regex Instance { get; }
+ = new ReferenceRegex();
}
}
}
diff --git a/tests/Testcontainers.Tests/Fixtures/Images/HealthCheckFixture.cs b/tests/Testcontainers.Tests/Fixtures/Images/HealthCheckFixture.cs
index 932c95526..4d0b31837 100644
--- a/tests/Testcontainers.Tests/Fixtures/Images/HealthCheckFixture.cs
+++ b/tests/Testcontainers.Tests/Fixtures/Images/HealthCheckFixture.cs
@@ -17,12 +17,16 @@ public sealed class HealthCheckFixture : IImage, IAsyncLifetime
public string Repository => _image.Repository;
- public string Name => _image.Name;
+ public string Registry => _image.Registry;
public string Tag => _image.Tag;
+ public string Digest => _image.Digest;
+
public string FullName => _image.FullName;
+ public string Name => _image.Name;
+
public string GetHostname()
{
return _image.GetHostname();
diff --git a/tests/Testcontainers.Tests/Unit/Configurations/DockerRegistryAuthenticationProviderTest.cs b/tests/Testcontainers.Tests/Unit/Configurations/DockerRegistryAuthenticationProviderTest.cs
index 2a954c030..ab140d8f2 100644
--- a/tests/Testcontainers.Tests/Unit/Configurations/DockerRegistryAuthenticationProviderTest.cs
+++ b/tests/Testcontainers.Tests/Unit/Configurations/DockerRegistryAuthenticationProviderTest.cs
@@ -45,13 +45,13 @@ public void GetHostnameFromDockerImage(string dockerImageName, string hostname)
}
[Theory]
- [InlineData("", "docker", "stable")]
- [InlineData("fedora", "httpd", "1.0")]
- [InlineData("foo/bar", "baz", "1.0.0")]
- public void GetHostnameFromHubImageNamePrefix(string repository, string name, string tag)
+ [InlineData("baz/foo/bar", null)]
+ [InlineData("baz/foo/bar", "")]
+ [InlineData("baz/foo/bar", "1.0.0")]
+ public void GetHostnameFromHubImageNamePrefix(string repository, string tag)
{
const string hubImageNamePrefix = "myregistry.azurecr.io";
- IImage image = new DockerImage(repository, name, tag, hubImageNamePrefix);
+ IImage image = new DockerImage(repository, null, tag, null, hubImageNamePrefix);
Assert.Equal(hubImageNamePrefix, image.GetHostname());
}
diff --git a/tests/Testcontainers.Tests/Unit/Images/TestcontainersImageTest.cs b/tests/Testcontainers.Tests/Unit/Images/TestcontainersImageTest.cs
index af5ff7a43..940e06744 100644
--- a/tests/Testcontainers.Tests/Unit/Images/TestcontainersImageTest.cs
+++ b/tests/Testcontainers.Tests/Unit/Images/TestcontainersImageTest.cs
@@ -12,7 +12,6 @@ public void ShouldThrowArgumentNullExceptionWhenInstantiateDockerImage()
{
Assert.Throws(() => new DockerImage((string)null));
Assert.Throws(() => new DockerImage(null, null));
- Assert.Throws(() => new DockerImage("fedora", null));
}
[Fact]
@@ -55,9 +54,11 @@ public void WhenImageNameGetsAssigned(DockerImageFixtureSerializable serializabl
// Then
Assert.Equal(expected.Repository, dockerImage.Repository);
- Assert.Equal(expected.Name, dockerImage.Name);
+ Assert.Equal(expected.Registry, dockerImage.Registry);
Assert.Equal(expected.Tag, dockerImage.Tag);
+ Assert.Equal(expected.Digest, dockerImage.Digest);
Assert.Equal(expected.FullName, dockerImage.FullName);
+ Assert.Equal(expected.Name, dockerImage.Name);
}
[Fact]
From 15b495fc45929793824ca0177dbe6acee72b27f5 Mon Sep 17 00:00:00 2001
From: Andre Hofmeister <9199345+HofmeisterAn@users.noreply.github.com>
Date: Mon, 9 Sep 2024 16:37:54 +0200
Subject: [PATCH 2/4] chore: Throw exception for invalid reference format
---
Directory.Build.props | 2 +-
src/Testcontainers.Pulsar/PulsarContainer.cs | 2 +-
src/Testcontainers/Images/MatchImage.cs | 7 +++++++
.../DockerRegistryAuthenticationProviderTest.cs | 7 +++----
tests/Testcontainers.Tests/Unit/GuardTest.cs | 4 ++--
.../Unit/Images/TestcontainersImageTest.cs | 8 ++++++++
6 files changed, 22 insertions(+), 8 deletions(-)
diff --git a/Directory.Build.props b/Directory.Build.props
index 93cab1326..f0c488fef 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -2,7 +2,7 @@
$(AssemblyName)
- 3.11.0
+ 4.0.0
$(Version)
$(Version)
Testcontainers
diff --git a/src/Testcontainers.Pulsar/PulsarContainer.cs b/src/Testcontainers.Pulsar/PulsarContainer.cs
index 927e60e5d..3989fe7f4 100644
--- a/src/Testcontainers.Pulsar/PulsarContainer.cs
+++ b/src/Testcontainers.Pulsar/PulsarContainer.cs
@@ -56,7 +56,7 @@ public async Task CreateAuthenticationTokenAsync(TimeSpan expiryTime, Ca
"--secret-key",
PulsarBuilder.SecretKeyFilePath,
"--subject",
- PulsarBuilder.Username
+ PulsarBuilder.Username,
};
if (!Timeout.InfiniteTimeSpan.Equals(expiryTime))
diff --git a/src/Testcontainers/Images/MatchImage.cs b/src/Testcontainers/Images/MatchImage.cs
index 3be5b114b..681fe4330 100644
--- a/src/Testcontainers/Images/MatchImage.cs
+++ b/src/Testcontainers/Images/MatchImage.cs
@@ -1,6 +1,7 @@
namespace DotNet.Testcontainers.Images
{
using System;
+ using System.Globalization;
using System.Text.RegularExpressions;
internal static class MatchImage
@@ -11,7 +12,13 @@ public static IImage Match(string image)
.NotNull()
.NotEmpty();
+ const string invalidReferenceFormat = "Error parsing reference: '{0}' is not a valid repository/tag.";
+
var referenceMatch = ReferenceRegex.Instance.Match(image);
+
+ _ = Guard.Argument(referenceMatch, nameof(image))
+ .ThrowIf(argument => !argument.Value.Success, argument => new ArgumentException(string.Format(CultureInfo.InvariantCulture, invalidReferenceFormat, image), argument.Name));
+
var remoteName = referenceMatch.Groups["remote_name"].Value;
var tag = referenceMatch.Groups["tag"].Value;
var digest = referenceMatch.Groups["digest"].Value;
diff --git a/tests/Testcontainers.Tests/Unit/Configurations/DockerRegistryAuthenticationProviderTest.cs b/tests/Testcontainers.Tests/Unit/Configurations/DockerRegistryAuthenticationProviderTest.cs
index ab140d8f2..8be2f65b3 100644
--- a/tests/Testcontainers.Tests/Unit/Configurations/DockerRegistryAuthenticationProviderTest.cs
+++ b/tests/Testcontainers.Tests/Unit/Configurations/DockerRegistryAuthenticationProviderTest.cs
@@ -34,10 +34,7 @@ public sealed class DockerRegistryAuthenticationProviderTest
[InlineData("fedora/httpd:version1.0", null)]
[InlineData("myregistryhost:5000/fedora/httpd:version1.0", "myregistryhost:5000")]
[InlineData("myregistryhost:5000/httpd:version1.0", "myregistryhost:5000")]
- [InlineData("baz/.foo/bar:1.0.0", null)]
- [InlineData("baz/:foo/bar:1.0.0", null)]
[InlineData("myregistry.azurecr.io/baz.foo/bar:1.0.0", "myregistry.azurecr.io")]
- [InlineData("myregistry.azurecr.io/baz:foo/bar:1.0.0", "myregistry.azurecr.io")]
public void GetHostnameFromDockerImage(string dockerImageName, string hostname)
{
IImage image = new DockerImage(dockerImageName);
@@ -58,7 +55,9 @@ public void GetHostnameFromHubImageNamePrefix(string repository, string tag)
[Fact]
public void ShouldGetDefaultDockerRegistryAuthenticationConfiguration()
{
- var authenticationProvider = new DockerRegistryAuthenticationProvider(DockerConfig.Instance, NullLogger.Instance);
+ // Make sure the auth provider does not accidentally read the user's `config.json` file.
+ ICustomConfiguration customConfiguration = new PropertiesFileConfiguration(new[] { "docker.config=" + Path.Combine("C:", "CON") });
+ var authenticationProvider = new DockerRegistryAuthenticationProvider(new DockerConfig(customConfiguration), NullLogger.Instance);
Assert.Equal(default(DockerRegistryAuthenticationConfiguration), authenticationProvider.GetAuthConfig("index.docker.io"));
}
diff --git a/tests/Testcontainers.Tests/Unit/GuardTest.cs b/tests/Testcontainers.Tests/Unit/GuardTest.cs
index 76b95f10f..e13ef47b3 100644
--- a/tests/Testcontainers.Tests/Unit/GuardTest.cs
+++ b/tests/Testcontainers.Tests/Unit/GuardTest.cs
@@ -12,7 +12,7 @@ public sealed class DoNotThrowException
[Fact]
public void IfNull()
{
- var exception = Record.Exception(() => Guard.Argument((object)null, nameof(IfNull)).Null());
+ var exception = Record.Exception(() => Guard.Argument