From d7b4f14473abfbf4ec6cb717a7d03d78224c3d6b Mon Sep 17 00:00:00 2001 From: Andre Hofmeister <9199345+HofmeisterAn@users.noreply.github.com> Date: Sun, 3 Mar 2024 09:38:28 +0100 Subject: [PATCH] fix: Remove Sonar findings, enhance reuse docs --- docs/api/resource_reuse.md | 21 +++++++++++++++++++ .../Commons/ResourceConfiguration.cs | 4 ++++ .../Volumes/UriResourceMapping.cs | 5 +++++ .../Containers/ResourceReaper.cs | 6 +++--- src/Testcontainers/Images/IgnoreFile.cs | 2 +- 5 files changed, 34 insertions(+), 4 deletions(-) diff --git a/docs/api/resource_reuse.md b/docs/api/resource_reuse.md index d104edebb..3f04c6901 100644 --- a/docs/api/resource_reuse.md +++ b/docs/api/resource_reuse.md @@ -15,6 +15,27 @@ _ = new ContainerBuilder() .WithLabel("reuse-id", "WeatherForecast"); ``` +The current implementation considers the following resource configurations and their corresponding builder APIs when calculating the hash value. + +- [ContainerConfiguration](https://github.com/testcontainers/testcontainers-dotnet/blob/develop/src/Testcontainers/Configurations/Containers/ContainerConfiguration.cs) + - Image + - Entrypoint + - Command + - Environments + - ExposedPorts + - PortBindings + - NetworkAliases + - ExtraHosts + - Labels +- [NetworkConfiguration](https://github.com/testcontainers/testcontainers-dotnet/blob/develop/src/Testcontainers/Configurations/Networks/NetworkConfiguration.cs) + - Name + - Labels +- [VolumeConfiguration](https://github.com/testcontainers/testcontainers-dotnet/blob/develop/src/Testcontainers/Configurations/Volumes/VolumeConfiguration.cs) + - Name + - Labels + +By default, all module resource configurations are included. This works well for simple value and reference types that can be serialized and deserialized to JSON without custom converters. However, more complex resource configurations may require a custom converter to properly serialize and deserialize their values. + !!!warning Reuse does not replace singleton implementations to improve test performance. Prefer proper shared instances according to your chosen test framework. diff --git a/src/Testcontainers/Configurations/Commons/ResourceConfiguration.cs b/src/Testcontainers/Configurations/Commons/ResourceConfiguration.cs index 0fa813bdf..4f6c3660d 100644 --- a/src/Testcontainers/Configurations/Commons/ResourceConfiguration.cs +++ b/src/Testcontainers/Configurations/Commons/ResourceConfiguration.cs @@ -81,10 +81,14 @@ public virtual string GetReuseHash() { var jsonUtf8Bytes = JsonSerializer.SerializeToUtf8Bytes(this, GetType()); +#if NET6_0_OR_GREATER + return Convert.ToBase64String(SHA1.HashData(jsonUtf8Bytes)); +#else using (var sha1 = SHA1.Create()) { return Convert.ToBase64String(sha1.ComputeHash(jsonUtf8Bytes)); } +#endif } } } diff --git a/src/Testcontainers/Configurations/Volumes/UriResourceMapping.cs b/src/Testcontainers/Configurations/Volumes/UriResourceMapping.cs index 132a56ed3..10c3a6f68 100644 --- a/src/Testcontainers/Configurations/Volumes/UriResourceMapping.cs +++ b/src/Testcontainers/Configurations/Volumes/UriResourceMapping.cs @@ -52,8 +52,13 @@ public async Task GetAllBytesAsync(CancellationToken ct = default) { using (var httpClient = new HttpClient()) { +#if NET6_0_OR_GREATER + return await httpClient.GetByteArrayAsync(_uri, ct) + .ConfigureAwait(false); +#else return await httpClient.GetByteArrayAsync(_uri) .ConfigureAwait(false); +#endif } } } diff --git a/src/Testcontainers/Containers/ResourceReaper.cs b/src/Testcontainers/Containers/ResourceReaper.cs index c068998e9..ee7fc6442 100644 --- a/src/Testcontainers/Containers/ResourceReaper.cs +++ b/src/Testcontainers/Containers/ResourceReaper.cs @@ -279,7 +279,7 @@ private async Task MaintainRyukConnection(TaskCompletionSource ryukInitial { if (!TryGetEndpoint(out var host, out var port)) { - await Task.Delay(TimeSpan.FromSeconds(RetryTimeoutInSeconds), default(CancellationToken)) + await Task.Delay(TimeSpan.FromSeconds(RetryTimeoutInSeconds), CancellationToken.None) .ConfigureAwait(false); continue; @@ -389,14 +389,14 @@ await Task.Delay(TimeSpan.FromSeconds(RetryTimeoutInSeconds), ct) { _resourceReaperContainer.Logger.CanNotConnectToResourceReaper(SessionId, host, port, e); - await Task.Delay(TimeSpan.FromSeconds(RetryTimeoutInSeconds), default(CancellationToken)) + await Task.Delay(TimeSpan.FromSeconds(RetryTimeoutInSeconds), CancellationToken.None) .ConfigureAwait(false); } catch (Exception e) { _resourceReaperContainer.Logger.LostConnectionToResourceReaper(SessionId, host, port, e); - await Task.Delay(TimeSpan.FromSeconds(RetryTimeoutInSeconds), default(CancellationToken)) + await Task.Delay(TimeSpan.FromSeconds(RetryTimeoutInSeconds), CancellationToken.None) .ConfigureAwait(false); } } diff --git a/src/Testcontainers/Images/IgnoreFile.cs b/src/Testcontainers/Images/IgnoreFile.cs index ae135a6be..cd18fc47d 100644 --- a/src/Testcontainers/Images/IgnoreFile.cs +++ b/src/Testcontainers/Images/IgnoreFile.cs @@ -136,7 +136,7 @@ private interface ISearchAndReplace public bool Accepts(string file) { var matches = _ignorePatterns.AsParallel().Where(ignorePattern => ignorePattern.Key.IsMatch(file)).ToArray(); - return !matches.Any() || matches[matches.Length - 1].Value; + return matches.Length == 0 || matches[matches.Length - 1].Value; } ///