From dca0c5d095e193b737c5419d7c8f65c72ea96644 Mon Sep 17 00:00:00 2001 From: Libby Date: Thu, 12 Nov 2026 18:47:44 +0000 Subject: [PATCH] C#: pin the one-value refusal on codec and Mesh single-file reads (#141) --- .../BytesAfterVectorTests.cs | 9 +++++++++ .../GameCult.Mesh.Tests/BytesAfterPathTests.cs | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/tests/GameCult.Caching.Tests/BytesAfterVectorTests.cs b/tests/GameCult.Caching.Tests/BytesAfterVectorTests.cs index 86d677e6..65b1d6da 100644 --- a/tests/GameCult.Caching.Tests/BytesAfterVectorTests.cs +++ b/tests/GameCult.Caching.Tests/BytesAfterVectorTests.cs @@ -110,6 +110,15 @@ namespace GameCult.Caching.Tests Assert.That(message, Does.Contain(typeof(UnionSurface).FullName).And.Contain($"1 {Clause}").And.Contain("refused on read")); } + // The inspector reads documents through CultCodec.Deserialize (type == document), not DecodeDocument: its branch is its own path. + [Test] + public void CodecDeserializeOfADocumentRefusesATail() + { + var codec = CultCacheMessagePack.CreateCodec(Registry); + var message = Message(() => codec.Deserialize(typeof(UnionSurface), typeof(UnionSurface), Base.Concat(new byte[] { 0xc0 }).ToArray())); + Assert.That(message, Does.Contain(typeof(UnionSurface).FullName).And.Contain($"1 {Clause}").And.Contain("refused on read")); + } + [Test] public void StoreLoadRefuses() { diff --git a/tests/GameCult.Mesh.Tests/BytesAfterPathTests.cs b/tests/GameCult.Mesh.Tests/BytesAfterPathTests.cs index ed9b904b..28c6d3de 100644 --- a/tests/GameCult.Mesh.Tests/BytesAfterPathTests.cs +++ b/tests/GameCult.Mesh.Tests/BytesAfterPathTests.cs @@ -58,4 +58,22 @@ public class BytesAfterPathTests .MakeGenericMethod(typeof(CultMeshCdnArtifactManifest)); Refusal(() => read.Invoke(null, new object[] { snapshot, record.SchemaId, record.RecordKey })).Should().Contain(Clause); } + + [Test] + public void ASingleFileDocumentReadRefusesATail() + { + var path = System.IO.Path.Combine(System.IO.Path.GetTempPath(), $"cultlib-bytesafter-mesh-{Guid.NewGuid():N}.cc"); + try + { + var descriptor = CultDocumentRegistry.Shared.GetRequired(); + var schema = new CultMeshSingleFileDocumentSchema(descriptor.SchemaId, descriptor.SchemaName, descriptor.SchemaVersion); + var payload = WithTail(Manifest()).Payload; + CultMesh.WriteSingleFileDocumentPayload(path, new CultRecordKey("k"), schema, null, payload); + Refusal(() => CultMesh.ReadSingleFileDocument(path, new CultRecordKey("k"))).Should().Contain(Clause); + } + finally + { + System.IO.File.Delete(path); + } + } }