Skip to content

Commit 6369cac

Browse files
committed
Implement stable reuse hashes by sorting dictionary keys
Fixes #1553
1 parent c5a366f commit 6369cac

File tree

3 files changed

+43
-22
lines changed

3 files changed

+43
-22
lines changed
Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,20 @@
11
namespace DotNet.Testcontainers.Configurations
22
{
3-
using System;
43
using System.Collections.Generic;
54
using System.Linq;
65
using System.Text.Json;
7-
using System.Text.Json.Serialization;
86
using DotNet.Testcontainers.Clients;
97
using DotNet.Testcontainers.Containers;
108

11-
internal sealed class JsonIgnoreRuntimeResourceLabels : JsonConverter<IReadOnlyDictionary<string, string>>
9+
internal sealed class JsonIgnoreRuntimeResourceLabels : JsonOrderedKeysConverter
1210
{
1311
private static readonly ISet<string> IgnoreLabels = new HashSet<string> { ResourceReaper.ResourceReaperSessionLabel, TestcontainersClient.TestcontainersVersionLabel, TestcontainersClient.TestcontainersSessionIdLabel };
1412

15-
public override bool CanConvert(Type typeToConvert)
16-
{
17-
return typeof(IEnumerable<KeyValuePair<string, string>>).IsAssignableFrom(typeToConvert);
18-
}
19-
20-
public override IReadOnlyDictionary<string, string> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
21-
{
22-
return JsonSerializer.Deserialize<IReadOnlyDictionary<string, string>>(ref reader);
23-
}
24-
2513
public override void Write(Utf8JsonWriter writer, IReadOnlyDictionary<string, string> value, JsonSerializerOptions options)
2614
{
2715
var labels = value.Where(label => !IgnoreLabels.Contains(label.Key)).ToDictionary(label => label.Key, label => label.Value);
2816

29-
writer.WriteStartObject();
30-
31-
foreach (var label in labels)
32-
{
33-
writer.WriteString(label.Key, label.Value);
34-
}
35-
36-
writer.WriteEndObject();
17+
base.Write(writer, labels, options);
3718
}
3819
}
3920
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
namespace DotNet.Testcontainers.Configurations
2+
{
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Text.Json;
7+
using System.Text.Json.Serialization;
8+
9+
internal class JsonOrderedKeysConverter : JsonConverter<IReadOnlyDictionary<string, string>>
10+
{
11+
public override bool CanConvert(Type typeToConvert)
12+
{
13+
return typeof(IEnumerable<KeyValuePair<string, string>>).IsAssignableFrom(typeToConvert);
14+
}
15+
16+
public override IReadOnlyDictionary<string, string> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
17+
{
18+
return JsonSerializer.Deserialize<IReadOnlyDictionary<string, string>>(ref reader);
19+
}
20+
21+
public override void Write(Utf8JsonWriter writer, IReadOnlyDictionary<string, string> value, JsonSerializerOptions options)
22+
{
23+
writer.WriteStartObject();
24+
25+
foreach (var item in value.OrderBy(item => item.Key))
26+
{
27+
writer.WriteString(item.Key, item.Value);
28+
}
29+
30+
writer.WriteEndObject();
31+
}
32+
}
33+
}

src/Testcontainers/Configurations/Commons/ResourceConfiguration.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ namespace DotNet.Testcontainers.Configurations
1414
[PublicAPI]
1515
public class ResourceConfiguration<TCreateResourceEntity> : IResourceConfiguration<TCreateResourceEntity>
1616
{
17+
private static readonly JsonSerializerOptions JsonSerializerOptions;
18+
19+
static ResourceConfiguration()
20+
{
21+
JsonSerializerOptions = new JsonSerializerOptions { Converters = { new JsonOrderedKeysConverter() } };
22+
}
23+
1724
/// <summary>
1825
/// Initializes a new instance of the <see cref="ResourceConfiguration{TCreateResourceEntity}" /> class.
1926
/// </summary>
@@ -88,7 +95,7 @@ protected ResourceConfiguration(IResourceConfiguration<TCreateResourceEntity> ol
8895
/// <inheritdoc />
8996
public virtual string GetReuseHash()
9097
{
91-
var jsonUtf8Bytes = JsonSerializer.SerializeToUtf8Bytes(this, GetType());
98+
var jsonUtf8Bytes = JsonSerializer.SerializeToUtf8Bytes(this, GetType(), JsonSerializerOptions);
9299

93100
#if NET6_0_OR_GREATER
94101
return Convert.ToBase64String(SHA1.HashData(jsonUtf8Bytes));

0 commit comments

Comments
 (0)