Skip to content

Commit 98c1c88

Browse files
committed
clusterlin tests: separate testing of SimpleLinearize and Linearize
The separates the existing fuzz test into: * clusterlin_linearize: establishes the correctness of Linearize() using the simpler SimpleLinearize() function. * clusterlin_simple_linearize: establishes the correctness of SimpleLinearize() by comparing with all valid linearizations computed by std::next_permutation. rather than combining the first two into a single fuzz test.
1 parent 10e90f7 commit 98c1c88

File tree

1 file changed

+56
-25
lines changed

1 file changed

+56
-25
lines changed

src/test/fuzz/cluster_linearize.cpp

Lines changed: 56 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,62 @@ FUZZ_TARGET(clusterlin_linearization_chunking)
942942
assert(chunking.NumChunksLeft() == 0);
943943
}
944944

945+
FUZZ_TARGET(clusterlin_simple_linearize)
946+
{
947+
// Verify the behavior of SimpleLinearize(). Note that SimpleLinearize is only used in tests;
948+
// the purpose of this fuzz test is to establish confidence in SimpleLinearize, so that it can
949+
// be used to test the real Linearize function in the fuzz test below.
950+
951+
// Retrieve an iteration count and a depgraph from the fuzz input.
952+
SpanReader reader(buffer);
953+
uint64_t iter_count{0};
954+
DepGraph<TestBitSet> depgraph;
955+
try {
956+
reader >> VARINT(iter_count) >> Using<DepGraphFormatter>(depgraph);
957+
} catch (const std::ios_base::failure&) {}
958+
iter_count %= MAX_SIMPLE_ITERATIONS;
959+
960+
// Invoke SimpleLinearize().
961+
auto [linearization, optimal] = SimpleLinearize(depgraph, iter_count);
962+
SanityCheck(depgraph, linearization);
963+
auto simple_chunking = ChunkLinearization(depgraph, linearization);
964+
965+
// If the iteration count is sufficiently high, an optimal linearization must be found.
966+
// SimpleLinearize on k transactions can take up to 2^(k-1) iterations (one per non-empty
967+
// connected topologically valid subset), which sums over k=1..n to (2^n)-1.
968+
const uint64_t n = depgraph.TxCount();
969+
if (n <= 63 && (iter_count >> n)) {
970+
assert(optimal);
971+
}
972+
973+
// If SimpleLinearize claims optimal result, and the cluster is sufficiently small (there are
974+
// n! linearizations), test that the result is as good as every valid linearization.
975+
if (optimal && depgraph.TxCount() <= 7) {
976+
std::vector<DepGraphIndex> perm_linearization;
977+
// Initialize with the lexicographically-first linearization.
978+
for (DepGraphIndex i : depgraph.Positions()) perm_linearization.push_back(i);
979+
// Iterate over all valid permutations.
980+
do {
981+
// Determine whether perm_linearization is topological.
982+
TestBitSet perm_done;
983+
bool perm_is_topo{true};
984+
for (auto i : perm_linearization) {
985+
perm_done.Set(i);
986+
if (!depgraph.Ancestors(i).IsSubsetOf(perm_done)) {
987+
perm_is_topo = false;
988+
break;
989+
}
990+
}
991+
// If so, verify that the obtained linearization is as good as the permutation.
992+
if (perm_is_topo) {
993+
auto perm_chunking = ChunkLinearization(depgraph, perm_linearization);
994+
auto cmp = CompareChunks(simple_chunking, perm_chunking);
995+
assert(cmp >= 0);
996+
}
997+
} while(std::next_permutation(perm_linearization.begin(), perm_linearization.end()));
998+
}
999+
}
1000+
9451001
FUZZ_TARGET(clusterlin_linearize)
9461002
{
9471003
// Verify the behavior of Linearize().
@@ -1017,31 +1073,6 @@ FUZZ_TARGET(clusterlin_linearize)
10171073
// If SimpleLinearize finds the optimal result too, they must be equal (if not,
10181074
// SimpleLinearize is broken).
10191075
if (simple_optimal) assert(cmp == 0);
1020-
1021-
// Only for very small clusters, test every topologically-valid permutation.
1022-
if (depgraph.TxCount() <= 7) {
1023-
std::vector<DepGraphIndex> perm_linearization;
1024-
for (DepGraphIndex i : depgraph.Positions()) perm_linearization.push_back(i);
1025-
// Iterate over all valid permutations.
1026-
do {
1027-
// Determine whether perm_linearization is topological.
1028-
TestBitSet perm_done;
1029-
bool perm_is_topo{true};
1030-
for (auto i : perm_linearization) {
1031-
perm_done.Set(i);
1032-
if (!depgraph.Ancestors(i).IsSubsetOf(perm_done)) {
1033-
perm_is_topo = false;
1034-
break;
1035-
}
1036-
}
1037-
// If so, verify that the obtained linearization is as good as the permutation.
1038-
if (perm_is_topo) {
1039-
auto perm_chunking = ChunkLinearization(depgraph, perm_linearization);
1040-
auto cmp = CompareChunks(chunking, perm_chunking);
1041-
assert(cmp >= 0);
1042-
}
1043-
} while(std::next_permutation(perm_linearization.begin(), perm_linearization.end()));
1044-
}
10451076
}
10461077
}
10471078

0 commit comments

Comments
 (0)