diff --git a/tests/GameCult.Caching.Tests/ElementIdEngineTests.cs b/tests/GameCult.Caching.Tests/ElementIdEngineTests.cs index bd9ddacd..dd7be0b5 100644 --- a/tests/GameCult.Caching.Tests/ElementIdEngineTests.cs +++ b/tests/GameCult.Caching.Tests/ElementIdEngineTests.cs @@ -310,6 +310,7 @@ namespace GameCult.Caching.Tests Assert.That(Problems(typeof(HFormattedOwner)).Single(), Does.Contain("FormattedOwner").And.Contain("[MessagePackFormatter]")); Assert.That(Problems(typeof(HFormattedMember)).Single(), Does.Contain("Inner").And.Contain("[MessagePackFormatter]")); Assert.That(Problems(typeof(HFormattedField)), Is.Empty, "a formatted type with no list below it is a field"); + Assert.That(Problems(typeof(HFormattedDerived)).Single(), Does.Contain("FormattedDerived").And.Contain("[MessagePackFormatter]"), "the attribute is inherited"); } // The id path is a fixed point, not the stack at the moment a list is found: a type in a cycle with the list's owner, and @@ -321,6 +322,11 @@ namespace GameCult.Caching.Tests Assert.That(path, Is.EquivalentTo(new[] { typeof(HDiamond), typeof(HLeft), typeof(HRight), typeof(HCycle), typeof(HCycleBack), typeof(EIded) })); Assert.That(CultElementIds.Inspect(typeof(HFine)).IdPath, Is.EquivalentTo(new[] { typeof(HFine), typeof(ENest), typeof(EIded) })); Assert.That(CultElementIds.Inspect(typeof(HFormattedField)).IdPath, Is.Empty); + + // A union base is on the path both as the type a list holds (its formatter writes the arm) and as a field type whose + // arm holds the list. + Assert.That(CultElementIds.Inspect(typeof(HPlainBaseList)).IdPath, Is.EquivalentTo(new[] { typeof(HPlainBaseList), typeof(PlainBase), typeof(PlainArm) })); + Assert.That(CultElementIds.Inspect(typeof(HIdBaseOwner)).IdPath, Is.EquivalentTo(new[] { typeof(HIdBaseOwner), typeof(IdBase), typeof(IdArm), typeof(EIded) })); } // ---- shapes ---- @@ -349,6 +355,15 @@ namespace GameCult.Caching.Tests [MessagePackObject] [MessagePackFormatter(typeof(NoFormatter))] public class FormattedLeaf { [Key(0)] public int N { get; set; } } [MessagePackObject] public class HFormattedField { [Key(0)] public FormattedLeaf Leaf { get; set; } = new(); [Key(1)] public List Tags { get; set; } = new(); } + [MessagePackObject] public class FormattedDerived : FormattedElement { } + [MessagePackObject] public class HFormattedDerived { [Key(0)] public List Items { get; set; } = new(); } + [Union(0, typeof(IdArm))] public abstract class IdBase { } + [MessagePackObject] public class IdArm : IdBase { [Key(0)] [CultElementId] public string Id { get; set; } = ""; [Key(1)] public List Items { get; set; } = new(); } + [Union(0, typeof(PlainArm))] public abstract class PlainBase { } + [MessagePackObject] public class PlainArm : PlainBase { [Key(0)] [CultElementId] public string Id { get; set; } = ""; } + [MessagePackObject] public class HPlainBaseList { [Key(0)] public List Items { get; set; } = new(); } + [MessagePackObject] public class HIdBaseOwner { [Key(0)] public IdBase? Root { get; set; } } + [MessagePackObject] public class HLeft { [Key(0)] public HCycle Cycle { get; set; } = new(); } [MessagePackObject] public class HRight { [Key(0)] public HCycle Cycle { get; set; } = new(); } [MessagePackObject] public class HCycle { [Key(0)] public HCycleBack Back { get; set; } = new(); } diff --git a/tests/GameCult.Caching.Tests/UnionArmGuardTests.cs b/tests/GameCult.Caching.Tests/UnionArmGuardTests.cs index 21fe44cf..eea8c4dc 100644 --- a/tests/GameCult.Caching.Tests/UnionArmGuardTests.cs +++ b/tests/GameCult.Caching.Tests/UnionArmGuardTests.cs @@ -290,6 +290,13 @@ namespace GameCult.Caching.Tests } } + [Test] + public void OptionsRefuseANullDocumentTypeOrAssembly() + { + Assert.Throws(() => CultDocumentMessagePackSerialization.OptionsFor(null!)); + Assert.Throws(() => CultDocumentMessagePackSerialization.OptionsForDocument(null!)); + } + [Union(0, typeof(ClaimArm))] public abstract class ClaimNode { }