From 5b86bc9faf398a35548e0e392ffba9a969fb541b Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Wed, 30 Sep 2026 15:32:57 +0200 Subject: [PATCH] Test: a flush storing a record under a new id gives it a later storedAt when the file no longer holds it Defends the id half of the whole-view restamp rule on its own: the record C# loaded under v1's id is gone from the file when a v2 cache flushes it back, so there are no stored bytes to compare, and only the changed id says it is a new store. Co-Authored-By: Claude Opus 5.5 --- .../CompatibleSchemaIdTests.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/GameCult.Caching.Tests/CompatibleSchemaIdTests.cs b/tests/GameCult.Caching.Tests/CompatibleSchemaIdTests.cs index 35179a4d..8ac1b87c 100644 --- a/tests/GameCult.Caching.Tests/CompatibleSchemaIdTests.cs +++ b/tests/GameCult.Caching.Tests/CompatibleSchemaIdTests.cs @@ -542,6 +542,25 @@ namespace GameCult.Caching.Tests }), Is.EqualTo(CultCommitOutcome.Committed)); } + // A whole-view write that stores a record under another id than it was loaded under gives it a later storedAt, even when + // the file no longer holds the record it loaded. + [Test] + public void AFlushStoringARecordUnderANewIdGivesItALaterStoredAtWhateverTheFileHolds() + { + using (var older = OpenRoll(RollV1)) + older.Commit(batch => batch.Upsert(RollV1, New(RollV1, ("Name", "k")), RollK)); + var loaded = Read(RollPath).Records.Single(); + + using var cache = OpenRoll(RollV2); + using (var older = OpenRoll(RollV1)) + older.Commit(batch => batch.Remove(RollK)); + cache.BackingStores.Single().PushAll(); + + var flushed = Read(RollPath).Records.Single(); + Assert.That(flushed.SchemaId, Is.Not.EqualTo(RollV1Id)); + Assert.That(string.CompareOrdinal(flushed.StoredAt, loaded.StoredAt), Is.GreaterThan(0)); + } + // A record a whole-view write stores exactly as the file holds it keeps its storedAt, so a condition another cache holds // on it survives an unrelated flush. [TestCase(false)]