Mesh tests: raw and typed writes share one readability vector test

The raw-write refusal test spelled the old header-only verdict (NotSupported for
a first slot that is a string, a legacy array replaced). The shared vector test
now drives both write paths; the old test keeps only the marked-file case.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Meta Vens 2026-09-30 02:05:56 +02:00
commit e1ff5b2278
2 changed files with 24 additions and 45 deletions

View file

@ -93,44 +93,14 @@ public sealed class CultMeshSingleFileElementIdTests
HeaderOf(path).Should().Be("cultcache.store.v3", "the payload's ids are not the writer's to see");
}
// A raw write does not read the store's records, but it does not overwrite a file it cannot read either: the runtimes agree.
// A raw write does not read the store's records, so a file already marked stays marked. (Which files it may replace is
// CultMeshSingleFileReadabilityTests, over the shared vectors.)
[Test]
public void RawPayloadWriteRefusesAFileItCannotReadAndLeavesItUntouched()
public void RawPayloadWriteOverAMarkedFileKeepsItMarked()
{
var schema = new CultMeshSingleFileDocumentSchema("raw:schema", "RawSchema", "1");
var marked = Path_("marked.cc");
CultMesh.WriteSingleFileDocument(marked, Key, Publication(Descriptor()));
var whole = File.ReadAllBytes(marked);
var truncated = Path_("truncated.cc");
File.WriteAllBytes(truncated, whole[..^1]);
var unknown = Path_("v9.cc");
File.WriteAllBytes(unknown, MessagePackSerializer.Serialize(new object[] { "cultcache.store.v9", Array.Empty<object>(), Array.Empty<object>() }));
// A file is a store only when it is exactly one MessagePack array whose first slot, if a string, is a store header.
var trailing = Path_("trailing.cc");
File.WriteAllBytes(trailing, whole.Concat(new byte[] { 1, 2, 3 }).ToArray());
var scalar = Path_("scalar.cc");
File.WriteAllBytes(scalar, new byte[] { 0x01 });
var map = Path_("map.cc");
File.WriteAllBytes(map, new byte[] { 0x80 });
var stringFirst = Path_("string-first.cc");
File.WriteAllBytes(stringFirst, MessagePackSerializer.Serialize(new object[] { "hello", 1 }));
foreach (var path in new[] { truncated, unknown, trailing, scalar, map, stringFirst })
{
var before = File.ReadAllBytes(path);
Assert.Throws<NotSupportedException>(() => CultMesh.WriteSingleFileDocumentPayload(path, Key, schema, null, new byte[] { 0x90 }), path);
File.ReadAllBytes(path).Should().Equal(before, path + " was rewritten");
}
// An empty file and a legacy envelope array (first slot not a string, empty included) carry no header and are written.
foreach (var (name, bytes) in new[] { ("empty.cc", Array.Empty<byte>()), ("empty-array.cc", new byte[] { 0x90 }), ("legacy.cc", new byte[] { 0x91, 0x80 }) })
{
var path = Path_(name);
File.WriteAllBytes(path, bytes);
CultMesh.WriteSingleFileDocumentPayload(path, Key, schema, null, new byte[] { 0x90 });
HeaderOf(path).Should().Be("cultcache.store.v1", name);
}
CultMesh.WriteSingleFileDocumentPayload(marked, Key, schema, null, new byte[] { 0x90 });
HeaderOf(marked).Should().Be("cultcache.store.v3", "a whole marked file is still written and stays marked");

View file

@ -56,20 +56,29 @@ public sealed class CultMeshSingleFileReadabilityTests
};
[TestCaseSource(nameof(Vectors))]
public void ATypedWriteReplacesAFileExactlyWhenItReads(string vector, bool reads)
public void AWriteReplacesAFileExactlyWhenItReads(string vector, bool reads)
{
var path = Path.Combine(_root, "doc.cc");
var bytes = File.ReadAllBytes(Path.Combine(VectorRoot(), vector));
File.WriteAllBytes(path, bytes);
if (reads)
var raw = new CultMeshSingleFileDocumentSchema("raw:schema", "RawSchema", "1");
var writes = new (string Name, Action<string> Write)[]
{
CultMesh.WriteSingleFileDocument(path, new CultRecordKey("publication"), Publication());
CultDocumentMessagePackSerialization.DeserializeSnapshot(File.ReadAllBytes(path)).Records.Should().ContainSingle();
return;
}
("typed", path => CultMesh.WriteSingleFileDocument(path, new CultRecordKey("publication"), Publication())),
("raw payload", path => CultMesh.WriteSingleFileDocumentPayload(path, new CultRecordKey("publication"), raw, null, new byte[] { 0x90 }))
};
foreach (var (name, write) in writes)
{
var path = Path.Combine(_root, name.Replace(' ', '-') + ".cc");
var bytes = File.ReadAllBytes(Path.Combine(VectorRoot(), vector));
File.WriteAllBytes(path, bytes);
Assert.That(() => CultMesh.WriteSingleFileDocument(path, new CultRecordKey("publication"), Publication()), Throws.Exception);
File.ReadAllBytes(path).Should().Equal(bytes, "a file this runtime cannot read was rewritten");
if (reads)
{
write(path);
CultDocumentMessagePackSerialization.DeserializeSnapshot(File.ReadAllBytes(path)).Records.Should().ContainSingle(name);
continue;
}
Assert.That(() => write(path), Throws.Exception, name);
File.ReadAllBytes(path).Should().Equal(bytes, name + " rewrote a file this runtime cannot read");
}
}
}