From c5e84e874fff92c0350b8d308cec9a2705ea9672 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Tue, 18 Jul 2023 21:13:30 -0500 Subject: [PATCH] Changed how fuzz tests are iterated to allow powerloss-fuzz testing Instead of iterating over a number of seeds in the test itself, the seeds are now permuted as a part of normal test defines. This lets each seed take advantage of other test features, mainly the ability to test powerlosses heuristically. This is probably how it should have been done in the first place, but the permutation tests can't do this since the number of permutations changes as the size of the test input changes. The test define system can't handle that very well. The tradeoffs here are: - We can't do cross-fuzz checks, such as the balance checks in the rbyd tests, though those really should be moved to benchmarks anyways. - The large number of cheap fuzz permutations skews the total permutation count, though I'm not sure this matters. before: 3083 permutations (-Gnor) after: 409893 permutations (-Gnor) --- scripts/bench.py | 12 +- scripts/test.py | 12 +- tests/t1_rbyd.toml | 943 +++++------ tests/t2_btree.toml | 3818 +++++++++++++++++++++---------------------- tests/t3_mtree.toml | 958 ++++++----- tests/t5_dirs.toml | 176 +- 6 files changed, 2795 insertions(+), 3124 deletions(-) diff --git a/scripts/bench.py b/scripts/bench.py index e42d84d3..ae98477e 100755 --- a/scripts/bench.py +++ b/scripts/bench.py @@ -758,20 +758,22 @@ def find_ids(runner, bench_ids=[], **args): # find suite/case by id bench_ids_ = [] for id in bench_ids: + # strip permutation + name, *_ = id.split(':', 1) bench_ids__ = [] # resolve globs - if '*' in id: + if '*' in name: bench_ids__.extend(suite for suite in expected_suite_perms.keys() - if fnmatch.fnmatch(suite, id)) + if fnmatch.fnmatch(suite, name)) bench_ids__.extend(case_ for case_ in expected_case_perms.keys() - if fnmatch.fnmatch(case_, id)) + if fnmatch.fnmatch(case_, name)) # literal suite - elif id in expected_suite_perms: + elif name in expected_suite_perms: bench_ids__.append(id) # literal case - elif id in expected_case_perms: + elif name in expected_case_perms: bench_ids__.append(id) # no suite/case found? error diff --git a/scripts/test.py b/scripts/test.py index 92d85253..e6ad2a1d 100755 --- a/scripts/test.py +++ b/scripts/test.py @@ -767,20 +767,22 @@ def find_ids(runner, test_ids=[], **args): # find suite/case by id test_ids_ = [] for id in test_ids: + # strip permutation + name, *_ = id.split(':', 1) test_ids__ = [] # resolve globs - if '*' in id: + if '*' in name: test_ids__.extend(suite for suite in expected_suite_perms.keys() - if fnmatch.fnmatch(suite, id)) + if fnmatch.fnmatch(suite, name)) test_ids__.extend(case_ for case_ in expected_case_perms.keys() - if fnmatch.fnmatch(case_, id)) + if fnmatch.fnmatch(case_, name)) # literal suite - elif id in expected_suite_perms: + elif name in expected_suite_perms: test_ids__.append(id) # literal case - elif id in expected_case_perms: + elif name in expected_case_perms: test_ids__.append(id) # no suite/case found? error diff --git a/tests/t1_rbyd.toml b/tests/t1_rbyd.toml index f075f465..009715c7 100644 --- a/tests/t1_rbyd.toml +++ b/tests/t1_rbyd.toml @@ -3542,10 +3542,7 @@ code = ''' # balancing algorithm [cases.t1_rbyd_fuzz_append_removes] defines.N = 'range(1, 33)' -defines.SAMPLES = 1000 -# -1 => all pseudo-random seeds -# n => reproduce a specific seed -defines.SEED = -1 +defines.SEED = 'range(1000)' # large progs take too long for now if = 'PROG_SIZE < 512' in = 'lfs.c' @@ -3564,119 +3561,92 @@ code = ''' const char *alpha = "abcdefghijklmnopqrstuvwxyz"; uint8_t buffer[4]; - // keep track of the worst case size and seed - lfs_size_t worst_size = 0; - uint32_t worst_seed = 0; + printf("perm: ["); + uint32_t prng = SEED; + for (unsigned i = 0; i < N; i++) { + // choose an attr + uint8_t attr = TEST_PRNG(&prng) % N; + // choose append or remove + if (TEST_PRNG(&prng) & 1) { + printf("a0x%02x=%c", attr, alpha[i % 26]); + } else { + printf("r0x%02x", attr); + } + if (i < N-1) { + printf(", "); + } + } + printf("]\n"); - // iterate through seeds so we can reproduce easily - for (uint32_t seed = (SEED == -1 ? 1 : SEED); - (SEED == -1 ? seed < SAMPLES+1 : seed == SEED); - seed++) { - printf("--- seed: %d ---\n", seed); - printf("perm: ["); - uint32_t prng = seed; - for (unsigned i = 0; i < N; i++) { - // choose an attr - uint8_t attr = TEST_PRNG(&prng) % N; - // choose append or remove - if (TEST_PRNG(&prng) & 1) { - printf("a0x%02x=%c", attr, alpha[i % 26]); - } else { - printf("r0x%02x", attr); - } - if (i < N-1) { + // set up a simulation to compare against + char *sim = malloc(N); + memset(sim, 0, N); + + // set up rbyd block + rbyd = init_rbyd; + lfs_bd_erase(&lfs, rbyd.block) => 0; + + prng = SEED; + for (unsigned i = 0; i < N; i++) { + // choose an attr + uint8_t attr = TEST_PRNG(&prng) % N; + // choose append or remove + if (TEST_PRNG(&prng) & 1) { + // update our sim + sim[attr] = alpha[i % 26]; + // update our rbyd + lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( + LFSR_ATTR(-1, UATTR(attr), 0, &alpha[i % 26], 1))) => 0; + } else { + // update our sim + sim[attr] = '\0'; + // update our rbyd + lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( + LFSR_ATTR(-1, RMUATTR(attr), 0, NULL, 0))) => 0; + } + } + + // compare rbyd vs simulation + printf("expd: ["); + bool first = true; + for (unsigned attr = 0; attr < N; attr++) { + if (sim[attr]) { + if (!first) { printf(", "); } + first = false; + printf("0x%02x=%c", attr, sim[attr]); } - printf("]\n"); - - // set up a simulation to compare against - char *sim = malloc(N); - memset(sim, 0, N); - - // set up rbyd block - rbyd = init_rbyd; - lfs_bd_erase(&lfs, rbyd.block) => 0; - - prng = seed; - for (unsigned i = 0; i < N; i++) { - // choose an attr - uint8_t attr = TEST_PRNG(&prng) % N; - // choose append or remove - if (TEST_PRNG(&prng) & 1) { - // update our sim - sim[attr] = alpha[i % 26]; - // update our rbyd - lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( - LFSR_ATTR(-1, UATTR(attr), 0, &alpha[i % 26], 1))) => 0; - } else { - // update our sim - sim[attr] = '\0'; - // update our rbyd - lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( - LFSR_ATTR(-1, RMUATTR(attr), 0, NULL, 0))) => 0; + } + printf("]\n"); + printf("rbyd: ["); + first = true; + for (unsigned attr = 0; attr < N; attr++) { + lfs_ssize_t size = lfsr_rbyd_get(&lfs, &rbyd, + -1, LFSR_TAG_UATTR(attr), buffer, 4); + if (size >= 0) { + if (!first) { + printf(", "); } + first = false; + printf("0x%02x=%.*s", attr, size, buffer); } + } + printf("]\n"); - // compare rbyd vs simulation - printf("expd: ["); - bool first = true; - for (unsigned attr = 0; attr < N; attr++) { - if (sim[attr]) { - if (!first) { - printf(", "); - } - first = false; - printf("0x%02x=%c", attr, sim[attr]); - } + for (unsigned attr = 0; attr < N; attr++) { + lfs_ssize_t size = lfsr_rbyd_get(&lfs, &rbyd, + -1, LFSR_TAG_UATTR(attr), buffer, 4); + if (sim[attr]) { + assert(size == 1); + assert(memcmp(&sim[attr], buffer, 1) == 0); + } else { + assert(size == LFS_ERR_NOENT); } - printf("]\n"); - printf("rbyd: ["); - first = true; - for (unsigned attr = 0; attr < N; attr++) { - lfs_ssize_t size = lfsr_rbyd_get(&lfs, &rbyd, - -1, LFSR_TAG_UATTR(attr), buffer, 4); - if (size >= 0) { - if (!first) { - printf(", "); - } - first = false; - printf("0x%02x=%.*s", attr, size, buffer); - } - } - printf("]\n"); - - for (unsigned attr = 0; attr < N; attr++) { - lfs_ssize_t size = lfsr_rbyd_get(&lfs, &rbyd, - -1, LFSR_TAG_UATTR(attr), buffer, 4); - if (sim[attr]) { - assert(size == 1); - assert(memcmp(&sim[attr], buffer, 1) == 0); - } else { - assert(size == LFS_ERR_NOENT); - } - } - - // keep track of the worst seed - if (rbyd.off > worst_size) { - worst_size = rbyd.off; - worst_seed = seed; - } - - // cleanup - free(sim); } - // print the worst seed + size - printf("--- summary ---\n"); - printf("worst seed: %d\n", worst_seed); - printf("worst size: %d\n", worst_size); - - // our tree should be strictly <= 2*log(n)+1, assume tags are strictly - // <=12 bytes, note this only holds true with byte-level progs - if (PROG_SIZE == 1) { - assert(worst_size <= N*12*(2*lfs_nlog2(N)+1)+1); - } + // cleanup + free(sim); ''' @@ -8279,10 +8249,7 @@ code = ''' # balancing algorithm [cases.t1_rbyd_fuzz_create_deletes] defines.N = 'range(1, 33)' -defines.SAMPLES = 1000 -# -1 => all pseudo-random seeds -# n => reproduce a specific seed -defines.SEED = -1 +defines.SEED = 'range(1000)' # large progs take too long for now if = 'PROG_SIZE < 512' in = 'lfs.c' @@ -8301,119 +8268,91 @@ code = ''' const char *alpha = "abcdefghijklmnopqrstuvwxyz"; uint8_t buffer[4]; - // keep track of the worst case size and seed - lfs_size_t worst_size = 0; - uint32_t worst_seed = 0; - - // iterate through seeds so we can reproduce easily - for (uint32_t seed = (SEED == -1 ? 1 : SEED); - (SEED == -1 ? seed < SAMPLES+1 : seed == SEED); - seed++) { - printf("--- seed: %d ---\n", seed); - printf("perm: ["); - uint32_t prng = seed; - lfs_size_t count = 0; - for (unsigned i = 0; i < N; i++) { - // choose an id - lfs_ssize_t id = TEST_PRNG(&prng) % (count+1); - // choose create or delete - if (id == (lfs_ssize_t)count || (TEST_PRNG(&prng) & 1)) { - printf("c%d=%c", id, alpha[i % 26]); - count += 1; - } else { - printf("d%d", id); - count -= 1; - } - if (i < N-1) { - printf(", "); - } + printf("perm: ["); + uint32_t prng = SEED; + lfs_size_t count = 0; + for (unsigned i = 0; i < N; i++) { + // choose an id + lfs_ssize_t id = TEST_PRNG(&prng) % (count+1); + // choose create or delete + if (id == (lfs_ssize_t)count || (TEST_PRNG(&prng) & 1)) { + printf("c%d=%c", id, alpha[i % 26]); + count += 1; + } else { + printf("d%d", id); + count -= 1; } - printf("]\n"); - - // set up a simulation to compare against, fun fact this performs - // worst than our actual rbyd block! - char *sim = malloc(N); - memset(sim, 0, N); - - // set up rbyd block - rbyd = init_rbyd; - lfs_bd_erase(&lfs, rbyd.block) => 0; - - prng = seed; - count = 0; - for (unsigned i = 0; i < N; i++) { - // choose an id - lfs_ssize_t id = TEST_PRNG(&prng) % (count+1); - // choose create or delete - if (id == (lfs_ssize_t)count || (TEST_PRNG(&prng) & 1)) { - // update our sim - memmove(sim+id+1, sim+id, count-id); - sim[id] = alpha[i % 26]; - count += 1; - // update our rbyd - lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( - LFSR_ATTR(id, REG, +1, &alpha[i % 26], 1))) => 0; - } else { - // update our sim - memmove(sim+id, sim+id+1, count-id-1); - count -= 1; - // update our rbyd - lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( - LFSR_ATTR(id, UNR, -1, NULL, 0))) => 0; - } + if (i < N-1) { + printf(", "); } + } + printf("]\n"); - // compare rbyd vs simulation - printf("expd: ["); - for (lfs_ssize_t id = 0; id < (lfs_ssize_t)count; id++) { - printf("%c", sim[id]); - if (id < (lfs_ssize_t)count-1) { - printf(", "); - } - } - printf("]\n"); - printf("rbyd: ["); - for (lfs_ssize_t id = 0; id < (lfs_ssize_t)rbyd.weight; id++) { - lfs_ssize_t size = lfsr_rbyd_get(&lfs, &rbyd, - id, LFSR_TAG_REG, buffer, 4); - if (size >= 0) { - printf("%.*s", size, buffer); - } else { - printf("?"); - } - if (id < (lfs_ssize_t)count-1) { - printf(", "); - } - } - printf("]\n"); + // set up a simulation to compare against, fun fact this performs + // worst than our actual rbyd block! + char *sim = malloc(N); + memset(sim, 0, N); - assert(count == rbyd.weight); - for (lfs_ssize_t id = 0; id < (lfs_ssize_t)count; id++) { - lfsr_rbyd_get(&lfs, &rbyd, id, LFSR_TAG_REG, buffer, 4) => 1; - assert(memcmp(&sim[id], buffer, 1) == 0); - } + // set up rbyd block + rbyd = init_rbyd; + lfs_bd_erase(&lfs, rbyd.block) => 0; - // keep track of the worst seed - if (rbyd.off > worst_size) { - worst_size = rbyd.off; - worst_seed = seed; + prng = SEED; + count = 0; + for (unsigned i = 0; i < N; i++) { + // choose an id + lfs_ssize_t id = TEST_PRNG(&prng) % (count+1); + // choose create or delete + if (id == (lfs_ssize_t)count || (TEST_PRNG(&prng) & 1)) { + // update our sim + memmove(sim+id+1, sim+id, count-id); + sim[id] = alpha[i % 26]; + count += 1; + // update our rbyd + lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( + LFSR_ATTR(id, REG, +1, &alpha[i % 26], 1))) => 0; + } else { + // update our sim + memmove(sim+id, sim+id+1, count-id-1); + count -= 1; + // update our rbyd + lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( + LFSR_ATTR(id, UNR, -1, NULL, 0))) => 0; } - - // cleanup - free(sim); } - // print the worst seed + size, and rerun it so it's left on the disk - // if used with -ddisk - printf("--- summary ---\n"); - printf("worst_seed: %d\n", worst_seed); - printf("worst_size: %d\n", worst_size); - - // our tree should be strictly <= 2*log(n)+1, assume tags are strictly - // <=12 bytes, note this only holds true with byte-level progs - if (PROG_SIZE == 1) { - assert(worst_size <= 2*N*12*(2*lfs_nlog2(N)+1)+1); + // compare rbyd vs simulation + printf("expd: ["); + for (lfs_ssize_t id = 0; id < (lfs_ssize_t)count; id++) { + printf("%c", sim[id]); + if (id < (lfs_ssize_t)count-1) { + printf(", "); + } } + printf("]\n"); + printf("rbyd: ["); + for (lfs_ssize_t id = 0; id < (lfs_ssize_t)rbyd.weight; id++) { + lfs_ssize_t size = lfsr_rbyd_get(&lfs, &rbyd, + id, LFSR_TAG_REG, buffer, 4); + if (size >= 0) { + printf("%.*s", size, buffer); + } else { + printf("?"); + } + if (id < (lfs_ssize_t)count-1) { + printf(", "); + } + } + printf("]\n"); + + assert(count == rbyd.weight); + for (lfs_ssize_t id = 0; id < (lfs_ssize_t)count; id++) { + lfsr_rbyd_get(&lfs, &rbyd, id, LFSR_TAG_REG, buffer, 4) => 1; + assert(memcmp(&sim[id], buffer, 1) == 0); + } + + // cleanup + free(sim); ''' @@ -11239,10 +11178,7 @@ code = ''' [cases.t1_rbyd_fuzz_mixed] defines.N = 'range(1, 33)' defines.M = 3 -defines.SAMPLES = 1000 -# -1 => all pseudo-random seeds -# n => reproduce a specific seed -defines.SEED = -1 +defines.SEED = 'range(1000)' # large progs take too long for now if = 'PROG_SIZE < 512' in = 'lfs.c' @@ -11261,170 +11197,139 @@ code = ''' const char *alpha = "abcdefghijklmnopqrstuvwxyz"; uint8_t buffer[4]; - // keep track of the worst case size and seed - lfs_size_t worst_size = 0; - uint32_t worst_seed = 0; + printf("perm: ["); + uint32_t prng = SEED; + lfs_size_t count = 0; + for (unsigned i = 0; i < N; i++) { + // choose create/delete or attr append/remove + uint8_t op = TEST_PRNG(&prng) % 4; + // choose an id + lfs_ssize_t id = TEST_PRNG(&prng) % (count+1); + // choose an attr + uint8_t u = TEST_PRNG(&prng) % M; - // iterate through seeds so we can reproduce easily - for (uint32_t seed = (SEED == -1 ? 1 : SEED); - (SEED == -1 ? seed < SAMPLES+1 : seed == SEED); - seed++) { - printf("--- seed: %d ---\n", seed); - printf("perm: ["); - uint32_t prng = seed; - lfs_size_t count = 0; - for (unsigned i = 0; i < N; i++) { - // choose create/delete or attr append/remove - uint8_t op = TEST_PRNG(&prng) % 4; - // choose an id - lfs_ssize_t id = TEST_PRNG(&prng) % (count+1); - // choose an attr - uint8_t u = TEST_PRNG(&prng) % M; + if (id == (lfs_ssize_t)count || op == 0) { + printf("c%d=%c", id, alpha[i % 26]); + count += 1; + } else if (op == 1) { + printf("d%d", id); + count -= 1; + } else if (op == 2) { + printf("a%d,%d=%c", id, u, alpha[i % 26]); + } else if (op == 3) { + printf("r%d,%d", id, u); + } + if (i < N-1) { + printf(", "); + } + } + printf("]\n"); - if (id == (lfs_ssize_t)count || op == 0) { - printf("c%d=%c", id, alpha[i % 26]); - count += 1; - } else if (op == 1) { - printf("d%d", id); - count -= 1; - } else if (op == 2) { - printf("a%d,%d=%c", id, u, alpha[i % 26]); - } else if (op == 3) { - printf("r%d,%d", id, u); - } - if (i < N-1) { - printf(", "); + // set up a simulation to compare against, fun fact this performs + // worst than our actual rbyd block! + char *sim = malloc(N*(M+1)); + memset(sim, 0, N*(M+1)); + + // set up rbyd block + rbyd = init_rbyd; + lfs_bd_erase(&lfs, rbyd.block) => 0; + + prng = SEED; + count = 0; + for (unsigned i = 0; i < N; i++) { + // choose create/delete or attr append/remove + uint8_t op = TEST_PRNG(&prng) % 4; + // choose an id + lfs_ssize_t id = TEST_PRNG(&prng) % (count+1); + // choose an attr + uint8_t u = TEST_PRNG(&prng) % M; + + if (id == (lfs_ssize_t)count || op == 0) { + // update our sim + memmove(sim+(id+1)*(M+1), sim+id*(M+1), (count-id)*(M+1)); + memset(&sim[id*(M+1)], 0, M+1); + sim[id*(M+1)] = alpha[i % 26]; + count += 1; + // update our rbyd + lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( + LFSR_ATTR(id, REG, +1, &alpha[i % 26], 1))) => 0; + } else if (op == 1) { + // update our sim + memmove(sim+id*(M+1), sim+(id+1)*(M+1), (count-id-1)*(M+1)); + count -= 1; + // update our rbyd + lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( + LFSR_ATTR(id, UNR, -1, NULL, 0))) => 0; + } else if (op == 2) { + // update our sim + sim[id*(M+1) + u+1] = alpha[i % 26]; + // update our rbyd + lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( + LFSR_ATTR(id, UATTR(u), 0, &alpha[i % 26], 1))) => 0; + + } else if (op == 3) { + // update our sim + sim[id*(M+1) + u+1] = '\0'; + // update our rbyd + lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( + LFSR_ATTR(id, RMUATTR(u), 0, NULL, 0))) => 0; + } + } + + // compare rbyd vs simulation + printf("expd: ["); + for (lfs_ssize_t id = 0; id < (lfs_ssize_t)count; id++) { + printf("%c", sim[id*(M+1)]); + for (uint8_t u = 0; u < M; u++) { + if (sim[id*(M+1) + u+1]) { + printf("%c", sim[id*(M+1) + u+1]); + } else { + printf("_"); } } - printf("]\n"); - - // set up a simulation to compare against, fun fact this performs - // worst than our actual rbyd block! - char *sim = malloc(N*(M+1)); - memset(sim, 0, N*(M+1)); - - // set up rbyd block - rbyd = init_rbyd; - lfs_bd_erase(&lfs, rbyd.block) => 0; - - prng = seed; - count = 0; - for (unsigned i = 0; i < N; i++) { - // choose create/delete or attr append/remove - uint8_t op = TEST_PRNG(&prng) % 4; - // choose an id - lfs_ssize_t id = TEST_PRNG(&prng) % (count+1); - // choose an attr - uint8_t u = TEST_PRNG(&prng) % M; - - if (id == (lfs_ssize_t)count || op == 0) { - // update our sim - memmove(sim+(id+1)*(M+1), sim+id*(M+1), (count-id)*(M+1)); - memset(&sim[id*(M+1)], 0, M+1); - sim[id*(M+1)] = alpha[i % 26]; - count += 1; - // update our rbyd - lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( - LFSR_ATTR(id, REG, +1, &alpha[i % 26], 1))) => 0; - } else if (op == 1) { - // update our sim - memmove(sim+id*(M+1), sim+(id+1)*(M+1), (count-id-1)*(M+1)); - count -= 1; - // update our rbyd - lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( - LFSR_ATTR(id, UNR, -1, NULL, 0))) => 0; - } else if (op == 2) { - // update our sim - sim[id*(M+1) + u+1] = alpha[i % 26]; - // update our rbyd - lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( - LFSR_ATTR(id, UATTR(u), 0, &alpha[i % 26], 1))) => 0; - - } else if (op == 3) { - // update our sim - sim[id*(M+1) + u+1] = '\0'; - // update our rbyd - lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( - LFSR_ATTR(id, RMUATTR(u), 0, NULL, 0))) => 0; - } + if (id < (lfs_ssize_t)count-1) { + printf(", "); } - - // compare rbyd vs simulation - printf("expd: ["); - for (lfs_ssize_t id = 0; id < (lfs_ssize_t)count; id++) { - printf("%c", sim[id*(M+1)]); - for (uint8_t u = 0; u < M; u++) { - if (sim[id*(M+1) + u+1]) { - printf("%c", sim[id*(M+1) + u+1]); - } else { - printf("_"); - } - } - if (id < (lfs_ssize_t)count-1) { - printf(", "); - } + } + printf("]\n"); + printf("rbyd: ["); + for (lfs_ssize_t id = 0; id < (lfs_ssize_t)rbyd.weight; id++) { + lfs_ssize_t size = lfsr_rbyd_get(&lfs, &rbyd, + id, LFSR_TAG_REG, buffer, 4); + if (size >= 0) { + printf("%.*s", size, buffer); + } else { + printf("?"); } - printf("]\n"); - printf("rbyd: ["); - for (lfs_ssize_t id = 0; id < (lfs_ssize_t)rbyd.weight; id++) { + for (uint8_t u = 0; u < M; u++) { lfs_ssize_t size = lfsr_rbyd_get(&lfs, &rbyd, - id, LFSR_TAG_REG, buffer, 4); + id, LFSR_TAG_UATTR(u), buffer, 4); if (size >= 0) { printf("%.*s", size, buffer); } else { - printf("?"); - } - for (uint8_t u = 0; u < M; u++) { - lfs_ssize_t size = lfsr_rbyd_get(&lfs, &rbyd, - id, LFSR_TAG_UATTR(u), buffer, 4); - if (size >= 0) { - printf("%.*s", size, buffer); - } else { - printf("_"); - } - } - if (id < (lfs_ssize_t)count-1) { - printf(", "); + printf("_"); } } - printf("]\n"); - - assert(count == rbyd.weight); - for (lfs_ssize_t id = 0; id < (lfs_ssize_t)count; id++) { - lfsr_rbyd_get(&lfs, &rbyd, id, LFSR_TAG_REG, buffer, 4) => 1; - assert(memcmp(&sim[id*(M+1)], buffer, 1) == 0); + if (id < (lfs_ssize_t)count-1) { + printf(", "); } + } + printf("]\n"); - // keep track of the worst seed - if (rbyd.off > worst_size) { - worst_size = rbyd.off; - worst_seed = seed; - } - - // cleanup - free(sim); + assert(count == rbyd.weight); + for (lfs_ssize_t id = 0; id < (lfs_ssize_t)count; id++) { + lfsr_rbyd_get(&lfs, &rbyd, id, LFSR_TAG_REG, buffer, 4) => 1; + assert(memcmp(&sim[id*(M+1)], buffer, 1) == 0); } - // print the worst seed + size, and rerun it so it's left on the disk - // if used with -ddisk - printf("--- summary ---\n"); - printf("worst_seed: %d\n", worst_seed); - printf("worst_size: %d\n", worst_size); - - // our tree should be strictly <= 2*log(n)+1, assume tags are strictly - // <=12 bytes, note this only holds true with byte-level progs - if (PROG_SIZE == 1) { - assert(worst_size <= 2*N*12*(2*lfs_nlog2(N)+1)+1); - } + // cleanup + free(sim); ''' [cases.t1_rbyd_fuzz_sparse] defines.N = 'range(1, 33)' defines.W = 5 -defines.SAMPLES = 1000 -# -1 => all pseudo-random seeds -# n => reproduce a specific seed -defines.SEED = -1 +defines.SEED = 'range(1000)' # large progs take too long for now if = 'PROG_SIZE < 512' in = 'lfs.c' @@ -11447,198 +11352,170 @@ code = ''' const char *alpha = "abcdefghijklmnopqrstuvwxyz"; uint8_t buffer[4]; - // keep track of the worst case size and seed - lfs_size_t worst_size = 0; - uint32_t worst_seed = 0; + printf("perm: ["); + uint32_t prng = SEED; + lfs_size_t count = 0; + for (unsigned i = 0; i < N; i++) { + // choose create/delete/grow/shrink + uint8_t op = TEST_PRNG(&prng) % 4; + // choose an id + lfs_ssize_t id = TEST_PRNG(&prng) % (count+1); + // choose a weight + lfs_size_t weight = 1 + (TEST_PRNG(&prng) % W); - // iterate through seeds so we can reproduce easily - for (uint32_t seed = (SEED == -1 ? 1 : SEED); - (SEED == -1 ? seed < SAMPLES+1 : seed == SEED); - seed++) { - printf("--- seed: %d ---\n", seed); - printf("perm: ["); - uint32_t prng = seed; - lfs_size_t count = 0; - for (unsigned i = 0; i < N; i++) { - // choose create/delete/grow/shrink - uint8_t op = TEST_PRNG(&prng) % 4; - // choose an id - lfs_ssize_t id = TEST_PRNG(&prng) % (count+1); - // choose a weight - lfs_size_t weight = 1 + (TEST_PRNG(&prng) % W); - - if (id == (lfs_ssize_t)count || op == 0) { - printf("c%dw%d=%c", id, weight, alpha[i % 26]); - count += 1; - } else if (op == 1) { - printf("d%d", id); - count -= 1; - } else if (op == 2) { - printf("g%dw%d", id, weight); - } else if (op == 3) { - printf("s%dw%d", id, weight); - } - if (i < N-1) { - printf(", "); - } + if (id == (lfs_ssize_t)count || op == 0) { + printf("c%dw%d=%c", id, weight, alpha[i % 26]); + count += 1; + } else if (op == 1) { + printf("d%d", id); + count -= 1; + } else if (op == 2) { + printf("g%dw%d", id, weight); + } else if (op == 3) { + printf("s%dw%d", id, weight); } - printf("]\n"); + if (i < N-1) { + printf(", "); + } + } + printf("]\n"); - // set up a simulation to compare against, fun fact this performs - // worst than our actual rbyd block! - char *sim = malloc(N); - lfs_size_t *sim_weights = malloc(N*sizeof(lfs_size_t)); - memset(sim, 0, N); - memset(sim_weights, 0, N*sizeof(lfs_size_t)); + // set up a simulation to compare against, fun fact this performs + // worst than our actual rbyd block! + char *sim = malloc(N); + lfs_size_t *sim_weights = malloc(N*sizeof(lfs_size_t)); + memset(sim, 0, N); + memset(sim_weights, 0, N*sizeof(lfs_size_t)); - // set up rbyd block - rbyd = init_rbyd; - lfs_bd_erase(&lfs, rbyd.block) => 0; + // set up rbyd block + rbyd = init_rbyd; + lfs_bd_erase(&lfs, rbyd.block) => 0; - prng = seed; - count = 0; - for (unsigned i = 0; i < N; i++) { - // choose create/delete/grow/shrink - uint8_t op = TEST_PRNG(&prng) % 4; - // choose an id - lfs_ssize_t id = TEST_PRNG(&prng) % (count+1); - // choose a weight - lfs_size_t weight = 1 + (TEST_PRNG(&prng) % W); + prng = SEED; + count = 0; + for (unsigned i = 0; i < N; i++) { + // choose create/delete/grow/shrink + uint8_t op = TEST_PRNG(&prng) % 4; + // choose an id + lfs_ssize_t id = TEST_PRNG(&prng) % (count+1); + // choose a weight + lfs_size_t weight = 1 + (TEST_PRNG(&prng) % W); - // calculate actual id in rbyd space - lfs_ssize_t weighted_id = 0; - for (lfs_ssize_t j = 0; j < id; j++) { - weighted_id += sim_weights[j]; - } - - if (id == (lfs_ssize_t)count || op == 0) { - // update our sim - memmove(sim+id+1, sim+id, count-id); - memmove(sim_weights+id+1, sim_weights+id, - (count-id)*sizeof(lfs_size_t)); - sim[id] = alpha[i % 26]; - sim_weights[id] = weight; - count += 1; - // update our rbyd - lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( - LFSR_ATTR(weighted_id, REG, - +weight, &alpha[i % 26], 1))) => 0; - } else if (op == 1) { - // get the correct weight from the sim - weight_ = sim_weights[id]; - // update our sim - memmove(sim+id, sim+id+1, count-id-1); - memmove(sim_weights+id, sim_weights+id+1, - (count-id-1)*sizeof(lfs_size_t)); - count -= 1; - // update our rbyd - lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( - LFSR_ATTR(weighted_id+weight_-1, UNR, - -weight_, NULL, 0))) => 0; - } else if (op == 2) { - // get the correct weight from the sim - weight_ = sim_weights[id]; - // update our sim - sim_weights[id] += weight; - // update our rbyd - lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( - LFSR_ATTR(weighted_id+weight_-1, GROW, - +weight, NULL, 0))) => 0; - } else if (op == 3) { - // get the correct weight from the sim - weight_ = sim_weights[id]; - // don't let shrink go to zero here! this is already hard enough - // to simulate - weight = lfs_min(weight, weight_-1); - // update our sim - sim_weights[id] -= weight; - // update our rbyd - lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( - LFSR_ATTR(weighted_id+weight_-1, GROW, - -weight, NULL, 0))) => 0; - } + // calculate actual id in rbyd space + lfs_ssize_t weighted_id = 0; + for (lfs_ssize_t j = 0; j < id; j++) { + weighted_id += sim_weights[j]; } - // compare rbyd vs simulation - printf("expd: ["); - for (lfs_ssize_t id = 0; id < (lfs_ssize_t)count; id++) { - printf("%cw%d", sim[id], sim_weights[id]); - if (id < (lfs_ssize_t)count-1) { - printf(", "); - } + if (id == (lfs_ssize_t)count || op == 0) { + // update our sim + memmove(sim+id+1, sim+id, count-id); + memmove(sim_weights+id+1, sim_weights+id, + (count-id)*sizeof(lfs_size_t)); + sim[id] = alpha[i % 26]; + sim_weights[id] = weight; + count += 1; + // update our rbyd + lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( + LFSR_ATTR(weighted_id, REG, + +weight, &alpha[i % 26], 1))) => 0; + } else if (op == 1) { + // get the correct weight from the sim + weight_ = sim_weights[id]; + // update our sim + memmove(sim+id, sim+id+1, count-id-1); + memmove(sim_weights+id, sim_weights+id+1, + (count-id-1)*sizeof(lfs_size_t)); + count -= 1; + // update our rbyd + lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( + LFSR_ATTR(weighted_id+weight_-1, UNR, + -weight_, NULL, 0))) => 0; + } else if (op == 2) { + // get the correct weight from the sim + weight_ = sim_weights[id]; + // update our sim + sim_weights[id] += weight; + // update our rbyd + lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( + LFSR_ATTR(weighted_id+weight_-1, GROW, + +weight, NULL, 0))) => 0; + } else if (op == 3) { + // get the correct weight from the sim + weight_ = sim_weights[id]; + // don't let shrink go to zero here! this is already hard enough + // to simulate + weight = lfs_min(weight, weight_-1); + // update our sim + sim_weights[id] -= weight; + // update our rbyd + lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( + LFSR_ATTR(weighted_id+weight_-1, GROW, + -weight, NULL, 0))) => 0; } - printf("]\n"); - printf("rbyd: ["); - for (lfs_ssize_t id = 0; id < (lfs_ssize_t)count; id++) { - // calculate actual id in rbyd space - lfs_ssize_t weighted_id = 0; - for (lfs_ssize_t j = 0; j < id; j++) { - weighted_id += sim_weights[j]; - } + } - int err = lfsr_rbyd_lookupnext(&lfs, &rbyd, - weighted_id, LFSR_TAG_REG, - &id_, &tag_, &weight_, &data_); - if (!err) { - lfs_ssize_t size = lfsr_rbyd_get(&lfs, &rbyd, - id_, tag_, buffer, 4); - if (size >= 0) { - printf("%.*sw%d", size, buffer, weight_); - } else { - printf("?"); - } + // compare rbyd vs simulation + printf("expd: ["); + for (lfs_ssize_t id = 0; id < (lfs_ssize_t)count; id++) { + printf("%cw%d", sim[id], sim_weights[id]); + if (id < (lfs_ssize_t)count-1) { + printf(", "); + } + } + printf("]\n"); + printf("rbyd: ["); + for (lfs_ssize_t id = 0; id < (lfs_ssize_t)count; id++) { + // calculate actual id in rbyd space + lfs_ssize_t weighted_id = 0; + for (lfs_ssize_t j = 0; j < id; j++) { + weighted_id += sim_weights[j]; + } + + int err = lfsr_rbyd_lookupnext(&lfs, &rbyd, + weighted_id, LFSR_TAG_REG, + &id_, &tag_, &weight_, &data_); + if (!err) { + lfs_ssize_t size = lfsr_rbyd_get(&lfs, &rbyd, + id_, tag_, buffer, 4); + if (size >= 0) { + printf("%.*sw%d", size, buffer, weight_); } else { printf("?"); } - if (id < (lfs_ssize_t)count-1) { - printf(", "); - } + } else { + printf("?"); } - printf("]\n"); - - // calculate total weight - lfs_size_t total_weight = 0; - for (lfs_ssize_t j = 0; j < (lfs_ssize_t)count; j++) { - total_weight += sim_weights[j]; + if (id < (lfs_ssize_t)count-1) { + printf(", "); } - assert(total_weight == rbyd.weight); + } + printf("]\n"); - for (lfs_ssize_t id = 0; id < (lfs_ssize_t)count; id++) { - // calculate actual id in rbyd space - lfs_ssize_t weighted_id = 0; - for (lfs_ssize_t j = 0; j < id; j++) { - weighted_id += sim_weights[j]; - } + // calculate total weight + lfs_size_t total_weight = 0; + for (lfs_ssize_t j = 0; j < (lfs_ssize_t)count; j++) { + total_weight += sim_weights[j]; + } + assert(total_weight == rbyd.weight); - lfsr_rbyd_lookupnext(&lfs, &rbyd, - weighted_id, LFSR_TAG_REG, - &id_, &tag_, &weight_, &data_) => 0; - lfsr_rbyd_get(&lfs, &rbyd, id_, tag_, buffer, 4) => 1; - assert(memcmp(&sim[id], buffer, 1) == 0); + for (lfs_ssize_t id = 0; id < (lfs_ssize_t)count; id++) { + // calculate actual id in rbyd space + lfs_ssize_t weighted_id = 0; + for (lfs_ssize_t j = 0; j < id; j++) { + weighted_id += sim_weights[j]; } - // keep track of the worst seed - if (rbyd.off > worst_size) { - worst_size = rbyd.off; - worst_seed = seed; - } - - // cleanup - free(sim); - free(sim_weights); + lfsr_rbyd_lookupnext(&lfs, &rbyd, + weighted_id, LFSR_TAG_REG, + &id_, &tag_, &weight_, &data_) => 0; + lfsr_rbyd_get(&lfs, &rbyd, id_, tag_, buffer, 4) => 1; + assert(memcmp(&sim[id], buffer, 1) == 0); } - // print the worst seed + size, and rerun it so it's left on the disk - // if used with -ddisk - printf("--- summary ---\n"); - printf("worst_seed: %d\n", worst_seed); - printf("worst_size: %d\n", worst_size); - - // our tree should be strictly <= 2*log(n)+1, assume tags are strictly - // <=12 bytes, note this only holds true with byte-level progs - if (PROG_SIZE == 1) { - assert(worst_size <= 2*N*12*(2*lfs_nlog2(N)+1)+1); - } + // cleanup + free(sim); + free(sim_weights); ''' diff --git a/tests/t2_btree.toml b/tests/t2_btree.toml index 6df19867..00ef8224 100644 --- a/tests/t2_btree.toml +++ b/tests/t2_btree.toml @@ -384,98 +384,87 @@ code = ''' [cases.t2_btree_push_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] -defines.SAMPLES = 10 -# -1 => all pseudo-random seeds -# n => reproduce a specific seed -defines.SEED = -1 +defines.SEED = 'range(10)' in = 'lfs.c' code = ''' const char *alphas = "abcdefghijklmnopqrstuvwxyz"; - // iterate through severals seeds that we can reproduce easily - for (uint32_t seed = (SEED == -1 ? 1 : SEED); - (SEED == -1 ? seed < SAMPLES+1 : seed == SEED); - seed++) { - printf("--- seed: %d ---\n", seed); - // create lfs here since we need to reset each iteration, we're - // space constrained and we can't expect gc to work at this point - 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); + 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); - // create a btree - lfsr_btree_t btree = LFSR_BTREE_NULL; + // create a btree + lfsr_btree_t btree = LFSR_BTREE_NULL; - // set up a simulation to compare against - // - // fun fact this is slower than our actual tree! unfun fact this is - // starting to be a problem... - char *sim = malloc(N); - lfs_size_t sim_size = 0; - memset(sim, 0, N); + // set up a simulation to compare against + // + // fun fact this is slower than our actual tree! unfun fact this is + // starting to be a problem... + char *sim = malloc(N); + lfs_size_t sim_size = 0; + memset(sim, 0, N); - uint32_t prng = seed; - for (lfs_size_t i = 0; i < N; i++) { - // choose a pseudo-random id - lfs_size_t id = TEST_PRNG(&prng) % (sim_size+1); + uint32_t prng = SEED; + for (lfs_size_t i = 0; i < N; i++) { + // choose a pseudo-random id + lfs_size_t id = TEST_PRNG(&prng) % (sim_size+1); - // add to btree - int err = lfsr_btree_push(&lfs, &btree, id, LFSR_TAG_INLINED, 1, - LFSR_DATA_BUF(&alphas[i % 26], 1)); - // ignore space issues - if (err == LFS_ERR_NOSPC) { - break; - } - assert(err == 0); - - // add to sim - memmove(&sim[id+1], &sim[id], sim_size-id); - sim[id] = alphas[i % 26]; - sim_size += 1; + // add to btree + int err = lfsr_btree_push(&lfs, &btree, id, LFSR_TAG_INLINED, 1, + LFSR_DATA_BUF(&alphas[i % 26], 1)); + // ignore space issues + if (err == LFS_ERR_NOSPC) { + break; } + assert(err == 0); - // check that btree matches sim - printf("expd: ["); - bool first = true; - for (lfs_size_t i = 0; i < sim_size; i++) { - if (!first) { - printf(", "); - } - first = false; - printf("%c", sim[i]); - } - printf("]\n"); - printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); - assert(lfsr_btree_weight(&btree) == sim_size); - - uint8_t buffer[4]; - lfsr_tag_t tag_; - lfs_size_t weight_; - for (lfs_size_t i = 0; i < sim_size; i++) { - lfsr_btree_get(&lfs, &btree, i, - &tag_, &weight_, buffer, 4) => 1; - assert(tag_ == LFSR_TAG_INLINED); - assert(weight_ == 1); - assert(memcmp(buffer, &sim[i], 1) == 0); - } - - // and no extra elements - lfsr_btree_get(&lfs, &btree, sim_size, - &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; - - // clean up sim - free(sim); - lfs_deinit(&lfs) => 0; + // add to sim + memmove(&sim[id+1], &sim[id], sim_size-id); + sim[id] = alphas[i % 26]; + sim_size += 1; } + + // check that btree matches sim + printf("expd: ["); + bool first = true; + for (lfs_size_t i = 0; i < sim_size; i++) { + if (!first) { + printf(", "); + } + first = false; + printf("%c", sim[i]); + } + printf("]\n"); + printf("btree: w%d 0x%x.%x\n", + btree.weight, + btree.root.block, + btree.root.trunk); + assert(lfsr_btree_weight(&btree) == sim_size); + + uint8_t buffer[4]; + lfsr_tag_t tag_; + lfs_size_t weight_; + for (lfs_size_t i = 0; i < sim_size; i++) { + lfsr_btree_get(&lfs, &btree, i, + &tag_, &weight_, buffer, 4) => 1; + assert(tag_ == LFSR_TAG_INLINED); + assert(weight_ == 1); + assert(memcmp(buffer, &sim[i], 1) == 0); + } + + // and no extra elements + lfsr_btree_get(&lfs, &btree, sim_size, + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; + + // clean up sim + free(sim); + lfs_deinit(&lfs) => 0; ''' [cases.t2_btree_push_sparse] @@ -550,151 +539,140 @@ code = ''' [cases.t2_btree_push_sparse_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] defines.W = 5 -defines.SAMPLES = 10 -# -1 => all pseudo-random seeds -# n => reproduce a specific seed -defines.SEED = -1 +defines.SEED = 'range(10)' in = 'lfs.c' code = ''' const char *alphas = "abcdefghijklmnopqrstuvwxyz"; - // iterate through severals seeds that we can reproduce easily - for (uint32_t seed = (SEED == -1 ? 1 : SEED); - (SEED == -1 ? seed < SAMPLES+1 : seed == SEED); - seed++) { - printf("--- seed: %d ---\n", seed); - // create lfs here since we need to reset each iteration, we're - // space constrained and we can't expect gc to work at this point - 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); + 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); - // create a btree - lfsr_btree_t btree = LFSR_BTREE_NULL; + // create a btree + lfsr_btree_t btree = LFSR_BTREE_NULL; - // set up a simulation to compare against - // - // fun fact this is slower than our actual tree! unfun fact this is - // starting to be a problem... - char *sim = malloc(N); - lfs_size_t *sim_weights = malloc(N*sizeof(lfs_size_t)); - lfs_size_t sim_size = 0; - memset(sim, 0, N); - memset(sim_weights, 0, N*sizeof(lfs_size_t)); + // set up a simulation to compare against + // + // fun fact this is slower than our actual tree! unfun fact this is + // starting to be a problem... + char *sim = malloc(N); + lfs_size_t *sim_weights = malloc(N*sizeof(lfs_size_t)); + lfs_size_t sim_size = 0; + memset(sim, 0, N); + memset(sim_weights, 0, N*sizeof(lfs_size_t)); - uint32_t prng = seed; - for (lfs_size_t i = 0; i < N; i++) { - // choose a pseudo-random id - lfs_size_t id = TEST_PRNG(&prng) % (sim_size+1); - // choose a pseudo-random weight - lfs_size_t weight = 1 + (TEST_PRNG(&prng) % W); + uint32_t prng = SEED; + for (lfs_size_t i = 0; i < N; i++) { + // choose a pseudo-random id + lfs_size_t id = TEST_PRNG(&prng) % (sim_size+1); + // choose a pseudo-random weight + lfs_size_t weight = 1 + (TEST_PRNG(&prng) % W); - // calculate actual id in btree space - lfs_size_t weighted_id = 0; - for (lfs_size_t j = 0; j < id; j++) { - weighted_id += sim_weights[j]; - } - - // add to btree - int err = lfsr_btree_push(&lfs, &btree, - weighted_id, LFSR_TAG_INLINED, weight, - LFSR_DATA_BUF(&alphas[i % 26], 1)); - // ignore space issues - if (err == LFS_ERR_NOSPC) { - break; - } - assert(err == 0); - - // add to sim - memmove(&sim[id+1], &sim[id], sim_size-id); - memmove(&sim_weights[id+1], &sim_weights[id], - (sim_size-id)*sizeof(lfs_size_t)); - sim[id] = alphas[i % 26]; - sim_weights[id] = weight; - sim_size += 1; + // calculate actual id in btree space + lfs_size_t weighted_id = 0; + for (lfs_size_t j = 0; j < id; j++) { + weighted_id += sim_weights[j]; } - // check that btree matches sim - printf("expd: ["); - bool first = true; - for (lfs_size_t i = 0; i < sim_size; i++) { - // calculate actual id in btree space - lfs_size_t weighted_id = 0; - for (lfs_size_t j = 0; j < i; j++) { - weighted_id += sim_weights[j]; - } - - if (!first) { - printf(", "); - } - first = false; - printf("%dw%d=%c", weighted_id+sim_weights[i]-1, - sim_weights[i], sim[i]); + // add to btree + int err = lfsr_btree_push(&lfs, &btree, + weighted_id, LFSR_TAG_INLINED, weight, + LFSR_DATA_BUF(&alphas[i % 26], 1)); + // ignore space issues + if (err == LFS_ERR_NOSPC) { + break; } - printf("]\n"); - printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + assert(err == 0); - lfs_size_t total_weight = 0; - for (lfs_size_t j = 0; j < sim_size; j++) { - total_weight += sim_weights[j]; - } - assert(lfsr_btree_weight(&btree) == total_weight); - - uint8_t buffer[4]; - lfsr_tag_t tag_; - lfs_size_t weight_; - for (lfs_size_t i = 0; i < sim_size; i++) { - // calculate actual id in btree space - lfs_size_t weighted_id = 0; - for (lfs_size_t j = 0; j < i; j++) { - weighted_id += sim_weights[j]; - } - - lfsr_btree_get(&lfs, &btree, weighted_id+sim_weights[i]-1, - &tag_, &weight_, buffer, 4) => 1; - assert(tag_ == LFSR_TAG_INLINED); - assert(weight_ == sim_weights[i]); - assert(memcmp(buffer, &sim[i], 1) == 0); - } - - // and no extra elements - lfsr_btree_get(&lfs, &btree, total_weight, - &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 < sim_size; i++) { - // calculate actual id in btree space - lfs_size_t weighted_id = 0; - for (lfs_size_t j = 0; j < i; j++) { - weighted_id += sim_weights[j]; - } - - lfsr_btree_lookupnext(&lfs, &btree, id_+1, - &id_, &tag_, &weight_, &data_) => 0; - assert(id_ == weighted_id+sim_weights[i]-1); - assert(tag_ == LFSR_TAG_INLINED); - assert(weight_ == sim_weights[i]); - - lfsr_data_read(&lfs, data_, 0, buffer, 4) => 1; - assert(memcmp(buffer, &sim[i], 1) == 0); - } - lfsr_btree_lookupnext(&lfs, &btree, id_+1, - &id_, &tag_, &weight_, &data_) => LFS_ERR_NOENT; - - // clean up sim - free(sim); + // add to sim + memmove(&sim[id+1], &sim[id], sim_size-id); + memmove(&sim_weights[id+1], &sim_weights[id], + (sim_size-id)*sizeof(lfs_size_t)); + sim[id] = alphas[i % 26]; + sim_weights[id] = weight; + sim_size += 1; } + + // check that btree matches sim + printf("expd: ["); + bool first = true; + for (lfs_size_t i = 0; i < sim_size; i++) { + // calculate actual id in btree space + lfs_size_t weighted_id = 0; + for (lfs_size_t j = 0; j < i; j++) { + weighted_id += sim_weights[j]; + } + + if (!first) { + printf(", "); + } + first = false; + printf("%dw%d=%c", weighted_id+sim_weights[i]-1, + sim_weights[i], sim[i]); + } + printf("]\n"); + printf("btree: w%d 0x%x.%x\n", + btree.weight, + btree.root.block, + btree.root.trunk); + + lfs_size_t total_weight = 0; + for (lfs_size_t j = 0; j < sim_size; j++) { + total_weight += sim_weights[j]; + } + assert(lfsr_btree_weight(&btree) == total_weight); + + uint8_t buffer[4]; + lfsr_tag_t tag_; + lfs_size_t weight_; + for (lfs_size_t i = 0; i < sim_size; i++) { + // calculate actual id in btree space + lfs_size_t weighted_id = 0; + for (lfs_size_t j = 0; j < i; j++) { + weighted_id += sim_weights[j]; + } + + lfsr_btree_get(&lfs, &btree, weighted_id+sim_weights[i]-1, + &tag_, &weight_, buffer, 4) => 1; + assert(tag_ == LFSR_TAG_INLINED); + assert(weight_ == sim_weights[i]); + assert(memcmp(buffer, &sim[i], 1) == 0); + } + + // and no extra elements + lfsr_btree_get(&lfs, &btree, total_weight, + &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 < sim_size; i++) { + // calculate actual id in btree space + lfs_size_t weighted_id = 0; + for (lfs_size_t j = 0; j < i; j++) { + weighted_id += sim_weights[j]; + } + + lfsr_btree_lookupnext(&lfs, &btree, id_+1, + &id_, &tag_, &weight_, &data_) => 0; + assert(id_ == weighted_id+sim_weights[i]-1); + assert(tag_ == LFSR_TAG_INLINED); + assert(weight_ == sim_weights[i]); + + lfsr_data_read(&lfs, data_, 0, buffer, 4) => 1; + assert(memcmp(buffer, &sim[i], 1) == 0); + } + lfsr_btree_lookupnext(&lfs, &btree, id_+1, + &id_, &tag_, &weight_, &data_) => LFS_ERR_NOENT; + + // clean up sim + free(sim); ''' @@ -926,109 +904,99 @@ code = ''' [cases.t2_btree_update_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] defines.SAMPLES = 10 -# -1 => all pseudo-random seeds -# n => reproduce a specific seed -defines.SEED = -1 +defines.SEED = 'range(10)' in = 'lfs.c' code = ''' const char *alphas = "abcdefghijklmnopqrstuvwxyz"; const char *uppers = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - // iterate through severals seeds that we can reproduce easily - for (uint32_t seed = (SEED == -1 ? 1 : SEED); - (SEED == -1 ? seed < SAMPLES+1 : seed == SEED); - seed++) { - printf("--- seed: %d ---\n", seed); - // create lfs here since we need to reset each iteration, we're - // space constrained and we can't expect gc to work at this point - 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); + 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); - // create a btree - lfsr_btree_t btree = LFSR_BTREE_NULL; - for (lfs_size_t i = 0; i < N; i++) { - int err = lfsr_btree_push(&lfs, &btree, i, LFSR_TAG_INLINED, 1, - LFSR_DATA_BUF(&alphas[i % 26], 1)); - // ignore space issues - if (err == LFS_ERR_NOSPC) { - printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); - return; - } - assert(err == 0); + // create a btree + lfsr_btree_t btree = LFSR_BTREE_NULL; + for (lfs_size_t i = 0; i < N; i++) { + int err = lfsr_btree_push(&lfs, &btree, i, LFSR_TAG_INLINED, 1, + LFSR_DATA_BUF(&alphas[i % 26], 1)); + // ignore space issues + if (err == LFS_ERR_NOSPC) { + printf("btree: w%d 0x%x.%x\n", + btree.weight, + btree.root.block, + btree.root.trunk); + return; } - - // set up a simulation to compare against - // - // fun fact this is slower than our actual tree! unfun fact this is - // starting to be a problem... - char *sim = malloc(N); - for (lfs_size_t i = 0; i < N; i++) { - sim[i] = alphas[i % 26]; - } - - uint32_t prng = seed; - for (lfs_size_t i = 0; i < N; i++) { - // choose a pseudo-random id - lfs_size_t id = TEST_PRNG(&prng) % N; - - // update btree - int err = lfsr_btree_set(&lfs, &btree, id, LFSR_TAG_INLINED, 1, - LFSR_DATA_BUF(&uppers[i % 26], 1)); - // ignore space issues - if (err == LFS_ERR_NOSPC) { - break; - } - assert(err == 0); - - // update sim - sim[id] = uppers[i % 26]; - } - - // check that btree matches sim - printf("expd: ["); - bool first = true; - for (lfs_size_t i = 0; i < N; i++) { - if (!first) { - printf(", "); - } - first = false; - printf("%c", sim[i]); - } - printf("]\n"); - printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); - assert(lfsr_btree_weight(&btree) == N); - - uint8_t buffer[4]; - lfsr_tag_t tag_; - lfs_size_t weight_; - for (lfs_size_t i = 0; i < N; i++) { - lfsr_btree_get(&lfs, &btree, i, - &tag_, &weight_, buffer, 4) => 1; - assert(tag_ == LFSR_TAG_INLINED); - assert(weight_ == 1); - assert(memcmp(buffer, &sim[i], 1) == 0); - } - - // and no extra elements - lfsr_btree_get(&lfs, &btree, N, - &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; - - // clean up sim - free(sim); + assert(err == 0); } + + // set up a simulation to compare against + // + // fun fact this is slower than our actual tree! unfun fact this is + // starting to be a problem... + char *sim = malloc(N); + for (lfs_size_t i = 0; i < N; i++) { + sim[i] = alphas[i % 26]; + } + + uint32_t prng = SEED; + for (lfs_size_t i = 0; i < N; i++) { + // choose a pseudo-random id + lfs_size_t id = TEST_PRNG(&prng) % N; + + // update btree + int err = lfsr_btree_set(&lfs, &btree, id, LFSR_TAG_INLINED, 1, + LFSR_DATA_BUF(&uppers[i % 26], 1)); + // ignore space issues + if (err == LFS_ERR_NOSPC) { + break; + } + assert(err == 0); + + // update sim + sim[id] = uppers[i % 26]; + } + + // check that btree matches sim + printf("expd: ["); + bool first = true; + for (lfs_size_t i = 0; i < N; i++) { + if (!first) { + printf(", "); + } + first = false; + printf("%c", sim[i]); + } + printf("]\n"); + printf("btree: w%d 0x%x.%x\n", + btree.weight, + btree.root.block, + btree.root.trunk); + assert(lfsr_btree_weight(&btree) == N); + + uint8_t buffer[4]; + lfsr_tag_t tag_; + lfs_size_t weight_; + for (lfs_size_t i = 0; i < N; i++) { + lfsr_btree_get(&lfs, &btree, i, + &tag_, &weight_, buffer, 4) => 1; + assert(tag_ == LFSR_TAG_INLINED); + assert(weight_ == 1); + assert(memcmp(buffer, &sim[i], 1) == 0); + } + + // and no extra elements + lfsr_btree_get(&lfs, &btree, N, + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; + + // clean up sim + free(sim); ''' [cases.t2_btree_update_sparse] @@ -1120,162 +1088,151 @@ code = ''' [cases.t2_btree_update_sparse_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] defines.W = 5 -defines.SAMPLES = 10 -# -1 => all pseudo-random seeds -# n => reproduce a specific seed -defines.SEED = -1 +defines.SEED = 'range(10)' in = 'lfs.c' code = ''' const char *alphas = "abcdefghijklmnopqrstuvwxyz"; const char *uppers = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - // iterate through severals seeds that we can reproduce easily - for (uint32_t seed = (SEED == -1 ? 1 : SEED); - (SEED == -1 ? seed < SAMPLES+1 : seed == SEED); - seed++) { - printf("--- seed: %d ---\n", seed); - // create lfs here since we need to reset each iteration, we're - // space constrained and we can't expect gc to work at this point - 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); + 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); - // create a btree - lfsr_btree_t btree = LFSR_BTREE_NULL; - for (lfs_size_t i = 0; i < N; i++) { - int err = lfsr_btree_push(&lfs, &btree, i*W, LFSR_TAG_INLINED, W, - LFSR_DATA_BUF(&alphas[i % 26], 1)); - // ignore space issues - if (err == LFS_ERR_NOSPC) { - printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); - return; - } - assert(err == 0); + // create a btree + lfsr_btree_t btree = LFSR_BTREE_NULL; + for (lfs_size_t i = 0; i < N; i++) { + int err = lfsr_btree_push(&lfs, &btree, i*W, LFSR_TAG_INLINED, W, + LFSR_DATA_BUF(&alphas[i % 26], 1)); + // ignore space issues + if (err == LFS_ERR_NOSPC) { + printf("btree: w%d 0x%x.%x\n", + btree.weight, + btree.root.block, + btree.root.trunk); + return; } - - // set up a simulation to compare against - // - // fun fact this is slower than our actual tree! unfun fact this is - // starting to be a problem... - char *sim = malloc(N); - lfs_size_t *sim_weights = malloc(N*sizeof(lfs_size_t)); - for (lfs_size_t i = 0; i < N; i++) { - sim[i] = alphas[i % 26]; - sim_weights[i] = W; - } - - uint32_t prng = seed; - for (lfs_size_t i = 0; i < N; i++) { - // choose a pseudo-random id - lfs_size_t id = TEST_PRNG(&prng) % N; - // choose a pseudo-random weight - lfs_size_t weight = 1 + (TEST_PRNG(&prng) % W); - - // calculate actual id in btree space - lfs_size_t weighted_id = 0; - for (lfs_size_t j = 0; j < id; j++) { - weighted_id += sim_weights[j]; - } - - // update btree - int err = lfsr_btree_set(&lfs, &btree, - weighted_id+sim_weights[id]-1, LFSR_TAG_INLINED, weight, - LFSR_DATA_BUF(&uppers[i % 26], 1)); - // ignore space issues - if (err == LFS_ERR_NOSPC) { - break; - } - assert(err == 0); - - // update sim - sim[id] = uppers[i % 26]; - sim_weights[id] = weight; - } - - // check that btree matches sim - printf("expd: ["); - bool first = true; - for (lfs_size_t i = 0; i < N; i++) { - // calculate actual id in btree space - lfs_size_t weighted_id = 0; - for (lfs_size_t j = 0; j < i; j++) { - weighted_id += sim_weights[j]; - } - - if (!first) { - printf(", "); - } - first = false; - printf("%dw%d=%c", weighted_id+sim_weights[i]-1, - sim_weights[i], sim[i]); - } - printf("]\n"); - printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); - - lfs_size_t total_weight = 0; - for (lfs_size_t j = 0; j < N; j++) { - total_weight += sim_weights[j]; - } - assert(lfsr_btree_weight(&btree) == total_weight); - - uint8_t buffer[4]; - lfsr_tag_t tag_; - lfs_size_t weight_; - for (lfs_size_t i = 0; i < N; i++) { - // calculate actual id in btree space - lfs_size_t weighted_id = 0; - for (lfs_size_t j = 0; j < i; j++) { - weighted_id += sim_weights[j]; - } - - lfsr_btree_get(&lfs, &btree, weighted_id+sim_weights[i]-1, - &tag_, &weight_, buffer, 4) => 1; - assert(tag_ == LFSR_TAG_INLINED); - assert(weight_ == sim_weights[i]); - assert(memcmp(buffer, &sim[i], 1) == 0); - } - - // and no extra elements - lfsr_btree_get(&lfs, &btree, total_weight, - &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++) { - // calculate actual id in btree space - lfs_size_t weighted_id = 0; - for (lfs_size_t j = 0; j < i; j++) { - weighted_id += sim_weights[j]; - } - - lfsr_btree_lookupnext(&lfs, &btree, id_+1, - &id_, &tag_, &weight_, &data_) => 0; - assert(id_ == weighted_id+sim_weights[i]-1); - assert(tag_ == LFSR_TAG_INLINED); - assert(weight_ == sim_weights[i]); - - lfsr_data_read(&lfs, data_, 0, buffer, 4) => 1; - assert(memcmp(buffer, &sim[i], 1) == 0); - } - lfsr_btree_lookupnext(&lfs, &btree, id_+1, - &id_, &tag_, &weight_, &data_) => LFS_ERR_NOENT; - - // clean up sim - free(sim); + assert(err == 0); } + + // set up a simulation to compare against + // + // fun fact this is slower than our actual tree! unfun fact this is + // starting to be a problem... + char *sim = malloc(N); + lfs_size_t *sim_weights = malloc(N*sizeof(lfs_size_t)); + for (lfs_size_t i = 0; i < N; i++) { + sim[i] = alphas[i % 26]; + sim_weights[i] = W; + } + + uint32_t prng = SEED; + for (lfs_size_t i = 0; i < N; i++) { + // choose a pseudo-random id + lfs_size_t id = TEST_PRNG(&prng) % N; + // choose a pseudo-random weight + lfs_size_t weight = 1 + (TEST_PRNG(&prng) % W); + + // calculate actual id in btree space + lfs_size_t weighted_id = 0; + for (lfs_size_t j = 0; j < id; j++) { + weighted_id += sim_weights[j]; + } + + // update btree + int err = lfsr_btree_set(&lfs, &btree, + weighted_id+sim_weights[id]-1, LFSR_TAG_INLINED, weight, + LFSR_DATA_BUF(&uppers[i % 26], 1)); + // ignore space issues + if (err == LFS_ERR_NOSPC) { + break; + } + assert(err == 0); + + // update sim + sim[id] = uppers[i % 26]; + sim_weights[id] = weight; + } + + // check that btree matches sim + printf("expd: ["); + bool first = true; + for (lfs_size_t i = 0; i < N; i++) { + // calculate actual id in btree space + lfs_size_t weighted_id = 0; + for (lfs_size_t j = 0; j < i; j++) { + weighted_id += sim_weights[j]; + } + + if (!first) { + printf(", "); + } + first = false; + printf("%dw%d=%c", weighted_id+sim_weights[i]-1, + sim_weights[i], sim[i]); + } + printf("]\n"); + printf("btree: w%d 0x%x.%x\n", + btree.weight, + btree.root.block, + btree.root.trunk); + + lfs_size_t total_weight = 0; + for (lfs_size_t j = 0; j < N; j++) { + total_weight += sim_weights[j]; + } + assert(lfsr_btree_weight(&btree) == total_weight); + + uint8_t buffer[4]; + lfsr_tag_t tag_; + lfs_size_t weight_; + for (lfs_size_t i = 0; i < N; i++) { + // calculate actual id in btree space + lfs_size_t weighted_id = 0; + for (lfs_size_t j = 0; j < i; j++) { + weighted_id += sim_weights[j]; + } + + lfsr_btree_get(&lfs, &btree, weighted_id+sim_weights[i]-1, + &tag_, &weight_, buffer, 4) => 1; + assert(tag_ == LFSR_TAG_INLINED); + assert(weight_ == sim_weights[i]); + assert(memcmp(buffer, &sim[i], 1) == 0); + } + + // and no extra elements + lfsr_btree_get(&lfs, &btree, total_weight, + &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++) { + // calculate actual id in btree space + lfs_size_t weighted_id = 0; + for (lfs_size_t j = 0; j < i; j++) { + weighted_id += sim_weights[j]; + } + + lfsr_btree_lookupnext(&lfs, &btree, id_+1, + &id_, &tag_, &weight_, &data_) => 0; + assert(id_ == weighted_id+sim_weights[i]-1); + assert(tag_ == LFSR_TAG_INLINED); + assert(weight_ == sim_weights[i]); + + lfsr_data_read(&lfs, data_, 0, buffer, 4) => 1; + assert(memcmp(buffer, &sim[i], 1) == 0); + } + lfsr_btree_lookupnext(&lfs, &btree, id_+1, + &id_, &tag_, &weight_, &data_) => LFS_ERR_NOENT; + + // clean up sim + free(sim); ''' @@ -1735,111 +1692,100 @@ code = ''' [cases.t2_btree_pop_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] defines.REMAINING = [64, 2, 1, 0] -defines.SAMPLES = 10 -# -1 => all pseudo-random seeds -# n => reproduce a specific seed -defines.SEED = -1 +defines.SEED = 'range(10)' if = 'N > REMAINING' in = 'lfs.c' code = ''' const char *alphas = "abcdefghijklmnopqrstuvwxyz"; - // iterate through severals seeds that we can reproduce easily - for (uint32_t seed = (SEED == -1 ? 1 : SEED); - (SEED == -1 ? seed < SAMPLES+1 : seed == SEED); - seed++) { - printf("--- seed: %d ---\n", seed); - // create lfs here since we need to reset each iteration, we're - // space constrained and we can't expect gc to work at this point - 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); + 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); - // create a btree - lfsr_btree_t btree = LFSR_BTREE_NULL; - for (lfs_size_t i = 0; i < N; i++) { - int err = lfsr_btree_push(&lfs, &btree, i, LFSR_TAG_INLINED, 1, - LFSR_DATA_BUF(&alphas[i % 26], 1)); - // ignore space issues - if (err == LFS_ERR_NOSPC) { - printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); - return; - } - assert(err == 0); + // create a btree + lfsr_btree_t btree = LFSR_BTREE_NULL; + for (lfs_size_t i = 0; i < N; i++) { + int err = lfsr_btree_push(&lfs, &btree, i, LFSR_TAG_INLINED, 1, + LFSR_DATA_BUF(&alphas[i % 26], 1)); + // ignore space issues + if (err == LFS_ERR_NOSPC) { + printf("btree: w%d 0x%x.%x\n", + btree.weight, + btree.root.block, + btree.root.trunk); + return; } - - // set up a simulation to compare against - // - // fun fact this is slower than our actual tree! unfun fact this is - // starting to be a problem... - char *sim = malloc(N); - lfs_size_t sim_size = N; - for (lfs_size_t i = 0; i < N; i++) { - sim[i] = alphas[i % 26]; - } - - uint32_t prng = seed; - for (lfs_size_t i = 0; i < (N-REMAINING); i++) { - // choose a pseudo-random id - lfs_size_t id = TEST_PRNG(&prng) % sim_size; - - // remove from btree - int err = lfsr_btree_pop(&lfs, &btree, id); - // ignore space issues - if (err == LFS_ERR_NOSPC) { - break; - } - assert(err == 0); - - // remove from sim - memmove(&sim[id], &sim[id+1], sim_size-(id+1)); - sim_size -= 1; - } - - // check that btree matches sim - printf("expd: ["); - bool first = true; - for (lfs_size_t i = 0; i < sim_size; i++) { - if (!first) { - printf(", "); - } - first = false; - printf("%c", sim[i]); - } - printf("]\n"); - printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); - assert(lfsr_btree_weight(&btree) == sim_size); - - uint8_t buffer[4]; - lfsr_tag_t tag_; - lfs_size_t weight_; - for (lfs_size_t i = 0; i < sim_size; i++) { - lfsr_btree_get(&lfs, &btree, i, - &tag_, &weight_, buffer, 4) => 1; - assert(tag_ == LFSR_TAG_INLINED); - assert(weight_ == 1); - assert(memcmp(buffer, &sim[i], 1) == 0); - } - - // and no extra elements - lfsr_btree_get(&lfs, &btree, sim_size, - &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; - - // clean up sim - free(sim); + assert(err == 0); } + + // set up a simulation to compare against + // + // fun fact this is slower than our actual tree! unfun fact this is + // starting to be a problem... + char *sim = malloc(N); + lfs_size_t sim_size = N; + for (lfs_size_t i = 0; i < N; i++) { + sim[i] = alphas[i % 26]; + } + + uint32_t prng = SEED; + for (lfs_size_t i = 0; i < (N-REMAINING); i++) { + // choose a pseudo-random id + lfs_size_t id = TEST_PRNG(&prng) % sim_size; + + // remove from btree + int err = lfsr_btree_pop(&lfs, &btree, id); + // ignore space issues + if (err == LFS_ERR_NOSPC) { + break; + } + assert(err == 0); + + // remove from sim + memmove(&sim[id], &sim[id+1], sim_size-(id+1)); + sim_size -= 1; + } + + // check that btree matches sim + printf("expd: ["); + bool first = true; + for (lfs_size_t i = 0; i < sim_size; i++) { + if (!first) { + printf(", "); + } + first = false; + printf("%c", sim[i]); + } + printf("]\n"); + printf("btree: w%d 0x%x.%x\n", + btree.weight, + btree.root.block, + btree.root.trunk); + assert(lfsr_btree_weight(&btree) == sim_size); + + uint8_t buffer[4]; + lfsr_tag_t tag_; + lfs_size_t weight_; + for (lfs_size_t i = 0; i < sim_size; i++) { + lfsr_btree_get(&lfs, &btree, i, + &tag_, &weight_, buffer, 4) => 1; + assert(tag_ == LFSR_TAG_INLINED); + assert(weight_ == 1); + assert(memcmp(buffer, &sim[i], 1) == 0); + } + + // and no extra elements + lfsr_btree_get(&lfs, &btree, sim_size, + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; + + // clean up sim + free(sim); ''' [cases.t2_btree_pop_sparse] @@ -1963,174 +1909,163 @@ code = ''' defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] defines.W = 5 defines.REMAINING = [64, 2, 1, 0] -defines.SAMPLES = 10 -# -1 => all pseudo-random seeds -# n => reproduce a specific seed -defines.SEED = -1 +defines.SEED = 'range(10)' if = 'N > REMAINING' in = 'lfs.c' code = ''' const char *alphas = "abcdefghijklmnopqrstuvwxyz"; - // iterate through severals seeds that we can reproduce easily - for (uint32_t seed = (SEED == -1 ? 1 : SEED); - (SEED == -1 ? seed < SAMPLES+1 : seed == SEED); - seed++) { - printf("--- seed: %d ---\n", seed); - // create lfs here since we need to reset each iteration, we're - // space constrained and we can't expect gc to work at this point - 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); + 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); - // create a btree - lfsr_btree_t btree = LFSR_BTREE_NULL; + // create a btree + lfsr_btree_t btree = LFSR_BTREE_NULL; - // set up a simulation to compare against - // - // fun fact this is slower than our actual tree! unfun fact this is - // starting to be a problem... - char *sim = malloc(N); - lfs_size_t *sim_weights = malloc(N*sizeof(lfs_size_t)); - lfs_size_t sim_size = 0; + // set up a simulation to compare against + // + // fun fact this is slower than our actual tree! unfun fact this is + // starting to be a problem... + char *sim = malloc(N); + lfs_size_t *sim_weights = malloc(N*sizeof(lfs_size_t)); + lfs_size_t sim_size = 0; - // set up simulation and btree with pseudo-random weights - uint32_t prng = seed; - for (lfs_size_t i = 0; i < N; i++) { - // choose a pseudo-random weight - lfs_size_t weight = 1 + (TEST_PRNG(&prng) % W); + // set up simulation and btree with pseudo-random weights + uint32_t prng = SEED; + for (lfs_size_t i = 0; i < N; i++) { + // choose a pseudo-random weight + lfs_size_t weight = 1 + (TEST_PRNG(&prng) % W); - // calculate actual id in btree space - lfs_size_t weighted_id = 0; - for (lfs_size_t j = 0; j < i; j++) { - weighted_id += sim_weights[j]; - } - - int err = lfsr_btree_push(&lfs, &btree, - weighted_id, LFSR_TAG_INLINED, weight, - LFSR_DATA_BUF(&alphas[i % 26], 1)); - // ignore space issues - if (err == LFS_ERR_NOSPC) { - printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); - return; - } - assert(err == 0); - - sim[i] = alphas[i % 26]; - sim_weights[i] = weight; - sim_size += 1; + // calculate actual id in btree space + lfs_size_t weighted_id = 0; + for (lfs_size_t j = 0; j < i; j++) { + weighted_id += sim_weights[j]; } - for (lfs_size_t i = 0; i < (N-REMAINING); i++) { - // choose a pseudo-random id - lfs_size_t id = TEST_PRNG(&prng) % sim_size; - - // calculate actual id in btree space - lfs_size_t weighted_id = 0; - for (lfs_size_t j = 0; j < id; j++) { - weighted_id += sim_weights[j]; - } - - // remove from btree - int err = lfsr_btree_pop(&lfs, &btree, - weighted_id+sim_weights[id]-1); - // ignore space issues - if (err == LFS_ERR_NOSPC) { - break; - } - assert(err == 0); - - // remove from sim - memmove(&sim[id], &sim[id+1], sim_size-(id+1)); - memmove(&sim_weights[id], &sim_weights[id+1], - (sim_size-(id+1))*sizeof(lfs_size_t)); - sim_size -= 1; + int err = lfsr_btree_push(&lfs, &btree, + weighted_id, LFSR_TAG_INLINED, weight, + LFSR_DATA_BUF(&alphas[i % 26], 1)); + // ignore space issues + if (err == LFS_ERR_NOSPC) { + printf("btree: w%d 0x%x.%x\n", + btree.weight, + btree.root.block, + btree.root.trunk); + return; } + assert(err == 0); - // check that btree matches sim - printf("expd: ["); - bool first = true; - for (lfs_size_t i = 0; i < sim_size; i++) { - // calculate actual id in btree space - lfs_size_t weighted_id = 0; - for (lfs_size_t j = 0; j < i; j++) { - weighted_id += sim_weights[j]; - } - - if (!first) { - printf(", "); - } - first = false; - printf("%dw%d=%c", weighted_id+sim_weights[i]-1, - sim_weights[i], sim[i]); - } - printf("]\n"); - printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); - - lfs_size_t total_weight = 0; - for (lfs_size_t j = 0; j < sim_size; j++) { - total_weight += sim_weights[j]; - } - assert(lfsr_btree_weight(&btree) == total_weight); - - uint8_t buffer[4]; - lfsr_tag_t tag_; - lfs_size_t weight_; - for (lfs_size_t i = 0; i < sim_size; i++) { - // calculate actual id in btree space - lfs_size_t weighted_id = 0; - for (lfs_size_t j = 0; j < i; j++) { - weighted_id += sim_weights[j]; - } - - lfsr_btree_get(&lfs, &btree, weighted_id+sim_weights[i]-1, - &tag_, &weight_, buffer, 4) => 1; - assert(tag_ == LFSR_TAG_INLINED); - assert(weight_ == sim_weights[i]); - assert(memcmp(buffer, &sim[i], 1) == 0); - } - - // and no extra elements - lfsr_btree_get(&lfs, &btree, total_weight, - &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 < sim_size; i++) { - // calculate actual id in btree space - lfs_size_t weighted_id = 0; - for (lfs_size_t j = 0; j < i; j++) { - weighted_id += sim_weights[j]; - } - - lfsr_btree_lookupnext(&lfs, &btree, id_+1, - &id_, &tag_, &weight_, &data_) => 0; - assert(id_ == weighted_id+sim_weights[i]-1); - assert(tag_ == LFSR_TAG_INLINED); - assert(weight_ == sim_weights[i]); - - lfsr_data_read(&lfs, data_, 0, buffer, 4) => 1; - assert(memcmp(buffer, &sim[i], 1) == 0); - } - lfsr_btree_lookupnext(&lfs, &btree, id_+1, - &id_, &tag_, &weight_, &data_) => LFS_ERR_NOENT; - - // clean up sim - free(sim); + sim[i] = alphas[i % 26]; + sim_weights[i] = weight; + sim_size += 1; } + + for (lfs_size_t i = 0; i < (N-REMAINING); i++) { + // choose a pseudo-random id + lfs_size_t id = TEST_PRNG(&prng) % sim_size; + + // calculate actual id in btree space + lfs_size_t weighted_id = 0; + for (lfs_size_t j = 0; j < id; j++) { + weighted_id += sim_weights[j]; + } + + // remove from btree + int err = lfsr_btree_pop(&lfs, &btree, + weighted_id+sim_weights[id]-1); + // ignore space issues + if (err == LFS_ERR_NOSPC) { + break; + } + assert(err == 0); + + // remove from sim + memmove(&sim[id], &sim[id+1], sim_size-(id+1)); + memmove(&sim_weights[id], &sim_weights[id+1], + (sim_size-(id+1))*sizeof(lfs_size_t)); + sim_size -= 1; + } + + // check that btree matches sim + printf("expd: ["); + bool first = true; + for (lfs_size_t i = 0; i < sim_size; i++) { + // calculate actual id in btree space + lfs_size_t weighted_id = 0; + for (lfs_size_t j = 0; j < i; j++) { + weighted_id += sim_weights[j]; + } + + if (!first) { + printf(", "); + } + first = false; + printf("%dw%d=%c", weighted_id+sim_weights[i]-1, + sim_weights[i], sim[i]); + } + printf("]\n"); + printf("btree: w%d 0x%x.%x\n", + btree.weight, + btree.root.block, + btree.root.trunk); + + lfs_size_t total_weight = 0; + for (lfs_size_t j = 0; j < sim_size; j++) { + total_weight += sim_weights[j]; + } + assert(lfsr_btree_weight(&btree) == total_weight); + + uint8_t buffer[4]; + lfsr_tag_t tag_; + lfs_size_t weight_; + for (lfs_size_t i = 0; i < sim_size; i++) { + // calculate actual id in btree space + lfs_size_t weighted_id = 0; + for (lfs_size_t j = 0; j < i; j++) { + weighted_id += sim_weights[j]; + } + + lfsr_btree_get(&lfs, &btree, weighted_id+sim_weights[i]-1, + &tag_, &weight_, buffer, 4) => 1; + assert(tag_ == LFSR_TAG_INLINED); + assert(weight_ == sim_weights[i]); + assert(memcmp(buffer, &sim[i], 1) == 0); + } + + // and no extra elements + lfsr_btree_get(&lfs, &btree, total_weight, + &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 < sim_size; i++) { + // calculate actual id in btree space + lfs_size_t weighted_id = 0; + for (lfs_size_t j = 0; j < i; j++) { + weighted_id += sim_weights[j]; + } + + lfsr_btree_lookupnext(&lfs, &btree, id_+1, + &id_, &tag_, &weight_, &data_) => 0; + assert(id_ == weighted_id+sim_weights[i]-1); + assert(tag_ == LFSR_TAG_INLINED); + assert(weight_ == sim_weights[i]); + + lfsr_data_read(&lfs, data_, 0, buffer, 4) => 1; + assert(memcmp(buffer, &sim[i], 1) == 0); + } + lfsr_btree_lookupnext(&lfs, &btree, id_+1, + &id_, &tag_, &weight_, &data_) => LFS_ERR_NOENT; + + // clean up sim + free(sim); ''' @@ -2192,104 +2127,93 @@ code = ''' [cases.t2_btree_split_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] -defines.SAMPLES = 10 -# -1 => all pseudo-random seeds -# n => reproduce a specific seed -defines.SEED = -1 +defines.SEED = 'range(10)' in = 'lfs.c' code = ''' const char *alphas = "abcdefghijklmnopqrstuvwxyz"; const char *uppers = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - // iterate through severals seeds that we can reproduce easily - for (uint32_t seed = (SEED == -1 ? 1 : SEED); - (SEED == -1 ? seed < SAMPLES+1 : seed == SEED); - seed++) { - printf("--- seed: %d ---\n", seed); - // create lfs here since we need to reset each iteration, we're - // space constrained and we can't expect gc to work at this point - 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); + 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); - // create a btree - lfsr_btree_t btree = LFSR_BTREE_NULL; - lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, 1, - LFSR_DATA_BUF("_", 1)) => 0; + // create a btree + lfsr_btree_t btree = LFSR_BTREE_NULL; + lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, 1, + LFSR_DATA_BUF("_", 1)) => 0; - // set up a simulation to compare against - // - // fun fact this is slower than our actual tree! unfun fact this is - // starting to be a problem... - char *sim = malloc(N); - lfs_size_t sim_size = 1; - memset(sim, 0, N); - sim[0] = '_'; + // set up a simulation to compare against + // + // fun fact this is slower than our actual tree! unfun fact this is + // starting to be a problem... + char *sim = malloc(N); + lfs_size_t sim_size = 1; + memset(sim, 0, N); + sim[0] = '_'; - uint32_t prng = seed; - for (lfs_size_t i = 1; i < N; i++) { - // choose a pseudo-random id - lfs_size_t id = TEST_PRNG(&prng) % sim_size; + uint32_t prng = SEED; + for (lfs_size_t i = 1; i < N; i++) { + // choose a pseudo-random id + lfs_size_t id = TEST_PRNG(&prng) % sim_size; - // split btree - int err = lfsr_btree_split(&lfs, &btree, id, LFSR_DATA_NULL, - LFSR_TAG_INLINED, 1, LFSR_DATA_BUF(&alphas[i % 26], 1), - LFSR_TAG_INLINED, 1, LFSR_DATA_BUF(&uppers[i % 26], 1)); - // ignore space issues - if (err == LFS_ERR_NOSPC) { - break; - } - assert(err == 0); - - // split sim - memmove(&sim[id+1], &sim[id], sim_size-id); - sim[id+0] = alphas[i % 26]; - sim[id+1] = uppers[i % 26]; - sim_size += 1; + // split btree + int err = lfsr_btree_split(&lfs, &btree, id, LFSR_DATA_NULL, + LFSR_TAG_INLINED, 1, LFSR_DATA_BUF(&alphas[i % 26], 1), + LFSR_TAG_INLINED, 1, LFSR_DATA_BUF(&uppers[i % 26], 1)); + // ignore space issues + if (err == LFS_ERR_NOSPC) { + break; } + assert(err == 0); - // check that btree matches sim - printf("expd: ["); - bool first = true; - for (lfs_size_t i = 0; i < sim_size; i++) { - if (!first) { - printf(", "); - } - first = false; - printf("%c", sim[i]); - } - printf("]\n"); - printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); - assert(lfsr_btree_weight(&btree) == sim_size); - - uint8_t buffer[4]; - lfsr_tag_t tag_; - lfs_size_t weight_; - for (lfs_size_t i = 0; i < sim_size; i++) { - lfsr_btree_get(&lfs, &btree, i, - &tag_, &weight_, buffer, 4) => 1; - assert(tag_ == LFSR_TAG_INLINED); - assert(weight_ == 1); - assert(memcmp(buffer, &sim[i], 1) == 0); - } - - // and no extra elements - lfsr_btree_get(&lfs, &btree, sim_size, - &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; - - // clean up sim - free(sim); - lfs_deinit(&lfs) => 0; + // split sim + memmove(&sim[id+1], &sim[id], sim_size-id); + sim[id+0] = alphas[i % 26]; + sim[id+1] = uppers[i % 26]; + sim_size += 1; } + + // check that btree matches sim + printf("expd: ["); + bool first = true; + for (lfs_size_t i = 0; i < sim_size; i++) { + if (!first) { + printf(", "); + } + first = false; + printf("%c", sim[i]); + } + printf("]\n"); + printf("btree: w%d 0x%x.%x\n", + btree.weight, + btree.root.block, + btree.root.trunk); + assert(lfsr_btree_weight(&btree) == sim_size); + + uint8_t buffer[4]; + lfsr_tag_t tag_; + lfs_size_t weight_; + for (lfs_size_t i = 0; i < sim_size; i++) { + lfsr_btree_get(&lfs, &btree, i, + &tag_, &weight_, buffer, 4) => 1; + assert(tag_ == LFSR_TAG_INLINED); + assert(weight_ == 1); + assert(memcmp(buffer, &sim[i], 1) == 0); + } + + // and no extra elements + lfsr_btree_get(&lfs, &btree, sim_size, + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; + + // clean up sim + free(sim); + lfs_deinit(&lfs) => 0; ''' [cases.t2_btree_split_sparse] @@ -2351,162 +2275,151 @@ code = ''' [cases.t2_btree_split_sparse_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] defines.W = 5 -defines.SAMPLES = 10 -# -1 => all pseudo-random seeds -# n => reproduce a specific seed -defines.SEED = -1 +defines.SEED = 'range(10)' in = 'lfs.c' code = ''' const char *alphas = "abcdefghijklmnopqrstuvwxyz"; const char *uppers = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - // iterate through severals seeds that we can reproduce easily - for (uint32_t seed = (SEED == -1 ? 1 : SEED); - (SEED == -1 ? seed < SAMPLES+1 : seed == SEED); - seed++) { - printf("--- seed: %d ---\n", seed); - // create lfs here since we need to reset each iteration, we're - // space constrained and we can't expect gc to work at this point - 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); + 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); - // create a btree - lfsr_btree_t btree = LFSR_BTREE_NULL; - lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, W, - LFSR_DATA_BUF("_", 1)) => 0; + // create a btree + lfsr_btree_t btree = LFSR_BTREE_NULL; + lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, W, + LFSR_DATA_BUF("_", 1)) => 0; - // set up a simulation to compare against - // - // fun fact this is slower than our actual tree! unfun fact this is - // starting to be a problem... - char *sim = malloc(N); - lfs_size_t *sim_weights = malloc(N*sizeof(lfs_size_t)); - lfs_size_t sim_size = 1; - memset(sim, 0, N); - memset(sim_weights, 0, N*sizeof(lfs_size_t)); - sim[0] = '_'; - sim_weights[0] = W; + // set up a simulation to compare against + // + // fun fact this is slower than our actual tree! unfun fact this is + // starting to be a problem... + char *sim = malloc(N); + lfs_size_t *sim_weights = malloc(N*sizeof(lfs_size_t)); + lfs_size_t sim_size = 1; + memset(sim, 0, N); + memset(sim_weights, 0, N*sizeof(lfs_size_t)); + sim[0] = '_'; + sim_weights[0] = W; - uint32_t prng = seed; - for (lfs_size_t i = 1; i < N; i++) { - // choose a pseudo-random id - lfs_size_t id = TEST_PRNG(&prng) % sim_size; - // choose pseudo-random weights - lfs_size_t weight1 = 1 + (TEST_PRNG(&prng) % W); - lfs_size_t weight2 = 1 + (TEST_PRNG(&prng) % W); + uint32_t prng = SEED; + for (lfs_size_t i = 1; i < N; i++) { + // choose a pseudo-random id + lfs_size_t id = TEST_PRNG(&prng) % sim_size; + // choose pseudo-random weights + lfs_size_t weight1 = 1 + (TEST_PRNG(&prng) % W); + lfs_size_t weight2 = 1 + (TEST_PRNG(&prng) % W); - // calculate actual id in btree space - lfs_size_t weighted_id = 0; - for (lfs_size_t j = 0; j < id; j++) { - weighted_id += sim_weights[j]; - } - - // split btree - int err = lfsr_btree_split(&lfs, &btree, - weighted_id+sim_weights[id]-1, LFSR_DATA_NULL, - LFSR_TAG_INLINED, weight1, - LFSR_DATA_BUF(&alphas[i % 26], 1), - LFSR_TAG_INLINED, weight2, - LFSR_DATA_BUF(&uppers[i % 26], 1)); - // ignore space issues - if (err == LFS_ERR_NOSPC) { - break; - } - assert(err == 0); - - // add to sim - memmove(&sim[id+1], &sim[id], sim_size-id); - memmove(&sim_weights[id+1], &sim_weights[id], - (sim_size-id)*sizeof(lfs_size_t)); - sim[id+0] = alphas[i % 26]; - sim[id+1] = uppers[i % 26]; - sim_weights[id+0] = weight1; - sim_weights[id+1] = weight2; - sim_size += 1; + // calculate actual id in btree space + lfs_size_t weighted_id = 0; + for (lfs_size_t j = 0; j < id; j++) { + weighted_id += sim_weights[j]; } - // check that btree matches sim - printf("expd: ["); - bool first = true; - for (lfs_size_t i = 0; i < sim_size; i++) { - // calculate actual id in btree space - lfs_size_t weighted_id = 0; - for (lfs_size_t j = 0; j < i; j++) { - weighted_id += sim_weights[j]; - } - - if (!first) { - printf(", "); - } - first = false; - printf("%dw%d=%c", weighted_id+sim_weights[i]-1, - sim_weights[i], sim[i]); + // split btree + int err = lfsr_btree_split(&lfs, &btree, + weighted_id+sim_weights[id]-1, LFSR_DATA_NULL, + LFSR_TAG_INLINED, weight1, + LFSR_DATA_BUF(&alphas[i % 26], 1), + LFSR_TAG_INLINED, weight2, + LFSR_DATA_BUF(&uppers[i % 26], 1)); + // ignore space issues + if (err == LFS_ERR_NOSPC) { + break; } - printf("]\n"); - printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + assert(err == 0); - lfs_size_t total_weight = 0; - for (lfs_size_t j = 0; j < sim_size; j++) { - total_weight += sim_weights[j]; - } - assert(lfsr_btree_weight(&btree) == total_weight); - - uint8_t buffer[4]; - lfsr_tag_t tag_; - lfs_size_t weight_; - for (lfs_size_t i = 0; i < sim_size; i++) { - // calculate actual id in btree space - lfs_size_t weighted_id = 0; - for (lfs_size_t j = 0; j < i; j++) { - weighted_id += sim_weights[j]; - } - - lfsr_btree_get(&lfs, &btree, weighted_id+sim_weights[i]-1, - &tag_, &weight_, buffer, 4) => 1; - assert(tag_ == LFSR_TAG_INLINED); - assert(weight_ == sim_weights[i]); - assert(memcmp(buffer, &sim[i], 1) == 0); - } - - // and no extra elements - lfsr_btree_get(&lfs, &btree, total_weight, - &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 < sim_size; i++) { - // calculate actual id in btree space - lfs_size_t weighted_id = 0; - for (lfs_size_t j = 0; j < i; j++) { - weighted_id += sim_weights[j]; - } - - lfsr_btree_lookupnext(&lfs, &btree, id_+1, - &id_, &tag_, &weight_, &data_) => 0; - assert(id_ == weighted_id+sim_weights[i]-1); - assert(tag_ == LFSR_TAG_INLINED); - assert(weight_ == sim_weights[i]); - - lfsr_data_read(&lfs, data_, 0, buffer, 4) => 1; - assert(memcmp(buffer, &sim[i], 1) == 0); - } - lfsr_btree_lookupnext(&lfs, &btree, id_+1, - &id_, &tag_, &weight_, &data_) => LFS_ERR_NOENT; - - // clean up sim - free(sim); + // add to sim + memmove(&sim[id+1], &sim[id], sim_size-id); + memmove(&sim_weights[id+1], &sim_weights[id], + (sim_size-id)*sizeof(lfs_size_t)); + sim[id+0] = alphas[i % 26]; + sim[id+1] = uppers[i % 26]; + sim_weights[id+0] = weight1; + sim_weights[id+1] = weight2; + sim_size += 1; } + + // check that btree matches sim + printf("expd: ["); + bool first = true; + for (lfs_size_t i = 0; i < sim_size; i++) { + // calculate actual id in btree space + lfs_size_t weighted_id = 0; + for (lfs_size_t j = 0; j < i; j++) { + weighted_id += sim_weights[j]; + } + + if (!first) { + printf(", "); + } + first = false; + printf("%dw%d=%c", weighted_id+sim_weights[i]-1, + sim_weights[i], sim[i]); + } + printf("]\n"); + printf("btree: w%d 0x%x.%x\n", + btree.weight, + btree.root.block, + btree.root.trunk); + + lfs_size_t total_weight = 0; + for (lfs_size_t j = 0; j < sim_size; j++) { + total_weight += sim_weights[j]; + } + assert(lfsr_btree_weight(&btree) == total_weight); + + uint8_t buffer[4]; + lfsr_tag_t tag_; + lfs_size_t weight_; + for (lfs_size_t i = 0; i < sim_size; i++) { + // calculate actual id in btree space + lfs_size_t weighted_id = 0; + for (lfs_size_t j = 0; j < i; j++) { + weighted_id += sim_weights[j]; + } + + lfsr_btree_get(&lfs, &btree, weighted_id+sim_weights[i]-1, + &tag_, &weight_, buffer, 4) => 1; + assert(tag_ == LFSR_TAG_INLINED); + assert(weight_ == sim_weights[i]); + assert(memcmp(buffer, &sim[i], 1) == 0); + } + + // and no extra elements + lfsr_btree_get(&lfs, &btree, total_weight, + &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 < sim_size; i++) { + // calculate actual id in btree space + lfs_size_t weighted_id = 0; + for (lfs_size_t j = 0; j < i; j++) { + weighted_id += sim_weights[j]; + } + + lfsr_btree_lookupnext(&lfs, &btree, id_+1, + &id_, &tag_, &weight_, &data_) => 0; + assert(id_ == weighted_id+sim_weights[i]-1); + assert(tag_ == LFSR_TAG_INLINED); + assert(weight_ == sim_weights[i]); + + lfsr_data_read(&lfs, data_, 0, buffer, 4) => 1; + assert(memcmp(buffer, &sim[i], 1) == 0); + } + lfsr_btree_lookupnext(&lfs, &btree, id_+1, + &id_, &tag_, &weight_, &data_) => LFS_ERR_NOENT; + + // clean up sim + free(sim); ''' @@ -2514,314 +2427,292 @@ code = ''' # Some more general fuzz testing [cases.t2_btree_general_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] -defines.SAMPLES = 100 -# -1 => all pseudo-random seeds -# n => reproduce a specific seed -defines.SEED = -1 +defines.SEED = 'range(100)' in = 'lfs.c' code = ''' const char *alphas = "abcdefghijklmnopqrstuvwxyz"; - // iterate through severals seeds that we can reproduce easily - for (uint32_t seed = (SEED == -1 ? 1 : SEED); - (SEED == -1 ? seed < SAMPLES+1 : seed == SEED); - seed++) { - printf("--- seed: %d ---\n", seed); - // create lfs here since we need to reset each iteration, we're - // space constrained and we can't expect gc to work at this point - 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); + 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); - // create a btree - lfsr_btree_t btree = LFSR_BTREE_NULL; + // create a btree + lfsr_btree_t btree = LFSR_BTREE_NULL; - // set up a simulation to compare against - // - // fun fact this is slower than our actual tree! unfun fact this is - // starting to be a problem... - char *sim = malloc(N); - lfs_size_t sim_size = 0; - memset(sim, 0, N); + // set up a simulation to compare against + // + // fun fact this is slower than our actual tree! unfun fact this is + // starting to be a problem... + char *sim = malloc(N); + lfs_size_t sim_size = 0; + memset(sim, 0, N); - uint32_t prng = seed; - for (lfs_size_t i = 0; i < N; i++) { - // choose a pseudo-random op - uint8_t op = TEST_PRNG(&prng) % 3; - // choose a pseudo-random id - lfs_size_t id = TEST_PRNG(&prng) % (sim_size+1); + uint32_t prng = SEED; + for (lfs_size_t i = 0; i < N; i++) { + // choose a pseudo-random op + uint8_t op = TEST_PRNG(&prng) % 3; + // choose a pseudo-random id + lfs_size_t id = TEST_PRNG(&prng) % (sim_size+1); - if (op == 0 || id == sim_size) { - // push to btree - int err = lfsr_btree_push(&lfs, &btree, id, - LFSR_TAG_INLINED, 1, - LFSR_DATA_BUF(&alphas[i % 26], 1)); - // ignore space issues - if (err == LFS_ERR_NOSPC) { - break; - } - assert(err == 0); - - // push to sim - memmove(&sim[id+1], &sim[id], sim_size-id); - sim[id] = alphas[i % 26]; - sim_size += 1; - - } else if (op == 1) { - // update btree - int err = lfsr_btree_set(&lfs, &btree, id, - LFSR_TAG_INLINED, 1, - LFSR_DATA_BUF(&alphas[i % 26], 1)); - // ignore space issues - if (err == LFS_ERR_NOSPC) { - break; - } - assert(err == 0); - - // update sim - sim[id] = alphas[i % 26]; - - } else { - // pop from btree - int err = lfsr_btree_pop(&lfs, &btree, id); - // ignore space issues - if (err == LFS_ERR_NOSPC) { - break; - } - assert(err == 0); - - // pop from sim - memmove(&sim[id], &sim[id+1], sim_size-(id+1)); - sim_size -= 1; + if (op == 0 || id == sim_size) { + // push to btree + int err = lfsr_btree_push(&lfs, &btree, id, + LFSR_TAG_INLINED, 1, + LFSR_DATA_BUF(&alphas[i % 26], 1)); + // ignore space issues + if (err == LFS_ERR_NOSPC) { + break; } - } + assert(err == 0); - // check that btree matches sim - printf("expd: ["); - bool first = true; - for (lfs_size_t i = 0; i < sim_size; i++) { - if (!first) { - printf(", "); + // push to sim + memmove(&sim[id+1], &sim[id], sim_size-id); + sim[id] = alphas[i % 26]; + sim_size += 1; + + } else if (op == 1) { + // update btree + int err = lfsr_btree_set(&lfs, &btree, id, + LFSR_TAG_INLINED, 1, + LFSR_DATA_BUF(&alphas[i % 26], 1)); + // ignore space issues + if (err == LFS_ERR_NOSPC) { + break; } - first = false; - printf("%c", sim[i]); + assert(err == 0); + + // update sim + sim[id] = alphas[i % 26]; + + } else { + // pop from btree + int err = lfsr_btree_pop(&lfs, &btree, id); + // ignore space issues + if (err == LFS_ERR_NOSPC) { + break; + } + assert(err == 0); + + // pop from sim + memmove(&sim[id], &sim[id+1], sim_size-(id+1)); + sim_size -= 1; } - printf("]\n"); - printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); - assert(lfsr_btree_weight(&btree) == sim_size); - - uint8_t buffer[4]; - lfsr_tag_t tag_; - lfs_size_t weight_; - for (lfs_size_t i = 0; i < sim_size; i++) { - lfsr_btree_get(&lfs, &btree, i, - &tag_, &weight_, buffer, 4) => 1; - assert(tag_ == LFSR_TAG_INLINED); - assert(weight_ == 1); - assert(memcmp(buffer, &sim[i], 1) == 0); - } - - // and no extra elements - lfsr_btree_get(&lfs, &btree, sim_size, - &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; - - // clean up sim - free(sim); } + + // check that btree matches sim + printf("expd: ["); + bool first = true; + for (lfs_size_t i = 0; i < sim_size; i++) { + if (!first) { + printf(", "); + } + first = false; + printf("%c", sim[i]); + } + printf("]\n"); + printf("btree: w%d 0x%x.%x\n", + btree.weight, + btree.root.block, + btree.root.trunk); + assert(lfsr_btree_weight(&btree) == sim_size); + + uint8_t buffer[4]; + lfsr_tag_t tag_; + lfs_size_t weight_; + for (lfs_size_t i = 0; i < sim_size; i++) { + lfsr_btree_get(&lfs, &btree, i, + &tag_, &weight_, buffer, 4) => 1; + assert(tag_ == LFSR_TAG_INLINED); + assert(weight_ == 1); + assert(memcmp(buffer, &sim[i], 1) == 0); + } + + // and no extra elements + lfsr_btree_get(&lfs, &btree, sim_size, + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; + + // clean up sim + free(sim); ''' [cases.t2_btree_general_sparse_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] defines.W = 5 -defines.SAMPLES = 100 -# -1 => all pseudo-random seeds -# n => reproduce a specific seed -defines.SEED = -1 +defines.SEED = 'range(100)' in = 'lfs.c' code = ''' const char *alphas = "abcdefghijklmnopqrstuvwxyz"; - // iterate through severals seeds that we can reproduce easily - for (uint32_t seed = (SEED == -1 ? 1 : SEED); - (SEED == -1 ? seed < SAMPLES+1 : seed == SEED); - seed++) { - printf("--- seed: %d ---\n", seed); - // create lfs here since we need to reset each iteration, we're - // space constrained and we can't expect gc to work at this point - 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); + 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); - // create a btree - lfsr_btree_t btree = LFSR_BTREE_NULL; + // create a btree + lfsr_btree_t btree = LFSR_BTREE_NULL; - // set up a simulation to compare against - // - // fun fact this is slower than our actual tree! unfun fact this is - // starting to be a problem... - char *sim = malloc(N); - lfs_size_t *sim_weights = malloc(N*sizeof(lfs_size_t)); - lfs_size_t sim_size = 0; - memset(sim, 0, N); - memset(sim_weights, 0, N*sizeof(lfs_size_t)); + // set up a simulation to compare against + // + // fun fact this is slower than our actual tree! unfun fact this is + // starting to be a problem... + char *sim = malloc(N); + lfs_size_t *sim_weights = malloc(N*sizeof(lfs_size_t)); + lfs_size_t sim_size = 0; + memset(sim, 0, N); + memset(sim_weights, 0, N*sizeof(lfs_size_t)); - uint32_t prng = seed; - for (lfs_size_t i = 0; i < N; i++) { - // choose a pseudo-random op - uint8_t op = TEST_PRNG(&prng) % 3; - // choose a pseudo-random id - lfs_size_t id = TEST_PRNG(&prng) % (sim_size+1); - // choose a pseudo-random weight - lfs_size_t weight = 1 + (TEST_PRNG(&prng) % W); + uint32_t prng = SEED; + for (lfs_size_t i = 0; i < N; i++) { + // choose a pseudo-random op + uint8_t op = TEST_PRNG(&prng) % 3; + // choose a pseudo-random id + lfs_size_t id = TEST_PRNG(&prng) % (sim_size+1); + // choose a pseudo-random weight + lfs_size_t weight = 1 + (TEST_PRNG(&prng) % W); - // calculate actual id in btree space - lfs_size_t weighted_id = 0; - for (lfs_size_t j = 0; j < id; j++) { - weighted_id += sim_weights[j]; - } - - if (op == 0 || id == sim_size) { - // push to btree - int err = lfsr_btree_push(&lfs, &btree, weighted_id, - LFSR_TAG_INLINED, weight, - LFSR_DATA_BUF(&alphas[i % 26], 1)); - // ignore space issues - if (err == LFS_ERR_NOSPC) { - break; - } - assert(err == 0); - - // push to sim - memmove(&sim[id+1], &sim[id], sim_size-id); - memmove(&sim_weights[id+1], &sim_weights[id], - (sim_size-id)*sizeof(lfs_size_t)); - sim[id] = alphas[i % 26]; - sim_weights[id] = weight; - sim_size += 1; - - } else if (op == 1) { - // update btree - int err = lfsr_btree_set(&lfs, &btree, - weighted_id+sim_weights[id]-1, LFSR_TAG_INLINED, weight, - LFSR_DATA_BUF(&alphas[i % 26], 1)); - // ignore space issues - if (err == LFS_ERR_NOSPC) { - break; - } - assert(err == 0); - - // update sim - sim[id] = alphas[i % 26]; - sim_weights[id] = weight; - - } else { - // remove from btree - int err = lfsr_btree_pop(&lfs, &btree, - weighted_id+sim_weights[id]-1); - // ignore space issues - if (err == LFS_ERR_NOSPC) { - break; - } - assert(err == 0); - - // remove from sim - memmove(&sim[id], &sim[id+1], sim_size-(id+1)); - memmove(&sim_weights[id], &sim_weights[id+1], - (sim_size-(id+1))*sizeof(lfs_size_t)); - sim_size -= 1; - } + // calculate actual id in btree space + lfs_size_t weighted_id = 0; + for (lfs_size_t j = 0; j < id; j++) { + weighted_id += sim_weights[j]; } - // check that btree matches sim - printf("expd: ["); - bool first = true; - for (lfs_size_t i = 0; i < sim_size; i++) { - // calculate actual id in btree space - lfs_size_t weighted_id = 0; - for (lfs_size_t j = 0; j < i; j++) { - weighted_id += sim_weights[j]; + if (op == 0 || id == sim_size) { + // push to btree + int err = lfsr_btree_push(&lfs, &btree, weighted_id, + LFSR_TAG_INLINED, weight, + LFSR_DATA_BUF(&alphas[i % 26], 1)); + // ignore space issues + if (err == LFS_ERR_NOSPC) { + break; } + assert(err == 0); - if (!first) { - printf(", "); + // push to sim + memmove(&sim[id+1], &sim[id], sim_size-id); + memmove(&sim_weights[id+1], &sim_weights[id], + (sim_size-id)*sizeof(lfs_size_t)); + sim[id] = alphas[i % 26]; + sim_weights[id] = weight; + sim_size += 1; + + } else if (op == 1) { + // update btree + int err = lfsr_btree_set(&lfs, &btree, + weighted_id+sim_weights[id]-1, LFSR_TAG_INLINED, weight, + LFSR_DATA_BUF(&alphas[i % 26], 1)); + // ignore space issues + if (err == LFS_ERR_NOSPC) { + break; } - first = false; - printf("%dw%d=%c", weighted_id+sim_weights[i]-1, - sim_weights[i], sim[i]); - } - printf("]\n"); - printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + assert(err == 0); - lfs_size_t total_weight = 0; - for (lfs_size_t j = 0; j < sim_size; j++) { - total_weight += sim_weights[j]; - } - assert(lfsr_btree_weight(&btree) == total_weight); + // update sim + sim[id] = alphas[i % 26]; + sim_weights[id] = weight; - uint8_t buffer[4]; - lfsr_tag_t tag_; - lfs_size_t weight_; - for (lfs_size_t i = 0; i < sim_size; i++) { - // calculate actual id in btree space - lfs_size_t weighted_id = 0; - for (lfs_size_t j = 0; j < i; j++) { - weighted_id += sim_weights[j]; + } else { + // remove from btree + int err = lfsr_btree_pop(&lfs, &btree, + weighted_id+sim_weights[id]-1); + // ignore space issues + if (err == LFS_ERR_NOSPC) { + break; } + assert(err == 0); - lfsr_btree_get(&lfs, &btree, weighted_id+sim_weights[i]-1, - &tag_, &weight_, buffer, 4) => 1; - assert(tag_ == LFSR_TAG_INLINED); - assert(weight_ == sim_weights[i]); - assert(memcmp(buffer, &sim[i], 1) == 0); + // remove from sim + memmove(&sim[id], &sim[id+1], sim_size-(id+1)); + memmove(&sim_weights[id], &sim_weights[id+1], + (sim_size-(id+1))*sizeof(lfs_size_t)); + sim_size -= 1; } - - // and no extra elements - lfsr_btree_get(&lfs, &btree, total_weight, - &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 < sim_size; i++) { - // calculate actual id in btree space - lfs_size_t weighted_id = 0; - for (lfs_size_t j = 0; j < i; j++) { - weighted_id += sim_weights[j]; - } - - lfsr_btree_lookupnext(&lfs, &btree, id_+1, - &id_, &tag_, &weight_, &data_) => 0; - assert(id_ == weighted_id+sim_weights[i]-1); - assert(tag_ == LFSR_TAG_INLINED); - assert(weight_ == sim_weights[i]); - - lfsr_data_read(&lfs, data_, 0, buffer, 4) => 1; - assert(memcmp(buffer, &sim[i], 1) == 0); - } - lfsr_btree_lookupnext(&lfs, &btree, id_+1, - &id_, &tag_, &weight_, &data_) => LFS_ERR_NOENT; - - // clean up sim - free(sim); } + + // check that btree matches sim + printf("expd: ["); + bool first = true; + for (lfs_size_t i = 0; i < sim_size; i++) { + // calculate actual id in btree space + lfs_size_t weighted_id = 0; + for (lfs_size_t j = 0; j < i; j++) { + weighted_id += sim_weights[j]; + } + + if (!first) { + printf(", "); + } + first = false; + printf("%dw%d=%c", weighted_id+sim_weights[i]-1, + sim_weights[i], sim[i]); + } + printf("]\n"); + printf("btree: w%d 0x%x.%x\n", + btree.weight, + btree.root.block, + btree.root.trunk); + + lfs_size_t total_weight = 0; + for (lfs_size_t j = 0; j < sim_size; j++) { + total_weight += sim_weights[j]; + } + assert(lfsr_btree_weight(&btree) == total_weight); + + uint8_t buffer[4]; + lfsr_tag_t tag_; + lfs_size_t weight_; + for (lfs_size_t i = 0; i < sim_size; i++) { + // calculate actual id in btree space + lfs_size_t weighted_id = 0; + for (lfs_size_t j = 0; j < i; j++) { + weighted_id += sim_weights[j]; + } + + lfsr_btree_get(&lfs, &btree, weighted_id+sim_weights[i]-1, + &tag_, &weight_, buffer, 4) => 1; + assert(tag_ == LFSR_TAG_INLINED); + assert(weight_ == sim_weights[i]); + assert(memcmp(buffer, &sim[i], 1) == 0); + } + + // and no extra elements + lfsr_btree_get(&lfs, &btree, total_weight, + &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 < sim_size; i++) { + // calculate actual id in btree space + lfs_size_t weighted_id = 0; + for (lfs_size_t j = 0; j < i; j++) { + weighted_id += sim_weights[j]; + } + + lfsr_btree_lookupnext(&lfs, &btree, id_+1, + &id_, &tag_, &weight_, &data_) => 0; + assert(id_ == weighted_id+sim_weights[i]-1); + assert(tag_ == LFSR_TAG_INLINED); + assert(weight_ == sim_weights[i]); + + lfsr_data_read(&lfs, data_, 0, buffer, 4) => 1; + assert(memcmp(buffer, &sim[i], 1) == 0); + } + lfsr_btree_lookupnext(&lfs, &btree, id_+1, + &id_, &tag_, &weight_, &data_) => LFS_ERR_NOENT; + + // clean up sim + free(sim); ''' @@ -3176,124 +3067,113 @@ code = ''' [cases.t2_btree_find_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] -defines.SAMPLES = 10 -# -1 => all pseudo-random seeds -# n => reproduce a specific seed -defines.SEED = -1 +defines.SEED = 'range(10)' in = 'lfs.c' code = ''' const char *alphas = "abcdefghijklmnopqrstuvwxyz"; const char *nums = "0123456789"; - // iterate through severals seeds that we can reproduce easily - for (uint32_t seed = (SEED == -1 ? 1 : SEED); - (SEED == -1 ? seed < SAMPLES+1 : seed == SEED); - seed++) { - printf("--- seed: %d ---\n", seed); - // create lfs here since we need to reset each iteration, we're - // space constrained and we can't expect gc to work at this point - 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); + 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); - // create a btree - lfsr_btree_t btree = LFSR_BTREE_NULL; - lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, 1, - LFSR_DATA_BUF("_", 1)) => 0; + // create a btree + lfsr_btree_t btree = LFSR_BTREE_NULL; + lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, 1, + LFSR_DATA_BUF("_", 1)) => 0; - // set up a simulation to compare against - // - // fun fact this is slower than our actual tree! unfun fact this is - // starting to be a problem... - char *sim = malloc(N); - char (*sim_names)[3] = malloc(N*3); - lfs_size_t sim_size = 1; - memset(sim, 0, N); - memset(sim_names, 0, N*3); - sim[0] = '_'; - memcpy(&sim_names[0], "___", 3); + // set up a simulation to compare against + // + // fun fact this is slower than our actual tree! unfun fact this is + // starting to be a problem... + char *sim = malloc(N); + char (*sim_names)[3] = malloc(N*3); + lfs_size_t sim_size = 1; + memset(sim, 0, N); + memset(sim_names, 0, N*3); + sim[0] = '_'; + memcpy(&sim_names[0], "___", 3); - uint32_t prng = seed; - for (lfs_size_t i = 1; i < N; i++) { - // choose a pseudo-random name - lfs_size_t x = TEST_PRNG(&prng) % (26*26*26); - char name[3] = { - alphas[(x/26/26) % 26], alphas[(x/26) % 26], alphas[x % 26] - }; + uint32_t prng = SEED; + for (lfs_size_t i = 1; i < N; i++) { + // choose a pseudo-random name + lfs_size_t x = TEST_PRNG(&prng) % (26*26*26); + char name[3] = { + alphas[(x/26/26) % 26], alphas[(x/26) % 26], alphas[x % 26] + }; - // find where to split - lfs_size_t id = 0; - while (id+1 < sim_size && memcmp(sim_names[id+1], name, 3) <= 0) { - id += 1; - } - // just skip exact matches for now - if (memcmp(sim_names[id], name, 3) == 0) { - continue; - } - - // split btree - int err = lfsr_btree_split(&lfs, &btree, id, - LFSR_DATA_DNAME(0, name, 3), - LFSR_TAG_INLINED, 1, LFSR_DATA_BUF(&nums[i % 10], 1), - LFSR_TAG_INLINED, 1, LFSR_DATA_BUF(&nums[i % 10], 1)); - // ignore space issues - if (err == LFS_ERR_NOSPC) { - break; - } - assert(err == 0); - - // split sim - memmove(&sim[id+1], &sim[id], sim_size-id); - memmove(&sim_names[id+1], &sim_names[id], (sim_size-id)*3); - sim[id+0] = nums[i % 10]; - sim[id+1] = nums[i % 10]; - memcpy(&sim_names[id+1], name, 3); - sim_size += 1; + // find where to split + lfs_size_t id = 0; + while (id+1 < sim_size && memcmp(sim_names[id+1], name, 3) <= 0) { + id += 1; + } + // just skip exact matches for now + if (memcmp(sim_names[id], name, 3) == 0) { + continue; } - // check that btree matches sim - printf("expd: ["); - bool first = true; - for (lfs_size_t i = 0; i < sim_size; i++) { - if (!first) { - printf(", "); - } - first = false; - printf("%.3s=%c", sim_names[i], sim[i]); + // split btree + int err = lfsr_btree_split(&lfs, &btree, id, + LFSR_DATA_DNAME(0, name, 3), + LFSR_TAG_INLINED, 1, LFSR_DATA_BUF(&nums[i % 10], 1), + LFSR_TAG_INLINED, 1, LFSR_DATA_BUF(&nums[i % 10], 1)); + // ignore space issues + if (err == LFS_ERR_NOSPC) { + break; } - printf("]\n"); - printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); - assert(lfsr_btree_weight(&btree) == sim_size); + assert(err == 0); - uint8_t buffer[4]; - lfsr_tag_t tag_; - lfs_size_t id_; - lfs_size_t weight_; - lfsr_data_t data_; - for (lfs_size_t i = 0; i < sim_size; i++) { - lfsr_btree_dnamelookup(&lfs, &btree, 0, sim_names[i], 3, - &id_, &tag_, &weight_, &data_) => 0; - assert(tag_ == LFSR_TAG_INLINED); - assert(id_ == i); - assert(weight_ == 1); - lfsr_data_read(&lfs, data_, 0, buffer, 4) => 1; - assert(memcmp(buffer, &sim[i], 1) == 0); - } - - // clean up sim - free(sim); - free(sim_names); - lfs_deinit(&lfs) => 0; + // split sim + memmove(&sim[id+1], &sim[id], sim_size-id); + memmove(&sim_names[id+1], &sim_names[id], (sim_size-id)*3); + sim[id+0] = nums[i % 10]; + sim[id+1] = nums[i % 10]; + memcpy(&sim_names[id+1], name, 3); + sim_size += 1; } + + // check that btree matches sim + printf("expd: ["); + bool first = true; + for (lfs_size_t i = 0; i < sim_size; i++) { + if (!first) { + printf(", "); + } + first = false; + printf("%.3s=%c", sim_names[i], sim[i]); + } + printf("]\n"); + printf("btree: w%d 0x%x.%x\n", + btree.weight, + btree.root.block, + btree.root.trunk); + assert(lfsr_btree_weight(&btree) == sim_size); + + uint8_t buffer[4]; + lfsr_tag_t tag_; + lfs_size_t id_; + lfs_size_t weight_; + lfsr_data_t data_; + for (lfs_size_t i = 0; i < sim_size; i++) { + lfsr_btree_dnamelookup(&lfs, &btree, 0, sim_names[i], 3, + &id_, &tag_, &weight_, &data_) => 0; + assert(tag_ == LFSR_TAG_INLINED); + assert(id_ == i); + assert(weight_ == 1); + lfsr_data_read(&lfs, data_, 0, buffer, 4) => 1; + assert(memcmp(buffer, &sim[i], 1) == 0); + } + + // clean up sim + free(sim); + free(sim_names); + lfs_deinit(&lfs) => 0; ''' [cases.t2_btree_find_sparse] @@ -3366,66 +3246,394 @@ code = ''' [cases.t2_btree_find_sparse_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] defines.W = 5 -defines.SAMPLES = 10 -# -1 => all pseudo-random seeds -# n => reproduce a specific seed -defines.SEED = -1 +defines.SEED = 'range(10)' in = 'lfs.c' code = ''' const char *alphas = "abcdefghijklmnopqrstuvwxyz"; const char *nums = "0123456789"; - // iterate through severals seeds that we can reproduce easily - for (uint32_t seed = (SEED == -1 ? 1 : SEED); - (SEED == -1 ? seed < SAMPLES+1 : seed == SEED); - seed++) { - printf("--- seed: %d ---\n", seed); - // create lfs here since we need to reset each iteration, we're - // space constrained and we can't expect gc to work at this point - 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); + 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); - // create a btree - lfsr_btree_t btree = LFSR_BTREE_NULL; - lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, W, - LFSR_DATA_BUF("_", 1)) => 0; + // create a btree + lfsr_btree_t btree = LFSR_BTREE_NULL; + lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, W, + LFSR_DATA_BUF("_", 1)) => 0; - // set up a simulation to compare against - // - // fun fact this is slower than our actual tree! unfun fact this is - // starting to be a problem... - char *sim = malloc(N); - char (*sim_names)[3] = malloc(N*3); - lfs_size_t *sim_weights = malloc(N*sizeof(lfs_size_t)); - lfs_size_t sim_size = 1; - memset(sim, 0, N); - memset(sim_names, 0, N*3); - memset(sim_weights, 0, N*sizeof(lfs_size_t)); - sim[0] = '_'; - memcpy(&sim_names[0], "___", 3); - sim_weights[0] = W; + // set up a simulation to compare against + // + // fun fact this is slower than our actual tree! unfun fact this is + // starting to be a problem... + char *sim = malloc(N); + char (*sim_names)[3] = malloc(N*3); + lfs_size_t *sim_weights = malloc(N*sizeof(lfs_size_t)); + lfs_size_t sim_size = 1; + memset(sim, 0, N); + memset(sim_names, 0, N*3); + memset(sim_weights, 0, N*sizeof(lfs_size_t)); + sim[0] = '_'; + memcpy(&sim_names[0], "___", 3); + sim_weights[0] = W; - uint32_t prng = seed; - for (lfs_size_t i = 1; i < N; i++) { - // choose a pseudo-random name - lfs_size_t x = TEST_PRNG(&prng) % (26*26*26); - char name[3] = { - alphas[(x/26/26) % 26], alphas[(x/26) % 26], alphas[x % 26] - }; - // choose pseudo-random weights - lfs_size_t weight1 = 1 + (TEST_PRNG(&prng) % W); - lfs_size_t weight2 = 1 + (TEST_PRNG(&prng) % W); + uint32_t prng = SEED; + for (lfs_size_t i = 1; i < N; i++) { + // choose a pseudo-random name + lfs_size_t x = TEST_PRNG(&prng) % (26*26*26); + char name[3] = { + alphas[(x/26/26) % 26], alphas[(x/26) % 26], alphas[x % 26] + }; + // choose pseudo-random weights + lfs_size_t weight1 = 1 + (TEST_PRNG(&prng) % W); + lfs_size_t weight2 = 1 + (TEST_PRNG(&prng) % W); + // find where to split + lfs_size_t id = 0; + while (id+1 < sim_size && memcmp(sim_names[id+1], name, 3) <= 0) { + id += 1; + } + // just skip exact matches for now + if (memcmp(sim_names[id], name, 3) == 0) { + continue; + } + + // calculate actual id in btree space + lfs_size_t weighted_id = 0; + for (lfs_size_t j = 0; j < id; j++) { + weighted_id += sim_weights[j]; + } + + // split btree + int err = lfsr_btree_split(&lfs, &btree, + weighted_id+sim_weights[id]-1, + LFSR_DATA_DNAME(0, name, 3), + LFSR_TAG_INLINED, weight1, LFSR_DATA_BUF(&nums[i % 10], 1), + LFSR_TAG_INLINED, weight2, LFSR_DATA_BUF(&nums[i % 10], 1)); + // ignore space issues + if (err == LFS_ERR_NOSPC) { + break; + } + assert(err == 0); + + // split sim + memmove(&sim[id+1], &sim[id], sim_size-id); + memmove(&sim_names[id+1], &sim_names[id], (sim_size-id)*3); + memmove(&sim_weights[id+1], &sim_weights[id], + (sim_size-id)*sizeof(lfs_size_t)); + sim[id+0] = nums[i % 10]; + sim[id+1] = nums[i % 10]; + memcpy(&sim_names[id+1], name, 3); + sim_weights[id+0] = weight1; + sim_weights[id+1] = weight2; + sim_size += 1; + } + + // check that btree matches sim + printf("expd: ["); + bool first = true; + for (lfs_size_t i = 0; i < sim_size; i++) { + // calculate actual id in btree space + lfs_size_t weighted_id = 0; + for (lfs_size_t j = 0; j < i; j++) { + weighted_id += sim_weights[j]; + } + + if (!first) { + printf(", "); + } + first = false; + printf("%.3sid%dw%d=%c", + sim_names[i], + weighted_id+sim_weights[i]-1, + sim_weights[i], + sim[i]); + } + printf("]\n"); + printf("btree: w%d 0x%x.%x\n", + btree.weight, + btree.root.block, + btree.root.trunk); + + lfs_size_t total_weight = 0; + for (lfs_size_t j = 0; j < sim_size; j++) { + total_weight += sim_weights[j]; + } + assert(lfsr_btree_weight(&btree) == total_weight); + + uint8_t buffer[4]; + lfsr_tag_t tag_; + lfs_size_t id_; + lfs_size_t weight_; + lfsr_data_t data_; + for (lfs_size_t i = 0; i < sim_size; i++) { + // calculate actual id in btree space + lfs_size_t weighted_id = 0; + for (lfs_size_t j = 0; j < i; j++) { + weighted_id += sim_weights[j]; + } + + lfsr_btree_dnamelookup(&lfs, &btree, 0, sim_names[i], 3, + &id_, &tag_, &weight_, &data_) => 0; + assert(tag_ == LFSR_TAG_INLINED); + assert(id_ == weighted_id+sim_weights[i]-1); + assert(weight_ == sim_weights[i]); + lfsr_data_read(&lfs, data_, 0, buffer, 4) => 1; + assert(memcmp(buffer, &sim[i], 1) == 0); + } + + // clean up sim + free(sim); + free(sim_names); + free(sim_weights); + lfs_deinit(&lfs) => 0; +''' + +# make sure we test finds with other operations +[cases.t2_btree_find_general_fuzz] +defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] +defines.SEED = 'range(100)' +in = 'lfs.c' +code = ''' + const char *alphas = "abcdefghijklmnopqrstuvwxyz"; + const char *nums = "0123456789"; + + 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); + + // create a btree + lfsr_btree_t btree = LFSR_BTREE_NULL; + lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, 1, + LFSR_DATA_BUF("_", 1)) => 0; + + // set up a simulation to compare against + // + // fun fact this is slower than our actual tree! unfun fact this is + // starting to be a problem... + char *sim = malloc(N); + char (*sim_names)[3] = malloc(N*3); + lfs_size_t sim_size = 1; + memset(sim, 0, N); + memset(sim_names, 0, N*3); + sim[0] = '_'; + memcpy(&sim_names[0], "___", 3); + + uint32_t prng = SEED; + for (lfs_size_t i = 0; i < N; i++) { + // choose a pseudo-random op + uint8_t op = TEST_PRNG(&prng) % 3; + // choose a pseudo-random id + lfs_size_t id = TEST_PRNG(&prng) % (sim_size == 0 ? 1 : sim_size); + // choose a pseudo-random name + lfs_size_t x = TEST_PRNG(&prng) % (26*26*26); + char name[3] = { + alphas[(x/26/26) % 26], alphas[(x/26) % 26], alphas[x % 26] + }; + + // don't let sim drop below one element + if (op == 0 || sim_size <= 1) { // find where to split lfs_size_t id = 0; - while (id+1 < sim_size && memcmp(sim_names[id+1], name, 3) <= 0) { + while (id+1 < sim_size + && memcmp(sim_names[id+1], name, 3) <= 0) { + id += 1; + } + // just skip exact matches for now + if (memcmp(sim_names[id], name, 3) == 0) { + continue; + } + + // split btree + lfs_size_t split_id; + lfsr_data_t split_data; + lfsr_btree_dnamelookup(&lfs, &btree, 0, name, 3, + &split_id, NULL, NULL, &split_data) => 0; + uint8_t split_buf[4]; + lfsr_data_read(&lfs, split_data, 0, split_buf, 4) => 1; + if (split_id > id) { + int err = lfsr_btree_split(&lfs, &btree, + split_id, + LFSR_DATA_DNAME(0, sim_names[id+1], 3), + LFSR_TAG_INLINED, 1, + LFSR_DATA_BUF(&nums[i % 10], 1), + LFSR_TAG_INLINED, 1, + LFSR_DATA_BUF(split_buf, 1)); + // ignore space issues + if (err == LFS_ERR_NOSPC) { + break; + } + assert(err == 0); + } else { + int err = lfsr_btree_split(&lfs, &btree, + split_id, LFSR_DATA_DNAME(0, name, 3), + LFSR_TAG_INLINED, 1, + LFSR_DATA_BUF(split_buf, 1), + LFSR_TAG_INLINED, 1, + LFSR_DATA_BUF(&nums[i % 10], 1)); + // ignore space issues + if (err == LFS_ERR_NOSPC) { + break; + } + assert(err == 0); + } + + // split sim + memmove(&sim[id+1], &sim[id], sim_size-id); + memmove(&sim_names[id+1], &sim_names[id], (sim_size-id)*3); + sim[id+1] = nums[i % 10]; + memcpy(&sim_names[id+1], name, 3); + sim_size += 1; + + } else if (op == 1) { + // update btree + int err = lfsr_btree_set(&lfs, &btree, id, + LFSR_TAG_INLINED, 1, + LFSR_DATA_BUF(&nums[i % 10], 1)); + // ignore space issues + if (err == LFS_ERR_NOSPC) { + break; + } + assert(err == 0); + + // update sim + sim[id] = nums[i % 10]; + + } else { + // pop from btree + int err = lfsr_btree_pop(&lfs, &btree, id); + // ignore space issues + if (err == LFS_ERR_NOSPC) { + break; + } + assert(err == 0); + + // pop from sim + memmove(&sim[id], &sim[id+1], sim_size-(id+1)); + memmove(&sim_names[id], &sim_names[id+1], (sim_size-(id+1))*3); + sim_size -= 1; + + // our B-tree doesn't actually track the name of id0, so we need + // mirror this in our sim + if (id == 0) { + memcpy(&sim_names[0], "___", 3); + } + } + } + + // check that btree matches sim + printf("expd: ["); + bool first = true; + for (lfs_size_t i = 0; i < sim_size; i++) { + if (!first) { + printf(", "); + } + first = false; + printf("%.3s=%c", sim_names[i], sim[i]); + } + printf("]\n"); + printf("btree: w%d 0x%x.%x\n", + btree.weight, + btree.root.block, + btree.root.trunk); + assert(lfsr_btree_weight(&btree) == sim_size); + + uint8_t buffer[4]; + lfsr_tag_t tag_; + lfs_size_t id_; + lfs_size_t weight_; + lfsr_data_t data_; + for (lfs_size_t i = 0; i < sim_size; i++) { + lfsr_btree_dnamelookup(&lfs, &btree, 0, sim_names[i], 3, + &id_, &tag_, &weight_, &data_) => 0; + assert(tag_ == LFSR_TAG_INLINED); + assert(id_ == i); + assert(weight_ == 1); + lfsr_data_read(&lfs, data_, 0, buffer, 4) => 1; + assert(memcmp(buffer, &sim[i], 1) == 0); + } + + // clean up sim + free(sim); + free(sim_names); +''' + +[cases.t2_btree_find_general_sparse_fuzz] +defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] +defines.W = 5 +defines.SEED = 'range(100)' +in = 'lfs.c' +code = ''' + const char *alphas = "abcdefghijklmnopqrstuvwxyz"; + const char *nums = "0123456789"; + + 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); + + // create a btree + lfsr_btree_t btree = LFSR_BTREE_NULL; + lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, W, + LFSR_DATA_BUF("_", 1)) => 0; + + // set up a simulation to compare against + // + // fun fact this is slower than our actual tree! unfun fact this is + // starting to be a problem... + char *sim = malloc(N); + char (*sim_names)[3] = malloc(N*3); + lfs_size_t *sim_weights = malloc(N*sizeof(lfs_size_t)); + lfs_size_t sim_size = 1; + memset(sim, 0, N); + memset(sim_names, 0, N*3); + memset(sim_weights, 0, N*sizeof(lfs_size_t)); + sim[0] = '_'; + memcpy(&sim_names[0], "___", 3); + sim_weights[0] = W; + + uint32_t prng = SEED; + for (lfs_size_t i = 0; i < N; i++) { + // choose a pseudo-random op + uint8_t op = TEST_PRNG(&prng) % 3; + // choose a pseudo-random id + lfs_size_t id = TEST_PRNG(&prng) % (sim_size == 0 ? 1 : sim_size); + // choose a pseudo-random name + lfs_size_t x = TEST_PRNG(&prng) % (26*26*26); + char name[3] = { + alphas[(x/26/26) % 26], alphas[(x/26) % 26], alphas[x % 26] + }; + // choose a pseudo-random weight + lfs_size_t weight = 1 + (TEST_PRNG(&prng) % W); + + // calculate actual id in btree space + lfs_size_t weighted_id = 0; + for (lfs_size_t j = 0; j < id; j++) { + weighted_id += sim_weights[j]; + } + + // don't let sim drop below one element + if (op == 0 || sim_size <= 1) { + // find where to split + lfs_size_t id = 0; + while (id+1 < sim_size + && memcmp(sim_names[id+1], name, 3) <= 0) { id += 1; } // just skip exact matches for now @@ -3440,508 +3648,147 @@ code = ''' } // split btree - int err = lfsr_btree_split(&lfs, &btree, - weighted_id+sim_weights[id]-1, - LFSR_DATA_DNAME(0, name, 3), - LFSR_TAG_INLINED, weight1, LFSR_DATA_BUF(&nums[i % 10], 1), - LFSR_TAG_INLINED, weight2, LFSR_DATA_BUF(&nums[i % 10], 1)); - // ignore space issues - if (err == LFS_ERR_NOSPC) { - break; + lfs_size_t split_id; + lfs_size_t split_weight; + lfsr_data_t split_data; + lfsr_btree_dnamelookup(&lfs, &btree, 0, name, 3, + &split_id, NULL, &split_weight, + &split_data) => 0; + uint8_t split_buf[4]; + lfsr_data_read(&lfs, split_data, 0, split_buf, 4) => 1; + if (split_id > weighted_id+sim_weights[id]-1) { + int err = lfsr_btree_split(&lfs, &btree, + split_id, LFSR_DATA_DNAME(0, sim_names[id+1], 3), + LFSR_TAG_INLINED, weight, + LFSR_DATA_BUF(&nums[i % 10], 1), + LFSR_TAG_INLINED, split_weight, + LFSR_DATA_BUF(split_buf, 1)); + // ignore space issues + if (err == LFS_ERR_NOSPC) { + break; + } + assert(err == 0); + } else { + int err = lfsr_btree_split(&lfs, &btree, + split_id, LFSR_DATA_DNAME(0, name, 3), + LFSR_TAG_INLINED, split_weight, + LFSR_DATA_BUF(split_buf, 1), + LFSR_TAG_INLINED, weight, + LFSR_DATA_BUF(&nums[i % 10], 1)); + // ignore space issues + if (err == LFS_ERR_NOSPC) { + break; + } + assert(err == 0); } - assert(err == 0); // split sim memmove(&sim[id+1], &sim[id], sim_size-id); memmove(&sim_names[id+1], &sim_names[id], (sim_size-id)*3); memmove(&sim_weights[id+1], &sim_weights[id], (sim_size-id)*sizeof(lfs_size_t)); - sim[id+0] = nums[i % 10]; sim[id+1] = nums[i % 10]; memcpy(&sim_names[id+1], name, 3); - sim_weights[id+0] = weight1; - sim_weights[id+1] = weight2; + sim_weights[id+1] = weight; sim_size += 1; - } - // check that btree matches sim - printf("expd: ["); - bool first = true; - for (lfs_size_t i = 0; i < sim_size; i++) { - // calculate actual id in btree space - lfs_size_t weighted_id = 0; - for (lfs_size_t j = 0; j < i; j++) { - weighted_id += sim_weights[j]; + } else if (op == 1) { + // update btree + int err = lfsr_btree_set(&lfs, &btree, + weighted_id+sim_weights[id]-1, LFSR_TAG_INLINED, weight, + LFSR_DATA_BUF(&nums[i % 10], 1)); + // ignore space issues + if (err == LFS_ERR_NOSPC) { + break; } + assert(err == 0); - if (!first) { - printf(", "); + // update sim + sim[id] = nums[i % 10]; + sim_weights[id] = weight; + + } else { + // pop from btree + int err = lfsr_btree_pop(&lfs, &btree, + weighted_id+sim_weights[id]-1); + // ignore space issues + if (err == LFS_ERR_NOSPC) { + break; } - first = false; - printf("%.3sid%dw%d=%c", - sim_names[i], - weighted_id+sim_weights[i]-1, - sim_weights[i], - sim[i]); - } - printf("]\n"); - printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + assert(err == 0); - lfs_size_t total_weight = 0; - for (lfs_size_t j = 0; j < sim_size; j++) { - total_weight += sim_weights[j]; - } - assert(lfsr_btree_weight(&btree) == total_weight); + // pop from sim + memmove(&sim[id], &sim[id+1], sim_size-(id+1)); + memmove(&sim_names[id], &sim_names[id+1], (sim_size-(id+1))*3); + memmove(&sim_weights[id], &sim_weights[id+1], + (sim_size-(id+1))*sizeof(lfs_size_t)); + sim_size -= 1; - uint8_t buffer[4]; - lfsr_tag_t tag_; - lfs_size_t id_; - lfs_size_t weight_; - lfsr_data_t data_; - for (lfs_size_t i = 0; i < sim_size; i++) { - // calculate actual id in btree space - lfs_size_t weighted_id = 0; - for (lfs_size_t j = 0; j < i; j++) { - weighted_id += sim_weights[j]; + // our B-tree doesn't actually track the name of id0, so we need + // mirror this in our sim + if (id == 0) { + memcpy(&sim_names[0], "___", 3); } - - lfsr_btree_dnamelookup(&lfs, &btree, 0, sim_names[i], 3, - &id_, &tag_, &weight_, &data_) => 0; - assert(tag_ == LFSR_TAG_INLINED); - assert(id_ == weighted_id+sim_weights[i]-1); - assert(weight_ == sim_weights[i]); - lfsr_data_read(&lfs, data_, 0, buffer, 4) => 1; - assert(memcmp(buffer, &sim[i], 1) == 0); } - - // clean up sim - free(sim); - free(sim_names); - free(sim_weights); - lfs_deinit(&lfs) => 0; } -''' -# make sure we test finds with other operations -[cases.t2_btree_find_general_fuzz] -defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] -defines.SAMPLES = 100 -# -1 => all pseudo-random seeds -# n => reproduce a specific seed -defines.SEED = -1 -in = 'lfs.c' -code = ''' - const char *alphas = "abcdefghijklmnopqrstuvwxyz"; - const char *nums = "0123456789"; - - // iterate through severals seeds that we can reproduce easily - for (uint32_t seed = (SEED == -1 ? 1 : SEED); - (SEED == -1 ? seed < SAMPLES+1 : seed == SEED); - seed++) { - printf("--- seed: %d ---\n", seed); - // create lfs here since we need to reset each iteration, we're - // space constrained and we can't expect gc to work at this point - 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); - - // create a btree - lfsr_btree_t btree = LFSR_BTREE_NULL; - lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, 1, - LFSR_DATA_BUF("_", 1)) => 0; - - // set up a simulation to compare against - // - // fun fact this is slower than our actual tree! unfun fact this is - // starting to be a problem... - char *sim = malloc(N); - char (*sim_names)[3] = malloc(N*3); - lfs_size_t sim_size = 1; - memset(sim, 0, N); - memset(sim_names, 0, N*3); - sim[0] = '_'; - memcpy(&sim_names[0], "___", 3); - - uint32_t prng = seed; - for (lfs_size_t i = 0; i < N; i++) { - // choose a pseudo-random op - uint8_t op = TEST_PRNG(&prng) % 3; - // choose a pseudo-random id - lfs_size_t id = TEST_PRNG(&prng) % (sim_size == 0 ? 1 : sim_size); - // choose a pseudo-random name - lfs_size_t x = TEST_PRNG(&prng) % (26*26*26); - char name[3] = { - alphas[(x/26/26) % 26], alphas[(x/26) % 26], alphas[x % 26] - }; - - // don't let sim drop below one element - if (op == 0 || sim_size <= 1) { - // find where to split - lfs_size_t id = 0; - while (id+1 < sim_size - && memcmp(sim_names[id+1], name, 3) <= 0) { - id += 1; - } - // just skip exact matches for now - if (memcmp(sim_names[id], name, 3) == 0) { - continue; - } - - // split btree - lfs_size_t split_id; - lfsr_data_t split_data; - lfsr_btree_dnamelookup(&lfs, &btree, 0, name, 3, - &split_id, NULL, NULL, &split_data) => 0; - uint8_t split_buf[4]; - lfsr_data_read(&lfs, split_data, 0, split_buf, 4) => 1; - if (split_id > id) { - int err = lfsr_btree_split(&lfs, &btree, - split_id, - LFSR_DATA_DNAME(0, sim_names[id+1], 3), - LFSR_TAG_INLINED, 1, - LFSR_DATA_BUF(&nums[i % 10], 1), - LFSR_TAG_INLINED, 1, - LFSR_DATA_BUF(split_buf, 1)); - // ignore space issues - if (err == LFS_ERR_NOSPC) { - break; - } - assert(err == 0); - } else { - int err = lfsr_btree_split(&lfs, &btree, - split_id, LFSR_DATA_DNAME(0, name, 3), - LFSR_TAG_INLINED, 1, - LFSR_DATA_BUF(split_buf, 1), - LFSR_TAG_INLINED, 1, - LFSR_DATA_BUF(&nums[i % 10], 1)); - // ignore space issues - if (err == LFS_ERR_NOSPC) { - break; - } - assert(err == 0); - } - - // split sim - memmove(&sim[id+1], &sim[id], sim_size-id); - memmove(&sim_names[id+1], &sim_names[id], (sim_size-id)*3); - sim[id+1] = nums[i % 10]; - memcpy(&sim_names[id+1], name, 3); - sim_size += 1; - - } else if (op == 1) { - // update btree - int err = lfsr_btree_set(&lfs, &btree, id, - LFSR_TAG_INLINED, 1, - LFSR_DATA_BUF(&nums[i % 10], 1)); - // ignore space issues - if (err == LFS_ERR_NOSPC) { - break; - } - assert(err == 0); - - // update sim - sim[id] = nums[i % 10]; - - } else { - // pop from btree - int err = lfsr_btree_pop(&lfs, &btree, id); - // ignore space issues - if (err == LFS_ERR_NOSPC) { - break; - } - assert(err == 0); - - // pop from sim - memmove(&sim[id], &sim[id+1], sim_size-(id+1)); - memmove(&sim_names[id], &sim_names[id+1], (sim_size-(id+1))*3); - sim_size -= 1; - - // our B-tree doesn't actually track the name of id0, so we need - // mirror this in our sim - if (id == 0) { - memcpy(&sim_names[0], "___", 3); - } - } + // check that btree matches sim + printf("expd: ["); + bool first = true; + for (lfs_size_t i = 0; i < sim_size; i++) { + // calculate actual id in btree space + lfs_size_t weighted_id = 0; + for (lfs_size_t j = 0; j < i; j++) { + weighted_id += sim_weights[j]; } - // check that btree matches sim - printf("expd: ["); - bool first = true; - for (lfs_size_t i = 0; i < sim_size; i++) { - if (!first) { - printf(", "); - } - first = false; - printf("%.3s=%c", sim_names[i], sim[i]); + if (!first) { + printf(", "); } - printf("]\n"); - printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); - assert(lfsr_btree_weight(&btree) == sim_size); - - uint8_t buffer[4]; - lfsr_tag_t tag_; - lfs_size_t id_; - lfs_size_t weight_; - lfsr_data_t data_; - for (lfs_size_t i = 0; i < sim_size; i++) { - lfsr_btree_dnamelookup(&lfs, &btree, 0, sim_names[i], 3, - &id_, &tag_, &weight_, &data_) => 0; - assert(tag_ == LFSR_TAG_INLINED); - assert(id_ == i); - assert(weight_ == 1); - lfsr_data_read(&lfs, data_, 0, buffer, 4) => 1; - assert(memcmp(buffer, &sim[i], 1) == 0); - } - - // clean up sim - free(sim); - free(sim_names); + first = false; + printf("%.3sid%dw%d=%c", + sim_names[i], + weighted_id+sim_weights[i]-1, + sim_weights[i], + sim[i]); } -''' + printf("]\n"); + printf("btree: w%d 0x%x.%x\n", + btree.weight, + btree.root.block, + btree.root.trunk); -[cases.t2_btree_find_general_sparse_fuzz] -defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] -defines.W = 5 -defines.SAMPLES = 100 -# -1 => all pseudo-random seeds -# n => reproduce a specific seed -defines.SEED = -1 -in = 'lfs.c' -code = ''' - const char *alphas = "abcdefghijklmnopqrstuvwxyz"; - const char *nums = "0123456789"; - - // iterate through severals seeds that we can reproduce easily - for (uint32_t seed = (SEED == -1 ? 1 : SEED); - (SEED == -1 ? seed < SAMPLES+1 : seed == SEED); - seed++) { - printf("--- seed: %d ---\n", seed); - // create lfs here since we need to reset each iteration, we're - // space constrained and we can't expect gc to work at this point - 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); - - // create a btree - lfsr_btree_t btree = LFSR_BTREE_NULL; - lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, W, - LFSR_DATA_BUF("_", 1)) => 0; - - // set up a simulation to compare against - // - // fun fact this is slower than our actual tree! unfun fact this is - // starting to be a problem... - char *sim = malloc(N); - char (*sim_names)[3] = malloc(N*3); - lfs_size_t *sim_weights = malloc(N*sizeof(lfs_size_t)); - lfs_size_t sim_size = 1; - memset(sim, 0, N); - memset(sim_names, 0, N*3); - memset(sim_weights, 0, N*sizeof(lfs_size_t)); - sim[0] = '_'; - memcpy(&sim_names[0], "___", 3); - sim_weights[0] = W; - - uint32_t prng = seed; - for (lfs_size_t i = 0; i < N; i++) { - // choose a pseudo-random op - uint8_t op = TEST_PRNG(&prng) % 3; - // choose a pseudo-random id - lfs_size_t id = TEST_PRNG(&prng) % (sim_size == 0 ? 1 : sim_size); - // choose a pseudo-random name - lfs_size_t x = TEST_PRNG(&prng) % (26*26*26); - char name[3] = { - alphas[(x/26/26) % 26], alphas[(x/26) % 26], alphas[x % 26] - }; - // choose a pseudo-random weight - lfs_size_t weight = 1 + (TEST_PRNG(&prng) % W); - - // calculate actual id in btree space - lfs_size_t weighted_id = 0; - for (lfs_size_t j = 0; j < id; j++) { - weighted_id += sim_weights[j]; - } - - // don't let sim drop below one element - if (op == 0 || sim_size <= 1) { - // find where to split - lfs_size_t id = 0; - while (id+1 < sim_size - && memcmp(sim_names[id+1], name, 3) <= 0) { - id += 1; - } - // just skip exact matches for now - if (memcmp(sim_names[id], name, 3) == 0) { - continue; - } - - // calculate actual id in btree space - lfs_size_t weighted_id = 0; - for (lfs_size_t j = 0; j < id; j++) { - weighted_id += sim_weights[j]; - } - - // split btree - lfs_size_t split_id; - lfs_size_t split_weight; - lfsr_data_t split_data; - lfsr_btree_dnamelookup(&lfs, &btree, 0, name, 3, - &split_id, NULL, &split_weight, - &split_data) => 0; - uint8_t split_buf[4]; - lfsr_data_read(&lfs, split_data, 0, split_buf, 4) => 1; - if (split_id > weighted_id+sim_weights[id]-1) { - int err = lfsr_btree_split(&lfs, &btree, - split_id, LFSR_DATA_DNAME(0, sim_names[id+1], 3), - LFSR_TAG_INLINED, weight, - LFSR_DATA_BUF(&nums[i % 10], 1), - LFSR_TAG_INLINED, split_weight, - LFSR_DATA_BUF(split_buf, 1)); - // ignore space issues - if (err == LFS_ERR_NOSPC) { - break; - } - assert(err == 0); - } else { - int err = lfsr_btree_split(&lfs, &btree, - split_id, LFSR_DATA_DNAME(0, name, 3), - LFSR_TAG_INLINED, split_weight, - LFSR_DATA_BUF(split_buf, 1), - LFSR_TAG_INLINED, weight, - LFSR_DATA_BUF(&nums[i % 10], 1)); - // ignore space issues - if (err == LFS_ERR_NOSPC) { - break; - } - assert(err == 0); - } - - // split sim - memmove(&sim[id+1], &sim[id], sim_size-id); - memmove(&sim_names[id+1], &sim_names[id], (sim_size-id)*3); - memmove(&sim_weights[id+1], &sim_weights[id], - (sim_size-id)*sizeof(lfs_size_t)); - sim[id+1] = nums[i % 10]; - memcpy(&sim_names[id+1], name, 3); - sim_weights[id+1] = weight; - sim_size += 1; - - } else if (op == 1) { - // update btree - int err = lfsr_btree_set(&lfs, &btree, - weighted_id+sim_weights[id]-1, LFSR_TAG_INLINED, weight, - LFSR_DATA_BUF(&nums[i % 10], 1)); - // ignore space issues - if (err == LFS_ERR_NOSPC) { - break; - } - assert(err == 0); - - // update sim - sim[id] = nums[i % 10]; - sim_weights[id] = weight; - - } else { - // pop from btree - int err = lfsr_btree_pop(&lfs, &btree, - weighted_id+sim_weights[id]-1); - // ignore space issues - if (err == LFS_ERR_NOSPC) { - break; - } - assert(err == 0); - - // pop from sim - memmove(&sim[id], &sim[id+1], sim_size-(id+1)); - memmove(&sim_names[id], &sim_names[id+1], (sim_size-(id+1))*3); - memmove(&sim_weights[id], &sim_weights[id+1], - (sim_size-(id+1))*sizeof(lfs_size_t)); - sim_size -= 1; - - // our B-tree doesn't actually track the name of id0, so we need - // mirror this in our sim - if (id == 0) { - memcpy(&sim_names[0], "___", 3); - } - } - } - - // check that btree matches sim - printf("expd: ["); - bool first = true; - for (lfs_size_t i = 0; i < sim_size; i++) { - // calculate actual id in btree space - lfs_size_t weighted_id = 0; - for (lfs_size_t j = 0; j < i; j++) { - weighted_id += sim_weights[j]; - } - - if (!first) { - printf(", "); - } - first = false; - printf("%.3sid%dw%d=%c", - sim_names[i], - weighted_id+sim_weights[i]-1, - sim_weights[i], - sim[i]); - } - printf("]\n"); - printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); - - lfs_size_t total_weight = 0; - for (lfs_size_t j = 0; j < sim_size; j++) { - total_weight += sim_weights[j]; - } - assert(lfsr_btree_weight(&btree) == total_weight); - - uint8_t buffer[4]; - lfsr_tag_t tag_; - lfs_size_t id_; - lfs_size_t weight_; - lfsr_data_t data_; - for (lfs_size_t i = 0; i < sim_size; i++) { - // calculate actual id in btree space - lfs_size_t weighted_id = 0; - for (lfs_size_t j = 0; j < i; j++) { - weighted_id += sim_weights[j]; - } - - lfsr_btree_dnamelookup(&lfs, &btree, 0, sim_names[i], 3, - &id_, &tag_, &weight_, &data_) => 0; - assert(tag_ == LFSR_TAG_INLINED); - assert(id_ == weighted_id+sim_weights[i]-1); - assert(weight_ == sim_weights[i]); - lfsr_data_read(&lfs, data_, 0, buffer, 4) => 1; - assert(memcmp(buffer, &sim[i], 1) == 0); - } - - // clean up sim - free(sim); - free(sim_names); - free(sim_weights); + lfs_size_t total_weight = 0; + for (lfs_size_t j = 0; j < sim_size; j++) { + total_weight += sim_weights[j]; } + assert(lfsr_btree_weight(&btree) == total_weight); + + uint8_t buffer[4]; + lfsr_tag_t tag_; + lfs_size_t id_; + lfs_size_t weight_; + lfsr_data_t data_; + for (lfs_size_t i = 0; i < sim_size; i++) { + // calculate actual id in btree space + lfs_size_t weighted_id = 0; + for (lfs_size_t j = 0; j < i; j++) { + weighted_id += sim_weights[j]; + } + + lfsr_btree_dnamelookup(&lfs, &btree, 0, sim_names[i], 3, + &id_, &tag_, &weight_, &data_) => 0; + assert(tag_ == LFSR_TAG_INLINED); + assert(id_ == weighted_id+sim_weights[i]-1); + assert(weight_ == sim_weights[i]); + lfsr_data_read(&lfs, data_, 0, buffer, 4) => 1; + assert(memcmp(buffer, &sim[i], 1) == 0); + } + + // clean up sim + free(sim); + free(sim_names); + free(sim_weights); ''' @@ -4068,180 +3915,169 @@ code = ''' [cases.t2_btree_traversal_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] -defines.SAMPLES = 10 -# -1 => all pseudo-random seeds -# n => reproduce a specific seed -defines.SEED = -1 +defines.SEED = 'range(10)' in = 'lfs.c' code = ''' const char *alphas = "abcdefghijklmnopqrstuvwxyz"; - // iterate through severals seeds that we can reproduce easily - for (uint32_t seed = (SEED == -1 ? 1 : SEED); - (SEED == -1 ? seed < SAMPLES+1 : seed == SEED); - seed++) { - printf("--- seed: %d ---\n", seed); - // create lfs here since we need to reset each iteration, we're - // space constrained and we can't expect gc to work at this point - 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); + 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); - // create a btree - lfsr_btree_t btree = LFSR_BTREE_NULL; + // create a btree + lfsr_btree_t btree = LFSR_BTREE_NULL; - // set up a simulation to compare against - // - // fun fact this is slower than our actual tree! unfun fact this is - // starting to be a problem... - char *sim = malloc(N); - lfs_size_t sim_size = 0; - memset(sim, 0, N); + // set up a simulation to compare against + // + // fun fact this is slower than our actual tree! unfun fact this is + // starting to be a problem... + char *sim = malloc(N); + lfs_size_t sim_size = 0; + memset(sim, 0, N); - uint32_t prng = seed; - for (lfs_size_t i = 0; i < N; i++) { - // choose a pseudo-random id - lfs_size_t id = TEST_PRNG(&prng) % (sim_size+1); + uint32_t prng = SEED; + for (lfs_size_t i = 0; i < N; i++) { + // choose a pseudo-random id + lfs_size_t id = TEST_PRNG(&prng) % (sim_size+1); - // add to btree - int err = lfsr_btree_push(&lfs, &btree, id, LFSR_TAG_INLINED, 1, - LFSR_DATA_BUF(&alphas[i % 26], 1)); - // ignore space issues - if (err == LFS_ERR_NOSPC) { - break; - } - assert(err == 0); - - // add to sim - memmove(&sim[id+1], &sim[id], sim_size-id); - sim[id] = alphas[i % 26]; - sim_size += 1; + // add to btree + int err = lfsr_btree_push(&lfs, &btree, id, LFSR_TAG_INLINED, 1, + LFSR_DATA_BUF(&alphas[i % 26], 1)); + // ignore space issues + if (err == LFS_ERR_NOSPC) { + break; } + assert(err == 0); - // check that btree matches sim - printf("expd: ["); - bool first = true; - for (lfs_size_t i = 0; i < sim_size; i++) { - if (!first) { - printf(", "); - } - first = false; - printf("%c", sim[i]); + // add to sim + memmove(&sim[id+1], &sim[id], sim_size-id); + sim[id] = alphas[i % 26]; + sim_size += 1; + } + + // check that btree matches sim + printf("expd: ["); + bool first = true; + for (lfs_size_t i = 0; i < sim_size; i++) { + if (!first) { + printf(", "); } - printf("]\n"); - printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); - assert(lfsr_btree_weight(&btree) == sim_size); + first = false; + printf("%c", sim[i]); + } + printf("]\n"); + printf("btree: w%d 0x%x.%x\n", + btree.weight, + btree.root.block, + btree.root.trunk); + assert(lfsr_btree_weight(&btree) == sim_size); - uint8_t buffer[4]; + uint8_t buffer[4]; + lfsr_tag_t tag_; + lfs_size_t weight_; + for (lfs_size_t i = 0; i < sim_size; i++) { + lfsr_btree_get(&lfs, &btree, i, + &tag_, &weight_, buffer, 4) => 1; + assert(tag_ == LFSR_TAG_INLINED); + assert(weight_ == 1); + assert(memcmp(buffer, &sim[i], 1) == 0); + } + + // and no extra elements + lfsr_btree_get(&lfs, &btree, sim_size, + &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); + memset(seen, 0, (BLOCK_COUNT+7)/8); + + lfsr_btree_traversal_t traversal = LFSR_BTREE_TRAVERSAL_INIT; + + for (lfs_block_t i = 0;; i++) { + // a bit hacky, but this catches infinite loops + assert(i < 2*N); + + lfs_size_t bid_; lfsr_tag_t tag_; lfs_size_t weight_; - for (lfs_size_t i = 0; i < sim_size; i++) { - lfsr_btree_get(&lfs, &btree, i, - &tag_, &weight_, buffer, 4) => 1; - assert(tag_ == LFSR_TAG_INLINED); - assert(weight_ == 1); - assert(memcmp(buffer, &sim[i], 1) == 0); + lfsr_data_t data_; + int err = lfsr_btree_traversal_next(&lfs, &btree, &traversal, + &bid_, &tag_, &weight_, &data_); + assert(!err || err == LFS_ERR_NOENT); + if (err == LFS_ERR_NOENT) { + break; } - // and no extra elements - lfsr_btree_get(&lfs, &btree, sim_size, - &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; + if (tag_ == LFSR_TAG_BTREE) { + lfsr_rbyd_t *branch = (lfsr_rbyd_t *)data_.buf.buffer; + printf("traversal: %d 0x%x w%d btree 0x%x.%x\n", + bid_, + tag_, + weight_, + branch->block, branch->trunk); - // 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_btree_traversal_t traversal = LFSR_BTREE_TRAVERSAL_INIT; - - for (lfs_block_t i = 0;; i++) { - // a bit hacky, but this catches infinite loops - assert(i < 2*N); - - lfs_size_t bid_; - lfsr_tag_t tag_; - lfs_size_t weight_; - lfsr_data_t data_; - int err = lfsr_btree_traversal_next(&lfs, &btree, &traversal, - &bid_, &tag_, &weight_, &data_); - assert(!err || err == LFS_ERR_NOENT); - if (err == LFS_ERR_NOENT) { - break; - } - - if (tag_ == LFSR_TAG_BTREE) { - lfsr_rbyd_t *branch = (lfsr_rbyd_t *)data_.buf.buffer; - printf("traversal: %d 0x%x w%d btree 0x%x.%x\n", - bid_, - tag_, - weight_, - branch->block, branch->trunk); - - // keep track of seen blocks - seen[branch->block / 8] |= 1 << (branch->block % 8); - } else { - printf("traversal: %d 0x%x w%d %d\n", - bid_, - tag_, - weight_, - lfsr_data_size(data_)); - } + // keep track of seen blocks + seen[branch->block / 8] |= 1 << (branch->block % 8); + } else { + printf("traversal: %d 0x%x w%d %d\n", + bid_, + tag_, + weight_, + lfsr_data_size(data_)); } - - // if traversal worked, we should be able to clobber all other blocks - uint8_t buffer_[BLOCK_SIZE]; - memset(buffer_, 0xcc, BLOCK_SIZE); - for (lfs_block_t block = 0; block < BLOCK_COUNT; block++) { - if (!(seen[block / 8] & (1 << (block % 8)))) { - cfg->erase(cfg, block) => 0; - cfg->prog(cfg, block, 0, buffer_, BLOCK_SIZE) => 0; - } - } - free(seen); - - // and the tree should still work - - // check that btree matches sim - printf("expd: ["); - first = true; - for (lfs_size_t i = 0; i < sim_size; i++) { - if (!first) { - printf(", "); - } - first = false; - printf("%c", sim[i]); - } - printf("]\n"); - printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); - assert(lfsr_btree_weight(&btree) == sim_size); - - for (lfs_size_t i = 0; i < sim_size; i++) { - lfsr_btree_get(&lfs, &btree, i, - &tag_, &weight_, buffer, 4) => 1; - assert(tag_ == LFSR_TAG_INLINED); - assert(weight_ == 1); - assert(memcmp(buffer, &sim[i], 1) == 0); - } - - // and no extra elements - lfsr_btree_get(&lfs, &btree, sim_size, - &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; - - // clean up sim - free(sim); - lfs_deinit(&lfs) => 0; } + + // if traversal worked, we should be able to clobber all other blocks + uint8_t buffer_[BLOCK_SIZE]; + memset(buffer_, 0xcc, BLOCK_SIZE); + for (lfs_block_t block = 0; block < BLOCK_COUNT; block++) { + if (!(seen[block / 8] & (1 << (block % 8)))) { + cfg->erase(cfg, block) => 0; + cfg->prog(cfg, block, 0, buffer_, BLOCK_SIZE) => 0; + } + } + free(seen); + + // and the tree should still work + + // check that btree matches sim + printf("expd: ["); + first = true; + for (lfs_size_t i = 0; i < sim_size; i++) { + if (!first) { + printf(", "); + } + first = false; + printf("%c", sim[i]); + } + printf("]\n"); + printf("btree: w%d 0x%x.%x\n", + btree.weight, + btree.root.block, + btree.root.trunk); + assert(lfsr_btree_weight(&btree) == sim_size); + + for (lfs_size_t i = 0; i < sim_size; i++) { + lfsr_btree_get(&lfs, &btree, i, + &tag_, &weight_, buffer, 4) => 1; + assert(tag_ == LFSR_TAG_INLINED); + assert(weight_ == 1); + assert(memcmp(buffer, &sim[i], 1) == 0); + } + + // and no extra elements + lfsr_btree_get(&lfs, &btree, sim_size, + &tag_, &weight_, buffer, 4) => LFS_ERR_NOENT; + + // clean up sim + free(sim); + lfs_deinit(&lfs) => 0; ''' diff --git a/tests/t3_mtree.toml b/tests/t3_mtree.toml index 7d4bcf0a..5cf99b78 100644 --- a/tests/t3_mtree.toml +++ b/tests/t3_mtree.toml @@ -474,117 +474,106 @@ code = ''' [cases.t3_mtree_split_fuzz] defines.N = [5, 10, 20, 40, 80, 160] defines.FORCE_COMPACTION = [false, true] -defines.SAMPLES = 100 -# -1 => all pseudo-random seeds -# n => reproduce a specific seed -defines.SEED = -1 +defines.SEED = 'range(100)' in = 'lfs.c' code = ''' const char *alphas = "abcdefghijklmnopqrstuvwxyz"; - // iterate through severals seeds that we can reproduce easily - for (uint32_t seed = (SEED == -1 ? 1 : SEED); - (SEED == -1 ? seed < SAMPLES+1 : seed == SEED); - seed++) { - printf("--- seed: %d ---\n", seed); - // create lfs here since we need to reset each iteration, we're - // space constrained and we can't expect gc to work at this point - lfs_t lfs; - lfsr_format(&lfs, cfg) => 0; - lfsr_mount(&lfs, cfg) => 0; - lfs_alloc_ack(&lfs); - // remove root dstart for now - lfsr_mdir_commit(&lfs, &lfs.mroot, &(lfs_ssize_t){-1}, LFSR_ATTRS( - LFSR_ATTR(0, UNR, -1, NULL, 0))) => 0; + lfs_t lfs; + lfsr_format(&lfs, cfg) => 0; + lfsr_mount(&lfs, cfg) => 0; + lfs_alloc_ack(&lfs); + // remove root dstart for now + lfsr_mdir_commit(&lfs, &lfs.mroot, &(lfs_ssize_t){-1}, LFSR_ATTRS( + LFSR_ATTR(0, UNR, -1, NULL, 0))) => 0; - // at least keep track of the number of entries we expect - lfs_size_t count = 0; + // at least keep track of the number of entries we expect + lfs_size_t count = 0; - uint32_t prng = seed; - for (lfs_size_t i = 0; i < N; i++) { - // choose a pseudo-random mid - lfs_ssize_t mid = lfsr_mtree_weight(&lfs) == 0 - ? -1 - : (lfs_ssize_t)(TEST_PRNG(&prng) % lfsr_mtree_weight(&lfs)); - // fetch mdir - lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; - // choose a pseudo-random rid - lfs_ssize_t rid = TEST_PRNG(&prng) % (lfsr_mdir_weight(&mdir)+1); + uint32_t prng = SEED; + for (lfs_size_t i = 0; i < N; i++) { + // choose a pseudo-random mid + lfs_ssize_t mid = lfsr_mtree_weight(&lfs) == 0 + ? -1 + : (lfs_ssize_t)(TEST_PRNG(&prng) % lfsr_mtree_weight(&lfs)); + // fetch mdir + lfsr_mdir_t mdir; + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; + // choose a pseudo-random rid + lfs_ssize_t rid = TEST_PRNG(&prng) % (lfsr_mdir_weight(&mdir)+1); - // force a compaction? - if (FORCE_COMPACTION) { - mdir.rbyd.off = cfg->block_size; - lfs.mroot.rbyd.off = cfg->block_size; - } + // force a compaction? + if (FORCE_COMPACTION) { + mdir.rbyd.off = cfg->block_size; + lfs.mroot.rbyd.off = cfg->block_size; + } - // add to rbyd, potentially splitting the mdir - lfsr_mdir_commit(&lfs, &mdir, &rid, LFSR_ATTRS( - LFSR_ATTR(rid, INLINED, +1, &alphas[i % 26], 1))) => 0; + // add to rbyd, potentially splitting the mdir + lfsr_mdir_commit(&lfs, &mdir, &rid, LFSR_ATTRS( + LFSR_ATTR(rid, INLINED, +1, &alphas[i % 26], 1))) => 0; - // make sure we can look up the new entry + // make sure we can look up the new entry + uint8_t buffer[4]; + lfsr_mdir_get(&lfs, &mdir, rid, LFSR_TAG_INLINED, + buffer, 4) => 1; + assert(memcmp(buffer, &alphas[i % 26], 1) == 0); + + count += 1; + } + + // try looking up each entry + lfs_size_t count_ = 0; + + for (lfs_ssize_t mid = (lfsr_mtree_isinlined(&lfs) ? -1 : 0); + mid < (lfs_ssize_t)lfsr_mtree_weight(&lfs); + mid++) { + lfsr_mdir_t mdir; + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; + for (lfs_ssize_t rid = 0; + rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); + rid++) { uint8_t buffer[4]; lfsr_mdir_get(&lfs, &mdir, rid, LFSR_TAG_INLINED, buffer, 4) => 1; - assert(memcmp(buffer, &alphas[i % 26], 1) == 0); - count += 1; + count_ += 1; } - - // try looking up each entry - lfs_size_t count_ = 0; - - for (lfs_ssize_t mid = (lfsr_mtree_isinlined(&lfs) ? -1 : 0); - mid < (lfs_ssize_t)lfsr_mtree_weight(&lfs); - mid++) { - lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; - for (lfs_ssize_t rid = 0; - rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); - rid++) { - uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, rid, LFSR_TAG_INLINED, - buffer, 4) => 1; - - count_ += 1; - } - } - - // the mtree is a bit difficult to simulate, but we can at least test - // we ended up with the right number of entries - assert(count_ == count); - - lfsr_unmount(&lfs) => 0; - - - // check things stay sane after remount - lfsr_mount(&lfs, cfg) => 0; - - // try looking up each entry - count_ = 0; - - for (lfs_ssize_t mid = (lfsr_mtree_isinlined(&lfs) ? -1 : 0); - mid < (lfs_ssize_t)lfsr_mtree_weight(&lfs); - mid++) { - lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; - for (lfs_ssize_t rid = 0; - rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); - rid++) { - uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, rid, LFSR_TAG_INLINED, - buffer, 4) => 1; - - count_ += 1; - } - } - - // the mtree is a bit difficult to simulate, but we can at least test - // we ended up with the right number of entries - assert(count_ == count); - - lfsr_unmount(&lfs) => 0; } + + // the mtree is a bit difficult to simulate, but we can at least test + // we ended up with the right number of entries + assert(count_ == count); + + lfsr_unmount(&lfs) => 0; + + + // check things stay sane after remount + lfsr_mount(&lfs, cfg) => 0; + + // try looking up each entry + count_ = 0; + + for (lfs_ssize_t mid = (lfsr_mtree_isinlined(&lfs) ? -1 : 0); + mid < (lfs_ssize_t)lfsr_mtree_weight(&lfs); + mid++) { + lfsr_mdir_t mdir; + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; + for (lfs_ssize_t rid = 0; + rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); + rid++) { + uint8_t buffer[4]; + lfsr_mdir_get(&lfs, &mdir, rid, LFSR_TAG_INLINED, + buffer, 4) => 1; + + count_ += 1; + } + } + + // the mtree is a bit difficult to simulate, but we can at least test + // we ended up with the right number of entries + assert(count_ == count); + + lfsr_unmount(&lfs) => 0; ''' @@ -1441,140 +1430,129 @@ code = ''' [cases.t3_mtree_drop_fuzz] defines.N = [5, 10, 20, 40, 80, 160] defines.FORCE_COMPACTION = [false, true] -defines.SAMPLES = 100 -# -1 => all pseudo-random seeds -# n => reproduce a specific seed -defines.SEED = -1 +defines.SEED = 'range(100)' in = 'lfs.c' code = ''' const char *alphas = "abcdefghijklmnopqrstuvwxyz"; - // iterate through severals seeds that we can reproduce easily - for (uint32_t seed = (SEED == -1 ? 1 : SEED); - (SEED == -1 ? seed < SAMPLES+1 : seed == SEED); - seed++) { - printf("--- seed: %d ---\n", seed); - // create lfs here since we need to reset each iteration, we're - // space constrained and we can't expect gc to work at this point - lfs_t lfs; - lfsr_format(&lfs, cfg) => 0; - lfsr_mount(&lfs, cfg) => 0; - lfs_alloc_ack(&lfs); - // remove root dstart for now - lfsr_mdir_commit(&lfs, &lfs.mroot, &(lfs_ssize_t){-1}, LFSR_ATTRS( - LFSR_ATTR(0, UNR, -1, NULL, 0))) => 0; + lfs_t lfs; + lfsr_format(&lfs, cfg) => 0; + lfsr_mount(&lfs, cfg) => 0; + lfs_alloc_ack(&lfs); + // remove root dstart for now + lfsr_mdir_commit(&lfs, &lfs.mroot, &(lfs_ssize_t){-1}, LFSR_ATTRS( + LFSR_ATTR(0, UNR, -1, NULL, 0))) => 0; - // at least keep track of the number of entries we expect - lfs_size_t count = 0; + // at least keep track of the number of entries we expect + lfs_size_t count = 0; - uint32_t prng = seed; - for (lfs_size_t i = 0; i < N; i++) { - // choose a pseudo-random mid - lfs_ssize_t mid = lfsr_mtree_weight(&lfs) == 0 - ? -1 - : (lfs_ssize_t)(TEST_PRNG(&prng) % lfsr_mtree_weight(&lfs)); - // fetch mdir - lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; - // choose a pseudo-random rid - lfs_ssize_t rid = TEST_PRNG(&prng) % (lfsr_mdir_weight(&mdir)+1); - // choose to create or delete - uint8_t op = (lfs_size_t)rid == lfsr_mdir_weight(&mdir) - ? 0 - : TEST_PRNG(&prng) % 2; + uint32_t prng = SEED; + for (lfs_size_t i = 0; i < N; i++) { + // choose a pseudo-random mid + lfs_ssize_t mid = lfsr_mtree_weight(&lfs) == 0 + ? -1 + : (lfs_ssize_t)(TEST_PRNG(&prng) % lfsr_mtree_weight(&lfs)); + // fetch mdir + lfsr_mdir_t mdir; + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; + // choose a pseudo-random rid + lfs_ssize_t rid = TEST_PRNG(&prng) % (lfsr_mdir_weight(&mdir)+1); + // choose to create or delete + uint8_t op = (lfs_size_t)rid == lfsr_mdir_weight(&mdir) + ? 0 + : TEST_PRNG(&prng) % 2; - // force a compaction? - if (FORCE_COMPACTION) { - mdir.rbyd.off = cfg->block_size; - lfs.mroot.rbyd.off = cfg->block_size; - } - - // create - if (op == 0) { - // add to rbyd, potentially splitting the mdir - lfsr_mdir_commit(&lfs, &mdir, &rid, LFSR_ATTRS( - LFSR_ATTR(rid, INLINED, +1, - &alphas[i % 26], 1))) => 0; - - // make sure we can look up the new entry - uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, rid, LFSR_TAG_INLINED, - buffer, 4) => 1; - assert(memcmp(buffer, &alphas[i % 26], 1) == 0); - - count += 1; - - // delete - } else { - lfsr_mdir_commit(&lfs, &mdir, &rid, LFSR_ATTRS( - LFSR_ATTR(rid, UNR, -1, NULL, 0))) => 0; - - count -= 1; - } + // force a compaction? + if (FORCE_COMPACTION) { + mdir.rbyd.off = cfg->block_size; + lfs.mroot.rbyd.off = cfg->block_size; } - // try looking up each entry - lfs_size_t count_ = 0; + // create + if (op == 0) { + // add to rbyd, potentially splitting the mdir + lfsr_mdir_commit(&lfs, &mdir, &rid, LFSR_ATTRS( + LFSR_ATTR(rid, INLINED, +1, + &alphas[i % 26], 1))) => 0; - for (lfs_ssize_t mid = (lfsr_mtree_isinlined(&lfs) ? -1 : 0); - mid < (lfs_ssize_t)lfsr_mtree_weight(&lfs); - mid++) { - lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; + // make sure we can look up the new entry + uint8_t buffer[4]; + lfsr_mdir_get(&lfs, &mdir, rid, LFSR_TAG_INLINED, + buffer, 4) => 1; + assert(memcmp(buffer, &alphas[i % 26], 1) == 0); - // drop should make sure we never have empty mdirs - assert(mdir.mid == -1 || mdir.rbyd.weight > 0); + count += 1; - for (lfs_ssize_t rid = 0; - rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); - rid++) { - uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, rid, LFSR_TAG_INLINED, - buffer, 4) => 1; + // delete + } else { + lfsr_mdir_commit(&lfs, &mdir, &rid, LFSR_ATTRS( + LFSR_ATTR(rid, UNR, -1, NULL, 0))) => 0; - count_ += 1; - } + count -= 1; } - - // the mtree is a bit difficult to simulate, but we can at least test - // we ended up with the right number of entries - assert(count_ == count); - - lfsr_unmount(&lfs) => 0; - - - // check things stay sane after remount - lfsr_mount(&lfs, cfg) => 0; - - // try looking up each entry - count_ = 0; - - for (lfs_ssize_t mid = (lfsr_mtree_isinlined(&lfs) ? -1 : 0); - mid < (lfs_ssize_t)lfsr_mtree_weight(&lfs); - mid++) { - lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; - - // drop should make sure we never have empty mdirs - assert(mdir.mid == -1 || mdir.rbyd.weight > 0); - - for (lfs_ssize_t rid = 0; - rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); - rid++) { - uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, rid, LFSR_TAG_INLINED, - buffer, 4) => 1; - - count_ += 1; - } - } - - // the mtree is a bit difficult to simulate, but we can at least test - // we ended up with the right number of entries - assert(count_ == count); - - lfsr_unmount(&lfs) => 0; } + + // try looking up each entry + lfs_size_t count_ = 0; + + for (lfs_ssize_t mid = (lfsr_mtree_isinlined(&lfs) ? -1 : 0); + mid < (lfs_ssize_t)lfsr_mtree_weight(&lfs); + mid++) { + lfsr_mdir_t mdir; + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; + + // drop should make sure we never have empty mdirs + assert(mdir.mid == -1 || mdir.rbyd.weight > 0); + + for (lfs_ssize_t rid = 0; + rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); + rid++) { + uint8_t buffer[4]; + lfsr_mdir_get(&lfs, &mdir, rid, LFSR_TAG_INLINED, + buffer, 4) => 1; + + count_ += 1; + } + } + + // the mtree is a bit difficult to simulate, but we can at least test + // we ended up with the right number of entries + assert(count_ == count); + + lfsr_unmount(&lfs) => 0; + + + // check things stay sane after remount + lfsr_mount(&lfs, cfg) => 0; + + // try looking up each entry + count_ = 0; + + for (lfs_ssize_t mid = (lfsr_mtree_isinlined(&lfs) ? -1 : 0); + mid < (lfs_ssize_t)lfsr_mtree_weight(&lfs); + mid++) { + lfsr_mdir_t mdir; + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; + + // drop should make sure we never have empty mdirs + assert(mdir.mid == -1 || mdir.rbyd.weight > 0); + + for (lfs_ssize_t rid = 0; + rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); + rid++) { + uint8_t buffer[4]; + lfsr_mdir_get(&lfs, &mdir, rid, LFSR_TAG_INLINED, + buffer, 4) => 1; + + count_ += 1; + } + } + + // the mtree is a bit difficult to simulate, but we can at least test + // we ended up with the right number of entries + assert(count_ == count); + + lfsr_unmount(&lfs) => 0; ''' @@ -2540,153 +2518,142 @@ code = ''' defines.N = [5, 10, 20, 40] defines.FORCE_COMPACTION = [false, true] defines.BLOCK_CYCLES = [5, 2, 1] -defines.SAMPLES = 500 -# -1 => all pseudo-random seeds -# n => reproduce a specific seed -defines.SEED = -1 +defines.SEED = 'range(500)' in = 'lfs.c' code = ''' const char *alphas = "abcdefghijklmnopqrstuvwxyz"; - // iterate through severals seeds that we can reproduce easily - for (uint32_t seed = (SEED == -1 ? 1 : SEED); - (SEED == -1 ? seed < SAMPLES+1 : seed == SEED); - seed++) { - printf("--- seed: %d ---\n", seed); - // create lfs here since we need to reset each iteration, we're - // space constrained and we can't expect gc to work at this point - lfs_t lfs; - lfsr_format(&lfs, cfg) => 0; - lfsr_mount(&lfs, cfg) => 0; - lfs_alloc_ack(&lfs); - // remove root dstart for now - lfsr_mdir_commit(&lfs, &lfs.mroot, &(lfs_ssize_t){-1}, LFSR_ATTRS( - LFSR_ATTR(0, UNR, -1, NULL, 0))) => 0; + lfs_t lfs; + lfsr_format(&lfs, cfg) => 0; + lfsr_mount(&lfs, cfg) => 0; + lfs_alloc_ack(&lfs); + // remove root dstart for now + lfsr_mdir_commit(&lfs, &lfs.mroot, &(lfs_ssize_t){-1}, LFSR_ATTRS( + LFSR_ATTR(0, UNR, -1, NULL, 0))) => 0; - // at least keep track of the number of entries we expect - lfs_size_t count = 0; + // at least keep track of the number of entries we expect + lfs_size_t count = 0; - uint32_t prng = seed; - for (lfs_size_t i = 0; i < N; i++) { - // choose a pseudo-random mid - lfs_ssize_t mid = lfsr_mtree_weight(&lfs) == 0 - ? -1 - : (lfs_ssize_t)(TEST_PRNG(&prng) % lfsr_mtree_weight(&lfs)); - // fetch mdir - lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; - // choose a pseudo-random rid - lfs_ssize_t rid = TEST_PRNG(&prng) % (lfsr_mdir_weight(&mdir)+1); - // choose to create or delete - uint8_t op = (lfs_size_t)rid == lfsr_mdir_weight(&mdir) - ? 0 - : TEST_PRNG(&prng) % 3; + uint32_t prng = SEED; + for (lfs_size_t i = 0; i < N; i++) { + // choose a pseudo-random mid + lfs_ssize_t mid = lfsr_mtree_weight(&lfs) == 0 + ? -1 + : (lfs_ssize_t)(TEST_PRNG(&prng) % lfsr_mtree_weight(&lfs)); + // fetch mdir + lfsr_mdir_t mdir; + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; + // choose a pseudo-random rid + lfs_ssize_t rid = TEST_PRNG(&prng) % (lfsr_mdir_weight(&mdir)+1); + // choose to create or delete + uint8_t op = (lfs_size_t)rid == lfsr_mdir_weight(&mdir) + ? 0 + : TEST_PRNG(&prng) % 3; - // force a compaction? - if (FORCE_COMPACTION) { - mdir.rbyd.off = cfg->block_size; - lfs.mroot.rbyd.off = cfg->block_size; - } - - // create - if (op == 0) { - // add to rbyd - lfsr_mdir_commit(&lfs, &mdir, &rid, LFSR_ATTRS( - LFSR_ATTR(rid, INLINED, +1, - &alphas[i % 26], 1))) => 0; - - // make sure we can look up the new entry - uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, rid, LFSR_TAG_INLINED, - buffer, 4) => 1; - assert(memcmp(buffer, &alphas[i % 26], 1) == 0); - - count += 1; - - // update - } else if (op == 1) { - // update rbyd - lfsr_mdir_commit(&lfs, &mdir, &rid, LFSR_ATTRS( - LFSR_ATTR(rid, INLINED, 0, - &alphas[i % 26], 1))) => 0; - - // make sure we can look up the new entry - uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, rid, LFSR_TAG_INLINED, - buffer, 4) => 1; - assert(memcmp(buffer, &alphas[i % 26], 1) == 0); - - // delete - } else { - lfsr_mdir_commit(&lfs, &mdir, &rid, LFSR_ATTRS( - LFSR_ATTR(rid, UNR, -1, NULL, 0))) => 0; - - count -= 1; - } + // force a compaction? + if (FORCE_COMPACTION) { + mdir.rbyd.off = cfg->block_size; + lfs.mroot.rbyd.off = cfg->block_size; } - // try looking up each entry - lfs_size_t count_ = 0; + // create + if (op == 0) { + // add to rbyd + lfsr_mdir_commit(&lfs, &mdir, &rid, LFSR_ATTRS( + LFSR_ATTR(rid, INLINED, +1, + &alphas[i % 26], 1))) => 0; - for (lfs_ssize_t mid = (lfsr_mtree_isinlined(&lfs) ? -1 : 0); - mid < (lfs_ssize_t)lfsr_mtree_weight(&lfs); - mid++) { - lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; + // make sure we can look up the new entry + uint8_t buffer[4]; + lfsr_mdir_get(&lfs, &mdir, rid, LFSR_TAG_INLINED, + buffer, 4) => 1; + assert(memcmp(buffer, &alphas[i % 26], 1) == 0); - // drop should make sure we never have empty mdirs - assert(mdir.mid == -1 || mdir.rbyd.weight > 0); + count += 1; - for (lfs_ssize_t rid = 0; - rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); - rid++) { - uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, rid, LFSR_TAG_INLINED, - buffer, 4) => 1; + // update + } else if (op == 1) { + // update rbyd + lfsr_mdir_commit(&lfs, &mdir, &rid, LFSR_ATTRS( + LFSR_ATTR(rid, INLINED, 0, + &alphas[i % 26], 1))) => 0; - count_ += 1; - } + // make sure we can look up the new entry + uint8_t buffer[4]; + lfsr_mdir_get(&lfs, &mdir, rid, LFSR_TAG_INLINED, + buffer, 4) => 1; + assert(memcmp(buffer, &alphas[i % 26], 1) == 0); + + // delete + } else { + lfsr_mdir_commit(&lfs, &mdir, &rid, LFSR_ATTRS( + LFSR_ATTR(rid, UNR, -1, NULL, 0))) => 0; + + count -= 1; } - - // the mtree is a bit difficult to simulate, but we can at least test - // we ended up with the right number of entries - assert(count_ == count); - - lfsr_unmount(&lfs) => 0; - - - // check things stay sane after remount - lfsr_mount(&lfs, cfg) => 0; - - // try looking up each entry - count_ = 0; - - for (lfs_ssize_t mid = (lfsr_mtree_isinlined(&lfs) ? -1 : 0); - mid < (lfs_ssize_t)lfsr_mtree_weight(&lfs); - mid++) { - lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; - - // drop should make sure we never have empty mdirs - assert(mdir.mid == -1 || mdir.rbyd.weight > 0); - - for (lfs_ssize_t rid = 0; - rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); - rid++) { - uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, rid, LFSR_TAG_INLINED, - buffer, 4) => 1; - - count_ += 1; - } - } - - // the mtree is a bit difficult to simulate, but we can at least test - // we ended up with the right number of entries - assert(count_ == count); - - lfsr_unmount(&lfs) => 0; } + + // try looking up each entry + lfs_size_t count_ = 0; + + for (lfs_ssize_t mid = (lfsr_mtree_isinlined(&lfs) ? -1 : 0); + mid < (lfs_ssize_t)lfsr_mtree_weight(&lfs); + mid++) { + lfsr_mdir_t mdir; + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; + + // drop should make sure we never have empty mdirs + assert(mdir.mid == -1 || mdir.rbyd.weight > 0); + + for (lfs_ssize_t rid = 0; + rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); + rid++) { + uint8_t buffer[4]; + lfsr_mdir_get(&lfs, &mdir, rid, LFSR_TAG_INLINED, + buffer, 4) => 1; + + count_ += 1; + } + } + + // the mtree is a bit difficult to simulate, but we can at least test + // we ended up with the right number of entries + assert(count_ == count); + + lfsr_unmount(&lfs) => 0; + + + // check things stay sane after remount + lfsr_mount(&lfs, cfg) => 0; + + // try looking up each entry + count_ = 0; + + for (lfs_ssize_t mid = (lfsr_mtree_isinlined(&lfs) ? -1 : 0); + mid < (lfs_ssize_t)lfsr_mtree_weight(&lfs); + mid++) { + lfsr_mdir_t mdir; + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; + + // drop should make sure we never have empty mdirs + assert(mdir.mid == -1 || mdir.rbyd.weight > 0); + + for (lfs_ssize_t rid = 0; + rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); + rid++) { + uint8_t buffer[4]; + lfsr_mdir_get(&lfs, &mdir, rid, LFSR_TAG_INLINED, + buffer, 4) => 1; + + count_ += 1; + } + } + + // the mtree is a bit difficult to simulate, but we can at least test + // we ended up with the right number of entries + assert(count_ == count); + + lfsr_unmount(&lfs) => 0; ''' @@ -4041,175 +4008,164 @@ code = ''' 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 -# n => reproduce a specific seed -defines.SEED = -1 +defines.SEED = 'range(100)' in = 'lfs.c' code = ''' const char *alphas = "abcdefghijklmnopqrstuvwxyz"; - // iterate through severals seeds that we can reproduce easily - for (uint32_t seed = (SEED == -1 ? 1 : SEED); - (SEED == -1 ? seed < SAMPLES+1 : seed == SEED); - seed++) { - printf("--- seed: %d ---\n", seed); - // create lfs here since we need to reset each iteration, we're - // space constrained and we can't expect gc to work at this point - lfs_t lfs; - lfsr_format(&lfs, cfg) => 0; - lfsr_mount(&lfs, cfg) => 0; - lfs_alloc_ack(&lfs); - // remove root dstart for now - lfsr_mdir_commit(&lfs, &lfs.mroot, &(lfs_ssize_t){-1}, LFSR_ATTRS( - LFSR_ATTR(0, UNR, -1, NULL, 0))) => 0; + lfs_t lfs; + lfsr_format(&lfs, cfg) => 0; + lfsr_mount(&lfs, cfg) => 0; + lfs_alloc_ack(&lfs); + // remove root dstart for now + lfsr_mdir_commit(&lfs, &lfs.mroot, &(lfs_ssize_t){-1}, LFSR_ATTRS( + LFSR_ATTR(0, UNR, -1, NULL, 0))) => 0; - // at least keep track of the number of entries we expect - lfs_size_t count = 0; + // at least keep track of the number of entries we expect + lfs_size_t count = 0; - uint32_t prng = seed; - for (lfs_size_t i = 0; i < N; i++) { - // choose a pseudo-random mid - lfs_ssize_t mid = lfsr_mtree_weight(&lfs) == 0 - ? -1 - : (lfs_ssize_t)(TEST_PRNG(&prng) % lfsr_mtree_weight(&lfs)); - // fetch mdir - lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; - // choose a pseudo-random rid - lfs_ssize_t rid = TEST_PRNG(&prng) % (lfsr_mdir_weight(&mdir)+1); + uint32_t prng = SEED; + for (lfs_size_t i = 0; i < N; i++) { + // choose a pseudo-random mid + lfs_ssize_t mid = lfsr_mtree_weight(&lfs) == 0 + ? -1 + : (lfs_ssize_t)(TEST_PRNG(&prng) % lfsr_mtree_weight(&lfs)); + // fetch mdir + lfsr_mdir_t mdir; + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; + // choose a pseudo-random rid + lfs_ssize_t rid = TEST_PRNG(&prng) % (lfsr_mdir_weight(&mdir)+1); - // force a compaction? - if (FORCE_COMPACTION) { - mdir.rbyd.off = cfg->block_size; - lfs.mroot.rbyd.off = cfg->block_size; - } + // force a compaction? + if (FORCE_COMPACTION) { + mdir.rbyd.off = cfg->block_size; + lfs.mroot.rbyd.off = cfg->block_size; + } - // add to rbyd, potentially splitting the mdir - lfsr_mdir_commit(&lfs, &mdir, &rid, LFSR_ATTRS( - LFSR_ATTR(rid, INLINED, +1, &alphas[i % 26], 1))) => 0; + // add to rbyd, potentially splitting the mdir + lfsr_mdir_commit(&lfs, &mdir, &rid, LFSR_ATTRS( + LFSR_ATTR(rid, INLINED, +1, &alphas[i % 26], 1))) => 0; - // make sure we can look up the new entry + // make sure we can look up the new entry + uint8_t buffer[4]; + lfsr_mdir_get(&lfs, &mdir, rid, LFSR_TAG_INLINED, + buffer, 4) => 1; + assert(memcmp(buffer, &alphas[i % 26], 1) == 0); + + count += 1; + } + + // try looking up each entry + lfs_size_t count_ = 0; + + for (lfs_ssize_t mid = (lfsr_mtree_isinlined(&lfs) ? -1 : 0); + mid < (lfs_ssize_t)lfsr_mtree_weight(&lfs); + mid++) { + lfsr_mdir_t mdir; + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; + for (lfs_ssize_t rid = 0; + rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); + rid++) { uint8_t buffer[4]; lfsr_mdir_get(&lfs, &mdir, rid, LFSR_TAG_INLINED, buffer, 4) => 1; - assert(memcmp(buffer, &alphas[i % 26], 1) == 0); - count += 1; + count_ += 1; } - - // try looking up each entry - lfs_size_t count_ = 0; - - for (lfs_ssize_t mid = (lfsr_mtree_isinlined(&lfs) ? -1 : 0); - mid < (lfs_ssize_t)lfsr_mtree_weight(&lfs); - mid++) { - lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; - for (lfs_ssize_t rid = 0; - rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); - rid++) { - uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, rid, LFSR_TAG_INLINED, - buffer, 4) => 1; - - count_ += 1; - } - } - - // the mtree is a bit difficult to simulate, but we can at least test - // 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 - uint8_t *seen = malloc((BLOCK_COUNT+7)/8); - memset(seen, 0, (BLOCK_COUNT+7)/8); - - 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 - assert(i < 2*(1+N)); - - lfs_size_t mid_; - lfsr_tag_t tag_; - lfsr_data_t data_; - int err = lfsr_mtree_traversal_next(&lfs, &traversal, - &mid_, &tag_, &data_); - assert(!err || err == LFS_ERR_NOENT); - if (err == LFS_ERR_NOENT) { - break; - } - - if (tag_ == LFSR_TAG_BTREE) { - lfsr_rbyd_t *branch = (lfsr_rbyd_t *)data_.buf.buffer; - printf("traversal: %d 0x%x btree 0x%x.%x\n", - mid_, - tag_, - branch->block, branch->trunk); - - // keep track of seen blocks - seen[branch->block / 8] |= 1 << (branch->block % 8); - } else if (tag_ == LFSR_TAG_MDIR) { - lfsr_mdir_t *mdir = (lfsr_mdir_t*)data_.buf.buffer; - printf("traversal: %d 0x%x mdir 0x{%x,%x}\n", - mid_, - tag_, - mdir->rbyd.block, mdir->redund_block); - - // keep track of seen blocks - seen[mdir->rbyd.block / 8] |= 1 << (mdir->rbyd.block % 8); - seen[mdir->redund_block / 8] |= 1 << (mdir->redund_block % 8); - } else { - // this shouldn't happen - printf("traversal: %d 0x%x %d\n", - mid_, - tag_, - lfsr_data_size(data_)); - assert(false); - } - } - - // if traversal worked, we should be able to clobber all other blocks - uint8_t buffer_[BLOCK_SIZE]; - memset(buffer_, 0xcc, BLOCK_SIZE); - for (lfs_block_t block = 0; block < BLOCK_COUNT; block++) { - if (!(seen[block / 8] & (1 << (block % 8)))) { - cfg->erase(cfg, block) => 0; - cfg->prog(cfg, block, 0, buffer_, BLOCK_SIZE) => 0; - } - } - free(seen); - - // and the tree should still work - - // try looking up each entry - count_ = 0; - - for (lfs_ssize_t mid = (lfsr_mtree_isinlined(&lfs) ? -1 : 0); - mid < (lfs_ssize_t)lfsr_mtree_weight(&lfs); - mid++) { - lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; - for (lfs_ssize_t rid = 0; - rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); - rid++) { - uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, rid, LFSR_TAG_INLINED, - buffer, 4) => 1; - - count_ += 1; - } - } - - // the mtree is a bit difficult to simulate, but we can at least test - // we ended up with the right number of entries - assert(count_ == count); - - lfsr_unmount(&lfs) => 0; } + + // the mtree is a bit difficult to simulate, but we can at least test + // 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 + uint8_t *seen = malloc((BLOCK_COUNT+7)/8); + memset(seen, 0, (BLOCK_COUNT+7)/8); + + 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 + assert(i < 2*(1+N)); + + lfs_size_t mid_; + lfsr_tag_t tag_; + lfsr_data_t data_; + int err = lfsr_mtree_traversal_next(&lfs, &traversal, + &mid_, &tag_, &data_); + assert(!err || err == LFS_ERR_NOENT); + if (err == LFS_ERR_NOENT) { + break; + } + + if (tag_ == LFSR_TAG_BTREE) { + lfsr_rbyd_t *branch = (lfsr_rbyd_t *)data_.buf.buffer; + printf("traversal: %d 0x%x btree 0x%x.%x\n", + mid_, + tag_, + branch->block, branch->trunk); + + // keep track of seen blocks + seen[branch->block / 8] |= 1 << (branch->block % 8); + } else if (tag_ == LFSR_TAG_MDIR) { + lfsr_mdir_t *mdir = (lfsr_mdir_t*)data_.buf.buffer; + printf("traversal: %d 0x%x mdir 0x{%x,%x}\n", + mid_, + tag_, + mdir->rbyd.block, mdir->redund_block); + + // keep track of seen blocks + seen[mdir->rbyd.block / 8] |= 1 << (mdir->rbyd.block % 8); + seen[mdir->redund_block / 8] |= 1 << (mdir->redund_block % 8); + } else { + // this shouldn't happen + printf("traversal: %d 0x%x %d\n", + mid_, + tag_, + lfsr_data_size(data_)); + assert(false); + } + } + + // if traversal worked, we should be able to clobber all other blocks + uint8_t buffer_[BLOCK_SIZE]; + memset(buffer_, 0xcc, BLOCK_SIZE); + for (lfs_block_t block = 0; block < BLOCK_COUNT; block++) { + if (!(seen[block / 8] & (1 << (block % 8)))) { + cfg->erase(cfg, block) => 0; + cfg->prog(cfg, block, 0, buffer_, BLOCK_SIZE) => 0; + } + } + free(seen); + + // and the tree should still work + + // try looking up each entry + count_ = 0; + + for (lfs_ssize_t mid = (lfsr_mtree_isinlined(&lfs) ? -1 : 0); + mid < (lfs_ssize_t)lfsr_mtree_weight(&lfs); + mid++) { + lfsr_mdir_t mdir; + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; + for (lfs_ssize_t rid = 0; + rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); + rid++) { + uint8_t buffer[4]; + lfsr_mdir_get(&lfs, &mdir, rid, LFSR_TAG_INLINED, + buffer, 4) => 1; + + count_ += 1; + } + } + + // the mtree is a bit difficult to simulate, but we can at least test + // we ended up with the right number of entries + assert(count_ == count); + + lfsr_unmount(&lfs) => 0; ''' diff --git a/tests/t5_dirs.toml b/tests/t5_dirs.toml index 48c45bbd..f161e553 100644 --- a/tests/t5_dirs.toml +++ b/tests/t5_dirs.toml @@ -706,99 +706,97 @@ code = ''' defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] defines.PARENT = [false, true] defines.REMOUNT = [false, true] -defines.SAMPLES = 10 -# -1 => all pseudo-random seeds -# n => reproduce a specific seed -defines.SEED = -1 +defines.SEED = 'range(10)' +reentrant = true code = ''' - // iterate through severals seeds that we can reproduce easily - for (uint32_t seed = (SEED == -1 ? 1 : SEED); - (SEED == -1 ? seed < SAMPLES+1 : seed == SEED); - seed++) { - printf("--- seed: %d ---\n", seed); - // reset lfs here each iteration - lfs_t lfs; + // format once per test + lfs_t lfs; + int err = lfsr_mount(&lfs, cfg); + if (err) { lfsr_format(&lfs, cfg) => 0; lfsr_mount(&lfs, cfg) => 0; - if (PARENT) { - lfsr_mkdir(&lfs, "parent") => 0; - } - - // set up a simulation to compare against - lfs_size_t *sim = malloc(N*sizeof(lfs_size_t)); - lfs_size_t sim_size = 0; - - uint32_t prng = seed; - for (lfs_size_t i = 0; i < N; i++) { - // choose a pseudo-random number, truncate to 4 decimals - lfs_size_t x = TEST_PRNG(&prng) % 1000; - - // insert into our sim - for (lfs_size_t j = 0;; j++) { - if (j >= sim_size || sim[j] >= x) { - // already seen? skip - if (sim[j] == x) { - goto next; - } - - // insert - memmove(&sim[j+1], &sim[j], - (sim_size-j)*sizeof(lfs_size_t)); - sim_size += 1; - sim[j] = x; - - // remount? - if (REMOUNT) { - lfsr_unmount(&lfs) => 0; - lfsr_mount(&lfs, cfg) => 0; - // grm should be zero here - assert(lfs.grm[0] == 0); - } - break; - } - } - - // create a directory here - char name[256]; - sprintf(name, "%s/dir%04d", (PARENT ? "parent" : ""), x); - lfsr_mkdir(&lfs, name) => 0; - next:; - } - - // test that our directories match our simulation - for (lfs_size_t j = 0; j < sim_size; j++) { - char name[256]; - sprintf(name, "%s/dir%04d", (PARENT ? "parent" : ""), sim[j]); - struct lfs_info info; - lfsr_stat(&lfs, name, &info) => 0; - char name2[256]; - sprintf(name2, "dir%04d", sim[j]); - assert(strcmp(info.name, name2) == 0); - assert(info.type == LFS_TYPE_DIR); - } - - lfsr_dir_t dir; - lfsr_dir_open(&lfs, &dir, (PARENT ? "parent" : "/")) => 0; - struct lfs_info info; - lfsr_dir_read(&lfs, &dir, &info) => 0; - assert(strcmp(info.name, ".") == 0); - assert(info.type == LFS_TYPE_DIR); - lfsr_dir_read(&lfs, &dir, &info) => 0; - assert(strcmp(info.name, "..") == 0); - assert(info.type == LFS_TYPE_DIR); - for (lfs_size_t j = 0; j < sim_size; j++) { - char name[256]; - sprintf(name, "dir%04d", sim[j]); - lfsr_dir_read(&lfs, &dir, &info) => 0; - assert(strcmp(info.name, name) == 0); - assert(info.type == LFS_TYPE_DIR); - } - lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT; - - // clean up sim/lfs - free(sim); - lfsr_unmount(&lfs) => 0; } + + if (PARENT) { + err = lfsr_mkdir(&lfs, "parent"); + assert(!err || (TEST_PL && err == LFS_ERR_EXIST)); + } + + // set up a simulation to compare against + lfs_size_t *sim = malloc(N*sizeof(lfs_size_t)); + lfs_size_t sim_size = 0; + + uint32_t prng = SEED; + for (lfs_size_t i = 0; i < N; i++) { + // choose a pseudo-random number, truncate to 4 decimals + lfs_size_t x = TEST_PRNG(&prng) % 1000; + + // insert into our sim + for (lfs_size_t j = 0;; j++) { + if (j >= sim_size || sim[j] >= x) { + // already seen? skip + if (j < sim_size && sim[j] == x) { + goto next; + } + + // insert + memmove(&sim[j+1], &sim[j], + (sim_size-j)*sizeof(lfs_size_t)); + sim_size += 1; + sim[j] = x; + break; + } + } + + // create a directory here + char name[256]; + sprintf(name, "%s/dir%04d", (PARENT ? "parent" : ""), x); + err = lfsr_mkdir(&lfs, name); + assert(!err || (TEST_PL && err == LFS_ERR_EXIST)); + next:; + } + + // remount? + if (REMOUNT) { + lfsr_unmount(&lfs) => 0; + lfsr_mount(&lfs, cfg) => 0; + // grm should be zero here + assert(lfs.grm[0] == 0); + } + + // test that our directories match our simulation + for (lfs_size_t j = 0; j < sim_size; j++) { + char name[256]; + sprintf(name, "%s/dir%04d", (PARENT ? "parent" : ""), sim[j]); + struct lfs_info info; + lfsr_stat(&lfs, name, &info) => 0; + char name2[256]; + sprintf(name2, "dir%04d", sim[j]); + assert(strcmp(info.name, name2) == 0); + assert(info.type == LFS_TYPE_DIR); + } + + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, (PARENT ? "parent" : "/")) => 0; + struct lfs_info info; + lfsr_dir_read(&lfs, &dir, &info) => 0; + assert(strcmp(info.name, ".") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_dir_read(&lfs, &dir, &info) => 0; + assert(strcmp(info.name, "..") == 0); + assert(info.type == LFS_TYPE_DIR); + for (lfs_size_t j = 0; j < sim_size; j++) { + char name[256]; + sprintf(name, "dir%04d", sim[j]); + lfsr_dir_read(&lfs, &dir, &info) => 0; + assert(strcmp(info.name, name) == 0); + assert(info.type == LFS_TYPE_DIR); + } + lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT; + + // clean up sim/lfs + free(sim); + lfsr_unmount(&lfs) => 0; '''