Fix conflict_set.py bug, and add full inner words test
All checks were successful
Tests / Clang total: 1091, passed: 1091
Clang |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / SIMD fallback total: 1091, passed: 1091
Tests / Release [gcc] total: 1091, passed: 1091
GNU C Compiler (gcc) |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Release [gcc,aarch64] total: 817, passed: 817
Tests / Coverage total: 818, passed: 818
weaselab/conflict-set/pipeline/head This commit looks good

Apparently all bytes were 0
This commit is contained in:
2024-04-17 14:11:26 -07:00
parent ed1388ed21
commit 64a98c529c
4 changed files with 43 additions and 20 deletions

View File

@@ -267,9 +267,10 @@ if(BUILD_TESTING)
COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/test_conflict_set.py COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/test_conflict_set.py
list OUTPUT_VARIABLE SCRIPT_TESTS) list OUTPUT_VARIABLE SCRIPT_TESTS)
foreach(TEST ${SCRIPT_TESTS}) foreach(TEST ${SCRIPT_TESTS})
add_test(NAME script_test_${TEST} add_test(
COMMAND ${Python3_EXECUTABLE} NAME script_test_${TEST}
${CMAKE_SOURCE_DIR}/test_conflict_set.py test ${TEST}) COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/test_conflict_set.py
test ${TEST} --build-dir ${CMAKE_BINARY_DIR})
endforeach() endforeach()
endif() endif()

View File

@@ -613,6 +613,10 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
for (int s = stripes - 1; s >= 0; s--) { for (int s = stripes - 1; s >= 0; s--) {
for (int i = 0; i * 2 < ss; ++i) { for (int i = 0; i * 2 < ss; ++i) {
const auto &w = writes[s * stripeSize / 2 + i]; const auto &w = writes[s * stripeSize / 2 + i];
#if DEBUG_VERBOSE
printf("Write begin: %s\n", printable(w.begin).c_str());
fflush(stdout);
#endif
values[i * 2] = {w.begin.p, size_t(w.begin.len)}; values[i * 2] = {w.begin.p, size_t(w.begin.len)};
values[i * 2 + 1] = w.end.len > 0 values[i * 2 + 1] = w.end.len > 0
? StringRef{w.end.p, size_t(w.end.len)} ? StringRef{w.end.p, size_t(w.end.len)}

View File

@@ -28,39 +28,38 @@ class Result(enum.Enum):
def write(begin: bytes, end: Optional[bytes] = None) -> WriteRange: def write(begin: bytes, end: Optional[bytes] = None) -> WriteRange:
b = (ctypes.c_ubyte * len(begin))() b = (ctypes.c_ubyte * len(begin)).from_buffer(bytearray(begin))
b.value = begin
if end is None: if end is None:
e = (ctypes.c_ubyte * 0)() e = (ctypes.c_ubyte * 0)()
e.value = b""
else: else:
e = (ctypes.c_ubyte * len(end))() e = (ctypes.c_ubyte * len(end)).from_buffer(bytearray(end))
e.value = end
return WriteRange(_Key(b, len(b)), _Key(e, len(e))) return WriteRange(_Key(b, len(b)), _Key(e, len(e)))
def read(version: int, begin: bytes, end: Optional[bytes] = None) -> ReadRange: def read(version: int, begin: bytes, end: Optional[bytes] = None) -> ReadRange:
b = (ctypes.c_ubyte * len(begin))() b = (ctypes.c_ubyte * len(begin)).from_buffer(bytearray(begin))
b.value = begin
if end is None: if end is None:
e = (ctypes.c_ubyte * 0)() e = (ctypes.c_ubyte * 0)()
e.value = b""
else: else:
e = (ctypes.c_ubyte * len(end))() e = (ctypes.c_ubyte * len(end)).from_buffer(bytearray(end))
e.value = end
return ReadRange(_Key(b, len(b)), _Key(e, len(e)), version) return ReadRange(_Key(b, len(b)), _Key(e, len(e)), version)
class ConflictSet: class ConflictSet:
def __init__(self, version: int = 0, implementation: Optional[str] = None) -> None: def __init__(
self,
version: int = 0,
build_dir: Optional[str] = None,
implementation: Optional[str] = None,
) -> None:
self._lib = None self._lib = None
if build_dir is None:
build_dir = os.path.dirname(__file__) + "/build"
if implementation is None: if implementation is None:
implementation = "radix_tree" implementation = "radix_tree"
for f in ( for f in (
os.path.dirname(__file__) build_dir + "/" + implementation + "/libconflict-set.so.0",
+ "/build/"
+ implementation
+ "/libconflict-set.so.0",
os.path.dirname(__file__) os.path.dirname(__file__)
+ "/build/" + "/build/"
+ implementation + implementation

View File

@@ -1,14 +1,21 @@
from conflict_set import * from conflict_set import *
build_dir = None
class DebugConflictSet: class DebugConflictSet:
""" """
Bisimulates the skip list and radix tree conflict sets for testing purposes Bisimulates the skip list and radix tree conflict sets for testing purposes
""" """
def __init__(self, version: int = 0) -> None: def __init__(self, version: int = 0) -> None:
self.skip_list = ConflictSet(version, implementation="skip_list") self.skip_list = ConflictSet(
self.radix_tree = ConflictSet(version, implementation="radix_tree") version, build_dir=build_dir, implementation="skip_list"
)
self.radix_tree = ConflictSet(
version, build_dir=build_dir, implementation="radix_tree"
)
def addWrites(self, version: int, *writes: WriteRange): def addWrites(self, version: int, *writes: WriteRange):
self.skip_list.addWrites(version, *writes) self.skip_list.addWrites(version, *writes)
@@ -49,6 +56,16 @@ def test_conflict_set():
assert cs.check(read(0, key)) == [Result.TOO_OLD] assert cs.check(read(0, key)) == [Result.TOO_OLD]
def test_inner_full_words():
with DebugConflictSet() as cs:
cs.addWrites(1, write(b"\x3f\x61"), write(b"\x81\x61"))
writes = []
for i in range(0x40, 0x81):
writes.append(write(bytes([i, 0x61])))
cs.addWrites(2, *writes)
cs.check(read(1, b"\x21", b"\xc2"))
if __name__ == "__main__": if __name__ == "__main__":
# budget "pytest" for ctest integration without pulling in a dependency. You can of course still use pytest in local development. # budget "pytest" for ctest integration without pulling in a dependency. You can of course still use pytest in local development.
import argparse import argparse
@@ -61,6 +78,7 @@ if __name__ == "__main__":
list_parser = subparsers.add_parser("list") list_parser = subparsers.add_parser("list")
test_parser = subparsers.add_parser("test") test_parser = subparsers.add_parser("test")
test_parser.add_argument("test") test_parser.add_argument("test")
test_parser.add_argument("--build-dir")
args = parser.parse_args() args = parser.parse_args()
@@ -74,4 +92,5 @@ if __name__ == "__main__":
) )
) )
elif args.command == "test": elif args.command == "test":
build_dir = args.build_dir
globals()["test_" + args.test]() globals()["test_" + args.test]()