diff --git a/tests/GameCult.Caching.Tests/NumericLeafVectorTests.cs b/tests/GameCult.Caching.Tests/NumericLeafVectorTests.cs index 5c066ee8..812109df 100644 --- a/tests/GameCult.Caching.Tests/NumericLeafVectorTests.cs +++ b/tests/GameCult.Caching.Tests/NumericLeafVectorTests.cs @@ -308,7 +308,7 @@ namespace GameCult.Caching.Tests { Id = "leaves", Flag = true, Blob = new byte[] { 1, 2, 3 }, I = -7, L = 5_000_000_000, F = 0.1f, D = 0.1, MaybeI = 9, Tags = new List { "a", "b" }, Names = new[] { "x", "y" }, Any = "text", - Nested = new LeafInner { N = "inner", W = 0.1f, Id = "n" }, Items = new List { new() { N = "one", W = 0.1f, Id = "i1" }, new() { N = "two", W = 1.5f, Id = "i2" } }, + Nested = new LeafInner { N = "inner", W = 0.1f, Id = "000000000011" }, Items = new List { new() { N = "one", W = 0.1f, Id = "000000000012" }, new() { N = "two", W = 1.5f, Id = "000000000013" } }, Shape = new LeafCircle { R = 0.1f }, Floats = new[] { 0.1f, 1.5f }, MaybeF = 0.1f, }; diff --git a/tests/GameCult.Caching.Tests/UnionArmGuardTests.cs b/tests/GameCult.Caching.Tests/UnionArmGuardTests.cs index 99f11b5c..d32bea1d 100644 --- a/tests/GameCult.Caching.Tests/UnionArmGuardTests.cs +++ b/tests/GameCult.Caching.Tests/UnionArmGuardTests.cs @@ -43,7 +43,7 @@ namespace GameCult.Caching.Tests }; // Unit8: slots [id]. - private static Emit UnitArm(int key) => (ref MessagePackWriter w) => { w.WriteArrayHeader(2); w.Write(key); w.WriteArrayHeader(1); w.Write("u"); }; + private static Emit UnitArm(int key) => (ref MessagePackWriter w) => { w.WriteArrayHeader(2); w.Write(key); w.WriteArrayHeader(1); w.Write("000000000007"); }; // Branch: slots [children, next, id]. private static Emit BranchArm(int key, Emit next, params Emit[] children) => (ref MessagePackWriter w) => @@ -53,7 +53,7 @@ namespace GameCult.Caching.Tests w.WriteArrayHeader(children.Length); foreach (var child in children) child(ref w); next(ref w); - w.Write("b"); + w.Write("000000000008"); }; private static Emit List(params Emit[] items) => (ref MessagePackWriter w) => @@ -123,22 +123,22 @@ namespace GameCult.Caching.Tests [TestCase(7)] [TestCase(10)] public void UnknownArmInFieldRefused(int key) => - AssertRefused(Doc(LeafArm(key, "r", Canary, 7)), NodeName, key, "3, 5, 8, 9"); + AssertRefused(Doc(LeafArm(key, "000000000005", Canary, 7)), NodeName, key, "3, 5, 8, 9"); [TestCase(0)] [TestCase(4)] [TestCase(10)] public void UnknownArmInListRefused(int key) => - AssertRefused(Doc(LeafArm(3, "r", "ok", 1), List(UnitArm(8), LeafArm(key, "i", Canary, 7))), NodeName, key, "3, 5, 8, 9"); + AssertRefused(Doc(LeafArm(3, "000000000005", "ok", 1), List(UnitArm(8), LeafArm(key, "000000000004", Canary, 7))), NodeName, key, "3, 5, 8, 9"); // Inside an arm's own list, and inside an arm's own field: the union nested under a union. [TestCase(4)] [TestCase(10)] public void UnknownArmNestedInArmRefused(int key) { - AssertRefused(Doc(BranchArm(5, Nil, UnitArm(8), LeafArm(key, "c", Canary, 7))), NodeName, key, "3, 5, 8, 9"); - AssertRefused(Doc(BranchArm(5, LeafArm(key, "n", Canary, 7))), NodeName, key, "3, 5, 8, 9"); - AssertRefused(Doc(BranchArm(5, Nil, BranchArm(5, Nil, BranchArm(5, Nil, LeafArm(key, "deep", Canary, 7))))), NodeName, key, "3, 5, 8, 9"); + AssertRefused(Doc(BranchArm(5, Nil, UnitArm(8), LeafArm(key, "000000000006", Canary, 7))), NodeName, key, "3, 5, 8, 9"); + AssertRefused(Doc(BranchArm(5, LeafArm(key, "000000000003", Canary, 7))), NodeName, key, "3, 5, 8, 9"); + AssertRefused(Doc(BranchArm(5, Nil, BranchArm(5, Nil, BranchArm(5, Nil, LeafArm(key, "000000000002", Canary, 7))))), NodeName, key, "3, 5, 8, 9"); } // A union whose arms are also a union has its own key set: 7 is Outer's (OuterOnly) and not Inner's. @@ -175,9 +175,9 @@ namespace GameCult.Caching.Tests foreach (var doc in new[] { new GuardDoc { Root = new Rogue() }, - new GuardDoc { Items = { new Unit8 { Id = "u" }, new Rogue() } }, - new GuardDoc { Root = new Branch { Id = "b", Children = { new Rogue() } } }, - new GuardDoc { Root = new Branch { Id = "b", Next = new Rogue() } }, + new GuardDoc { Items = { new Unit8 { Id = "000000000007" }, new Rogue() } }, + new GuardDoc { Root = new Branch { Id = "000000000008", Children = { new Rogue() } } }, + new GuardDoc { Root = new Branch { Id = "000000000008", Next = new Rogue() } }, new GuardDoc { Root = new DerivedLeaf() }, new GuardDoc { Crafted = new Unlisted() }, }) @@ -206,26 +206,26 @@ namespace GameCult.Caching.Tests Id = "d1", Root = new Branch { - Id = "b", + Id = "000000000008", Children = { - new Leaf { Id = "a", Content = "x", Weight = 1 }, - new Unit8 { Id = "u" }, - new Branch { Id = "b", Children = { new Branch { Id = "b", Children = { new Leaf { Id = "deep", Content = "y", Weight = 2 } } } } } + new Leaf { Id = "000000000001", Content = "x", Weight = 1 }, + new Unit8 { Id = "000000000007" }, + new Branch { Id = "000000000008", Children = { new Branch { Id = "000000000008", Children = { new Leaf { Id = "000000000002", Content = "y", Weight = 2 } } } } } }, - Next = new Leaf { Id = "n", Content = "z", Weight = 3 } + Next = new Leaf { Id = "000000000003", Content = "z", Weight = 3 } }, - Items = { new Unit8 { Id = "u" }, new Leaf { Id = "i", Content = "w", Weight = 4 }, null! }, + Items = { new Unit8 { Id = "000000000007" }, new Leaf { Id = "000000000004", Content = "w", Weight = 4 }, null! }, Crafted = new InnerB { N = 9 }, Any = new InnerA { N = 8 } }; private static byte[] KnownArmBytes() => Doc( - BranchArm(5, LeafArm(3, "n", "z", 3), - LeafArm(3, "a", "x", 1), + BranchArm(5, LeafArm(3, "000000000003", "z", 3), + LeafArm(3, "000000000001", "x", 1), UnitArm(8), - BranchArm(5, Nil, BranchArm(5, Nil, LeafArm(3, "deep", "y", 2)))), - List(UnitArm(8), LeafArm(3, "i", "w", 4), Nil), + BranchArm(5, Nil, BranchArm(5, Nil, LeafArm(3, "000000000002", "y", 2)))), + List(UnitArm(8), LeafArm(3, "000000000004", "w", 4), Nil), InnerArm(1, 9), InnerArm(1, 8)); @@ -458,13 +458,13 @@ namespace GameCult.Caching.Tests new CultPersistedRecord { Key = "base", SchemaId = descriptor.SchemaId, StoredAt = "2026-01-01T00:00:00.0000000Z", - Payload = Doc(LeafArm(3, "r", "ok", 1)) + Payload = Doc(LeafArm(3, "000000000005", "ok", 1)) }, new CultPersistedRecord { Key = "variant", SchemaId = descriptor.SchemaId, StoredAt = "2026-01-01T00:00:00.0000000Z", Payload = Array.Empty(), - Variant = new CultVariantDelta("base", new[] { CultVariantOverride.Set(1, Raw(LeafArm(4, "r", Canary, 7))) }) + Variant = new CultVariantDelta("base", new[] { CultVariantOverride.Set(1, Raw(LeafArm(4, "000000000005", Canary, 7))) }) } } })); @@ -498,14 +498,14 @@ namespace GameCult.Caching.Tests try { var path = Path.Combine(folder, "guard.cc"); - var genuine = Doc(LeafArm(3, "r", Canary, 7)); + var genuine = Doc(LeafArm(3, "000000000005", Canary, 7)); using (var writer = CultCacheMessagePack.Create(path, new CultCacheOpenOptions { Registry = Registry, UseDirectoryStore = directory, StoreFlushOnDispose = true })) { - await writer.UpsertAsync(typeof(GuardDoc), new GuardDoc { Id = "d1", Root = new Leaf { Id = "r", Content = Canary, Weight = 7 } }, new CultRecordKey("d1")); + await writer.UpsertAsync(typeof(GuardDoc), new GuardDoc { Id = "d1", Root = new Leaf { Id = "000000000005", Content = Canary, Weight = 7 } }, new CultRecordKey("d1")); await writer.FlushAsync(); } - var forged = Doc(LeafArm(key, "r", Canary, 7)); + var forged = Doc(LeafArm(key, "000000000005", Canary, 7)); Assert.That(forged.Length, Is.EqualTo(genuine.Length)); // A directory store names a page by the SHA-256 of its bytes and its manifest commits to that hash, so a forged // page is renamed and the manifest told its new hash: the store then holds a well-formed page the reader must refuse. diff --git a/tests/GameCult.Caching.Tests/UnionParityVectorTests.cs b/tests/GameCult.Caching.Tests/UnionParityVectorTests.cs index edfcb377..172cf604 100644 --- a/tests/GameCult.Caching.Tests/UnionParityVectorTests.cs +++ b/tests/GameCult.Caching.Tests/UnionParityVectorTests.cs @@ -162,24 +162,24 @@ namespace GameCult.Caching.Tests Version = 3, Root = root ?? new Box { - Id = "root", + Id = "0000000000c0", Children = { - new Text { Id = "t1", Content = "hello" }, + new Text { Id = "0000000000c1", Content = "hello" }, new Use { - Id = "u1", + Id = "0000000000c2", Composition = new Composition { Name = "comp", - Body = new Box { Id = "inner", Children = { new Text { Id = "deep", Content = "x" }, new Image { Id = "img", Uri = "uri://a", Alt = "alt" } } } + Body = new Box { Id = "0000000000d0", Children = { new Text { Id = "0000000000d1", Content = "x" }, new Image { Id = "0000000000d2", Uri = "uri://a", Alt = "alt" } } } }, - Slots = { new Text { Id = "s1", Content = "slot" }, null!, new Box { Id = "b2" } } + Slots = { new Text { Id = "0000000000e1", Content = "slot" }, null!, new Box { Id = "0000000000e2" } } }, - new Image { Id = "i2", Uri = "uri://b", Alt = "" } + new Image { Id = "0000000000c3", Uri = "uri://b", Alt = "" } } }, - Outcomes = { new Pending { Message = "wait", Id = "p" }, new Completed { SourceVersion = 7, Id = "c" }, new Denied { Id = "d" } }, + Outcomes = { new Pending { Message = "wait", Id = "0000000000a1" }, new Completed { SourceVersion = 7, Id = "0000000000a2" }, new Denied { Id = "0000000000a3" } }, Part = new Tool { Name = "hammer", Uses = 12 }, Crafted = new Part { Name = "gear", Count = 4 }, Missing = null @@ -255,13 +255,13 @@ namespace GameCult.Caching.Tests private static byte[] Surface(Emit? root = null, Emit? outcomes = null, Emit? crafted = null, Extra? extra = null, Emit? trailing = null) { extra ??= new Extra(); - root ??= BoxArm("root", Slots( - TextArm("t1", "hello"), - ArmOf(2, Str("u1"), - Plus(extra.Composition, Str("comp"), BoxArm("inner", Slots(TextArm("deep", "x"), ImageArm("img", "uri://a", "alt")))), - Slots(TextArm("s1", "slot", extra.ListElement), Nil, BoxArm("b2", Slots()))), - ImageArm("i2", "uri://b", "")), extra.RootArm); - outcomes ??= Slots(ArmOf(0, Str("wait"), Str("p")), ArmOf(1, Num(7), Str("c")), ArmOf(2, Str("d"))); + root ??= BoxArm("0000000000c0", Slots( + TextArm("0000000000c1", "hello"), + ArmOf(2, Str("0000000000c2"), + Plus(extra.Composition, Str("comp"), BoxArm("0000000000d0", Slots(TextArm("0000000000d1", "x"), ImageArm("0000000000d2", "uri://a", "alt")))), + Slots(TextArm("0000000000e1", "slot", extra.ListElement), Nil, BoxArm("0000000000e2", Slots()))), + ImageArm("0000000000c3", "uri://b", "")), extra.RootArm); + outcomes ??= Slots(ArmOf(0, Str("wait"), Str("0000000000a1")), ArmOf(1, Num(7), Str("0000000000a2")), ArmOf(2, Str("0000000000a3"))); crafted ??= ArmOf(1, Str("gear"), Num(4)); var slots = new[] { Str("surface"), Num(3), root, outcomes, ArmOf(1, Str("hammer"), Num(12)), crafted, Nil }; return Raw(Slots(trailing != null ? slots.Append(trailing).ToArray() : extra.Record ? slots.Append(ExtraSlot).ToArray() : slots)); @@ -284,7 +284,7 @@ namespace GameCult.Caching.Tests new Case("unknown-arm-list.msgpack", "refused", "Outcome", 7, "unknown-arm", Surface(outcomes: Slots(ArmOf(0, Str("wait")), ArmOf(7, Str(Canary))))), new Case("unknown-arm-nested.msgpack", "refused", "Node", 9, "unknown-arm", - Surface(root: BoxArm("root", Slots(BoxArm("l1", Slots(BoxArm("l2", Slots(ArmOf(9, Str("deep"), Str(Canary)))))))))), + Surface(root: BoxArm("0000000000c0", Slots(BoxArm("0000000000d3", Slots(BoxArm("0000000000d4", Slots(ArmOf(9, Str("deep"), Str(Canary)))))))))), new Case("inner-union-outer-key.msgpack", "refused", "CraftedItem", 2, "unknown-arm", Surface(crafted: ArmOf(2, Str("gear"), Num(4)))), new Case("arm-arity.msgpack", "refused", "Node", 1, "arity", @@ -461,30 +461,30 @@ namespace GameCult.Caching.Tests Slots(slots)(ref w); }; - private static Emit WithOutcome(Emit element) => Slots(ArmOf(0, Str("wait"), Str("p")), ArmOf(1, Num(7), Str("c")), ArmOf(2, Str("d")), element); + private static Emit WithOutcome(Emit element) => Slots(ArmOf(0, Str("wait"), Str("0000000000a1")), ArmOf(1, Num(7), Str("0000000000a2")), ArmOf(2, Str("0000000000a3")), element); - private static Emit WrapChain(int wraps, Emit leaf) => wraps == 0 ? leaf : ArmOf(6, WrapChain(wraps - 1, leaf), Str("w")); + private static Emit WrapChain(int wraps, Emit leaf) => wraps == 0 ? leaf : ArmOf(6, WrapChain(wraps - 1, leaf), Str("0000000000b1")); private static Node WrapChainValue(int wraps, Node leaf) { - for (var i = 0; i < wraps; i++) leaf = new Wrap { Inner = leaf, Id = "w" }; + for (var i = 0; i < wraps; i++) leaf = new Wrap { Inner = leaf, Id = "0000000000b1" }; return leaf; } // n arrays nested inside one another around a single string. private static Emit Nested(int n) => n == 1 ? Slots(Str(Canary)) : Slots(Nested(n - 1)); - private static Emit AtLimitLeaf => BoxArm("leaf", Slots()); - private static Emit PastLimitLeaf => TextArm("leaf", Canary); + private static Emit AtLimitLeaf => BoxArm("0000000000f0", Slots()); + private static Emit PastLimitLeaf => TextArm("0000000000f0", Canary); private static IReadOnlyList BoundsCases() => new[] { new Case("arm-key-int32-min.msgpack", "accepted", "Outcome", int.MinValue, "arm-key-int32-min.msgpack", - Surface(outcomes: WithOutcome(ArmOf(int.MinValue, Str("f"))))), + Surface(outcomes: WithOutcome(ArmOf(int.MinValue, Str("0000000000a4"))))), new Case("arm-key-int32-max.msgpack", "accepted", "Outcome", int.MaxValue, "arm-key-int32-max.msgpack", - Surface(outcomes: WithOutcome(ArmOf(int.MaxValue, Str("x"))))), + Surface(outcomes: WithOutcome(ArmOf(int.MaxValue, Str("0000000000a5"))))), new Case("arm-key-wide-coding.msgpack", "accepted", "Outcome", int.MaxValue, "arm-key-int32-max.msgpack", - Surface(outcomes: WithOutcome(RawKey((ref MessagePackWriter w) => w.WriteUInt64(int.MaxValue), Str("x"))))), + Surface(outcomes: WithOutcome(RawKey((ref MessagePackWriter w) => w.WriteUInt64(int.MaxValue), Str("0000000000a5"))))), new Case("arm-key-above-int32.msgpack", "refused", "Outcome", null, "key-out-of-range", Surface(outcomes: WithOutcome(RawKey((ref MessagePackWriter w) => w.Write(0x80000000u))))), new Case("arm-key-below-int32.msgpack", "refused", "Outcome", null, "key-out-of-range", @@ -650,7 +650,7 @@ namespace GameCult.Caching.Tests var payload = Committed("depth-at-limit.msgpack"); Assert.That(DepthOf(payload), Is.EqualTo(Limit), "the vector nests exactly the limit, counted independently"); Assert.That(Convert.ToHexString(SerializeValue(Decode(payload))), Is.EqualTo(Convert.ToHexString(payload)), "read, then written again"); - var built = Constructed(WrapChainValue(AtLimitWraps, new Box { Id = "leaf" })); + var built = Constructed(WrapChainValue(AtLimitWraps, new Box { Id = "0000000000f0" })); Assert.That(Convert.ToHexString(SerializeValue(built)), Is.EqualTo(Convert.ToHexString(payload)), "the constructed value writes the vector"); } @@ -663,7 +663,7 @@ namespace GameCult.Caching.Tests Assert.That(read, Does.Contain(typeof(UnionSurface).FullName).And.Contain($"the limit is {Limit}").And.Contain("refused on read").And.Not.Contain(Canary)); byte[]? written = null; - var write = Chain(Refusal(() => written = SerializeValue(Constructed(WrapChainValue(PastLimitWraps, new Text { Id = "leaf", Content = Canary }))))); + var write = Chain(Refusal(() => written = SerializeValue(Constructed(WrapChainValue(PastLimitWraps, new Text { Id = "0000000000f0", Content = Canary }))))); Assert.That(written, Is.Null, "nothing is returned"); Assert.That(write, Does.Contain(typeof(UnionSurface).FullName).And.Contain($"the limit is {Limit}").And.Contain("refused on write").And.Not.Contain(Canary));