From 3975bada0c95582da50c93b44aa614ed8412408e Mon Sep 17 00:00:00 2001 From: Andrew Noyes Date: Sat, 16 Mar 2024 22:02:00 -0700 Subject: [PATCH] Add a simple language for scripting tests --- CMakeLists.txt | 4 ++ ScriptTest.cpp | 136 +++++++++++++++++++++++++++++++++++++++++ script_tests/first.txt | 9 +++ 3 files changed, 149 insertions(+) create mode 100644 ScriptTest.cpp create mode 100644 script_tests/first.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 845f786..658f144 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -171,6 +171,10 @@ if(BUILD_TESTING) target_compile_options(driver PRIVATE ${TEST_FLAGS}) target_link_libraries(driver PRIVATE ${PROJECT_NAME}) + add_executable(script_test ScriptTest.cpp) + target_compile_options(script_test PRIVATE ${TEST_FLAGS}) + target_link_libraries(script_test PRIVATE ${PROJECT_NAME}) + add_executable(driver_skip_list TestDriver.cpp) target_compile_options(driver_skip_list PRIVATE ${TEST_FLAGS}) target_link_libraries(driver_skip_list PRIVATE skip_list) diff --git a/ScriptTest.cpp b/ScriptTest.cpp new file mode 100644 index 0000000..e9f26bd --- /dev/null +++ b/ScriptTest.cpp @@ -0,0 +1,136 @@ +#include "Internal.h" +#include + +#include +#include +#include +#include +#include +#include +#include + +inline size_t getPageSize() { + static size_t kPageSize = sysconf(_SC_PAGESIZE); + return kPageSize; +} + +/// Helper for rounding up to page size (or some other alignment) +constexpr inline size_t rightAlign(size_t offset, size_t alignment) { + return offset % alignment == 0 ? offset + : ((offset / alignment) + 1) * alignment; +} + +using StringView = std::basic_string_view; + +inline StringView operator"" _v(const char *str, size_t size) { + return {reinterpret_cast(str), size}; +} + +int main(int argc, const char **argv) { + + ConflictSet cs{0}; + ReferenceImpl ref{0}; + + for (int i = 1; i < argc; ++i) { + int fd = open(argv[i], O_RDONLY); + struct stat st; + if (fstat(fd, &st) == -1) { + int err = errno; + fprintf(stderr, "stat error %s - %s\n", argv[i], strerror(err)); + fflush(stderr); + abort(); + } + + int64_t size = rightAlign(st.st_size, getPageSize()); + const uint8_t *begin = + (uint8_t *)mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0); + madvise((void *)begin, size, MADV_SEQUENTIAL); + auto *const mapOriginal = begin; + const auto sizeOriginal = size; + + StringView b; + StringView e; + int64_t v = 0; + std::vector writeRanges; + std::vector readRanges; + std::vector results; + + for (uint8_t *end = (uint8_t *)memchr(begin, '\n', size); end != nullptr;) { + StringView line{begin, static_cast(end - begin)}; + size -= end - begin + 1; + begin = end + 1; + end = (uint8_t *)memchr(begin, '\n', size); + + if (line.starts_with("begin"_v)) { + b = line.substr("begin "_v.size(), line.size()); + printf("b <- %.*s\n", int(b.size()), b.data()); + } else if (line.starts_with("end"_v)) { + e = line.substr("end "_v.size(), line.size()); + printf("e <- %.*s\n", int(e.size()), e.data()); + } else if (line.starts_with("version"_v)) { + line = line.substr("version "_v.size(), line.size()); + v = 0; + for (auto c : line) { + v = v * 10 + int(c) - int('0'); + } + printf("v <- %" PRId64 "\n", v); + } else if (line.starts_with("pointread"_v)) { + printf("pointread\n"); + ConflictSet::ReadRange r; + r.begin.p = b.data(); + r.begin.len = b.size(); + r.end.len = 0; + r.readVersion = v; + readRanges.push_back(r); + } else if (line.starts_with("pointwrite"_v)) { + printf("pointwrite\n"); + ConflictSet::WriteRange w; + w.begin.p = b.data(); + w.begin.len = b.size(); + w.end.len = 0; + writeRanges.push_back(w); + } else if (line.starts_with("rangeread"_v)) { + printf("rangeread\n"); + ConflictSet::ReadRange r; + r.begin.p = b.data(); + r.begin.len = b.size(); + r.end.p = e.data(); + r.end.len = e.size(); + r.readVersion = v; + readRanges.push_back(r); + } else if (line.starts_with("rangewrite"_v)) { + printf("rangewrite\n"); + ConflictSet::WriteRange w; + w.begin.p = b.data(); + w.begin.len = b.size(); + w.end.p = e.data(); + w.end.len = e.size(); + writeRanges.push_back(w); + } else if (line.starts_with("check"_v)) { + printf("check\n"); + Arena arena; + auto *expected = new (arena) ConflictSet::Result[readRanges.size()]; + auto *actual = new (arena) ConflictSet::Result[readRanges.size()]; + ref.check(readRanges.data(), expected, readRanges.size()); + cs.check(readRanges.data(), actual, readRanges.size()); + for (int i = 0; i < int(readRanges.size()); ++i) { + assert(expected[i] == actual[i]); + } + readRanges = {}; + } else if (line.starts_with("addwrites"_v)) { + printf("addwrites\n"); + cs.addWrites(writeRanges.data(), writeRanges.size(), v); + ref.addWrites(writeRanges.data(), writeRanges.size(), v); + writeRanges = {}; + } else if (line.starts_with("setoldest"_v)) { + printf("setoldest\n"); + cs.setOldestVersion(v); + ref.setOldestVersion(v); + } else { + printf("Unrecognized line: %.*s\n", int(line.size()), line.data()); + } + } + munmap((void *)mapOriginal, sizeOriginal); + close(fd); + } +} diff --git a/script_tests/first.txt b/script_tests/first.txt new file mode 100644 index 0000000..3d3d6dc --- /dev/null +++ b/script_tests/first.txt @@ -0,0 +1,9 @@ +begin aa +pointwrite +version 1 +addwrites +begin aa +end bb +version 0 +rangeread +check