Replaced tn/bn prefixes with an actual dependency system in tests/benches

The previous system of relying on test name prefixes for ordering was
simple, but organizing tests by dependencies and topologically sorting
during compilation is 1. more flexible and 2. simplifies test names,
which get typed a lot.

Note these are not "hard" dependencies, each test suite should work fine
in isolation. These "after" dependencies just hint an ordering when all
tests are ran.

As such, it's worth noting the tests should NOT error of a dependency is
missing. This unfortunately makes it a bit hard to catch typos, but
allows faster compilation of a subset of tests.

---

To make this work the way tests are linked has changed from using custom
linker section (fun linker magic!) to a weakly linked array appended to
every source file (also fun linker magic!).

At least with this method test.py has strict control over the test
ordering, and doesn't depend on 1. the order in which the linker merges
sections, and 2. the order tests are passed to test.py. I didn't realize
the previous system was so fragile.
This commit is contained in:
Christopher Haster
2023-08-04 13:33:00 -05:00
parent 2835b17d14
commit 5be7bae518
15 changed files with 579 additions and 463 deletions
+113
View File
@@ -0,0 +1,113 @@
# Bench our mid-level B-trees
after = 'bench_rbyd'
# maximize lookahead buffer, we don't actually gc so we only get one pass
# of the disk for these tests
defines.LOOKAHEAD_SIZE = 'BLOCK_COUNT / 8'
[cases.bench_btree_lookup]
defines.N = [8, 16, 32, 64, 128, 256, 1024]
# 0 = in-order
# 1 = reversed-order
# 2 = random-order
defines.ORDER = [0, 1, 2]
defines.SEED = 42
in = 'lfs.c'
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
// create free lookahead
memset(lfs.lookahead.buffer, 0, lfs.cfg->lookahead_size);
lfs.lookahead.start = 0;
lfs.lookahead.size = lfs_min(8*lfs.cfg->lookahead_size,
lfs.cfg->block_count);
lfs.lookahead.next = 0;
lfs_alloc_ack(&lfs);
uint32_t prng = SEED;
// create a tree with N elements
lfsr_btree_t btree = LFSR_BTREE_NULL;
const char *alphas = "abcdefghijklmnopqrstuvwxyz";
for (lfs_size_t i = 0; i < N; i++) {
lfs_off_t i_
= (ORDER == 0) ? i
: (ORDER == 1) ? 0
: BENCH_PRNG(&prng) % (lfsr_btree_weight(&btree)+1);
lfsr_btree_push(&lfs, &btree, i_, LFSR_TAG_INLINED, 1,
LFSR_DATA_BUF(&alphas[i % 26], 1)) => 0;
}
// assume an unfetched btree
btree.root.off = 0;
// bench lookup
BENCH_START();
lfs_size_t i = BENCH_PRNG(&prng) % N;
uint8_t buffer[4];
lfsr_tag_t tag_;
lfs_size_t weight_;
lfsr_btree_get(&lfs, &btree, i,
&tag_, &weight_, buffer, 4) => 1;
assert(tag_ == LFSR_TAG_INLINED);
assert(weight_ == 1);
BENCH_STOP();
'''
[cases.bench_btree_commit]
defines.N = [8, 16, 32, 64, 128, 256, 1024]
# 0 = in-order
# 1 = reversed-order
# 2 = random-order
defines.ORDER = [0, 1, 2]
defines.SEED = 42
defines.AMORTIZED = false
in = 'lfs.c'
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
// create free lookahead
memset(lfs.lookahead.buffer, 0, lfs.cfg->lookahead_size);
lfs.lookahead.start = 0;
lfs.lookahead.size = lfs_min(8*lfs.cfg->lookahead_size,
lfs.cfg->block_count);
lfs.lookahead.next = 0;
lfs_alloc_ack(&lfs);
uint32_t prng = SEED;
// create a tree with N elements
if (AMORTIZED) {
BENCH_START();
}
lfsr_btree_t btree = LFSR_BTREE_NULL;
const char *alphas = "abcdefghijklmnopqrstuvwxyz";
for (lfs_size_t i = 0; i < N; i++) {
lfs_off_t i_
= (ORDER == 0) ? i
: (ORDER == 1) ? 0
: BENCH_PRNG(&prng) % (lfsr_btree_weight(&btree)+1);
lfsr_btree_push(&lfs, &btree, i_, LFSR_TAG_INLINED, 1,
LFSR_DATA_BUF(&alphas[i % 26], 1)) => 0;
}
// bench appending a new id
if (!AMORTIZED) {
BENCH_START();
}
lfs_size_t i = BENCH_PRNG(&prng) % N;
lfsr_btree_push(&lfs, &btree, i, LFSR_TAG_INLINED, 1,
LFSR_DATA_BUF(&alphas[i % 26], 1)) => 0;
BENCH_STOP();
uint8_t buffer[4];
lfsr_tag_t tag_;
lfs_size_t weight_;
lfsr_btree_get(&lfs, &btree, i,
&tag_, &weight_, buffer, 4) => 1;
assert(tag_ == LFSR_TAG_INLINED);
assert(weight_ == 1);
'''