Add fuzz test

This commit is contained in:
2024-01-19 15:48:07 -08:00
parent a2a55c9717
commit 756f74c6de
3 changed files with 58 additions and 7 deletions

View File

@@ -1,2 +1,2 @@
CompileFlags: CompileFlags:
Add: [-DENABLE_TESTS, -UNDEBUG] Add: [-DENABLE_TESTS, -UNDEBUG, -DENABLE_FUZZ]

View File

@@ -14,19 +14,21 @@ target_compile_options(conflict_set PRIVATE -fno-exceptions -fvisibility=hidden)
target_link_options(conflict_set PRIVATE -nodefaultlibs -lc -fvisibility=hidden) target_link_options(conflict_set PRIVATE -nodefaultlibs -lc -fvisibility=hidden)
add_custom_command(TARGET conflict_set POST_BUILD COMMAND ${CMAKE_STRIP} -x $<TARGET_FILE:conflict_set>) add_custom_command(TARGET conflict_set POST_BUILD COMMAND ${CMAKE_STRIP} -x $<TARGET_FILE:conflict_set>)
include(CTest)
# unit test
add_executable(conflict_set_test ConflictSet.cpp ConflictSet.h) add_executable(conflict_set_test ConflictSet.cpp ConflictSet.h)
target_compile_definitions(conflict_set_test PRIVATE ENABLE_TESTS) target_compile_definitions(conflict_set_test PRIVATE ENABLE_TESTS)
# keep asserts for test # keep asserts for test
target_compile_options(conflict_set_test PRIVATE -UNDEBUG) target_compile_options(conflict_set_test PRIVATE -UNDEBUG)
# Only emit compile warnings for test # Only emit compile warnings for test
target_compile_options(conflict_set_test PRIVATE -Wall -Wextra -Wpedantic -Wunreachable-code) target_compile_options(conflict_set_test PRIVATE -Wall -Wextra -Wpedantic -Wunreachable-code)
include(CTest)
add_test(NAME conflict_set_test COMMAND conflict_set_test) add_test(NAME conflict_set_test COMMAND conflict_set_test)
# api smoke tests # api smoke tests
# c89 # c99
add_executable(conflict_set_c_api_test conflict_set_c_api_test.c ConflictSet.h) add_executable(conflict_set_c_api_test conflict_set_c_api_test.c ConflictSet.h)
target_link_libraries(conflict_set_c_api_test PRIVATE conflict_set) target_link_libraries(conflict_set_c_api_test PRIVATE conflict_set)
target_compile_options(conflict_set_c_api_test PRIVATE -UNDEBUG) target_compile_options(conflict_set_c_api_test PRIVATE -UNDEBUG)
@@ -41,3 +43,17 @@ target_compile_options(conflict_set_cxx_api_test PRIVATE -UNDEBUG)
set_property(TARGET conflict_set_cxx_api_test PROPERTY CXX_STANDARD 98) set_property(TARGET conflict_set_cxx_api_test PROPERTY CXX_STANDARD 98)
add_test(NAME conflict_set_cxx_api_test COMMAND conflict_set_cxx_api_test) add_test(NAME conflict_set_cxx_api_test COMMAND conflict_set_cxx_api_test)
target_compile_options(conflict_set_cxx_api_test PRIVATE -Wall -Wextra -Wpedantic -Wunreachable-code -Werror) target_compile_options(conflict_set_cxx_api_test PRIVATE -Wall -Wextra -Wpedantic -Wunreachable-code -Werror)
# fuzz test
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag(HAS_LIB_FUZZER -fsanitize=fuzzer)
if (HAS_LIB_FUZZER)
add_executable(conflict_set_fuzz_test ConflictSet.cpp ConflictSet.h)
target_compile_definitions(conflict_set_fuzz_test PRIVATE ENABLE_FUZZ)
# keep asserts for test
target_compile_options(conflict_set_fuzz_test PRIVATE -UNDEBUG)
target_compile_options(conflict_set_fuzz_test PRIVATE -Wall -Wextra -Wpedantic -Wunreachable-code)
target_compile_options(conflict_set_fuzz_test PRIVATE -fsanitize=fuzzer)
target_link_options(conflict_set_fuzz_test PRIVATE -fsanitize=fuzzer)
endif()

View File

@@ -6,6 +6,7 @@
#include <cstring> #include <cstring>
#include <map> #include <map>
#include <random> #include <random>
#include <set>
#include <span> #include <span>
#include <string> #include <string>
#include <string_view> #include <string_view>
@@ -825,7 +826,7 @@ void rotate(Node **node, bool dir) {
updateMaxVersion(l); updateMaxVersion(l);
} }
void checkParentPointers(Node *node, bool &success) { [[maybe_unused]] void checkParentPointers(Node *node, bool &success) {
for (int i = 0; i < 2; ++i) { for (int i = 0; i < 2; ++i) {
if (node->child[i] != nullptr) { if (node->child[i] != nullptr) {
if (node->child[i]->parent != node) { if (node->child[i]->parent != node) {
@@ -839,7 +840,7 @@ void checkParentPointers(Node *node, bool &success) {
} }
} }
int64_t checkMaxVersion(Node *node, bool &success) { [[maybe_unused]] int64_t checkMaxVersion(Node *node, bool &success) {
int64_t expected = std::max(node->pointVersion, node->rangeVersion); int64_t expected = std::max(node->pointVersion, node->rangeVersion);
for (int i = 0; i < 2; ++i) { for (int i = 0; i < 2; ++i) {
if (node->child[i] != nullptr) { if (node->child[i] != nullptr) {
@@ -1214,3 +1215,37 @@ int main(void) {
return success ? 0 : 1; return success ? 0 : 1;
} }
#endif #endif
#ifdef ENABLE_FUZZ
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
initFuzz(data, size);
int64_t writeVersion = 0;
ConflictSet::Impl cs{writeVersion};
ReferenceImpl refImpl{writeVersion};
while (gArbitrary.hasEntropy()) {
Arena arena;
int numWrites = gArbitrary.bounded(10);
int64_t v = ++writeVersion;
auto *writes = new (arena) ConflictSet::WriteRange[numWrites];
std::set<int> keys;
while (int(keys.size()) < numWrites) {
keys.insert(gRandom.bounded(100));
}
auto iter = keys.begin();
for (int i = 0; i < numWrites; ++i) {
writes[i].begin = toKey(arena, *iter++);
writes[i].end.len = 0;
writes[i].writeVersion = v;
}
cs.addWrites(writes, numWrites);
refImpl.addWrites(writes, numWrites);
bool success = checkCorrectness(cs.root, refImpl);
if (!success) {
abort();
}
}
return 0;
}
#endif