Naive range reads implementation and test

This commit is contained in:
2024-02-05 13:59:10 -08:00
parent e3e0e7ba44
commit 57ec97f2ee
2 changed files with 83 additions and 22 deletions

View File

@@ -441,7 +441,7 @@ inline std::string printable(const Key &key) {
namespace {
template <class ConflictSetImpl> struct TestDriver {
// TODO call setOldestVersion, and check range writes/reads
// TODO call setOldestVersion
Arbitrary arbitrary;
explicit TestDriver(const uint8_t *data, size_t size)
: arbitrary({data, size}) {}
@@ -536,11 +536,13 @@ template <class ConflictSetImpl> struct TestDriver {
refImpl.addWrites(writes, numPointWrites + numRangeWrites);
}
{
int numReads = arbitrary.bounded(10);
int numPointReads = arbitrary.bounded(100);
int numRangeReads = arbitrary.bounded(100);
int64_t v = std::max<int64_t>(writeVersion - arbitrary.bounded(10), 0);
auto *reads = new (arena) ConflictSet::ReadRange[numReads];
auto *reads =
new (arena) ConflictSet::ReadRange[numPointReads + numRangeReads];
auto keys = set<std::string_view>(arena);
while (int(keys.size()) < numReads) {
while (int(keys.size()) < numPointReads + numRangeReads * 2) {
if (!arbitrary.hasEntropy()) {
return true;
}
@@ -549,29 +551,68 @@ template <class ConflictSetImpl> struct TestDriver {
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;
int i = 0;
for (int pointsRemaining = numPointReads, rangesRemaining = numRangeReads;
pointsRemaining > 0 || rangesRemaining > 0; ++i) {
bool pointRead = pointsRemaining > 0 && rangesRemaining > 0
? bool(arbitrary.bounded(2))
: pointsRemaining > 0;
if (pointRead) {
assert(pointsRemaining > 0);
reads[i].begin.p = (const uint8_t *)iter->data();
reads[i].begin.len = iter->size();
reads[i].end.len = 0;
++iter;
--pointsRemaining;
} else {
assert(rangesRemaining > 0);
reads[i].begin.p = (const uint8_t *)iter->data();
reads[i].begin.len = iter->size();
++iter;
reads[i].end.p = (const uint8_t *)iter->data();
reads[i].end.len = iter->size();
++iter;
--rangesRemaining;
}
reads[i].readVersion = v;
#if DEBUG_VERBOSE && !defined(NDEBUG)
fprintf(stderr, "Read: {%s} at %d\n", printable(reads[i].begin).c_str(),
int(reads[i].readVersion));
if (reads[i].end.len == 0) {
fprintf(stderr, "Read: {%s} @ %d\n",
printable(reads[i].begin).c_str(), int(reads[i].readVersion));
} else {
fprintf(stderr, "Read: [%s, %s) @ %d\n",
printable(reads[i].begin).c_str(),
printable(reads[i].end).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) {
assert(i == numPointReads + numRangeReads);
auto *results1 =
new (arena) ConflictSet::Result[numPointReads + numRangeReads];
auto *results2 =
new (arena) ConflictSet::Result[numPointReads + numRangeReads];
cs.check(reads, results1, numPointReads + numRangeReads);
refImpl.check(reads, results2, numPointReads + numRangeReads);
for (int i = 0; i < numPointReads + numRangeReads; ++i) {
if (results1[i] != results2[i]) {
fprintf(stderr,
"Expected %s, got %s for read of %s at version %" PRId64 "\n",
resultToStr(results2[i]), resultToStr(results1[i]),
printable(reads[i].begin).c_str(), reads[i].readVersion);
if (reads[i].end.len == 0) {
fprintf(stderr,
"Expected %s, got %s for read of {%s} at version %" PRId64
"\n",
resultToStr(results2[i]), resultToStr(results1[i]),
printable(reads[i].begin).c_str(), reads[i].readVersion);
} else {
fprintf(
stderr,
"Expected %s, got %s for read of [%s, %s) at version %" PRId64
"\n",
resultToStr(results2[i]), resultToStr(results1[i]),
printable(reads[i].begin).c_str(),
printable(reads[i].end).c_str(), reads[i].readVersion);
}
ok = false;
return true;
}