using System.Text.Json; using MultiversalDiplomacy.Adjudicate; using MultiversalDiplomacy.Adjudicate.Decision; using MultiversalDiplomacy.Model; using NUnit.Framework; namespace MultiversalDiplomacyTests; public class SerializationTest { private JsonSerializerOptions Options = new(World.JsonOptions) { WriteIndented = true, }; [Test] public void SerializeRoundTrip_Timelines() { Timelines one = Timelines.Create(); string serial1 = JsonSerializer.Serialize(one, Options); Timelines two = JsonSerializer.Deserialize(serial1, Options) ?? throw new AssertionException("Failed to deserialize"); Assert.That(two.Next, Is.EqualTo(one.Next), "Failed to reserialize next timeline"); Assert.That(two.Pasts, Is.EquivalentTo(one.Pasts), "Failed to reserialize pasts"); Timelines three = two .WithNewSeason(Season.First, out var a1) .WithNewSeason(a1, out var a2) .WithNewSeason(a1, out var b2); string serial2 = JsonSerializer.Serialize(three, Options); Timelines four = JsonSerializer.Deserialize(serial2, Options) ?? throw new AssertionException("Failed to deserialize"); Assert.That(four.Next, Is.EqualTo(three.Next), "Failed to reserialize next timeline"); Assert.That(four.Pasts, Is.EquivalentTo(three.Pasts), "Failed to reserialize pasts"); } [Test] public void SerializeRoundTrip_NewGame() { World world = World.WithStandardMap(); JsonElement document = JsonSerializer.SerializeToDocument(world, Options).RootElement; Assert.That( document.EnumerateObject().Select(prop => prop.Name), Is.EquivalentTo(new List { "mapType", "units", "retreatingUnits", "orderHistory", "options", "timelines", })); string serialized = JsonSerializer.Serialize(world, Options); World? deserialized = JsonSerializer.Deserialize(serialized, Options); Assert.That(deserialized, Is.Not.Null, "Failed to deserialize"); Assert.That(deserialized!.Map, Is.Not.Null, "Failed to deserialize map"); Assert.That(deserialized!.Units, Is.Not.Null, "Failed to deserialize units"); Assert.That(deserialized!.RetreatingUnits, Is.Not.Null, "Failed to deserialize retreats"); Assert.That(deserialized!.OrderHistory, Is.Not.Null, "Failed to deserialize history"); Assert.That(deserialized!.Timelines, Is.Not.Null, "Failed to deserialize timelines"); Assert.That(deserialized!.Timelines.Pasts, Is.Not.Null, "Failed to deserialize timeline pasts"); Assert.That(deserialized!.Timelines.Next, Is.EqualTo(world.Timelines.Next)); Assert.That(deserialized!.Options, Is.Not.Null, "Failed to deserialize options"); } [Test] public void SerializeRoundTrip_MDATC_3_A_2() { // Set up MDATC 3.A.2 TestCaseBuilder setup = new(World.WithStandardMap(), MovementPhaseAdjudicator.Instance); setup[("a", 0)] .GetReference(out Season s0) ["Germany"] .Army("Mun").MovesTo("Tyr").GetReference(out var mun0) ["Austria"] .Army("Tyr").Holds().GetReference(out var tyr0); setup.ValidateOrders(); Assert.That(mun0, Is.Valid); Assert.That(tyr0, Is.Valid); setup.AdjudicateOrders(); Assert.That(mun0, Is.Repelled); Assert.That(tyr0, Is.NotDislodged); setup.UpdateWorld(); Assert.That(setup.World.OrderHistory[s0.Key].Orders.Count, Is.GreaterThan(0), "Missing orders"); Assert.That(setup.World.OrderHistory[s0.Key].DoesMoveOutcomes.Count, Is.GreaterThan(0), "Missing moves"); Assert.That(setup.World.OrderHistory[s0.Key].IsDislodgedOutcomes.Count, Is.GreaterThan(0), "Missing dislodges"); // Serialize and deserialize the world string serialized = JsonSerializer.Serialize(setup.World, Options); World reserialized = JsonSerializer.Deserialize(serialized, Options) ?? throw new AssertionException("Failed to reserialize world"); Assert.Multiple(() => { Assert.That(reserialized.OrderHistory[s0.Key].Orders.Count, Is.GreaterThan(0), "Missing orders"); Assert.That(reserialized.OrderHistory[s0.Key].DoesMoveOutcomes.Count, Is.GreaterThan(0), "Missing moves"); Assert.That(reserialized.OrderHistory[s0.Key].IsDislodgedOutcomes.Count, Is.GreaterThan(0), "Missing dislodges"); Assert.That(reserialized.Timelines.Pasts, Is.Not.Empty, "Missing timeline history"); }); // Resume the test case setup = new(reserialized, MovementPhaseAdjudicator.Instance); setup[("a", 1)] ["Germany"] .Army("Mun").Supports.Army("Mun", season: s0).MoveTo("Tyr").GetReference(out var mun1) ["Austria"] .Army("Tyr").Holds(); setup.ValidateOrders(); Assert.That(mun1, Is.Valid); var adjudications = setup.AdjudicateOrders(); Assert.That(mun1, Is.NotCut); AttackStrength mun0attack = adjudications.OfType().Single(); Assert.That(mun0attack.Supports, Is.Not.Empty, "Support not tracked"); DoesMove mun0move = adjudications.OfType().Single(move => move.Order.Unit.Key == mun0.Order.Unit.Key); Assert.That(mun0move.Outcome, Is.True); IsDislodged tyr0dislodge = adjudications.OfType().Single(dis => dis.Order.Unit.Key == tyr0.Order.Unit.Key); Assert.That(tyr0dislodge.Outcome, Is.True); // Confirm that an alternate future is created. World world = setup.UpdateWorld(); Season fork = new("b1"); Unit tyr1 = world.GetUnitAt("Tyr", fork); Assert.That( tyr1.Past, Is.EqualTo(mun0.Order.Unit.Key), "Expected A Mun a0 to advance to Tyr b1"); Assert.That( world.RetreatingUnits.Count, Is.EqualTo(1), "Expected A Tyr a0 to be in retreat"); Assert.That(world.RetreatingUnits.First().Unit.Key, Is.EqualTo(tyr0.Order.Unit.Key)); } }