# maximize lookahead buffer, we don't actually gc so we only get one pass # of the disk for these tests defines.LOOKAHEAD_SIZE = 'BLOCK_COUNT / 8' # test an empty tree [cases.test_btree_zero] in = 'lfs.c' code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; // create free lookahead memset(lfs.free.buffer, 0, lfs.cfg->lookahead_size); lfs.free.off = 0; lfs.free.size = lfs_min(8*lfs.cfg->lookahead_size, lfs.cfg->block_count); lfs.free.i = 0; lfs_alloc_ack(&lfs); // create an empty tree lfsr_btree_t btree = LFSR_BTREE_NULL; // try looking up tags uint8_t buffer[4]; lfsr_tag_t tag_; lfs_size_t id_; lfs_size_t weight_; lfsr_btree_get(&lfs, &btree, 0, &tag_, &id_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' # test an inlined tree [cases.test_btree_one] in = 'lfs.c' code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; // create free lookahead memset(lfs.free.buffer, 0, lfs.cfg->lookahead_size); lfs.free.off = 0; lfs.free.size = lfs_min(8*lfs.cfg->lookahead_size, lfs.cfg->block_count); lfs.free.i = 0; lfs_alloc_ack(&lfs); // create a single-entry tree lfsr_btree_t btree = LFSR_BTREE_NULL; lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, 1, "a", 1) => 0; // try looking up tags uint8_t buffer[4]; lfsr_tag_t tag_; lfs_size_t id_; lfs_size_t weight_; lfsr_btree_get(&lfs, &btree, 0, &tag_, &id_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(id_ == 0); assert(weight_ == 1); assert(memcmp(buffer, "a", 1) == 0); lfsr_btree_get(&lfs, &btree, 1, &tag_, &id_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' # test a single-rbyd tree [cases.test_btree_two] in = 'lfs.c' code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; // create free lookahead memset(lfs.free.buffer, 0, lfs.cfg->lookahead_size); lfs.free.off = 0; lfs.free.size = lfs_min(8*lfs.cfg->lookahead_size, lfs.cfg->block_count); lfs.free.i = 0; lfs_alloc_ack(&lfs); // create a two-entry tree lfsr_btree_t btree = LFSR_BTREE_NULL; lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, 1, "a", 1) => 0; lfsr_btree_push(&lfs, &btree, 1, LFSR_TAG_INLINED, 1, "b", 1) => 0; // try looking up tags uint8_t buffer[4]; lfsr_tag_t tag_; lfs_size_t id_; lfs_size_t weight_; lfsr_btree_get(&lfs, &btree, 0, &tag_, &id_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(id_ == 0); assert(weight_ == 1); assert(memcmp(buffer, "a", 1) == 0); lfsr_btree_get(&lfs, &btree, 1, &tag_, &id_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(id_ == 1); assert(weight_ == 1); assert(memcmp(buffer, "b", 1) == 0); lfsr_btree_get(&lfs, &btree, 2, &tag_, &id_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' [cases.test_btree_two_backwards] in = 'lfs.c' code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; // create free lookahead memset(lfs.free.buffer, 0, lfs.cfg->lookahead_size); lfs.free.off = 0; lfs.free.size = lfs_min(8*lfs.cfg->lookahead_size, lfs.cfg->block_count); lfs.free.i = 0; lfs_alloc_ack(&lfs); // create a two-entry tree lfsr_btree_t btree = LFSR_BTREE_NULL; lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, 1, "b", 1) => 0; lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, 1, "a", 1) => 0; // try looking up tags uint8_t buffer[4]; lfsr_tag_t tag_; lfs_size_t id_; lfs_size_t weight_; lfsr_btree_get(&lfs, &btree, 0, &tag_, &id_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(id_ == 0); assert(weight_ == 1); assert(memcmp(buffer, "a", 1) == 0); lfsr_btree_get(&lfs, &btree, 1, &tag_, &id_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(id_ == 1); assert(weight_ == 1); assert(memcmp(buffer, "b", 1) == 0); lfsr_btree_get(&lfs, &btree, 2, &tag_, &id_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' # still a single-rbyd tree, just making sure it works [cases.test_btree_three] in = 'lfs.c' code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; // create free lookahead memset(lfs.free.buffer, 0, lfs.cfg->lookahead_size); lfs.free.off = 0; lfs.free.size = lfs_min(8*lfs.cfg->lookahead_size, lfs.cfg->block_count); lfs.free.i = 0; lfs_alloc_ack(&lfs); // create a two-entry tree lfsr_btree_t btree = LFSR_BTREE_NULL; lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, 1, "a", 1) => 0; lfsr_btree_push(&lfs, &btree, 1, LFSR_TAG_INLINED, 1, "b", 1) => 0; lfsr_btree_push(&lfs, &btree, 2, LFSR_TAG_INLINED, 1, "c", 1) => 0; // try looking up tags uint8_t buffer[4]; lfsr_tag_t tag_; lfs_size_t id_; lfs_size_t weight_; lfsr_btree_get(&lfs, &btree, 0, &tag_, &id_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(id_ == 0); assert(weight_ == 1); assert(memcmp(buffer, "a", 1) == 0); lfsr_btree_get(&lfs, &btree, 1, &tag_, &id_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(id_ == 1); assert(weight_ == 1); assert(memcmp(buffer, "b", 1) == 0); lfsr_btree_get(&lfs, &btree, 2, &tag_, &id_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(id_ == 2); assert(weight_ == 1); assert(memcmp(buffer, "c", 1) == 0); lfsr_btree_get(&lfs, &btree, 3, &tag_, &id_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' [cases.test_btree_three_backwards] in = 'lfs.c' code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; // create free lookahead memset(lfs.free.buffer, 0, lfs.cfg->lookahead_size); lfs.free.off = 0; lfs.free.size = lfs_min(8*lfs.cfg->lookahead_size, lfs.cfg->block_count); lfs.free.i = 0; lfs_alloc_ack(&lfs); // create a two-entry tree lfsr_btree_t btree = LFSR_BTREE_NULL; lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, 1, "c", 1) => 0; lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, 1, "b", 1) => 0; lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, 1, "a", 1) => 0; // try looking up tags uint8_t buffer[4]; lfsr_tag_t tag_; lfs_size_t id_; lfs_size_t weight_; lfsr_btree_get(&lfs, &btree, 0, &tag_, &id_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(id_ == 0); assert(weight_ == 1); assert(memcmp(buffer, "a", 1) == 0); lfsr_btree_get(&lfs, &btree, 1, &tag_, &id_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(id_ == 1); assert(weight_ == 1); assert(memcmp(buffer, "b", 1) == 0); lfsr_btree_get(&lfs, &btree, 2, &tag_, &id_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(id_ == 2); assert(weight_ == 1); assert(memcmp(buffer, "c", 1) == 0); lfsr_btree_get(&lfs, &btree, 3, &tag_, &id_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' # try larger trees, when exactly a tree splits depends on the disk geometry, so # we don't really have a better way of testing multi-rbyd trees [cases.test_btree_push] defines.N = [4, 8, 16, 32, 64, 128, 256, 512, 1024] in = 'lfs.c' code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; // create free lookahead memset(lfs.free.buffer, 0, lfs.cfg->lookahead_size); lfs.free.off = 0; lfs.free.size = lfs_min(8*lfs.cfg->lookahead_size, lfs.cfg->block_count); lfs.free.i = 0; lfs_alloc_ack(&lfs); // create a tree with N elements lfsr_btree_t btree = LFSR_BTREE_NULL; const char *alphas = "abcdefghijklmnopqrstuvwxyz"; for (lfs_size_t i = 0; i < N; i++) { lfsr_btree_push(&lfs, &btree, i, LFSR_TAG_INLINED, 1, &alphas[i % 26], 1) => 0; } // check that the elements are in the tree uint8_t buffer[4]; lfsr_tag_t tag_; lfs_size_t id_; lfs_size_t weight_; for (lfs_size_t i = 0; i < N; i++) { lfsr_btree_get(&lfs, &btree, i, &tag_, &id_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(id_ == i); assert(weight_ == 1); assert(memcmp(buffer, &alphas[i % 26], 1) == 0); } // and check that we can't lookup elements that aren't in the tree lfsr_btree_get(&lfs, &btree, N, &tag_, &id_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' [cases.test_btree_push_backwards] defines.N = [4, 8, 16, 32, 64, 128, 256, 512, 1024] in = 'lfs.c' code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; // create free lookahead memset(lfs.free.buffer, 0, lfs.cfg->lookahead_size); lfs.free.off = 0; lfs.free.size = lfs_min(8*lfs.cfg->lookahead_size, lfs.cfg->block_count); lfs.free.i = 0; lfs_alloc_ack(&lfs); // create a tree with N elements lfsr_btree_t btree = LFSR_BTREE_NULL; const char *alphas = "abcdefghijklmnopqrstuvwxyz"; for (lfs_size_t i = 0; i < N; i++) { lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, 1, &alphas[(N-1-i) % 26], 1) => 0; } // check that the elements are in the tree uint8_t buffer[4]; lfsr_tag_t tag_; lfs_size_t id_; lfs_size_t weight_; for (lfs_size_t i = 0; i < N; i++) { lfsr_btree_get(&lfs, &btree, i, &tag_, &id_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(id_ == i); assert(weight_ == 1); assert(memcmp(buffer, &alphas[i % 26], 1) == 0); } // and check that we can't lookup elements that aren't in the tree lfsr_btree_get(&lfs, &btree, N, &tag_, &id_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' [cases.test_btree_push_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] defines.ITER = 10 in = 'lfs.c' code = ''' const char *alphas = "abcdefghijklmnopqrstuvwxyz"; // iterate through severals seeds that we can reproduce easily for (uint32_t seed = 1; seed < ITER+1; 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.free.buffer, 0, lfs.cfg->lookahead_size); lfs.free.off = 0; lfs.free.size = lfs_min(8*lfs.cfg->lookahead_size, lfs.cfg->block_count); lfs.free.i = 0; lfs_alloc_ack(&lfs); // 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); 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 lfsr_btree_push(&lfs, &btree, id, LFSR_TAG_INLINED, 1, &alphas[i % 26], 1) => 0; // add to sim memcpy(&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 < N; i++) { if (!first) { printf(", "); } first = false; printf("%c", sim[i]); } printf("]\n"); assert(btree.weight == N); uint8_t buffer[4]; lfsr_tag_t tag_; lfs_size_t id_; lfs_size_t weight_; for (lfs_size_t i = 0; i < N; i++) { lfsr_btree_get(&lfs, &btree, i, &tag_, &id_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(id_ == i); assert(weight_ == 1); assert(memcmp(buffer, &sim[i], 1) == 0); } // and no extra elements lfsr_btree_get(&lfs, &btree, N, &tag_, &id_, &weight_, buffer, 4) => LFS_ERR_NOENT; // clean up sim free(sim); } ''' [cases.test_btree_sparse] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] defines.W = 5 in = 'lfs.c' code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; // create free lookahead memset(lfs.free.buffer, 0, lfs.cfg->lookahead_size); lfs.free.off = 0; lfs.free.size = lfs_min(8*lfs.cfg->lookahead_size, lfs.cfg->block_count); lfs.free.i = 0; lfs_alloc_ack(&lfs); // create a tree with N elements lfsr_btree_t btree = LFSR_BTREE_NULL; const char *alphas = "abcdefghijklmnopqrstuvwxyz"; for (lfs_size_t i = 0; i < N; i++) { lfsr_btree_push(&lfs, &btree, i*W, LFSR_TAG_INLINED, W, &alphas[i % 26], 1) => 0; } // check that the elements are in the tree uint8_t buffer[4]; lfsr_tag_t tag_; lfs_size_t id_; lfs_size_t weight_; for (lfs_size_t i = 0; i < N; i++) { lfsr_btree_get(&lfs, &btree, i*W+W-1, &tag_, &id_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(id_ == i*W+W-1); assert(weight_ == W); assert(memcmp(buffer, &alphas[i % 26], 1) == 0); } // and check that we can't lookup elements that aren't in the tree lfsr_btree_get(&lfs, &btree, N*W, &tag_, &id_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' [cases.test_btree_sparse_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] defines.W = 5 defines.ITER = 10 in = 'lfs.c' code = ''' const char *alphas = "abcdefghijklmnopqrstuvwxyz"; // iterate through severals seeds that we can reproduce easily for (uint32_t seed = 1; seed < ITER+1; 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.free.buffer, 0, lfs.cfg->lookahead_size); lfs.free.off = 0; lfs.free.size = lfs_min(8*lfs.cfg->lookahead_size, lfs.cfg->block_count); lfs.free.i = 0; lfs_alloc_ack(&lfs); // 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)); 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 lfsr_btree_push(&lfs, &btree, weighted_id, LFSR_TAG_INLINED, weight, &alphas[i % 26], 1) => 0; // add to sim memcpy(&sim[id+1], &sim[id], sim_size-id); memcpy(&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 < 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"); lfs_size_t total_weight = 0; for (lfs_size_t j = 0; j < N; j++) { total_weight += sim_weights[j]; } assert(btree.weight == total_weight); uint8_t buffer[4]; lfsr_tag_t tag_; lfs_size_t id_; 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_, &id_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(id_ == weighted_id+sim_weights[i]-1); assert(weight_ == sim_weights[i]); assert(memcmp(buffer, &sim[i], 1) == 0); } // and no extra elements lfsr_btree_get(&lfs, &btree, total_weight, &tag_, &id_, &weight_, buffer, 4) => LFS_ERR_NOENT; // clean up sim free(sim); } ''' [cases.test_btree_traverse] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] defines.W = 5 in = 'lfs.c' code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; // create free lookahead memset(lfs.free.buffer, 0, lfs.cfg->lookahead_size); lfs.free.off = 0; lfs.free.size = lfs_min(8*lfs.cfg->lookahead_size, lfs.cfg->block_count); lfs.free.i = 0; lfs_alloc_ack(&lfs); // create a tree with N elements lfsr_btree_t btree = LFSR_BTREE_NULL; const char *alphas = "abcdefghijklmnopqrstuvwxyz"; for (lfs_size_t i = 0; i < N; i++) { lfsr_btree_push(&lfs, &btree, i*W, LFSR_TAG_INLINED, W, &alphas[i % 26], 1) => 0; } // traverse the elements in the tree uint8_t buffer[4]; lfs_size_t id_ = -1; lfsr_tag_t tag_; lfs_size_t weight_; for (lfs_size_t i = 0; i < N; i++) { lfsr_btree_get(&lfs, &btree, id_+1, &tag_, &id_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(id_ == i*W+W-1); assert(weight_ == W); assert(memcmp(buffer, &alphas[i % 26], 1) == 0); } // and check that we can't lookup elements that aren't in the tree lfsr_btree_get(&lfs, &btree, id_+1, &tag_, &id_, &weight_, buffer, 4) => LFS_ERR_NOENT; ''' [cases.test_btree_traverse_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] defines.W = 5 defines.ITER = 10 in = 'lfs.c' code = ''' const char *alphas = "abcdefghijklmnopqrstuvwxyz"; // iterate through severals seeds that we can reproduce easily for (uint32_t seed = 1; seed < ITER+1; 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.free.buffer, 0, lfs.cfg->lookahead_size); lfs.free.off = 0; lfs.free.size = lfs_min(8*lfs.cfg->lookahead_size, lfs.cfg->block_count); lfs.free.i = 0; lfs_alloc_ack(&lfs); // 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)); 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 lfsr_btree_push(&lfs, &btree, weighted_id, LFSR_TAG_INLINED, weight, &alphas[i % 26], 1) => 0; // add to sim memcpy(&sim[id+1], &sim[id], sim_size-id); memcpy(&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 < 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"); lfs_size_t total_weight = 0; for (lfs_size_t j = 0; j < N; j++) { total_weight += sim_weights[j]; } assert(btree.weight == total_weight); uint8_t buffer[4]; lfs_size_t id_ = -1; 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, id_+1, &tag_, &id_, &weight_, buffer, 4) => 1; assert(tag_ == LFSR_TAG_INLINED); assert(id_ == weighted_id+sim_weights[i]-1); assert(weight_ == sim_weights[i]); assert(memcmp(buffer, &sim[i], 1) == 0); } // and no extra elements lfsr_btree_get(&lfs, &btree, id_+1, &tag_, &id_, &weight_, buffer, 4) => LFS_ERR_NOENT; // clean up sim free(sim); } ''' # [cases.test_btree_update] # [cases.test_btree_update_fuzz] # [cases.test_btree_update_sparse] # [cases.test_btree_update_sparse_fuzz] # [cases.test_btree_update_traverse] # [cases.test_btree_update_traverse_fuzz] # [cases.test_btree_pop] # [cases.test_btree_pop_fuzz] # [cases.test_btree_split] # [cases.test_btree_split_fuzz] # [cases.test_btree_general_fuzz] # TODO also test copy-on-write!