From 09b3d240366f9aa2a3f441751eaa2848387e1151 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Sat, 27 May 2023 13:29:30 -0500 Subject: [PATCH] Moved btree rbyd validation into mtree traversal Validating btree nodes during lfsr_btree_lookup was useful as a proof-of-concept, but it's not really needed if we validate btree nodes during mtree traversal. mtree traversal provides the first reads into the filesystem. It's how we find the real mroot, and (in theory at the moment) it provides the core operation for error detection in correction. With this in mind, implementing btree node validation in mtree traversal makes a lot of sense, with lfsr_btree_lookup leveraging an assumed successful validation for faster/smaller btree walks. Note that btree node validation during traversal is still optional. We really don't want to pay this cost during block allocation for example. --- It may look concerning that there's no related validation in btree traversal layer itself. It turns out that a quirk of btree traversal returning inner btree nodes on first visit, before actually traversing the btree node, is that it's safe for us to validte the btree node in only the mtree traversal layer. As long as we don't continue traversing on finding a corrupted btree, the btree traversal layer will never traverse an unvalidated btree node. This keeps all the validation logic in the same place, mtree traversal. I don't know if this will stay this way if/when more error correction features are added, but it's convenient in the meantime. --- benches/bench_btree.toml | 8 +- lfs.c | 122 ++++++------- tests/test_btree.toml | 376 +++++++++++++-------------------------- tests/test_mtree.toml | 27 ++- 4 files changed, 199 insertions(+), 334 deletions(-) diff --git a/benches/bench_btree.toml b/benches/bench_btree.toml index 4d94b79d..a3ee3ada 100644 --- a/benches/bench_btree.toml +++ b/benches/bench_btree.toml @@ -5,7 +5,6 @@ defines.LOOKAHEAD_SIZE = 'BLOCK_COUNT / 8' [cases.bench_btree_lookup] defines.N = [8, 16, 32, 64, 128, 256, 1024] -defines.VALIDATE = [1, 0] # 0 = in-order # 1 = reversed-order # 2 = random-order @@ -48,8 +47,7 @@ code = ''' lfs_size_t weight_; lfsr_btree_get(&lfs, &btree, i, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); BENCH_STOP(); @@ -57,7 +55,6 @@ code = ''' [cases.bench_btree_commit] defines.N = [8, 16, 32, 64, 128, 256, 1024] -defines.VALIDATE = 0 # 0 = in-order # 1 = reversed-order # 2 = random-order @@ -107,8 +104,7 @@ code = ''' lfs_size_t weight_; lfsr_btree_get(&lfs, &btree, i, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); ''' diff --git a/lfs.c b/lfs.c index f5c7efd2..9a741dc4 100644 --- a/lfs.c +++ b/lfs.c @@ -3042,8 +3042,7 @@ static lfs_ssize_t lfsr_btree_fromdisk(lfs_t *lfs, lfsr_btree_t *btree, static int lfsr_btree_lookupnext_(lfs_t *lfs, const lfsr_btree_t *btree, lfs_size_t bid, lfs_size_t *bid_, lfsr_rbyd_t *rbyd_, lfs_ssize_t *rid_, - lfsr_tag_t *tag_, lfs_size_t *weight_, - lfsr_data_t *data_, bool validate) { + lfsr_tag_t *tag_, lfs_size_t *weight_, lfsr_data_t *data_) { // in range? if (bid >= lfsr_btree_weight(btree)) { return LFS_ERR_NOENT; @@ -3071,48 +3070,6 @@ static int lfsr_btree_lookupnext_(lfs_t *lfs, lfsr_rbyd_t branch = btree->root; lfs_ssize_t rid = bid; while (true) { - // if we're validating during our lookup, we need to fetch each branch, - // otherwise we can get away with assuming our stored block+trunk is - // correct - // - // though we assume fetched branches have already been validated, this - // generally only affects the root rbyd but note the root rbyd is the - // most heavily accessed - // - if (validate && !lfsr_rbyd_isfetched(&branch)) { - lfsr_rbyd_t branch_; - int err = lfsr_rbyd_fetch(lfs, &branch_, - branch.block, branch.trunk, NULL); - if (err) { - if (err == LFS_ERR_CORRUPT) { - LFS_ERROR("Corrupted rbyd found during btree lookup " - "(rbyd=0x%"PRIx32".%"PRIx32", " - "0x%08"PRIx32" != 0x%08"PRIx32")", - branch.block, branch.trunk, - branch_.crc, branch.crc); - } - return err; - } - - // test that our branch's crc matches what's expected - // - // it should be noted it's very unlikely for this to be hit without - // the above fetch failing since it includes both an internal - // crc check and trunk check - if (branch_.crc != branch.crc) { - LFS_ERROR("Corrupted rbyd found during btree lookup " - "(rbyd=0x%"PRIx32".%"PRIx32", " - "0x%08"PRIx32" != 0x%08"PRIx32")", - branch.block, branch.trunk, - branch_.crc, branch.crc); - return LFS_ERR_CORRUPT; - } - - LFS_ASSERT(branch_.trunk == branch.trunk); - LFS_ASSERT(branch_.weight == branch.weight); - branch = branch_; - } - // each branch is a pair of optional name + on-disk structure lfs_ssize_t rid__; lfsr_tag_t tag__; @@ -3178,20 +3135,17 @@ static int lfsr_btree_lookupnext_(lfs_t *lfs, static int lfsr_btree_lookupnext(lfs_t *lfs, const lfsr_btree_t *btree, lfs_size_t bid, lfs_size_t *bid_, lfsr_tag_t *tag_, lfs_size_t *weight_, - lfsr_data_t *data_, bool validate) { + lfsr_data_t *data_) { return lfsr_btree_lookupnext_(lfs, btree, bid, - bid_, NULL, NULL, tag_, weight_, data_, - validate); + bid_, NULL, NULL, tag_, weight_, data_); } static int lfsr_btree_lookup(lfs_t *lfs, const lfsr_btree_t *btree, lfs_size_t bid, - lfsr_tag_t *tag_, lfs_size_t *weight_, - lfsr_data_t *data_, bool validate) { + lfsr_tag_t *tag_, lfs_size_t *weight_, lfsr_data_t *data_) { lfs_size_t bid_; int err = lfsr_btree_lookupnext(lfs, btree, bid, - &bid_, tag_, weight_, data_, - validate); + &bid_, tag_, weight_, data_); if (err) { return err; } @@ -3210,12 +3164,10 @@ static int lfsr_btree_lookup(lfs_t *lfs, static int lfsr_btree_get(lfs_t *lfs, const lfsr_btree_t *btree, lfs_size_t bid, lfsr_tag_t *tag_, lfs_size_t *weight_, - void *buffer, lfs_size_t size, - bool validate) { + void *buffer, lfs_size_t size) { lfsr_data_t data; int err = lfsr_btree_lookup(lfs, btree, bid, - tag_, weight_, &data, - validate); + tag_, weight_, &data); if (err) { return err; } @@ -4080,8 +4032,7 @@ static int lfsr_btree_push(lfs_t *lfs, lfsr_btree_t *btree, lfs_ssize_t rid = -1; lfs_size_t rweight = 0; int err = lfsr_btree_lookupnext_(lfs, btree, bid_, - NULL, &rbyd, &rid, NULL, &rweight, NULL, - false); + NULL, &rbyd, &rid, NULL, &rweight, NULL); if (err && err != LFS_ERR_NOENT) { return err; } @@ -4149,8 +4100,7 @@ static int lfsr_btree_update(lfs_t *lfs, lfsr_btree_t *btree, lfs_ssize_t rid; lfs_size_t rweight; int err = lfsr_btree_lookupnext_(lfs, btree, bid, - NULL, &rbyd, &rid, &rtag, &rweight, NULL, - false); + NULL, &rbyd, &rid, &rtag, &rweight, NULL); if (err) { return err; } @@ -4204,8 +4154,7 @@ static int lfsr_btree_pop(lfs_t *lfs, lfsr_btree_t *btree, lfs_size_t bid) { lfs_ssize_t rid; lfs_size_t rweight; int err = lfsr_btree_lookupnext_(lfs, btree, bid, - NULL, &rbyd, &rid, &rtag, &rweight, NULL, - false); + NULL, &rbyd, &rid, &rtag, &rweight, NULL); if (err) { return err; } @@ -4320,8 +4269,7 @@ static int lfsr_btree_split(lfs_t *lfs, lfsr_btree_t *btree, lfs_ssize_t rid; lfs_size_t rweight; int err = lfsr_btree_lookupnext_(lfs, btree, bid, - NULL, &rbyd, &rid, NULL, &rweight, NULL, - false); + NULL, &rbyd, &rid, NULL, &rweight, NULL); if (err) { return err; } @@ -4741,7 +4689,7 @@ static int lfsr_mtree_lookup(lfs_t *lfs, lfs_ssize_t mid, lfsr_mdir_t *mdir_) { lfsr_tag_t tag; lfsr_data_t data; int err = lfsr_btree_lookup(lfs, &lfs->mtree, mid, - &tag, NULL, &data, false); + &tag, NULL, &data); if (err) { return err; } @@ -5563,11 +5511,17 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid, // incremental mtree traversal typedef struct lfsr_mtree_traversal { + uint8_t flags; lfsr_mdir_t mdir; lfsr_btree_traversal_t mtraversal; } lfsr_mtree_traversal_t; -#define LFSR_MTREE_TRAVERSAL_INIT ((lfsr_mtree_traversal_t){ \ +enum { + LFSR_MTREE_TRAVERSAL_VALIDATE = 0x1, +}; + +#define LFSR_MTREE_TRAVERSAL_INIT(_flags) ((lfsr_mtree_traversal_t){ \ + .flags = _flags, \ .mdir.rbyd.trunk = 0, \ .mtraversal = LFSR_BTREE_TRAVERSAL_INIT, \ }) @@ -5688,6 +5642,44 @@ static int lfsr_mtree_traversal_next(lfs_t *lfs, // inner btree nodes already decoded if (tag == LFSR_TAG_BTREE) { + // validate our btree nodes if requested, this just means we need + // to do a full rbyd fetch and make sure the checksums match + if (traversal->flags & LFSR_MTREE_TRAVERSAL_VALIDATE) { + lfsr_rbyd_t *branch = (lfsr_rbyd_t*)data.buf.buffer; + lfsr_rbyd_t branch_; + int err = lfsr_rbyd_fetch(lfs, &branch_, + branch->block, branch->trunk, NULL); + if (err) { + if (err == LFS_ERR_CORRUPT) { + LFS_ERROR("Corrupted rbyd during mtree traversal " + "(rbyd=0x%"PRIx32".%"PRIx32", 0x%08"PRIx32")", + branch->block, branch->trunk, branch->crc); + } + return err; + } + + // test that our branch's crc matches what's expected + // + // it should be noted it's very unlikely for this to be hit without + // the above fetch failing since it includes both an internal + // crc check and trunk check + if (branch_.crc != branch->crc) { + LFS_ERROR("Checksum mismatch during mtree traversal " + "(rbyd=0x%"PRIx32".%"PRIx32", " + "0x%08"PRIx32" != 0x%08"PRIx32")", + branch->block, branch->trunk, + branch_.crc, branch->crc); + return LFS_ERR_CORRUPT; + } + + LFS_ASSERT(branch_.trunk == branch->trunk); + LFS_ASSERT(branch_.weight == branch->weight); + + // TODO is this useful at all? + // change our branch to the fetched version + *branch = branch_; + } + // still update our mdir mid so we don't get stuck in a loop // traversing mroots traversal->mdir.mid = mid; diff --git a/tests/test_btree.toml b/tests/test_btree.toml index e96906af..f646692c 100644 --- a/tests/test_btree.toml +++ b/tests/test_btree.toml @@ -6,7 +6,6 @@ defines.LOOKAHEAD_SIZE = 'lfs_alignup(BLOCK_COUNT / 8, 8)' # test an empty tree [cases.test_btree_zero] -defines.VALIDATE = [1, 0] in = 'lfs.c' code = ''' lfs_t lfs; @@ -33,13 +32,11 @@ code = ''' lfs_size_t weight_; lfsr_btree_get(&lfs, &btree, 0, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' # test an inlined tree [cases.test_btree_one] -defines.VALIDATE = [1, 0] in = 'lfs.c' code = ''' lfs_t lfs; @@ -68,20 +65,17 @@ code = ''' lfs_size_t weight_; lfsr_btree_get(&lfs, &btree, 0, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "a", 1) == 0); lfsr_btree_get(&lfs, &btree, 1, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' # test a single-rbyd tree [cases.test_btree_two] -defines.VALIDATE = [1, 0] in = 'lfs.c' code = ''' lfs_t lfs; @@ -112,26 +106,22 @@ code = ''' lfs_size_t weight_; lfsr_btree_get(&lfs, &btree, 0, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "a", 1) == 0); lfsr_btree_get(&lfs, &btree, 1, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "b", 1) == 0); lfsr_btree_get(&lfs, &btree, 2, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' [cases.test_btree_two_backwards] -defines.VALIDATE = [1, 0] in = 'lfs.c' code = ''' lfs_t lfs; @@ -162,27 +152,23 @@ code = ''' lfs_size_t weight_; lfsr_btree_get(&lfs, &btree, 0, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "a", 1) == 0); lfsr_btree_get(&lfs, &btree, 1, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "b", 1) == 0); lfsr_btree_get(&lfs, &btree, 2, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' # still a single-rbyd tree, just making sure it works [cases.test_btree_three] -defines.VALIDATE = [1, 0] in = 'lfs.c' code = ''' lfs_t lfs; @@ -215,33 +201,28 @@ code = ''' lfs_size_t weight_; lfsr_btree_get(&lfs, &btree, 0, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "a", 1) == 0); lfsr_btree_get(&lfs, &btree, 1, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "b", 1) == 0); lfsr_btree_get(&lfs, &btree, 2, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "c", 1) == 0); lfsr_btree_get(&lfs, &btree, 3, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' [cases.test_btree_three_backwards] -defines.VALIDATE = [1, 0] in = 'lfs.c' code = ''' lfs_t lfs; @@ -274,36 +255,31 @@ code = ''' lfs_size_t weight_; lfsr_btree_get(&lfs, &btree, 0, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "a", 1) == 0); lfsr_btree_get(&lfs, &btree, 1, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "b", 1) == 0); lfsr_btree_get(&lfs, &btree, 2, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "c", 1) == 0); lfsr_btree_get(&lfs, &btree, 3, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' # try larger trees, when exactly a tree splits depends on the disk geometry, so # we don't really have a better way of testing multi-rbyd trees [cases.test_btree_push] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] -defines.VALIDATE = [1, 0] in = 'lfs.c' code = ''' lfs_t lfs; @@ -343,8 +319,7 @@ code = ''' for (lfs_size_t i = 0; i < n; i++) { lfsr_btree_get(&lfs, &btree, i, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, &alphas[i % 26], 1) == 0); @@ -352,13 +327,11 @@ code = ''' // and check that we can't lookup elements that aren't in the tree lfsr_btree_get(&lfs, &btree, n, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' [cases.test_btree_push_backwards] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] -defines.VALIDATE = [1, 0] in = 'lfs.c' code = ''' lfs_t lfs; @@ -398,8 +371,7 @@ code = ''' for (lfs_size_t i = 0; i < n; i++) { lfsr_btree_get(&lfs, &btree, n-1-i, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, &alphas[(N-1-i) % 26], 1) == 0); @@ -407,13 +379,11 @@ code = ''' // and check that we can't lookup elements that aren't in the tree lfsr_btree_get(&lfs, &btree, n, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' [cases.test_btree_push_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] -defines.VALIDATE = [1, 0] defines.SAMPLES = 10 # -1 => all pseudo-random seeds # n => reproduce a specific seed @@ -492,8 +462,7 @@ code = ''' lfs_size_t weight_; for (lfs_size_t i = 0; i < sim_size; i++) { lfsr_btree_get(&lfs, &btree, i, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, &sim[i], 1) == 0); @@ -501,8 +470,7 @@ code = ''' // and no extra elements lfsr_btree_get(&lfs, &btree, sim_size, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; // clean up sim free(sim); @@ -513,7 +481,6 @@ code = ''' [cases.test_btree_push_sparse] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] defines.W = 5 -defines.VALIDATE = [1, 0] in = 'lfs.c' code = ''' lfs_t lfs; @@ -553,8 +520,7 @@ code = ''' for (lfs_size_t i = 0; i < n; i++) { lfsr_btree_get(&lfs, &btree, i*W+W-1, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == W); assert(memcmp(buffer, &alphas[i % 26], 1) == 0); @@ -562,15 +528,14 @@ code = ''' // and check that we can't lookup elements that aren't in the tree lfsr_btree_get(&lfs, &btree, n*W, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; // also test that we can traverse the tree without prior knowledge lfs_size_t id_ = -1; lfsr_data_t data_; for (lfs_size_t i = 0; i < n; i++) { lfsr_btree_lookupnext(&lfs, &btree, id_+1, - &id_, &tag_, &weight_, &data_, VALIDATE) => 0; + &id_, &tag_, &weight_, &data_) => 0; assert(id_ == i*W+W-1); assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == W); @@ -579,13 +544,12 @@ code = ''' assert(memcmp(buffer, &alphas[i % 26], 1) == 0); } lfsr_btree_lookupnext(&lfs, &btree, id_+1, - &id_, &tag_, &weight_, &data_, VALIDATE) => LFS_ERR_NOENT; + &id_, &tag_, &weight_, &data_) => LFS_ERR_NOENT; ''' [cases.test_btree_push_sparse_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] defines.W = 5 -defines.VALIDATE = [1, 0] defines.SAMPLES = 10 # -1 => all pseudo-random seeds # n => reproduce a specific seed @@ -696,8 +660,7 @@ code = ''' } lfsr_btree_get(&lfs, &btree, weighted_id+sim_weights[i]-1, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == sim_weights[i]); assert(memcmp(buffer, &sim[i], 1) == 0); @@ -705,8 +668,7 @@ code = ''' // and no extra elements lfsr_btree_get(&lfs, &btree, total_weight, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; // also test that we can traverse the tree without prior knowledge lfs_size_t id_ = -1; @@ -719,7 +681,7 @@ code = ''' } lfsr_btree_lookupnext(&lfs, &btree, id_+1, - &id_, &tag_, &weight_, &data_, VALIDATE) => 0; + &id_, &tag_, &weight_, &data_) => 0; assert(id_ == weighted_id+sim_weights[i]-1); assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == sim_weights[i]); @@ -728,7 +690,7 @@ code = ''' assert(memcmp(buffer, &sim[i], 1) == 0); } lfsr_btree_lookupnext(&lfs, &btree, id_+1, - &id_, &tag_, &weight_, &data_, VALIDATE) => LFS_ERR_NOENT; + &id_, &tag_, &weight_, &data_) => LFS_ERR_NOENT; // clean up sim free(sim); @@ -740,7 +702,6 @@ code = ''' # try some small trees for easy corner cases first [cases.test_btree_update_one] -defines.VALIDATE = [1, 0] in = 'lfs.c' code = ''' lfs_t lfs; @@ -772,19 +733,16 @@ code = ''' lfs_size_t weight_; lfsr_btree_get(&lfs, &btree, 0, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "A", 1) == 0); lfsr_btree_get(&lfs, &btree, 1, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' [cases.test_btree_update_two] -defines.VALIDATE = [1, 0] in = 'lfs.c' code = ''' lfs_t lfs; @@ -820,26 +778,22 @@ code = ''' lfs_size_t weight_; lfsr_btree_get(&lfs, &btree, 0, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "A", 1) == 0); lfsr_btree_get(&lfs, &btree, 1, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "B", 1) == 0); lfsr_btree_get(&lfs, &btree, 2, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' [cases.test_btree_update_three] -defines.VALIDATE = [1, 0] in = 'lfs.c' code = ''' lfs_t lfs; @@ -879,34 +833,29 @@ code = ''' lfs_size_t weight_; lfsr_btree_get(&lfs, &btree, 0, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "A", 1) == 0); lfsr_btree_get(&lfs, &btree, 1, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "B", 1) == 0); lfsr_btree_get(&lfs, &btree, 2, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "C", 1) == 0); lfsr_btree_get(&lfs, &btree, 3, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' [cases.test_btree_update] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] -defines.VALIDATE = [1, 0] in = 'lfs.c' code = ''' lfs_t lfs; @@ -963,8 +912,7 @@ code = ''' for (lfs_size_t i = 0; i < N; i++) { lfsr_btree_get(&lfs, &btree, i, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, &uppers[i % 26], 1) == 0); @@ -972,13 +920,11 @@ code = ''' // and check that we can't lookup elements that aren't in the tree lfsr_btree_get(&lfs, &btree, N, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' [cases.test_btree_update_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] -defines.VALIDATE = [1, 0] defines.SAMPLES = 10 # -1 => all pseudo-random seeds # n => reproduce a specific seed @@ -1070,8 +1016,7 @@ code = ''' lfs_size_t weight_; for (lfs_size_t i = 0; i < N; i++) { lfsr_btree_get(&lfs, &btree, i, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, &sim[i], 1) == 0); @@ -1079,8 +1024,7 @@ code = ''' // and no extra elements lfsr_btree_get(&lfs, &btree, N, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; // clean up sim free(sim); @@ -1090,7 +1034,6 @@ code = ''' [cases.test_btree_update_sparse] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] defines.W = 5 -defines.VALIDATE = [1, 0] in = 'lfs.c' code = ''' lfs_t lfs; @@ -1147,8 +1090,7 @@ code = ''' for (lfs_size_t i = 0; i < N; i++) { lfsr_btree_get(&lfs, &btree, i*W+W-1, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == W); assert(memcmp(buffer, &uppers[i % 26], 1) == 0); @@ -1156,15 +1098,14 @@ code = ''' // and check that we can't lookup elements that aren't in the tree lfsr_btree_get(&lfs, &btree, N*W, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; // also test that we can traverse the tree without prior knowledge lfs_size_t id_ = -1; lfsr_data_t data_; for (lfs_size_t i = 0; i < N; i++) { lfsr_btree_lookupnext(&lfs, &btree, id_+1, - &id_, &tag_, &weight_, &data_, VALIDATE) => 0; + &id_, &tag_, &weight_, &data_) => 0; assert(id_ == i*W+W-1); assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == W); @@ -1173,13 +1114,12 @@ code = ''' assert(memcmp(buffer, &uppers[i % 26], 1) == 0); } lfsr_btree_lookupnext(&lfs, &btree, id_+1, - &id_, &tag_, &weight_, &data_, VALIDATE) => LFS_ERR_NOENT; + &id_, &tag_, &weight_, &data_) => LFS_ERR_NOENT; ''' [cases.test_btree_update_sparse_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] defines.W = 5 -defines.VALIDATE = [1, 0] defines.SAMPLES = 10 # -1 => all pseudo-random seeds # n => reproduce a specific seed @@ -1301,8 +1241,7 @@ code = ''' } lfsr_btree_get(&lfs, &btree, weighted_id+sim_weights[i]-1, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == sim_weights[i]); assert(memcmp(buffer, &sim[i], 1) == 0); @@ -1310,8 +1249,7 @@ code = ''' // and no extra elements lfsr_btree_get(&lfs, &btree, total_weight, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; // also test that we can traverse the tree without prior knowledge lfs_size_t id_ = -1; @@ -1324,7 +1262,7 @@ code = ''' } lfsr_btree_lookupnext(&lfs, &btree, id_+1, - &id_, &tag_, &weight_, &data_, VALIDATE) => 0; + &id_, &tag_, &weight_, &data_) => 0; assert(id_ == weighted_id+sim_weights[i]-1); assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == sim_weights[i]); @@ -1333,7 +1271,7 @@ code = ''' assert(memcmp(buffer, &sim[i], 1) == 0); } lfsr_btree_lookupnext(&lfs, &btree, id_+1, - &id_, &tag_, &weight_, &data_, VALIDATE) => LFS_ERR_NOENT; + &id_, &tag_, &weight_, &data_) => LFS_ERR_NOENT; // clean up sim free(sim); @@ -1346,7 +1284,6 @@ code = ''' # try some corner cases first, these are actually pretty tricky since we # need to recognize when to collapse back into an inlined tree [cases.test_btree_pop_one] -defines.VALIDATE = [1, 0] in = 'lfs.c' code = ''' lfs_t lfs; @@ -1377,8 +1314,7 @@ code = ''' lfs_size_t weight_; lfsr_btree_get(&lfs, &btree, 0, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; // try to putting it back to see if things still work lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, 1, @@ -1391,19 +1327,16 @@ code = ''' // try looking up tags lfsr_btree_get(&lfs, &btree, 0, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "A", 1) == 0); lfsr_btree_get(&lfs, &btree, 1, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' [cases.test_btree_pop_two] -defines.VALIDATE = [1, 0] in = 'lfs.c' code = ''' lfs_t lfs; @@ -1436,15 +1369,13 @@ code = ''' lfs_size_t weight_; lfsr_btree_get(&lfs, &btree, 0, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "a", 1) == 0); lfsr_btree_get(&lfs, &btree, 1, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; // try to putting it back to see if things still work lfsr_btree_push(&lfs, &btree, 1, LFSR_TAG_INLINED, 1, @@ -1457,26 +1388,22 @@ code = ''' // try looking up tags lfsr_btree_get(&lfs, &btree, 0, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "a", 1) == 0); lfsr_btree_get(&lfs, &btree, 1, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "B", 1) == 0); lfsr_btree_get(&lfs, &btree, 2, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' [cases.test_btree_pop_two_other] -defines.VALIDATE = [1, 0] in = 'lfs.c' code = ''' lfs_t lfs; @@ -1509,15 +1436,13 @@ code = ''' lfs_size_t weight_; lfsr_btree_get(&lfs, &btree, 0, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "b", 1) == 0); lfsr_btree_get(&lfs, &btree, 1, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; // try to putting it back to see if things still work lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, 1, @@ -1530,26 +1455,22 @@ code = ''' // try looking up tags lfsr_btree_get(&lfs, &btree, 0, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "A", 1) == 0); lfsr_btree_get(&lfs, &btree, 1, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "b", 1) == 0); lfsr_btree_get(&lfs, &btree, 2, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' [cases.test_btree_pop_three] -defines.VALIDATE = [1, 0] in = 'lfs.c' code = ''' lfs_t lfs; @@ -1584,22 +1505,19 @@ code = ''' lfs_size_t weight_; lfsr_btree_get(&lfs, &btree, 0, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "a", 1) == 0); lfsr_btree_get(&lfs, &btree, 1, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "b", 1) == 0); lfsr_btree_get(&lfs, &btree, 2, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; // try to putting it back to see if things still work lfsr_btree_push(&lfs, &btree, 2, LFSR_TAG_INLINED, 1, @@ -1612,35 +1530,30 @@ code = ''' // try looking up tags lfsr_btree_get(&lfs, &btree, 0, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "a", 1) == 0); lfsr_btree_get(&lfs, &btree, 1, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "b", 1) == 0); lfsr_btree_get(&lfs, &btree, 2, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "C", 1) == 0); lfsr_btree_get(&lfs, &btree, 3, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' [cases.test_btree_pop] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] defines.REMAINING = [64, 2, 1, 0] -defines.VALIDATE = [1, 0] if = 'N > REMAINING' in = 'lfs.c' code = ''' @@ -1697,8 +1610,7 @@ code = ''' for (lfs_size_t i = 0; i < REMAINING; i++) { lfsr_btree_get(&lfs, &btree, i, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, &alphas[i % 26], 1) == 0); @@ -1706,8 +1618,7 @@ code = ''' // and check that we can't lookup elements that aren't in the tree lfsr_btree_get(&lfs, &btree, REMAINING, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; // try recovering lfsr_btree_push(&lfs, &btree, REMAINING, LFSR_TAG_INLINED, 1, @@ -1715,29 +1626,25 @@ code = ''' for (lfs_size_t i = 0; i < REMAINING; i++) { lfsr_btree_get(&lfs, &btree, i, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, &alphas[i % 26], 1) == 0); } lfsr_btree_get(&lfs, &btree, REMAINING, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "R", 1) == 0); lfsr_btree_get(&lfs, &btree, REMAINING+1, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' [cases.test_btree_pop_backwards] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] defines.REMAINING = [64, 2, 1, 0] -defines.VALIDATE = [1, 0] if = 'N > REMAINING' in = 'lfs.c' code = ''' @@ -1793,8 +1700,7 @@ code = ''' for (lfs_size_t i = 0; i < REMAINING; i++) { lfsr_btree_get(&lfs, &btree, i, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, &alphas[(i+(N-REMAINING)) % 26], 1) == 0); @@ -1802,38 +1708,33 @@ code = ''' // and check that we can't lookup elements that aren't in the tree lfsr_btree_get(&lfs, &btree, REMAINING, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; // try recovering lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, 1, LFSR_DATA_BUF("R", 1)) => 0; lfsr_btree_get(&lfs, &btree, 0, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, "R", 1) == 0); for (lfs_size_t i = 0; i < REMAINING; i++) { lfsr_btree_get(&lfs, &btree, i+1, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, &alphas[(i+(N-REMAINING)) % 26], 1) == 0); } lfsr_btree_get(&lfs, &btree, REMAINING+1, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' [cases.test_btree_pop_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] defines.REMAINING = [64, 2, 1, 0] -defines.VALIDATE = [1, 0] defines.SAMPLES = 10 # -1 => all pseudo-random seeds # n => reproduce a specific seed @@ -1926,8 +1827,7 @@ code = ''' lfs_size_t weight_; for (lfs_size_t i = 0; i < sim_size; i++) { lfsr_btree_get(&lfs, &btree, i, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, &sim[i], 1) == 0); @@ -1935,8 +1835,7 @@ code = ''' // and no extra elements lfsr_btree_get(&lfs, &btree, sim_size, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; // clean up sim free(sim); @@ -1947,7 +1846,6 @@ code = ''' defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] defines.W = 5 defines.REMAINING = [64, 2, 1, 0] -defines.VALIDATE = [1, 0] if = 'N > REMAINING' in = 'lfs.c' code = ''' @@ -2003,8 +1901,7 @@ code = ''' for (lfs_size_t i = 0; i < REMAINING; i++) { lfsr_btree_get(&lfs, &btree, i*W+W-1, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == W); assert(memcmp(buffer, &alphas[i % 26], 1) == 0); @@ -2012,8 +1909,7 @@ code = ''' // and check that we can't lookup elements that aren't in the tree lfsr_btree_get(&lfs, &btree, REMAINING*W+W-1, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; // try recovering lfsr_btree_push(&lfs, &btree, REMAINING*W, LFSR_TAG_INLINED, W, @@ -2021,30 +1917,27 @@ code = ''' for (lfs_size_t i = 0; i < REMAINING; i++) { lfsr_btree_get(&lfs, &btree, i*W+W-1, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == W); assert(memcmp(buffer, &alphas[i % 26], 1) == 0); } lfsr_btree_get(&lfs, &btree, REMAINING*W+W-1, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == W); assert(memcmp(buffer, "R", 1) == 0); lfsr_btree_get(&lfs, &btree, (REMAINING+1)*W+W-1, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; // also test that we can traverse the tree without prior knowledge lfs_size_t id_ = -1; lfsr_data_t data_; for (lfs_size_t i = 0; i < REMAINING; i++) { lfsr_btree_lookupnext(&lfs, &btree, id_+1, - &id_, &tag_, &weight_, &data_, VALIDATE) => 0; + &id_, &tag_, &weight_, &data_) => 0; assert(id_ == i*W+W-1); assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == W); @@ -2054,7 +1947,7 @@ code = ''' } lfsr_btree_lookupnext(&lfs, &btree, id_+1, - &id_, &tag_, &weight_, &data_, VALIDATE) => 0; + &id_, &tag_, &weight_, &data_) => 0; assert(id_ == REMAINING*W+W-1); assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == W); @@ -2063,14 +1956,13 @@ code = ''' assert(memcmp(buffer, "R", 1) == 0); lfsr_btree_lookupnext(&lfs, &btree, id_+1, - &id_, &tag_, &weight_, &data_, VALIDATE) => LFS_ERR_NOENT; + &id_, &tag_, &weight_, &data_) => LFS_ERR_NOENT; ''' [cases.test_btree_pop_sparse_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] defines.W = 5 defines.REMAINING = [64, 2, 1, 0] -defines.VALIDATE = [1, 0] defines.SAMPLES = 10 # -1 => all pseudo-random seeds # n => reproduce a specific seed @@ -2204,8 +2096,7 @@ code = ''' } lfsr_btree_get(&lfs, &btree, weighted_id+sim_weights[i]-1, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == sim_weights[i]); assert(memcmp(buffer, &sim[i], 1) == 0); @@ -2213,8 +2104,7 @@ code = ''' // and no extra elements lfsr_btree_get(&lfs, &btree, total_weight, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; // also test that we can traverse the tree without prior knowledge lfs_size_t id_ = -1; @@ -2227,7 +2117,7 @@ code = ''' } lfsr_btree_lookupnext(&lfs, &btree, id_+1, - &id_, &tag_, &weight_, &data_, VALIDATE) => 0; + &id_, &tag_, &weight_, &data_) => 0; assert(id_ == weighted_id+sim_weights[i]-1); assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == sim_weights[i]); @@ -2236,7 +2126,7 @@ code = ''' assert(memcmp(buffer, &sim[i], 1) == 0); } lfsr_btree_lookupnext(&lfs, &btree, id_+1, - &id_, &tag_, &weight_, &data_, VALIDATE) => LFS_ERR_NOENT; + &id_, &tag_, &weight_, &data_) => LFS_ERR_NOENT; // clean up sim free(sim); @@ -2247,7 +2137,6 @@ code = ''' # test btree splits [cases.test_btree_split] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] -defines.VALIDATE = [1, 0] in = 'lfs.c' code = ''' lfs_t lfs; @@ -2290,8 +2179,7 @@ code = ''' for (lfs_size_t i = 0; i < n; i++) { lfsr_btree_get(&lfs, &btree, i, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, &alphas[i % 26], 1) == 0); @@ -2299,13 +2187,11 @@ code = ''' // and check that we can't lookup elements that aren't in the tree lfsr_btree_get(&lfs, &btree, n, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' [cases.test_btree_split_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] -defines.VALIDATE = [1, 0] defines.SAMPLES = 10 # -1 => all pseudo-random seeds # n => reproduce a specific seed @@ -2390,8 +2276,7 @@ code = ''' lfs_size_t weight_; for (lfs_size_t i = 0; i < sim_size; i++) { lfsr_btree_get(&lfs, &btree, i, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, &sim[i], 1) == 0); @@ -2399,8 +2284,7 @@ code = ''' // and no extra elements lfsr_btree_get(&lfs, &btree, sim_size, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; // clean up sim free(sim); @@ -2411,7 +2295,6 @@ code = ''' [cases.test_btree_split_sparse] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] defines.W = 5 -defines.VALIDATE = [1, 0] in = 'lfs.c' code = ''' lfs_t lfs; @@ -2454,8 +2337,7 @@ code = ''' for (lfs_size_t i = 0; i < n; i++) { lfsr_btree_get(&lfs, &btree, i*W+W-1, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == W); assert(memcmp(buffer, &alphas[i % 26], 1) == 0); @@ -2463,14 +2345,12 @@ code = ''' // and check that we can't lookup elements that aren't in the tree lfsr_btree_get(&lfs, &btree, n*W, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' [cases.test_btree_split_sparse_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] defines.W = 5 -defines.VALIDATE = [1, 0] defines.SAMPLES = 10 # -1 => all pseudo-random seeds # n => reproduce a specific seed @@ -2592,8 +2472,7 @@ code = ''' } lfsr_btree_get(&lfs, &btree, weighted_id+sim_weights[i]-1, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == sim_weights[i]); assert(memcmp(buffer, &sim[i], 1) == 0); @@ -2601,8 +2480,7 @@ code = ''' // and no extra elements lfsr_btree_get(&lfs, &btree, total_weight, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; // also test that we can traverse the tree without prior knowledge lfs_size_t id_ = -1; @@ -2615,7 +2493,7 @@ code = ''' } lfsr_btree_lookupnext(&lfs, &btree, id_+1, - &id_, &tag_, &weight_, &data_, VALIDATE) => 0; + &id_, &tag_, &weight_, &data_) => 0; assert(id_ == weighted_id+sim_weights[i]-1); assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == sim_weights[i]); @@ -2624,7 +2502,7 @@ code = ''' assert(memcmp(buffer, &sim[i], 1) == 0); } lfsr_btree_lookupnext(&lfs, &btree, id_+1, - &id_, &tag_, &weight_, &data_, VALIDATE) => LFS_ERR_NOENT; + &id_, &tag_, &weight_, &data_) => LFS_ERR_NOENT; // clean up sim free(sim); @@ -2636,7 +2514,6 @@ code = ''' # Some more general fuzz testing [cases.test_btree_general_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] -defines.VALIDATE = [1, 0] defines.SAMPLES = 100 # -1 => all pseudo-random seeds # n => reproduce a specific seed @@ -2747,8 +2624,7 @@ code = ''' lfs_size_t weight_; for (lfs_size_t i = 0; i < sim_size; i++) { lfsr_btree_get(&lfs, &btree, i, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, &sim[i], 1) == 0); @@ -2756,8 +2632,7 @@ code = ''' // and no extra elements lfsr_btree_get(&lfs, &btree, sim_size, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; // clean up sim free(sim); @@ -2767,7 +2642,6 @@ code = ''' [cases.test_btree_general_sparse_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] defines.W = 5 -defines.VALIDATE = [1, 0] defines.SAMPLES = 100 # -1 => all pseudo-random seeds # n => reproduce a specific seed @@ -2913,8 +2787,7 @@ code = ''' } lfsr_btree_get(&lfs, &btree, weighted_id+sim_weights[i]-1, - &tag_, &weight_, - buffer, 4, VALIDATE) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == sim_weights[i]); assert(memcmp(buffer, &sim[i], 1) == 0); @@ -2922,8 +2795,7 @@ code = ''' // and no extra elements lfsr_btree_get(&lfs, &btree, total_weight, - &tag_, &weight_, - buffer, 4, VALIDATE) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; // also test that we can traverse the tree without prior knowledge lfs_size_t id_ = -1; @@ -2936,7 +2808,7 @@ code = ''' } lfsr_btree_lookupnext(&lfs, &btree, id_+1, - &id_, &tag_, &weight_, &data_, VALIDATE) => 0; + &id_, &tag_, &weight_, &data_) => 0; assert(id_ == weighted_id+sim_weights[i]-1); assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == sim_weights[i]); @@ -2945,7 +2817,7 @@ code = ''' assert(memcmp(buffer, &sim[i], 1) == 0); } lfsr_btree_lookupnext(&lfs, &btree, id_+1, - &id_, &tag_, &weight_, &data_, VALIDATE) => LFS_ERR_NOENT; + &id_, &tag_, &weight_, &data_) => LFS_ERR_NOENT; // clean up sim free(sim); @@ -4101,8 +3973,7 @@ code = ''' for (lfs_size_t i = 0; i < n; i++) { lfsr_btree_get(&lfs, &btree, i, - &tag_, &weight_, - buffer, 4, false) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, &alphas[i % 26], 1) == 0); @@ -4110,8 +3981,7 @@ code = ''' // and check that we can't lookup elements that aren't in the tree lfsr_btree_get(&lfs, &btree, n, - &tag_, &weight_, - buffer, 4, false) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; // test that we can traverse the tree, keeping track of all blocks we see uint8_t *seen = malloc((BLOCK_COUNT+7)/8); @@ -4169,8 +4039,7 @@ code = ''' // check that the elements are in the tree for (lfs_size_t i = 0; i < n; i++) { lfsr_btree_get(&lfs, &btree, i, - &tag_, &weight_, - buffer, 4, false) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, &alphas[i % 26], 1) == 0); @@ -4178,8 +4047,7 @@ code = ''' // and check that we can't lookup elements that aren't in the tree lfsr_btree_get(&lfs, &btree, n, - &tag_, &weight_, - buffer, 4, false) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' [cases.test_btree_traversal_fuzz] @@ -4262,8 +4130,7 @@ code = ''' lfs_size_t weight_; for (lfs_size_t i = 0; i < sim_size; i++) { lfsr_btree_get(&lfs, &btree, i, - &tag_, &weight_, - buffer, 4, false) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, &sim[i], 1) == 0); @@ -4271,8 +4138,7 @@ code = ''' // and no extra elements lfsr_btree_get(&lfs, &btree, sim_size, - &tag_, &weight_, - buffer, 4, false) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; // test that we can traverse the tree, keeping track of all blocks // we see @@ -4347,8 +4213,7 @@ code = ''' for (lfs_size_t i = 0; i < sim_size; i++) { lfsr_btree_get(&lfs, &btree, i, - &tag_, &weight_, - buffer, 4, false) => 1; + &tag_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(weight_ == 1); assert(memcmp(buffer, &sim[i], 1) == 0); @@ -4356,8 +4221,7 @@ code = ''' // and no extra elements lfsr_btree_get(&lfs, &btree, sim_size, - &tag_, &weight_, - buffer, 4, false) => LFS_ERR_NOENT; + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; // clean up sim free(sim); diff --git a/tests/test_mtree.toml b/tests/test_mtree.toml index 78273ab6..657920b7 100644 --- a/tests/test_mtree.toml +++ b/tests/test_mtree.toml @@ -2970,6 +2970,7 @@ code = ''' # test specific corner cases [cases.test_mtree_traversal] +defines.VALIDATE = [false, true] in = 'lfs.c' code = ''' const char *alphas = "abcdefghijklmnopqrstuvwxyz"; @@ -2993,7 +2994,8 @@ code = ''' uint8_t *seen = malloc((BLOCK_COUNT+7)/8); memset(seen, 0, (BLOCK_COUNT+7)/8); - lfsr_mtree_traversal_t traversal = LFSR_MTREE_TRAVERSAL_INIT; + lfsr_mtree_traversal_t traversal = LFSR_MTREE_TRAVERSAL_INIT( + VALIDATE ? LFSR_MTREE_TRAVERSAL_VALIDATE : 0); for (lfs_block_t i = 0;; i++) { // a bit hacky, but this catches infinite loops @@ -3064,6 +3066,7 @@ code = ''' [cases.test_mtree_traversal_uninline] # this should be set so only one entry can fit in a metadata block defines.SIZE = 'BLOCK_SIZE / 4' +defines.VALIDATE = [false, true] in = 'lfs.c' code = ''' const char *alphas = "abcdefghijklmnopqrstuvwxyz"; @@ -3109,7 +3112,8 @@ code = ''' uint8_t *seen = malloc((BLOCK_COUNT+7)/8); memset(seen, 0, (BLOCK_COUNT+7)/8); - lfsr_mtree_traversal_t traversal = LFSR_MTREE_TRAVERSAL_INIT; + lfsr_mtree_traversal_t traversal = LFSR_MTREE_TRAVERSAL_INIT( + VALIDATE ? LFSR_MTREE_TRAVERSAL_VALIDATE : 0); for (lfs_block_t i = 0;; i++) { // a bit hacky, but this catches infinite loops @@ -3191,6 +3195,7 @@ code = ''' [cases.test_mtree_traversal_split] # this should be set so only one entry can fit in a metadata block defines.SIZE = 'BLOCK_SIZE / 4' +defines.VALIDATE = [false, true] in = 'lfs.c' code = ''' const char *alphas = "abcdefghijklmnopqrstuvwxyz"; @@ -3236,7 +3241,8 @@ code = ''' uint8_t *seen = malloc((BLOCK_COUNT+7)/8); memset(seen, 0, (BLOCK_COUNT+7)/8); - lfsr_mtree_traversal_t traversal = LFSR_MTREE_TRAVERSAL_INIT; + lfsr_mtree_traversal_t traversal = LFSR_MTREE_TRAVERSAL_INIT( + VALIDATE ? LFSR_MTREE_TRAVERSAL_VALIDATE : 0); for (lfs_block_t i = 0;; i++) { // a bit hacky, but this catches infinite loops @@ -3320,6 +3326,7 @@ code = ''' defines.SIZE = 'BLOCK_SIZE / 4' # make it so blocks relocate every two compacts defines.BLOCK_CYCLES = 2 +defines.VALIDATE = [false, true] in = 'lfs.c' code = ''' const char *alphas = "abcdefghijklmnopqrstuvwxyz"; @@ -3355,7 +3362,8 @@ code = ''' uint8_t *seen = malloc((BLOCK_COUNT+7)/8); memset(seen, 0, (BLOCK_COUNT+7)/8); - lfsr_mtree_traversal_t traversal = LFSR_MTREE_TRAVERSAL_INIT; + lfsr_mtree_traversal_t traversal = LFSR_MTREE_TRAVERSAL_INIT( + VALIDATE ? LFSR_MTREE_TRAVERSAL_VALIDATE : 0); for (lfs_block_t i = 0;; i++) { // a bit hacky, but this catches infinite loops @@ -3427,6 +3435,7 @@ code = ''' # larger traversal tests [cases.test_mtree_traversal_many] defines.N = [5, 10, 20, 40, 80, 160, 320] +defines.VALIDATE = [false, true] defines.FORCE_COMPACTION = [false, true] in = 'lfs.c' code = ''' @@ -3481,7 +3490,8 @@ code = ''' uint8_t *seen = malloc((BLOCK_COUNT+7)/8); memset(seen, 0, (BLOCK_COUNT+7)/8); - lfsr_mtree_traversal_t traversal = LFSR_MTREE_TRAVERSAL_INIT; + lfsr_mtree_traversal_t traversal = LFSR_MTREE_TRAVERSAL_INIT( + VALIDATE ? LFSR_MTREE_TRAVERSAL_VALIDATE : 0); for (lfs_block_t i = 0;; i++) { // a bit hacky, but this catches infinite loops @@ -3563,6 +3573,7 @@ code = ''' [cases.test_mtree_traversal_fuzz] defines.N = [5, 10, 20, 40, 80, 160] +defines.VALIDATE = [false, true] defines.FORCE_COMPACTION = [false, true] defines.SAMPLES = 100 # -1 => all pseudo-random seeds @@ -3640,11 +3651,13 @@ code = ''' // we ended up with the right number of entries assert(count_ == count); - // test that we can traverse the tree, keeping track of all blocks we see + // test that we can traverse the tree, keeping track of all blocks + // we see uint8_t *seen = malloc((BLOCK_COUNT+7)/8); memset(seen, 0, (BLOCK_COUNT+7)/8); - lfsr_mtree_traversal_t traversal = LFSR_MTREE_TRAVERSAL_INIT; + lfsr_mtree_traversal_t traversal = LFSR_MTREE_TRAVERSAL_INIT( + VALIDATE ? LFSR_MTREE_TRAVERSAL_VALIDATE : 0); for (lfs_block_t i = 0;; i++) { // a bit hacky, but this catches infinite loops