Caching: a binary-encoded stamp is refused; directory manifest readers name their stamp rule; the I/O refusal test fails the real read
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
39e8ab5efd
commit
6adc321a73
4 changed files with 13 additions and 19 deletions
|
|
@ -198,6 +198,9 @@ public static class CultDocumentMessagePackSerialization
|
|||
|
||||
if (fieldCount > 0)
|
||||
{
|
||||
// A stamp encoded as binary is not one this runtime wrote or reads; it is refused here, not parsed as damage.
|
||||
if (reader.NextMessagePackType == MessagePackType.Binary)
|
||||
throw new NotSupportedException("Store snapshot declares its format version as binary; this runtime reads " + CultPersistedStoreSnapshot.FormatV1 + " and " + CultPersistedStoreSnapshot.FormatV2 + " as strings.");
|
||||
snapshot.FormatVersion = reader.ReadString()
|
||||
?? throw new NotSupportedException("Store snapshot declares no format version; this runtime reads " + CultPersistedStoreSnapshot.FormatV1 + " and " + CultPersistedStoreSnapshot.FormatV2 + ".");
|
||||
requireReadable(snapshot.FormatVersion);
|
||||
|
|
|
|||
|
|
@ -428,7 +428,7 @@ namespace GameCult.Caching.Tests
|
|||
await seed.FlushAsync();
|
||||
}
|
||||
|
||||
var manifest = CultDocumentMessagePackSerialization.DeserializeSnapshot(File.ReadAllBytes(filePath));
|
||||
var manifest = CultDocumentMessagePackSerialization.DeserializeSnapshot(File.ReadAllBytes(filePath), _ => { });
|
||||
Assert.That(manifest.FormatVersion, Is.EqualTo("cultcache.store.v4.directory-content-addressed-pages"));
|
||||
Assert.That(manifest.Records, Has.Length.EqualTo(2));
|
||||
Assert.That(manifest.Records.All(record => record.Payload.Length == 32), Is.True,
|
||||
|
|
@ -730,7 +730,7 @@ namespace GameCult.Caching.Tests
|
|||
}
|
||||
|
||||
Assert.That(store.IsDirty, Is.False);
|
||||
var compacted = CultDocumentMessagePackSerialization.DeserializeSnapshot(File.ReadAllBytes(filePath));
|
||||
var compacted = CultDocumentMessagePackSerialization.DeserializeSnapshot(File.ReadAllBytes(filePath), _ => { });
|
||||
Assert.That(compacted.SchemaCatalog, Is.Empty);
|
||||
Assert.That(compacted.Records, Is.Empty);
|
||||
var reader = new CultCache();
|
||||
|
|
|
|||
|
|
@ -223,7 +223,7 @@ namespace GameCult.Caching.Tests
|
|||
}
|
||||
|
||||
private CultPersistedRecord ManifestRecord(CultRecordKey key) =>
|
||||
CultDocumentMessagePackSerialization.DeserializeSnapshot(File.ReadAllBytes(_manifest)).Records.Single(record => record.Key == key.Value);
|
||||
CultDocumentMessagePackSerialization.DeserializeSnapshot(File.ReadAllBytes(_manifest), _ => { }).Records.Single(record => record.Key == key.Value);
|
||||
|
||||
private string PagePath(byte[] identity) =>
|
||||
Path.Combine(_records, BitConverter.ToString(identity).Replace("-", string.Empty).ToLowerInvariant() + ".msgpack");
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ namespace GameCult.Caching.Tests
|
|||
try
|
||||
{
|
||||
var manifest = Path.Combine(root, "store.cc");
|
||||
Assert.That(CultDocumentMessagePackSerialization.DeserializeSnapshot(File.ReadAllBytes(manifest)).FormatVersion,
|
||||
Assert.That(CultDocumentMessagePackSerialization.DeserializeSnapshot(File.ReadAllBytes(manifest), _ => { }).FormatVersion,
|
||||
Is.EqualTo("cultcache.store.v4.directory-content-addressed-pages"));
|
||||
|
||||
using var cache = new CultCache();
|
||||
|
|
@ -342,16 +342,6 @@ namespace GameCult.Caching.Tests
|
|||
CultDocumentMessagePackSerialization.DeserializeUntyped(documentType, payload, Registry);
|
||||
}
|
||||
|
||||
private sealed class FlakyReadStore : SingleFileMessagePackBackingStore
|
||||
{
|
||||
public Exception? FailReadWith;
|
||||
|
||||
public FlakyReadStore(string path) : base(path) { }
|
||||
|
||||
protected override CultPersistedStoreSnapshot DeserializeSnapshot(byte[] data) =>
|
||||
FailReadWith != null ? throw FailReadWith : base.DeserializeSnapshot(data);
|
||||
}
|
||||
|
||||
private static void StampHeader(string file, string header)
|
||||
{
|
||||
var snapshot = CultDocumentMessagePackSerialization.DeserializeSnapshot(File.ReadAllBytes(file));
|
||||
|
|
@ -431,15 +421,16 @@ namespace GameCult.Caching.Tests
|
|||
try
|
||||
{
|
||||
var file = Path.Combine(root, "store.msgpack");
|
||||
var store = new FlakyReadStore(file);
|
||||
using var cache = new CultCache();
|
||||
cache.AddBackingStore(store);
|
||||
cache.AddBackingStore(new SingleFileMessagePackBackingStore(file));
|
||||
await cache.PullAllBackingStoresAsync();
|
||||
var before = File.ReadAllBytes(file);
|
||||
|
||||
await cache.AddAsync(new PreCut2FixtureNote { Text = "staged" });
|
||||
store.FailReadWith = new IOException("transient");
|
||||
Assert.Throws<IOException>(() => cache.FlushAllBackingStores());
|
||||
using (new FileStream(file, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
|
||||
{
|
||||
Assert.Throws<IOException>(() => cache.FlushAllBackingStores());
|
||||
}
|
||||
Assert.That(File.ReadAllBytes(file), Is.EqualTo(before));
|
||||
}
|
||||
finally
|
||||
|
|
@ -460,7 +451,7 @@ namespace GameCult.Caching.Tests
|
|||
cache.AddBackingStore(new DirectoryMessagePackBackingStore(manifest));
|
||||
await cache.PullAllBackingStoresAsync();
|
||||
|
||||
var snapshot = CultDocumentMessagePackSerialization.DeserializeSnapshot(File.ReadAllBytes(manifest));
|
||||
var snapshot = CultDocumentMessagePackSerialization.DeserializeSnapshot(File.ReadAllBytes(manifest), _ => { });
|
||||
snapshot.FormatVersion = newer;
|
||||
File.WriteAllBytes(manifest, CultDocumentMessagePackSerialization.SerializeSnapshot(snapshot));
|
||||
Func<System.Collections.Generic.Dictionary<string, byte[]>> files = () => Directory
|
||||
|
|
|
|||
Loading…
Reference in a new issue