diff --git a/test_conflict_set.py b/test_conflict_set.py index 924e89e..9d5456e 100644 --- a/test_conflict_set.py +++ b/test_conflict_set.py @@ -205,8 +205,32 @@ def test_internal_version_zero(): def test_two_billion_versions(): with DebugConflictSet() as cs: cs.addWrites(int(2e9) + 1) - cs.check(read(0, b"\x00", b"\xff")) - cs.check(read(1, b"\x00", b"\xff")) + assert cs.check(read(0, b"\x00", b"\xff")) == [Result.TOO_OLD] + assert cs.check(read(1, b"\x00", b"\xff")) == [Result.COMMIT] + + +def test_two_billion_version_window(): + # Regression test for issue #98: `addWrites` advances `newestVersion`, so a + # read whose readVersion fell more than two billion versions behind it is + # TooOld. `hash_table` used to discard writeVersion entirely, so it reported + # Conflict/Commit for reads far outside the version window. + window = 2 * 10**9 + newest = 2**32 + + def probe(implementation, read_version, *writes): + with ConflictSet(0, build_dir=build_dir, implementation=implementation) as cs: + cs.addWrites(newest, *writes) + return cs.check(read(read_version, b"k"))[0] + + for implementation in ("radix_tree", "skip_list", "hash_table"): + # The window advances even when addWrites added no writes at all. + assert probe(implementation, 0, write(b"k")) == Result.TOO_OLD + assert probe(implementation, 0) == Result.TOO_OLD + assert probe(implementation, newest - window - 1, write(b"k")) == Result.TOO_OLD + assert probe(implementation, newest - window - 1) == Result.TOO_OLD + # Exactly `window` versions behind newestVersion is still evaluable. + assert probe(implementation, newest - window, write(b"k")) == Result.CONFLICT + assert probe(implementation, newest - window) == Result.COMMIT def test_positive_bytes():