5 Commits

Author SHA1 Message Date
andrew 55271ad06c Update corpus
Tests / Clang total: 15, passed: 15
Clang |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Debug total: 13, passed: 13
Tests / SIMD fallback total: 15, passed: 15
Tests / Release [gcc] total: 15, passed: 15
GNU C Compiler (gcc) |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Release [gcc,aarch64] total: 4, passed: 4
Tests / Coverage total: 13, passed: 13
Code Coverage #### Project Overview No changes detected, that affect the code coverage. * Line Coverage: 66.27% (1167/1761) * Branch Coverage: 18.79% (448/2384) * Complexity Density: 0.00 * Lines of Code: 1761 #### Quality Gates Summary Output truncated.
weaselab/conflict-set/pipeline/head This commit looks good
To match new "interleaving" test setup
2024-07-23 16:54:03 -07:00
andrew e675612599 Suppress some warnings in test code 2024-07-23 16:50:02 -07:00
andrew 42b5d50492 Update DEBUG_VERBOSE for interleaving conflict sets in test 2024-07-23 15:44:29 -07:00
andrew 6394995def Add a test where the "zero" bug causes an incorrect commit 2024-07-23 14:39:45 -07:00
andrew c649bc7964 Interleave calls for two conflict sets in tests 2024-07-23 11:12:02 -07:00
385 changed files with 167 additions and 100 deletions
+33 -17
View File
@@ -3928,7 +3928,7 @@ checkMaxVersion(Node *root, Node *node, InternalVersionT oldestVersion,
bool &success, ConflictSet::Impl *impl) {
checkVersionsGeqOldestExtant(node,
InternalVersionT(impl->oldestExtantVersion));
auto expected = InternalVersionT::zero;
auto expected = oldestVersion;
if (node->entryPresent) {
expected = std::max(expected, node->entry.pointVersion);
}
@@ -4151,26 +4151,42 @@ int main(void) { printTree(); }
#ifdef ENABLE_FUZZ
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
TestDriver<ConflictSet::Impl> driver{data, size};
Arbitrary arbitrary({data, size});
TestDriver<ConflictSet::Impl> driver1{arbitrary};
TestDriver<ConflictSet::Impl> driver2{arbitrary};
bool done1 = false;
bool done2 = false;
for (;;) {
bool done = driver.next();
if (!driver.ok) {
debugPrintDot(stdout, driver.cs.root, &driver.cs);
fflush(stdout);
abort();
if (!done1) {
done1 = driver1.next();
if (!driver1.ok) {
debugPrintDot(stdout, driver1.cs.root, &driver1.cs);
fflush(stdout);
abort();
}
if (!checkCorrectness(driver1.cs.root, driver1.cs.oldestVersion,
&driver1.cs)) {
debugPrintDot(stdout, driver1.cs.root, &driver1.cs);
fflush(stdout);
abort();
}
}
#if DEBUG_VERBOSE && !defined(NDEBUG)
fprintf(stderr, "Check correctness\n");
#endif
bool success =
checkCorrectness(driver.cs.root, driver.cs.oldestVersion, &driver.cs);
if (!success) {
debugPrintDot(stdout, driver.cs.root, &driver.cs);
fflush(stdout);
abort();
if (!done2) {
done2 = driver2.next();
if (!driver2.ok) {
debugPrintDot(stdout, driver2.cs.root, &driver2.cs);
fflush(stdout);
abort();
}
if (!checkCorrectness(driver2.cs.root, driver2.cs.oldestVersion,
&driver2.cs)) {
debugPrintDot(stdout, driver2.cs.root, &driver2.cs);
fflush(stdout);
abort();
}
}
if (done) {
if (done1 && done2) {
break;
}
}
+69 -57
View File
@@ -580,11 +580,14 @@ namespace {
template <class ConflictSetImpl, bool kEnableAssertions = true>
struct TestDriver {
Arbitrary arbitrary;
explicit TestDriver(const uint8_t *data, size_t size)
: arbitrary({data, size}) {}
Arbitrary *arbitrary;
explicit TestDriver(Arbitrary &a) : arbitrary(&a) {
#if DEBUG_VERBOSE && !defined(NDEBUG)
fprintf(stderr, "%p Initial version: {%" PRId64 "}\n", this, writeVersion);
#endif
}
int64_t oldestVersion = arbitrary.next();
int64_t oldestVersion = arbitrary->next();
int64_t writeVersion = oldestVersion;
ConflictSetImpl cs{oldestVersion};
ReferenceImpl refImpl{oldestVersion};
@@ -593,33 +596,34 @@ struct TestDriver {
bool ok = true;
const int prefixLen = arbitrary.bounded(512);
const int prefixByte = arbitrary.randT<uint8_t>();
const int prefixLen = arbitrary->bounded(512);
const int prefixByte = arbitrary->randT<uint8_t>();
// Call until it returns true, for "done". Check internal invariants etc
// between calls to next.
bool next() {
assert(cs.getBytes() >= 0);
if (!arbitrary.hasEntropy()) {
if (!arbitrary->hasEntropy()) {
return true;
}
Arena arena;
{
int numPointWrites = arbitrary.bounded(100);
int numRangeWrites = arbitrary.bounded(100);
int64_t v = (writeVersion += arbitrary.bounded(10) ? arbitrary.bounded(10)
: arbitrary.next());
int numPointWrites = arbitrary->bounded(100);
int numRangeWrites = arbitrary->bounded(100);
int64_t v =
(writeVersion +=
arbitrary->bounded(10) ? arbitrary->bounded(10) : arbitrary->next());
auto *writes =
new (arena) ConflictSet::WriteRange[numPointWrites + numRangeWrites];
auto keys = set<std::string_view>(arena);
while (int(keys.size()) < numPointWrites + numRangeWrites * 2) {
if (!arbitrary.hasEntropy()) {
if (!arbitrary->hasEntropy()) {
return true;
}
int keyLen = prefixLen + arbitrary.bounded(kMaxKeySuffixLen);
int keyLen = prefixLen + arbitrary->bounded(kMaxKeySuffixLen);
auto *begin = new (arena) uint8_t[keyLen];
memset(begin, prefixByte, prefixLen);
arbitrary.randomBytes(begin + prefixLen, keyLen - prefixLen);
arbitrary->randomBytes(begin + prefixLen, keyLen - prefixLen);
keys.insert(std::string_view((const char *)begin, keyLen));
}
@@ -629,7 +633,7 @@ struct TestDriver {
rangesRemaining = numRangeWrites;
pointsRemaining > 0 || rangesRemaining > 0; ++i) {
bool pointRead = pointsRemaining > 0 && rangesRemaining > 0
? bool(arbitrary.bounded(2))
? bool(arbitrary->bounded(2))
: pointsRemaining > 0;
if (pointRead) {
assert(pointsRemaining > 0);
@@ -648,33 +652,20 @@ struct TestDriver {
++iter;
--rangesRemaining;
}
#if DEBUG_VERBOSE && !defined(NDEBUG)
if (writes[i].end.len == 0) {
fprintf(stderr, "Write: {%s}\n", printable(writes[i].begin).c_str());
} else {
fprintf(stderr, "Write: [%s, %s)\n",
printable(writes[i].begin).c_str(),
printable(writes[i].end).c_str());
}
#endif
}
assert(iter == keys.end());
assert(i == numPointWrites + numRangeWrites);
#if DEBUG_VERBOSE && !defined(NDEBUG)
fprintf(stderr, "Write @ %" PRId64 "\n", v);
#endif
// Test non-canonical writes
if (numPointWrites > 0) {
int overlaps = arbitrary.bounded(numPointWrites);
int overlaps = arbitrary->bounded(numPointWrites);
for (int i = 0; i < numPointWrites + numRangeWrites && overlaps > 0;
++i) {
if (writes[i].end.len == 0) {
int keyLen = prefixLen + arbitrary.bounded(kMaxKeySuffixLen);
int keyLen = prefixLen + arbitrary->bounded(kMaxKeySuffixLen);
auto *begin = new (arena) uint8_t[keyLen];
memset(begin, prefixByte, prefixLen);
arbitrary.randomBytes(begin + prefixLen, keyLen - prefixLen);
arbitrary->randomBytes(begin + prefixLen, keyLen - prefixLen);
writes[i].end.len = keyLen;
writes[i].end.p = begin;
auto c =
@@ -692,10 +683,10 @@ struct TestDriver {
}
}
}
if (arbitrary.bounded(2)) {
if (arbitrary->bounded(2)) {
// Shuffle writes
for (int i = numPointWrites + numRangeWrites - 1; i > 0; --i) {
int j = arbitrary.bounded(i + 1);
int j = arbitrary->bounded(i + 1);
if (i != j) {
using std::swap;
swap(writes[i], writes[j]);
@@ -704,7 +695,7 @@ struct TestDriver {
}
oldestVersion +=
arbitrary.bounded(10) ? arbitrary.bounded(10) : arbitrary.next();
arbitrary->bounded(10) ? arbitrary->bounded(10) : arbitrary->next();
oldestVersion = std::min(oldestVersion, writeVersion);
#ifdef THREAD_TEST
@@ -721,6 +712,20 @@ struct TestDriver {
ready.wait();
#endif
#if DEBUG_VERBOSE && !defined(NDEBUG)
for (int i = 0; i < numPointWrites + numRangeWrites; ++i) {
if (writes[i].end.len == 0) {
fprintf(stderr, "%p Write: {%s}\n", this,
printable(writes[i].begin).c_str());
} else {
fprintf(stderr, "%p Write: [%s, %s)\n", this,
printable(writes[i].begin).c_str(),
printable(writes[i].end).c_str());
}
}
fprintf(stderr, "%p Write @ %" PRId64 "\n", this, v);
#endif
CALLGRIND_START_INSTRUMENTATION;
cs.addWrites(writes, numPointWrites + numRangeWrites, v);
CALLGRIND_STOP_INSTRUMENTATION;
@@ -729,6 +734,10 @@ struct TestDriver {
refImpl.addWrites(writes, numPointWrites + numRangeWrites, v);
}
#if DEBUG_VERBOSE && !defined(NDEBUG)
fprintf(stderr, "%p Set oldest version: %" PRId64 "\n", this,
oldestVersion);
#endif
cs.setOldestVersion(oldestVersion);
if constexpr (kEnableAssertions) {
refImpl.setOldestVersion(oldestVersion);
@@ -739,24 +748,24 @@ struct TestDriver {
#endif
}
{
int numPointReads = arbitrary.bounded(100);
int numRangeReads = arbitrary.bounded(100);
int numPointReads = arbitrary->bounded(100);
int numRangeReads = arbitrary->bounded(100);
int64_t v = std::max<int64_t>(writeVersion - (arbitrary.bounded(10)
? arbitrary.bounded(10)
: arbitrary.next()),
int64_t v = std::max<int64_t>(writeVersion - (arbitrary->bounded(10)
? arbitrary->bounded(10)
: arbitrary->next()),
0);
auto *reads =
new (arena) ConflictSet::ReadRange[numPointReads + numRangeReads];
auto keys = set<std::string_view>(arena);
while (int(keys.size()) < numPointReads + numRangeReads * 2) {
if (!arbitrary.hasEntropy()) {
if (!arbitrary->hasEntropy()) {
return true;
}
int keyLen = prefixLen + arbitrary.bounded(kMaxKeySuffixLen);
int keyLen = prefixLen + arbitrary->bounded(kMaxKeySuffixLen);
auto *begin = new (arena) uint8_t[keyLen];
memset(begin, prefixByte, prefixLen);
arbitrary.randomBytes(begin + prefixLen, keyLen - prefixLen);
arbitrary->randomBytes(begin + prefixLen, keyLen - prefixLen);
keys.insert(std::string_view((const char *)begin, keyLen));
}
@@ -765,7 +774,7 @@ struct TestDriver {
for (int pointsRemaining = numPointReads, rangesRemaining = numRangeReads;
pointsRemaining > 0 || rangesRemaining > 0; ++i) {
bool pointRead = pointsRemaining > 0 && rangesRemaining > 0
? bool(arbitrary.bounded(2))
? bool(arbitrary->bounded(2))
: pointsRemaining > 0;
if (pointRead) {
assert(pointsRemaining > 0);
@@ -787,10 +796,10 @@ struct TestDriver {
reads[i].readVersion = v;
#if DEBUG_VERBOSE && !defined(NDEBUG)
if (reads[i].end.len == 0) {
fprintf(stderr, "Read: {%s} @ %" PRId64 "\n",
fprintf(stderr, "%p Read: {%s} @ %" PRId64 "\n", this,
printable(reads[i].begin).c_str(), reads[i].readVersion);
} else {
fprintf(stderr, "Read: [%s, %s) @ %" PRId64 "\n",
fprintf(stderr, "%p Read: [%s, %s) @ %" PRId64 "\n", this,
printable(reads[i].begin).c_str(),
printable(reads[i].end).c_str(), reads[i].readVersion);
}
@@ -839,24 +848,27 @@ struct TestDriver {
refImpl.check(reads, results2, numPointReads + numRangeReads);
}
auto compareResults = [reads](ConflictSet::Result *results1,
ConflictSet::Result *results2, int count) {
auto compareResults = [reads, this](ConflictSet::Result *results1,
ConflictSet::Result *results2,
int count) {
for (int i = 0; i < count; ++i) {
if (results1[i] != results2[i]) {
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
"%p Expected %s, got %s for read of {%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);
(void *)this, resultToStr(results2[i]),
resultToStr(results1[i]), printable(reads[i].begin).c_str(),
reads[i].readVersion);
} else {
fprintf(stderr,
"%p Expected %s, got %s for read of [%s, %s) at version "
"%" PRId64 "\n",
(void *)this, resultToStr(results2[i]),
resultToStr(results1[i]),
printable(reads[i].begin).c_str(),
printable(reads[i].end).c_str(), reads[i].readVersion);
}
return false;
}
-4
View File
@@ -778,10 +778,6 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
for (int s = stripes - 1; s >= 0; s--) {
for (int i = 0; i * 2 < ss; ++i) {
const auto &w = combinedWriteConflictRanges[s * stripeSize / 2 + i];
#if DEBUG_VERBOSE
printf("Write begin: %s\n", printable(w.begin).c_str());
fflush(stdout);
#endif
values[i * 2] = w.first;
values[i * 2 + 1] = w.second;
keyUpdates += 3;
+50 -17
View File
@@ -13,25 +13,58 @@ int main(int argc, char **argv) {
std::stringstream buffer;
buffer << t.rdbuf();
auto str = buffer.str();
TestDriver<ConflictSet, !PERF_TEST> driver{(const uint8_t *)str.data(),
str.size()};
while (!driver.next())
;
if (!driver.ok) {
abort();
Arbitrary arbitrary({(const uint8_t *)str.data(), str.size()});
TestDriver<ConflictSet, !PERF_TEST> driver1{arbitrary};
TestDriver<ConflictSet, !PERF_TEST> driver2{arbitrary};
bool done1 = false;
bool done2 = false;
for (;;) {
if (!done1) {
done1 = driver1.next();
if (!driver1.ok) {
abort();
}
}
if (!done2) {
done2 = driver2.next();
if (!driver2.ok) {
abort();
}
}
if (done1 && done2) {
break;
}
}
ConflictSet::MetricsV1 *metrics;
int metricsCount;
driver.cs.getMetricsV1(&metrics, &metricsCount);
printf("#################### METRICS FOR %s ####################\n",
argv[i]);
for (int i = 0; i < metricsCount; ++i) {
printf("# HELP %s %s\n", metrics[i].name, metrics[i].help);
printf("# TYPE %s %s\n", metrics[i].name,
metrics[i].type == metrics[i].Counter ? "counter" : "gauge");
printf("%s %g\n", metrics[i].name, metrics[i].getValue());
{
ConflictSet::MetricsV1 *metrics;
int metricsCount;
driver1.cs.getMetricsV1(&metrics, &metricsCount);
printf("#################### METRICS for ConflictSet 1 for %s "
"####################\n",
argv[i]);
for (int i = 0; i < metricsCount; ++i) {
printf("# HELP %s %s\n", metrics[i].name, metrics[i].help);
printf("# TYPE %s %s\n", metrics[i].name,
metrics[i].type == metrics[i].Counter ? "counter" : "gauge");
printf("%s %g\n", metrics[i].name, metrics[i].getValue());
}
puts("");
}
{
ConflictSet::MetricsV1 *metrics;
int metricsCount;
driver2.cs.getMetricsV1(&metrics, &metricsCount);
printf("#################### METRICS for ConflictSet 2 for %s "
"####################\n",
argv[i]);
for (int i = 0; i < metricsCount; ++i) {
printf("# HELP %s %s\n", metrics[i].name, metrics[i].help);
printf("# TYPE %s %s\n", metrics[i].name,
metrics[i].type == metrics[i].Counter ? "counter" : "gauge");
printf("%s %g\n", metrics[i].name, metrics[i].getValue());
}
puts("");
}
puts("");
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More