Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ private static string RelativePath(string name, [CallerFilePath] string sourceFi
name);
}

private static readonly JsonSerializerOptions IndentedDefaultJsonOptions = new()
{
WriteIndented = true,
};
private async Task<string> GetRoundTrippedIndentedSnapshot(string sourceSnapshotPath, [CallerMemberName] string fwDataProjectName = "")
{
var fwDataProject = new FwDataProject(
Expand All @@ -99,6 +103,6 @@ private async Task<string> GetRoundTrippedIndentedSnapshot(string sourceSnapshot
{
AllowTrailingCommas = true,
}) ?? throw new InvalidOperationException("Could not parse json node");
return node.ToJsonString(new JsonSerializerOptions { WriteIndented = true });
return node.ToJsonString(IndentedDefaultJsonOptions);
}
}
9 changes: 5 additions & 4 deletions backend/FwLite/FwLiteProjectSync.Tests/Sena3SyncTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ public class Sena3SyncTests : IClassFixture<Sena3Fixture>, IAsyncLifetime
private FwDataMiniLcmApi _fwDataApi = null!;
private TestProject _project = null!;
private MiniLcmImport _miniLcmImport = null!;
private static readonly JsonSerializerOptions IndentedDefaultJsonOptions = new()
{
WriteIndented = true,
};


public Sena3SyncTests(Sena3Fixture fixture)
Expand Down Expand Up @@ -228,10 +232,7 @@ public async Task LiveSena3Sync()
var throwAnyVerifyException = () => { if (verifyException is not null) throw verifyException; };
try
{
await Verify(JsonSerializer.Serialize(fwHeadlessSnapshot, new JsonSerializerOptions
{
WriteIndented = true,
}))
await Verify(JsonSerializer.Serialize(fwHeadlessSnapshot, IndentedDefaultJsonOptions))
.UseStrictJson()
.UseFileName("sena-3-live_snapshot");
}
Expand Down
22 changes: 11 additions & 11 deletions backend/FwLite/LcmCrdt.Tests/Changes/ChangeSerializationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ public void CanRoundTripChanges(IChange change)
//commit id is not serialized
change.CommitId = Guid.Empty;
var type = change.GetType();
var json = JsonSerializer.Serialize(change, Options);
var newChange = JsonSerializer.Deserialize(json, type, Options);
var json = JsonSerializer.Serialize(change, HarmonyJsonOptions);
var newChange = JsonSerializer.Deserialize(json, type, HarmonyJsonOptions);
newChange.Should().BeEquivalentTo(change);
}

Expand All @@ -89,7 +89,7 @@ public void CanDeserializeLatestRegressionData()
//changes are updated and appended by RegressionDataUpToDate() whenever it finds a "latest" change that doesn't stably round-trip
//or when it finds a change type that isn't represented
using var jsonFile = File.OpenRead(GetJsonFilePath("ChangeDeserializationRegressionData.latest.verified.txt"));
var changes = JsonSerializer.Deserialize<List<IChange>>(jsonFile, Options);
var changes = JsonSerializer.Deserialize<List<IChange>>(jsonFile, HarmonyJsonOptions);
changes.Should().NotBeNullOrEmpty().And.NotContainNulls();

