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; '''