namespace DodoSSH.Client.Sync.Tests; /// /// The id a rescued item takes. /// /// /// Determinism here is what makes the rescue crash-safe. The reconciler queues the restored copy before /// it clears the original, and those are two separate transactions — so a process that dies between them /// leaves the original pending and resurrects again on the next pass. Landing on the same id means that /// second attempt coalesces into the row already queued instead of leaving the user with duplicates. /// public sealed class ResurrectionIdTests { private static readonly Guid Original = Guid.Parse("0192f0c8-1234-7c3d-8e4f-5a6b7c8d9e0f"); private static readonly Guid Other = Guid.Parse("0192f0c8-5678-7c3d-8e4f-5a6b7c8d9e0f"); [Fact] public void TheSameTombstone_AlwaysYieldsTheSameId() { ResurrectionId.For(Original, 3).ShouldBe(ResurrectionId.For(Original, 3)); } [Fact] public void ADifferentItem_YieldsADifferentId() { ResurrectionId.For(Original, 3).ShouldNotBe(ResurrectionId.For(Other, 3)); } [Fact] public void ADifferentTombstoneVersion_YieldsADifferentId() { // An item deleted, restored, and deleted again must produce a second rescue rather than // colliding with the first. ResurrectionId.For(Original, 3).ShouldNotBe(ResurrectionId.For(Original, 4)); } [Fact] public void TheIdIsNotTheOriginal() { // The tombstone stands, so the rescued copy has to be a different item. Reusing the id would // conflict against the tombstone for ever. ResurrectionId.For(Original, 1).ShouldNotBe(Original); ResurrectionId.For(Original, 1).ShouldNotBe(Guid.Empty); } }