//ensure that all change types are represented and none should be removed from AllChangeTypes
Expand All @@ -116,7 +116,7 @@ public void CanDeserializeLegacyRegressionData()
// when it detects that they don't stably round-trip and
// (2) keeps the round-trip output of the changes up to date
using var jsonFile = File.OpenRead(GetJsonFilePath("ChangeDeserializationRegressionData.legacy.verified.txt"));
var changes = JsonSerializer.Deserialize<List<LegacyChangeRecord>>(jsonFile, Options);
var changes = JsonSerializer.Deserialize<List<LegacyChangeRecord>>(jsonFile, HarmonyJsonOptions);
changes.Should().NotBeNullOrEmpty().And.NotContainNulls();
changes.SelectMany(c => new[] { c.Input, c.Output })
.Should().NotContainNulls()
Expand All @@ -138,9 +138,9 @@ public async Task RegressionDataUpToDate()
legacyJson.Should().NotBeNullOrWhiteSpace();
var legacyOutputJson = ToNormalizedIndentedJsonString(legacyJsonNode[nameof(LegacyChangeRecord.Output)]!);
legacyOutputJson.Should().NotBeNullOrWhiteSpace();
var change = JsonSerializer.Deserialize<IChange>(legacyJson, Options);
var change = JsonSerializer.Deserialize<IChange>(legacyJson, HarmonyJsonOptions);
change.Should().NotBeNull();
var newLegacyOutputJson = JsonSerializer.Serialize(change, OptionsIndented);
var newLegacyOutputJson = JsonSerializer.Serialize(change, IndentedHarmonyJsonOptions);
if (legacyOutputJson != newLegacyOutputJson)
{
//the legacy change no longer round-trips to the same output, so we should verify the new output
Expand All @@ -155,10 +155,10 @@ public async Task RegressionDataUpToDate()
latestJsonNode.Should().NotBeNull();
var latestJson = ToNormalizedIndentedJsonString(latestJsonNode);
latestJson.Should().NotBeNullOrWhiteSpace();
var change = JsonSerializer.Deserialize<IChange>(latestJsonNode, Options);
var change = JsonSerializer.Deserialize<IChange>(latestJsonNode, HarmonyJsonOptions);
change.Should().NotBeNull();
seenChangeTypes.Add(change.GetType());
var newLatestJson = JsonSerializer.Serialize(change, OptionsIndented);
var newLatestJson = JsonSerializer.Serialize(change, IndentedHarmonyJsonOptions);

if (latestJson != newLatestJson)
{
Expand All @@ -177,7 +177,7 @@ public async Task RegressionDataUpToDate()
// to generate and insert them manually. We can remove this if it's too noisy.
foreach (var generatedChange in GeneratedChangesForType(change.GetType()))
{
var serialized = JsonSerializer.Serialize(generatedChange, OptionsIndented);
var serialized = JsonSerializer.Serialize(generatedChange, IndentedHarmonyJsonOptions);
newLatestJsonArray.Add(JsonNode.Parse(serialized));
}
}
Expand All @@ -194,7 +194,7 @@ public async Task RegressionDataUpToDate()
{
foreach (var generatedChange in GeneratedChangesForType(changeType))
{
var serialized = JsonSerializer.Serialize(generatedChange, OptionsIndented);
var serialized = JsonSerializer.Serialize(generatedChange, IndentedHarmonyJsonOptions);
newLatestJsonArray.Add(JsonNode.Parse(serialized));
}
}
Expand All @@ -215,6 +215,6 @@ await Task.WhenAll(
public static void GenerateNewJsonFile()
{
using var jsonFile = File.Open(GetJsonFilePath("NewJson.json"), FileMode.Create);
JsonSerializer.Serialize(jsonFile, GeneratedChanges(), OptionsIndented);
JsonSerializer.Serialize(jsonFile, GeneratedChanges(), IndentedHarmonyJsonOptions);
}
}
25 changes: 11 additions & 14 deletions backend/FwLite/LcmCrdt.Tests/Data/BaseSerializationTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,11 @@ namespace LcmCrdt.Tests.Data;

public abstract class BaseSerializationTest
{
protected static readonly Lazy<JsonSerializerOptions> LazyOptions = new(() =>
protected static readonly JsonSerializerOptions HarmonyJsonOptions = new(TestJsonOptions.Harmony())
{
var options = TestJsonOptions.Harmony();
options.ReadCommentHandling = JsonCommentHandling.Skip;
return options;
});

protected static readonly JsonSerializerOptions Options = LazyOptions.Value;
protected static readonly JsonSerializerOptions OptionsIndented = new(Options)
ReadCommentHandling = JsonCommentHandling.Skip,
};
protected static readonly JsonSerializerOptions IndentedHarmonyJsonOptions = new(HarmonyJsonOptions)
{
WriteIndented = true,
};
Expand Down Expand Up @@ -72,13 +68,14 @@ protected static string GetJsonFilePath(string name, [CallerFilePath] string sou
name);
}

