#include "Facade.h" #include "Internal.h" #include "KeyCompare.h" #include #include #include #define DEBUG 0 constexpr int kKeySize = 4; weaselab::VersionedMap::Key randomKey(Arena &arena) { auto *result = new (arena) uint8_t[kKeySize]; gRandom.randomHex(result, kKeySize); return {result, kKeySize}; } weaselab::VersionedMap::Key arbitraryKey(Arena &arena) { auto *result = new (arena) uint8_t[kKeySize]; gArbitrary.randomHex(result, kKeySize); return {result, kKeySize}; } struct KeyComp { bool operator()(const weaselab::VersionedMap::Key &lhs, const weaselab::VersionedMap::Key &rhs) const { return lhs < rhs; } }; extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { initFuzz(data, size); Facade facade{0}; Arena arena; while (gArbitrary.hasEntropy()) { switch (gArbitrary.bounded(3)) { case 0: { // Add mutations const int numKeys = gArbitrary.bounded(10); std::set keySet; while (int(keySet.size()) < numKeys) { keySet.insert(randomKey(arena)); } std::vector keys; keys.insert(keys.end(), keySet.begin(), keySet.end()); std::vector mutations; for (int i = 0; i < int(keys.size());) { switch (gArbitrary.bounded(3)) { case 0: { // Point write auto val = randomKey(arena); mutations.push_back({keys[i].p, val.p, keys[i].len, val.len, weaselab::VersionedMap::Set}); ++i; } break; case 1: { // Point clear mutations.push_back({keys[i].p, nullptr, keys[i].len, 0, weaselab::VersionedMap::Clear}); ++i; } break; case 2: { // Range clear if (i + 1 < int(keys.size())) { mutations.push_back({keys[i].p, keys[i + 1].p, keys[i].len, keys[i + 1].len, weaselab::VersionedMap::Clear}); i += 2; } } break; } } facade.addMutations(mutations.data(), mutations.size(), facade.getVersion() + 1); } break; case 1: { // Set oldest version const int64_t newOldestVersion = facade.getOldestVersion() + gArbitrary.bounded(facade.getVersion() - facade.getOldestVersion() + 1); facade.setOldestVersion(newOldestVersion); } break; case 2: { // Check range read const int64_t version = facade.getOldestVersion() + gArbitrary.bounded(facade.getVersion() - facade.getOldestVersion() + 1); auto begin = arbitraryKey(arena); auto end = arbitraryKey(arena); const int limit = gArbitrary.bounded(100000); const bool reverse = gArbitrary.bounded(2); facade.viewAt(version).rangeRead(String(begin.p, begin.len), String(end.p, end.len), limit, reverse); } break; } } return 0; }