Merge pull request 'Keep Python wrapper key buffers alive in WriteRange/ReadRange' (#43) from weaselbot/conflict-set:weaselbot/issue-42 into main
CI / pre-commit (push) Successful in 2m10s
CI / release (arm64, ubuntu-latest-arm64) (push) Successful in 3m32s
CI / test (-DCMAKE_BUILD_TYPE=Debug, debug) (push) Successful in 3m39s
CI / test (-DCMAKE_CXX_FLAGS=-DUSE_64_BIT=1, 64-bit-versions) (push) Successful in 3m31s
CI / test (-DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++, gcc) (push) Successful in 3m41s
CI / test (-DUSE_SIMD_FALLBACK=ON, simd-fallback) (push) Successful in 3m30s
CI / release (amd64, ubuntu-latest-amd64) (push) Successful in 4m58s
CI / coverage (push) Successful in 3m43s

Reviewed-on: #43
Reviewed-by: andrew <andrew@weaselab.dev>
This commit was merged in pull request #43.
This commit is contained in:
2026-06-23 01:17:45 +00:00
2 changed files with 59 additions and 9 deletions
+36
View File
@@ -57,6 +57,42 @@ def test_conflict_set():
assert cs.check(read(0, key), read(1, key)) == [Result.TOO_OLD, Result.COMMIT]
def test_write_read_without_outer_reference():
# Regression test for issue #42: WriteRange/ReadRange must keep their
# backing key buffers alive, because the C library reads the pointer
# stored in _Key while addWrites/check run.
with DebugConflictSet() as cs:
# The bytes literal is not referenced after this expression.
cs.addWrites(1, write(b"key"))
assert cs.check(read(0, b"key")) == [Result.CONFLICT]
cs.addWrites(2, write(b"a", b"z"))
assert cs.check(read(1, b"a", b"z")) == [Result.CONFLICT]
assert cs.check(read(1, b"b")) == [Result.CONFLICT]
assert cs.check(read(1, b"0")) == [Result.COMMIT]
def test_range_keeps_key_buffers_alive():
# Verify the fix for issue #42: returned range objects must retain a
# reference to the backing bytearray so the C pointer stays valid after
# the helper returns.
w = write(b"key")
assert w._begin_buf == bytearray(b"key")
assert w._end_buf is None
w2 = write(b"a", b"z")
assert w2._begin_buf == bytearray(b"a")
assert w2._end_buf == bytearray(b"z")
r = read(0, b"key")
assert r._begin_buf == bytearray(b"key")
assert r._end_buf is None
r2 = read(1, b"a", b"z")
assert r2._begin_buf == bytearray(b"a")
assert r2._end_buf == bytearray(b"z")
def test_update_zero_should_commit():
with DebugConflictSet() as cs1:
with DebugConflictSet() as cs2: