Add TestDriver class

This commit is contained in:
2024-01-30 11:13:21 -08:00
parent 47faa51a35
commit 3735a43553
2 changed files with 102 additions and 92 deletions

View File

@@ -17,8 +17,6 @@
#include <arm_neon.h>
#endif
#define DEBUG_VERBOSE 0
// ==================== BEGIN IMPLEMENTATION ====================
struct Entry {
@@ -45,11 +43,6 @@ struct Node {
Type type = Type::Invalid;
};
Node *getChild(Node *self, uint8_t index);
int getChildGeq(Node *self, int child);
Node *&getOrCreateChild(Node *&self, uint8_t index);
Node *newNode();
void eraseChild(Node *self, uint8_t index);
struct Node4 : Node {
// Sorted
@@ -1015,95 +1008,15 @@ int main(void) {
#ifdef ENABLE_FUZZ
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// TODO call setOldestVersion, and check range writes/reads
Arbitrary arbitrary{{data, size}};
TestDriver<ConflictSet::Impl> driver{data, size};
int64_t writeVersion = 0;
ConflictSet::Impl cs{writeVersion};
ReferenceImpl refImpl{writeVersion};
while (arbitrary.hasEntropy()) {
Arena arena;
{
int numWrites = arbitrary.bounded(10);
int64_t v = ++writeVersion;
auto *writes = new (arena) ConflictSet::WriteRange[numWrites];
auto keys = set<std::string_view>(arena);
while (int(keys.size()) < numWrites) {
if (!arbitrary.hasEntropy()) {
// Tell the fuzzer it's not interesting
return -1;
}
int keyLen = arbitrary.bounded(8);
auto *begin = new (arena) uint8_t[keyLen];
arbitrary.randomBytes(begin, keyLen);
keys.insert(std::string_view((const char *)begin, keyLen));
}
auto iter = keys.begin();
for (int i = 0; i < numWrites; ++i) {
writes[i].begin.p = (const uint8_t *)iter->data();
writes[i].begin.len = iter->size();
++iter;
writes[i].end.len = 0;
writes[i].writeVersion = v;
#if DEBUG_VERBOSE && !defined(NDEBUG)
printf("Write: {%s} -> %d\n", printable(writes[i].begin).c_str(),
int(writes[i].writeVersion));
#endif
}
assert(iter == keys.end());
cs.addWrites(writes, numWrites);
refImpl.addWrites(writes, numWrites);
}
bool success = checkCorrectness(cs.root, refImpl);
do {
bool success = checkCorrectness(driver.cs.root, driver.refImpl);
if (!success) {
abort();
}
{
int numReads = arbitrary.bounded(10);
int64_t v = writeVersion - arbitrary.bounded(10);
auto *reads = new (arena) ConflictSet::ReadRange[numReads];
auto keys = set<std::string_view>(arena);
while (int(keys.size()) < numReads) {
if (!arbitrary.hasEntropy()) {
// Tell the fuzzer it's not interesting
return -1;
}
int keyLen = arbitrary.bounded(8);
auto *begin = new (arena) uint8_t[keyLen];
arbitrary.randomBytes(begin, keyLen);
keys.insert(std::string_view((const char *)begin, keyLen));
}
auto iter = keys.begin();
for (int i = 0; i < numReads; ++i) {
reads[i].begin.p = (const uint8_t *)iter->data();
reads[i].begin.len = iter->size();
++iter;
reads[i].end.len = 0;
reads[i].readVersion = v;
#if DEBUG_VERBOSE && !defined(NDEBUG)
printf("Read: {%s} at %d\n", printable(reads[i].begin).c_str(),
int(reads[i].readVersion));
#endif
}
assert(iter == keys.end());
auto *results1 = new (arena) ConflictSet::Result[numReads];
auto *results2 = new (arena) ConflictSet::Result[numReads];
cs.check(reads, results1, numReads);
refImpl.check(reads, results2, numReads);
for (int i = 0; i < numReads; ++i) {
if (results1[i] != results2[i]) {
fprintf(stderr, "Expected %d, got %d for read of %s at version %d\n",
results2[i], results1[i], printable(reads[i].begin).c_str(),
int(reads[i].readVersion));
std::string referenceLogicalMap;
refImpl.printLogical(referenceLogicalMap);
fprintf(stderr, "Logical map:\n\n%s\n", referenceLogicalMap.c_str());
abort();
}
}
}
}
} while (!driver.next());
return 0;
}
#endif