private static readonly JsonSerializerOptions RegressionJsonOptions = new()
{
WriteIndented = true,
Encoder = HarmonyJsonOptions.Encoder,
};
protected static string SerializeRegressionData(JsonArray jsonArray)
{
return JsonSerializer.Serialize(jsonArray, new JsonSerializerOptions
{
WriteIndented = true,
Encoder = Options.Encoder,
})
return JsonSerializer.Serialize(jsonArray, RegressionJsonOptions)
// The "+" in DateTimeOffsets does not get escaped by our standard crdt serializer,
// but it does here. Presumably, because it's reading it as a string and not a DateTimeOffset
.Replace("\\u002B", "+");
Expand All @@ -87,7 +84,7 @@ protected static string SerializeRegressionData(JsonArray jsonArray)
private static readonly JsonWriterOptions GenericJsonWriterOptions = new()
{
Indented = true,
Encoder = Options.Encoder,
Encoder = HarmonyJsonOptions.Encoder,
};

protected static string ToNormalizedIndentedJsonString(JsonNode element)
Expand Down
22 changes: 8 additions & 14 deletions backend/FwLite/LcmCrdt.Tests/Data/MigrationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ namespace LcmCrdt.Tests.Data;
public class MigrationTests : IAsyncLifetime
{
private readonly RegressionTestHelper _helper = new("MigrationTest");
private static readonly JsonSerializerOptions IndentedHarmonyJsonOptions = new(TestJsonOptions.Harmony())
{
WriteIndented = true
};

[ModuleInitializer]
internal static void Init()
Expand Down Expand Up @@ -56,11 +60,6 @@ public async Task VerifyAfterMigrationFromScriptedDb(RegressionTestHelper.Regres
await _helper.InitializeAsync(regressionVersion);
var api = _helper.Services.GetRequiredService<IMiniLcmApi>();
var crdtConfig = _helper.Services.GetRequiredService<IOptions<CrdtConfig>>().Value;
// todo use TestJsonOptions instead
var jsonSerializerOptions = new JsonSerializerOptions(crdtConfig.JsonSerializerOptions)
{
WriteIndented = true
};

await using var dbContext = await _helper.Services.GetRequiredService<ICrdtDbContextFactory>().CreateDbContextAsync();
var snapshots = await dbContext.Snapshots.AsNoTracking()
Expand All @@ -86,9 +85,9 @@ public async Task VerifyAfterMigrationFromScriptedDb(RegressionTestHelper.Regres
.ToArray();
var project = await TakeProjectSnapshot(api);

var snapshotsJson = JsonSerializer.Serialize(snapshots, jsonSerializerOptions);
var changesJson = JsonSerializer.Serialize(changes, jsonSerializerOptions);
var projectJson = JsonSerializer.Serialize(project, jsonSerializerOptions);
var snapshotsJson = JsonSerializer.Serialize(snapshots, IndentedHarmonyJsonOptions);
var changesJson = JsonSerializer.Serialize(changes, IndentedHarmonyJsonOptions);
var projectJson = JsonSerializer.Serialize(project, IndentedHarmonyJsonOptions);

await Task.WhenAll(
Verify(snapshotsJson)
Expand All @@ -112,11 +111,6 @@ public async Task VerifyRegeneratedSnapshotsAfterMigrationFromScriptedDb(Regress
await _helper.InitializeAsync(regressionVersion);
var api = _helper.Services.GetRequiredService<IMiniLcmApi>();
var crdtConfig = _helper.Services.GetRequiredService<IOptions<CrdtConfig>>().Value;
// todo use TestJsonOptions instead
var jsonSerializerOptions = new JsonSerializerOptions(crdtConfig.JsonSerializerOptions)
{
WriteIndented = true
};

await using var dbContext = await _helper.Services.GetRequiredService<ICrdtDbContextFactory>().CreateDbContextAsync();
await using var dataModel = _helper.Services.GetRequiredService<DataModel>();
Expand All @@ -142,7 +136,7 @@ public async Task VerifyRegeneratedSnapshotsAfterMigrationFromScriptedDb(Regress

// this happens to result in null properties being omitted, which is probably fine
// strangely VerifyJson(string).UseStrictJson() keeps null properties, but omits empty arrays and objects, which seems bizarre
var snapshotsJson = JsonSerializer.SerializeToDocument(latestSnapshots, jsonSerializerOptions);
var snapshotsJson = JsonSerializer.SerializeToDocument(latestSnapshots, IndentedHarmonyJsonOptions);

// it would be nice to only scrub the snapshot Guid, because those are the only ones that should be different,
// but Verify doesn't have a way to do that, so we just let it scrub all of them
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public void CanDeserializeProjectDumpRegressionData()
//nothing should ever be removed from this file
//this file represents projects which already have snapshots and changes applied, we want to ensure that we don't break anything.
using var jsonFile = File.OpenRead(GetJsonFilePath("SnapshotDeserializationRegressionData.ProjectDump.1.json"));
var snapshots = JsonSerializer.Deserialize<List<IObjectBase>>(jsonFile, Options);
var snapshots = JsonSerializer.Deserialize<List<IObjectBase>>(jsonFile, HarmonyJsonOptions);
snapshots.Should().NotBeNullOrEmpty().And.NotContainNulls();
}

Expand All @@ -56,7 +56,7 @@ public void CanDeserializeLatestRegressionData()
//or when it finds a snapshot type that isn't represented
//this file was initialized with a small selection of snapshots from a project dump
using var jsonFile = File.OpenRead(GetJsonFilePath("SnapshotDeserializationRegressionData.latest.verified.txt"));
var snapshots = JsonSerializer.Deserialize<List<IObjectBase>>(jsonFile, Options);
var snapshots = JsonSerializer.Deserialize<List<IObjectBase>>(jsonFile, HarmonyJsonOptions);
snapshots.Should().NotBeNullOrEmpty().And.NotContainNulls();

//ensure that all snapshot types are represented and none should be removed from AllObjectTypes
Expand All @@ -83,7 +83,7 @@ public void CanDeserializeLegacyRegressionData()
// when it detects that they don't stably round-trip and
// (2) keeps the round-trip output of the snapshots up to date
using var jsonFile = File.OpenRead(GetJsonFilePath("SnapshotDeserializationRegressionData.legacy.verified.txt"));
var snapshots = JsonSerializer.Deserialize<List<LegacySnapshotRecord>>(jsonFile, Options);
var snapshots = JsonSerializer.Deserialize<List<LegacySnapshotRecord>>(jsonFile, HarmonyJsonOptions);
snapshots.Should().NotBeNullOrEmpty().And.NotContainNulls();
snapshots.SelectMany(c => new[] { c.Input, c.Output })
.Should().NotContainNulls()
Expand All @@ -105,9 +105,9 @@ public async Task RegressionDataUpToDate()
legacyJson.Should().NotBeNullOrWhiteSpace();
var legacyOutputJson = ToNormalizedIndentedJsonString(legacyJsonNode[nameof(LegacySnapshotRecord.Output)]!);
legacyOutputJson.Should().NotBeNullOrWhiteSpace();
var snapshot = JsonSerializer.Deserialize<IObjectBase>(legacyJson, Options);
var snapshot = JsonSerializer.Deserialize<IObjectBase>(legacyJson, HarmonyJsonOptions);
snapshot.Should().NotBeNull();
var newLegacyOutputJson = JsonSerializer.Serialize(snapshot, OptionsIndented);
var newLegacyOutputJson = JsonSerializer.Serialize(snapshot, IndentedHarmonyJsonOptions);
if (legacyOutputJson != newLegacyOutputJson)
{
//the legacy snapshot no longer round-trips to the same output, so we should verify the new output
Expand All @@ -122,10 +122,10 @@ public async Task RegressionDataUpToDate()
latestJsonNode.Should().NotBeNull();
var latestJson = ToNormalizedIndentedJsonString(latestJsonNode);
latestJson.Should().NotBeNullOrWhiteSpace();
var snapshot = JsonSerializer.Deserialize<IObjectBase>(latestJsonNode, Options);
var snapshot = JsonSerializer.Deserialize<IObjectBase>(latestJsonNode, HarmonyJsonOptions);
snapshot.Should().NotBeNull();
seenObjectTypes.Add(snapshot.DbObject.GetType());
var newLatestJson = JsonSerializer.Serialize(snapshot, OptionsIndented);
var newLatestJson = JsonSerializer.Serialize(snapshot, IndentedHarmonyJsonOptions);

if (latestJson != newLatestJson)
{
Expand All @@ -143,7 +143,7 @@ public async Task RegressionDataUpToDate()
// Anyhow, it's much easier for a dev to remove unwanted snapshots than
// to generate and insert them manually. We can remove this if it's too noisy.
var generatedSnapshot = GenerateSnapshotForType(snapshot.DbObject.GetType());
var serialized = JsonSerializer.Serialize(generatedSnapshot, OptionsIndented);
var serialized = JsonSerializer.Serialize(generatedSnapshot, IndentedHarmonyJsonOptions);
newLatestJsonArray.Add(JsonNode.Parse(serialized));
}
else
Expand All @@ -158,7 +158,7 @@ public async Task RegressionDataUpToDate()
.Where(snapshotType => !seenObjectTypes.Contains(snapshotType)))
{
var generatedSnapshot = GenerateSnapshotForType(snapshotType);
var serialized = JsonSerializer.Serialize(generatedSnapshot, OptionsIndented);
var serialized = JsonSerializer.Serialize(generatedSnapshot, IndentedHarmonyJsonOptions);
newLatestJsonArray.Add(JsonNode.Parse(serialized));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace MiniLcm.Tests.RichText;

public class ColorJsonConverterTests
{
private JsonSerializerOptions options = new JsonSerializerOptions(JsonSerializerDefaults.General)
private static readonly JsonSerializerOptions ColorJsonOptions = new(JsonSerializerDefaults.General)
{
Converters = { new ColorJsonConverter() }
};
Expand All @@ -15,13 +15,13 @@ public class ColorJsonConverterTests
public void WritesTransparentToHexA()
{
Color? color = Color.Transparent;
JsonSerializer.Serialize(color, options).Should().Be("\"#00000000\"");
JsonSerializer.Serialize(color, ColorJsonOptions).Should().Be("\"#00000000\"");
}

[Fact]
public void ReadsTransparentToAnUnNamedColor()
{
var color = JsonSerializer.Deserialize<Color?>("\"#00000000\"", options);
var color = JsonSerializer.Deserialize<Color?>("\"#00000000\"", ColorJsonOptions);
color.Should().NotBeNull();
color.Value.IsKnownColor.Should().BeFalse();
color.Value.IsNamedColor.Should().BeFalse();
Expand Down
Loading