Changed rbyd testing to ignore block_size, now testing with all geometries

This turned out to be a bit tricky, and the scheme in bench_rbyd is
broken.

The core issue is that we don't have a distinction between physical and
logical block sizes, so we can't use a block device configured for one
geometry with a littlefs instance operating on a different geometry. For
this and other reasons we should probably have two configuration
variables in the future, but at the moment that is out of scope.

The problem with the approach in bench_rbyd, which changes the
lfs_config at runtime, is that this breaks emubd which also depends on
lfs_config due to a leaky abstraction. This causes unnoticed memory
corruption.

---

To get something working, the tests now change the underlying BLOCK_SIZE
test define before the tests are run. This starts the test with a block
device configured with a large block_size. To keep this from breaking
things the geometry definitions in the test and bench runners no longer
use default dependent definitions, instead defining everything
explicitly.

With block_size being so large, this makes some of the emubd operations
less performant, notably the --disk option for exposing block device
state during testing.

It would also be nice to use the copy-on-write backend of emubd for some
of the permutation testing, but since it operates on a block-by-block
basis, it doesn't really work when the block device is just one big
block.
This commit is contained in:
Christopher Haster
2023-02-10 18:51:44 -06:00
parent 34168d7874
commit f7dbaf7707
5 changed files with 228 additions and 138 deletions
+16 -20
View File
@@ -1235,12 +1235,16 @@ static void list_implicit_defines(void) {
// geometries to bench
const bench_geometry_t builtin_geometries[] = {
{"default", {{0}, BENCH_CONST(16), BENCH_CONST(512), {0}}},
{"eeprom", {{0}, BENCH_CONST(1), BENCH_CONST(512), {0}}},
{"emmc", {{0}, {0}, BENCH_CONST(512), {0}}},
{"nor", {{0}, BENCH_CONST(1), BENCH_CONST(4096), {0}}},
{"nand", {{0}, BENCH_CONST(4096), BENCH_CONST(32768), {0}}},
{NULL, {{0}, {0}, {0}, {0}}},
#define BENCH_GEO(name, read_size, prog_size, block_size) \
{name, { \
BENCH_CONST(read_size), \
BENCH_CONST(prog_size), \
BENCH_CONST(block_size), \
}},
BENCH_GEOMETRIES
#undef BENCH_GEO
{NULL, {{0}, {0}, {0}}},
};
const bench_geometry_t *bench_geometries = builtin_geometries;
@@ -1273,7 +1277,7 @@ static void list_geometries(void) {
PROG_SIZE,
BLOCK_SIZE,
BLOCK_COUNT,
BLOCK_SIZE*BLOCK_COUNT);
DISK_SIZE);
}
}
@@ -1731,13 +1735,13 @@ invalid_define:
}
}
// comma-separated read/prog/erase/count
// comma-separated read/prog/erase
if (*optarg == '{') {
lfs_size_t sizes[4];
lfs_size_t sizes[3];
size_t count = 0;
char *s = optarg + 1;
while (count < 4) {
while (count < 3) {
char *parsed = NULL;
sizes[count] = strtoumax(s, &parsed, 0);
count += 1;
@@ -1772,24 +1776,20 @@ invalid_define:
geometry->defines[BLOCK_SIZE_i]
= BENCH_LIT(sizes[0]);
}
if (count >= 4) {
geometry->defines[BLOCK_COUNT_i]
= BENCH_LIT(sizes[3]);
}
optarg = s;
goto geometry_next;
}
// leb16-encoded read/prog/erase/count
if (*optarg == ':') {
lfs_size_t sizes[4];
lfs_size_t sizes[3];
size_t count = 0;
char *s = optarg + 1;
while (true) {
char *parsed = NULL;
uintmax_t x = leb16_parse(s, &parsed);
if (parsed == s || count >= 4) {
if (parsed == s || count >= 3) {
break;
}
@@ -1816,10 +1816,6 @@ invalid_define:
geometry->defines[BLOCK_SIZE_i]
= BENCH_LIT(sizes[0]);
}
if (count >= 4) {
geometry->defines[BLOCK_COUNT_i]
= BENCH_LIT(sizes[3]);
}
optarg = s;
goto geometry_next;
}
+32 -20
View File
@@ -87,22 +87,27 @@ intmax_t bench_define(size_t define);
// a few preconfigured defines that control how benches run
#define BENCH_IMPLICIT_DEFINE_COUNT 12
#define BENCH_GEOMETRY_DEFINE_COUNT 3
#define READ_SIZE_i 0
#define PROG_SIZE_i 1
#define BLOCK_SIZE_i 2
#define BLOCK_COUNT_i 3
#define CACHE_SIZE_i 4
#define LOOKAHEAD_SIZE_i 5
#define BLOCK_CYCLES_i 6
#define ERASE_VALUE_i 7
#define ERASE_CYCLES_i 8
#define BADBLOCK_BEHAVIOR_i 9
#define POWERLOSS_BEHAVIOR_i 10
#define DISK_SIZE_i 4
#define CACHE_SIZE_i 5
#define LOOKAHEAD_SIZE_i 6
#define BLOCK_CYCLES_i 7
#define ERASE_VALUE_i 8
#define ERASE_CYCLES_i 9
#define BADBLOCK_BEHAVIOR_i 10
#define POWERLOSS_BEHAVIOR_i 11
#define READ_SIZE bench_define(READ_SIZE_i)
#define PROG_SIZE bench_define(PROG_SIZE_i)
#define BLOCK_SIZE bench_define(BLOCK_SIZE_i)
#define BLOCK_COUNT bench_define(BLOCK_COUNT_i)
#define DISK_SIZE bench_define(DISK_SIZE_i)
#define CACHE_SIZE bench_define(CACHE_SIZE_i)
#define LOOKAHEAD_SIZE bench_define(LOOKAHEAD_SIZE_i)
#define BLOCK_CYCLES bench_define(BLOCK_CYCLES_i)
@@ -112,20 +117,27 @@ intmax_t bench_define(size_t define);
#define POWERLOSS_BEHAVIOR bench_define(POWERLOSS_BEHAVIOR_i)
#define BENCH_IMPLICIT_DEFINES \
BENCH_DEF(READ_SIZE, PROG_SIZE) \
BENCH_DEF(PROG_SIZE, BLOCK_SIZE) \
BENCH_DEF(BLOCK_SIZE, 0) \
BENCH_DEF(BLOCK_COUNT, (1024*1024)/BLOCK_SIZE) \
BENCH_DEF(CACHE_SIZE, lfs_max(64,lfs_max(READ_SIZE,PROG_SIZE))) \
BENCH_DEF(LOOKAHEAD_SIZE, 16) \
BENCH_DEF(BLOCK_CYCLES, -1) \
BENCH_DEF(ERASE_VALUE, 0xff) \
BENCH_DEF(ERASE_CYCLES, 0) \
BENCH_DEF(BADBLOCK_BEHAVIOR, LFS_EMUBD_BADBLOCK_PROGERROR) \
BENCH_DEF(POWERLOSS_BEHAVIOR, LFS_EMUBD_POWERLOSS_NOOP)
/* name value (overridable) */ \
BENCH_DEF(READ_SIZE, PROG_SIZE ) \
BENCH_DEF(PROG_SIZE, BLOCK_SIZE ) \
BENCH_DEF(BLOCK_SIZE, 0 ) \
BENCH_DEF(BLOCK_COUNT, DISK_SIZE/BLOCK_SIZE ) \
BENCH_DEF(DISK_SIZE, 1024*1024 ) \
BENCH_DEF(CACHE_SIZE, lfs_max(64, lfs_max(READ_SIZE, PROG_SIZE))) \
BENCH_DEF(LOOKAHEAD_SIZE, 16 ) \
BENCH_DEF(BLOCK_CYCLES, -1 ) \
BENCH_DEF(ERASE_VALUE, 0xff ) \
BENCH_DEF(ERASE_CYCLES, 0 ) \
BENCH_DEF(BADBLOCK_BEHAVIOR, LFS_EMUBD_BADBLOCK_PROGERROR ) \
BENCH_DEF(POWERLOSS_BEHAVIOR, LFS_EMUBD_POWERLOSS_NOOP )
#define BENCH_GEOMETRY_DEFINE_COUNT 4
#define BENCH_IMPLICIT_DEFINE_COUNT 11
#define BENCH_GEOMETRIES \
/* name read_size prog_size block_size */ \
BENCH_GEO("default", 16, 16, 512 ) \
BENCH_GEO("eeprom", 1, 1, 512 ) \
BENCH_GEO("emmc", 512, 512, 512 ) \
BENCH_GEO("nor", 1, 1, 4096 ) \
BENCH_GEO("nand", 4096, 4096, 32768 )
#endif
+16 -20
View File
@@ -1276,12 +1276,16 @@ static void list_implicit_defines(void) {
// geometries to test
const test_geometry_t builtin_geometries[] = {
{"default", {{0}, TEST_CONST(16), TEST_CONST(512), {0}}},
{"eeprom", {{0}, TEST_CONST(1), TEST_CONST(512), {0}}},
{"emmc", {{0}, {0}, TEST_CONST(512), {0}}},
{"nor", {{0}, TEST_CONST(1), TEST_CONST(4096), {0}}},
{"nand", {{0}, TEST_CONST(4096), TEST_CONST(32768), {0}}},
{NULL, {{0}, {0}, {0}, {0}}},
#define TEST_GEO(name, read_size, prog_size, block_size) \
{name, { \
TEST_CONST(read_size), \
TEST_CONST(prog_size), \
TEST_CONST(block_size), \
}},
TEST_GEOMETRIES
#undef TEST_GEO
{NULL, {{0}, {0}, {0}}},
};
const test_geometry_t *test_geometries = builtin_geometries;
@@ -1314,7 +1318,7 @@ static void list_geometries(void) {
PROG_SIZE,
BLOCK_SIZE,
BLOCK_COUNT,
BLOCK_SIZE*BLOCK_COUNT);
DISK_SIZE);
}
}
@@ -2269,13 +2273,13 @@ invalid_define:
}
}
// comma-separated read/prog/erase/count
// comma-separated read/prog/erase
if (*optarg == '{') {
lfs_size_t sizes[4];
lfs_size_t sizes[3];
size_t count = 0;
char *s = optarg + 1;
while (count < 4) {
while (count < 3) {
char *parsed = NULL;
sizes[count] = strtoumax(s, &parsed, 0);
count += 1;
@@ -2310,24 +2314,20 @@ invalid_define:
geometry->defines[BLOCK_SIZE_i]
= TEST_LIT(sizes[0]);
}
if (count >= 4) {
geometry->defines[BLOCK_COUNT_i]
= TEST_LIT(sizes[3]);
}
optarg = s;
goto geometry_next;
}
// leb16-encoded read/prog/erase/count
if (*optarg == ':') {
lfs_size_t sizes[4];
lfs_size_t sizes[3];
size_t count = 0;
char *s = optarg + 1;
while (true) {
char *parsed = NULL;
uintmax_t x = leb16_parse(s, &parsed);
if (parsed == s || count >= 4) {
if (parsed == s || count >= 3) {
break;
}
@@ -2354,10 +2354,6 @@ invalid_define:
geometry->defines[BLOCK_SIZE_i]
= TEST_LIT(sizes[0]);
}
if (count >= 4) {
geometry->defines[BLOCK_COUNT_i]
= TEST_LIT(sizes[3]);
}
optarg = s;
goto geometry_next;
}
+32 -20
View File
@@ -80,22 +80,27 @@ intmax_t test_define(size_t define);
// a few preconfigured defines that control how tests run
#define TEST_IMPLICIT_DEFINE_COUNT 12
#define TEST_GEOMETRY_DEFINE_COUNT 3
#define READ_SIZE_i 0
#define PROG_SIZE_i 1
#define BLOCK_SIZE_i 2
#define BLOCK_COUNT_i 3
#define CACHE_SIZE_i 4
#define LOOKAHEAD_SIZE_i 5
#define BLOCK_CYCLES_i 6
#define ERASE_VALUE_i 7
#define ERASE_CYCLES_i 8
#define BADBLOCK_BEHAVIOR_i 9
#define POWERLOSS_BEHAVIOR_i 10
#define DISK_SIZE_i 4
#define CACHE_SIZE_i 5
#define LOOKAHEAD_SIZE_i 6
#define BLOCK_CYCLES_i 7
#define ERASE_VALUE_i 8
#define ERASE_CYCLES_i 9
#define BADBLOCK_BEHAVIOR_i 10
#define POWERLOSS_BEHAVIOR_i 11
#define READ_SIZE TEST_DEFINE(READ_SIZE_i)
#define PROG_SIZE TEST_DEFINE(PROG_SIZE_i)
#define BLOCK_SIZE TEST_DEFINE(BLOCK_SIZE_i)
#define BLOCK_COUNT TEST_DEFINE(BLOCK_COUNT_i)
#define DISK_SIZE TEST_DEFINE(DISK_SIZE_i)
#define CACHE_SIZE TEST_DEFINE(CACHE_SIZE_i)
#define LOOKAHEAD_SIZE TEST_DEFINE(LOOKAHEAD_SIZE_i)
#define BLOCK_CYCLES TEST_DEFINE(BLOCK_CYCLES_i)
@@ -105,20 +110,27 @@ intmax_t test_define(size_t define);
#define POWERLOSS_BEHAVIOR TEST_DEFINE(POWERLOSS_BEHAVIOR_i)
#define TEST_IMPLICIT_DEFINES \
TEST_DEF(READ_SIZE, PROG_SIZE) \
TEST_DEF(PROG_SIZE, BLOCK_SIZE) \
TEST_DEF(BLOCK_SIZE, 0) \
TEST_DEF(BLOCK_COUNT, (1024*1024)/BLOCK_SIZE) \
TEST_DEF(CACHE_SIZE, lfs_max(64,lfs_max(READ_SIZE,PROG_SIZE))) \
TEST_DEF(LOOKAHEAD_SIZE, 16) \
TEST_DEF(BLOCK_CYCLES, -1) \
TEST_DEF(ERASE_VALUE, 0xff) \
TEST_DEF(ERASE_CYCLES, 0) \
TEST_DEF(BADBLOCK_BEHAVIOR, LFS_EMUBD_BADBLOCK_PROGERROR) \
TEST_DEF(POWERLOSS_BEHAVIOR, LFS_EMUBD_POWERLOSS_NOOP)
/* name value (overridable) */ \
TEST_DEF(READ_SIZE, PROG_SIZE ) \
TEST_DEF(PROG_SIZE, BLOCK_SIZE ) \
TEST_DEF(BLOCK_SIZE, 0 ) \
TEST_DEF(BLOCK_COUNT, DISK_SIZE/BLOCK_SIZE ) \
TEST_DEF(DISK_SIZE, 1024*1024 ) \
TEST_DEF(CACHE_SIZE, lfs_max(64, lfs_max(READ_SIZE, PROG_SIZE)) ) \
TEST_DEF(LOOKAHEAD_SIZE, 16 ) \
TEST_DEF(BLOCK_CYCLES, -1 ) \
TEST_DEF(ERASE_VALUE, 0xff ) \
TEST_DEF(ERASE_CYCLES, 0 ) \
TEST_DEF(BADBLOCK_BEHAVIOR, LFS_EMUBD_BADBLOCK_PROGERROR ) \
TEST_DEF(POWERLOSS_BEHAVIOR, LFS_EMUBD_POWERLOSS_NOOP )
#define TEST_IMPLICIT_DEFINE_COUNT 11
#define TEST_GEOMETRY_DEFINE_COUNT 4
#define TEST_GEOMETRIES \
/* name read_size prog_size block_size */ \
TEST_GEO("default", 16, 16, 512 ) \
TEST_GEO("eeprom", 1, 1, 512 ) \
TEST_GEO("emmc", 512, 512, 512 ) \
TEST_GEO("nor", 1, 1, 4096 ) \
TEST_GEO("nand", 4096, 4096, 32768 )
#endif
+129 -55
View File
@@ -4,6 +4,15 @@
# test with a number of different erase values
defines.ERASE_VALUE = [0xff, 0x00, 0x1b]
# set block_size to the full size of disk so we can test arbitrarily
# large rbyd trees, we don't really care about block sizes at this
# abstraction level
#
# ok not quite full disk size (we do use the full disk size in bench_rbyd),
# but a bit less since erasing the full disk takes time and we don't want to
# waste time when testing
defines.BLOCK_SIZE = 32768
[cases.test_rbyd_commit]
in = 'lfs.c'
code = '''
@@ -45,7 +54,6 @@ code = '''
[cases.test_rbyd_multi_commit]
in = 'lfs.c'
if = 'BLOCK_SIZE/PROG_SIZE >= 2'
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
@@ -86,7 +94,6 @@ code = '''
[cases.test_rbyd_commit_fetch_commit]
in = 'lfs.c'
if = 'BLOCK_SIZE/PROG_SIZE >= 2'
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
@@ -247,7 +254,6 @@ code = '''
[cases.test_rbyd_multi_lookup]
in = 'lfs.c'
if = 'BLOCK_SIZE/PROG_SIZE >= 2'
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
@@ -468,7 +474,6 @@ code = '''
[cases.test_rbyd_multi_get]
in = 'lfs.c'
if = 'BLOCK_SIZE/PROG_SIZE >= 2'
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
@@ -2124,8 +2129,9 @@ code = '''
[cases.test_rbyd_multi_permutations]
defines.N = 'range(1, 8)'
# large progs take too long for now
if = 'PROG_SIZE < 512'
in = 'lfs.c'
if = 'BLOCK_SIZE/PROG_SIZE >= N'
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
@@ -2315,7 +2321,6 @@ code = '''
[cases.test_rbyd_multi_traverse]
in = 'lfs.c'
if = 'BLOCK_SIZE/PROG_SIZE >= 2'
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
@@ -2500,6 +2505,8 @@ code = '''
[cases.test_rbyd_multi_traverse_permutations]
defines.N = 'range(1, 8)'
# large progs take too long for now
if = 'PROG_SIZE < 512'
in = 'lfs.c'
code = '''
lfs_t lfs;
@@ -2584,10 +2591,13 @@ code = '''
}
'''
# NOTE if we separate physical/logical block sizes we may be able to
# use emubd's copy-on-write copy to speed this up significantly
[cases.test_rbyd_update_permutations]
defines.N = 'range(1, 8)'
# large progs take too long for now
if = 'PROG_SIZE < 512'
in = 'lfs.c'
if = 'BLOCK_SIZE/PROG_SIZE >= N'
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
@@ -2622,7 +2632,7 @@ code = '''
// copy block so we can reset after each remove
lfsr_rbyd_t backup_rbyd = rbyd;
uint8_t backup_block[BLOCK_SIZE];
uint8_t *backup_block = malloc(rbyd.off);
lfs_bd_read(&lfs, NULL, &lfs.rcache, rbyd.off,
rbyd.block, 0, backup_block, rbyd.off) => 0;
@@ -2693,6 +2703,9 @@ code = '''
}
}
// cleanup
free(backup_block);
// test that tree is self-balancing, we should be strictly bounded
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
lfs_size_t n = 1 + N + N;
@@ -2779,7 +2792,6 @@ code = '''
[cases.test_rbyd_remove]
in = 'lfs.c'
if = 'BLOCK_SIZE/PROG_SIZE >= 2'
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
@@ -2885,10 +2897,13 @@ code = '''
&tag_, &id_, &off_, &size_) => LFS_ERR_NOENT;
'''
# NOTE if we separate physical/logical block sizes we may be able to
# use emubd's copy-on-write copy to speed this up significantly
[cases.test_rbyd_remove_permutations]
defines.N = 'range(1, 7)'
# large progs take too long for now
if = 'PROG_SIZE < 512'
in = 'lfs.c'
if = 'BLOCK_SIZE/PROG_SIZE >= N+1'
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
@@ -2942,7 +2957,7 @@ code = '''
// copy block so we can reset after each remove
lfsr_rbyd_t backup_rbyd = rbyd;
uint8_t backup_block[BLOCK_SIZE];
uint8_t *backup_block = malloc(rbyd.off);
lfs_bd_read(&lfs, NULL, &lfs.rcache, rbyd.off,
rbyd.block, 0, backup_block, rbyd.off) => 0;
@@ -3010,6 +3025,9 @@ code = '''
worst_size = lfs_max(worst_size, rbyd.off);
}
// cleanup
free(backup_block);
// next permutation using Heap's algorithm
if (stack[i] < i) {
if (i % 2 == 0) {
@@ -3042,10 +3060,13 @@ code = '''
}
'''
# NOTE if we separate physical/logical block sizes we may be able to
# use emubd's copy-on-write copy to speed this up significantly
[cases.test_rbyd_remove_traverse_permutations]
defines.N = 'range(1, 7)'
# large progs take too long for now
if = 'PROG_SIZE < 512'
in = 'lfs.c'
if = 'BLOCK_SIZE/PROG_SIZE >= N+1'
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
@@ -3096,7 +3117,7 @@ code = '''
// copy block so we can reset after each remove
lfsr_rbyd_t backup_rbyd = rbyd;
uint8_t backup_block[BLOCK_SIZE];
uint8_t *backup_block = malloc(rbyd.off);
lfs_bd_read(&lfs, NULL, &lfs.rcache, rbyd.off,
rbyd.block, 0, backup_block, rbyd.off) => 0;
@@ -3138,6 +3159,9 @@ code = '''
&tag_, &id_, &off_, &size_) => LFS_ERR_NOENT;
}
// cleanup
free(backup_block);
// next permutation using Heap's algorithm
if (stack[i] < i) {
if (i % 2 == 0) {
@@ -3160,7 +3184,6 @@ code = '''
[cases.test_rbyd_remove_missing]
in = 'lfs.c'
if = 'BLOCK_SIZE/PROG_SIZE >= 4'
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
@@ -3314,7 +3337,6 @@ code = '''
[cases.test_rbyd_remove_again]
in = 'lfs.c'
if = 'BLOCK_SIZE/PROG_SIZE >= 8'
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
@@ -3554,7 +3576,6 @@ code = '''
[cases.test_rbyd_remove_all]
in = 'lfs.c'
if = 'BLOCK_SIZE/PROG_SIZE >= 2'
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
@@ -3636,10 +3657,13 @@ code = '''
&tag_, &id_, &off_, &size_) => LFS_ERR_NOENT;
'''
# NOTE if we separate physical/logical block sizes we may be able to
# use emubd's copy-on-write copy to speed this up significantly
[cases.test_rbyd_remove_all_permutations]
defines.N = 'range(1, 7)'
# large progs take too long for now
if = 'PROG_SIZE < 512'
in = 'lfs.c'
if = 'BLOCK_SIZE/PROG_SIZE >= 2*N+1'
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
@@ -3674,7 +3698,7 @@ code = '''
// copy block so we can reset after each remove
lfsr_rbyd_t backup_rbyd = rbyd;
uint8_t backup_block[BLOCK_SIZE];
uint8_t *backup_block = malloc(rbyd.off);
lfs_bd_read(&lfs, NULL, &lfs.rcache, rbyd.off,
rbyd.block, 0, backup_block, rbyd.off) => 0;
@@ -3756,6 +3780,9 @@ code = '''
}
}
// cleanup
free(backup_block);
// test that tree is self-balancing, we should be strictly bounded
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
lfs_size_t n = 1 + N + N + 1;
@@ -3774,6 +3801,8 @@ code = '''
[cases.test_rbyd_random_append_removes]
defines.N = 'range(1, 33)'
defines.ITER = 1000
# large progs take too long for now
if = 'PROG_SIZE < 512'
in = 'lfs.c'
code = '''
lfs_t lfs;
@@ -4100,7 +4129,6 @@ code = '''
[cases.test_rbyd_multi_create]
in = 'lfs.c'
if = 'BLOCK_SIZE/PROG_SIZE >= 3'
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
@@ -4374,8 +4402,9 @@ code = '''
[cases.test_rbyd_multi_create_permutations]
defines.N = 'range(1, 8)'
# large progs take too long for now
if = 'PROG_SIZE < 512'
in = 'lfs.c'
if = 'BLOCK_SIZE/PROG_SIZE >= N'
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
@@ -4594,7 +4623,6 @@ code = '''
[cases.test_rbyd_multi_create_traverse]
in = 'lfs.c'
if = 'BLOCK_SIZE/PROG_SIZE >= 2'
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
@@ -4817,6 +4845,8 @@ code = '''
[cases.test_rbyd_multi_create_traverse_permutations]
defines.N = 'range(1, 8)'
# large progs take too long for now
if = 'PROG_SIZE < 512'
in = 'lfs.c'
code = '''
lfs_t lfs;
@@ -5622,6 +5652,8 @@ code = '''
[cases.test_rbyd_multi_mixed_permutations]
defines.N = 'range(1, 7)'
defines.M = 'range(1, 4)'
# large progs take too long for now
if = 'PROG_SIZE < 512'
in = 'lfs.c'
code = '''
lfs_t lfs;
@@ -6219,6 +6251,8 @@ code = '''
[cases.test_rbyd_multi_mixed_traverse_permutations]
defines.N = 'range(1, 7)'
defines.M = 'range(1, 4)'
# large progs take too long for now
if = 'PROG_SIZE < 512'
in = 'lfs.c'
code = '''
lfs_t lfs;
@@ -6341,11 +6375,14 @@ code = '''
}
'''
# NOTE if we separate physical/logical block sizes we may be able to
# use emubd's copy-on-write copy to speed this up significantly
[cases.test_rbyd_mixed_update_permutations]
defines.N = 'range(1, 4)'
defines.M = 'range(1, 3)'
# large progs take too long for now
if = 'PROG_SIZE < 512'
in = 'lfs.c'
if = 'BLOCK_SIZE/PROG_SIZE >= N'
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
@@ -6391,7 +6428,7 @@ code = '''
// copy block so we can reset after each remove
lfsr_rbyd_t backup_rbyd = rbyd;
uint8_t backup_block[BLOCK_SIZE];
uint8_t *backup_block = malloc(rbyd.off);
lfs_bd_read(&lfs, NULL, &lfs.rcache, rbyd.off,
rbyd.block, 0, backup_block, rbyd.off) => 0;
@@ -6465,6 +6502,9 @@ code = '''
}
}
// cleanup
free(backup_block);
// test that tree is self-balancing, we should be strictly bounded
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
lfs_size_t n = 1 + N + N*M + N*M;
@@ -6478,11 +6518,14 @@ code = '''
}
'''
# NOTE if we separate physical/logical block sizes we may be able to
# use emubd's copy-on-write copy to speed this up significantly
[cases.test_rbyd_mixed_remove_permutations]
defines.N = 'range(1, 7)'
defines.M = 'range(1, 4)'
# large progs take too long for now
if = 'PROG_SIZE < 512'
in = 'lfs.c'
if = 'BLOCK_SIZE/PROG_SIZE >= N+1'
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
@@ -6559,7 +6602,7 @@ code = '''
// copy block so we can reset after each remove
lfsr_rbyd_t backup_rbyd = rbyd;
uint8_t backup_block[BLOCK_SIZE];
uint8_t *backup_block = malloc(rbyd.off);
lfs_bd_read(&lfs, NULL, &lfs.rcache, rbyd.off,
rbyd.block, 0, backup_block, rbyd.off) => 0;
@@ -6651,6 +6694,9 @@ code = '''
worst_size = lfs_max(worst_size, rbyd.off);
}
// cleanup
free(backup_block);
// next permutation using Heap's algorithm
if (stack[i] < i) {
if (i % 2 == 0) {
@@ -6683,11 +6729,14 @@ code = '''
}
'''
# NOTE if we separate physical/logical block sizes we may be able to
# use emubd's copy-on-write copy to speed this up significantly
[cases.test_rbyd_mixed_remove_all_permutations]
defines.N = 'range(1, 4)'
defines.M = 'range(1, 3)'
# large progs take too long for now
if = 'PROG_SIZE < 512'
in = 'lfs.c'
if = 'BLOCK_SIZE/PROG_SIZE >= N'
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
@@ -6733,7 +6782,7 @@ code = '''
// copy block so we can reset after each remove
lfsr_rbyd_t backup_rbyd = rbyd;
uint8_t backup_block[BLOCK_SIZE];
uint8_t *backup_block = malloc(rbyd.off);
lfs_bd_read(&lfs, NULL, &lfs.rcache, rbyd.off,
rbyd.block, 0, backup_block, rbyd.off) => 0;
@@ -6805,6 +6854,9 @@ code = '''
}
}
// cleanup
free(backup_block);
// test that tree is self-balancing, we should be strictly bounded
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
lfs_size_t n = 1 + N + N*M + N*M;
@@ -6917,7 +6969,6 @@ code = '''
[cases.test_rbyd_delete]
in = 'lfs.c'
if = 'BLOCK_SIZE/PROG_SIZE >= 2'
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
@@ -7046,7 +7097,6 @@ code = '''
[cases.test_rbyd_delete_range]
in = 'lfs.c'
if = 'BLOCK_SIZE/PROG_SIZE >= 2'
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
@@ -7285,10 +7335,13 @@ code = '''
=> LFS_ERR_NOENT;
'''
# NOTE if we separate physical/logical block sizes we may be able to
# use emubd's copy-on-write copy to speed this up significantly
[cases.test_rbyd_delete_permutations]
defines.N = 'range(1, 7)'
# large progs take too long for now
if = 'PROG_SIZE < 512'
in = 'lfs.c'
if = 'BLOCK_SIZE/PROG_SIZE >= N+1'
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
@@ -7357,7 +7410,7 @@ code = '''
// copy block so we can reset after each delete
lfsr_rbyd_t backup_rbyd = rbyd;
uint8_t backup_block[BLOCK_SIZE];
uint8_t *backup_block = malloc(rbyd.off);
lfs_bd_read(&lfs, NULL, &lfs.rcache, rbyd.off,
rbyd.block, 0, backup_block, rbyd.off) => 0;
@@ -7415,6 +7468,9 @@ code = '''
worst_size = lfs_max(worst_size, rbyd.off);
}
// cleanup
free(backup_block);
// next permutation using Heap's algorithm
if (stack[i] < i) {
if (i % 2 == 0) {
@@ -7447,14 +7503,14 @@ code = '''
}
'''
# NOTE if we separate physical/logical block sizes we may be able to
# use emubd's copy-on-write copy to speed this up significantly
[cases.test_rbyd_delete_range_permutations]
defines.N = 'range(1, 7)'
defines.M = 'range(1, 4)'
# large progs take too long for now
if = 'PROG_SIZE < 512'
in = 'lfs.c'
if = '''
BLOCK_SIZE/PROG_SIZE >= N+N*M+1
&& BLOCK_SIZE >= 4096
'''
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
@@ -7529,7 +7585,7 @@ code = '''
// copy block so we can reset after each delete
lfsr_rbyd_t backup_rbyd = rbyd;
uint8_t backup_block[BLOCK_SIZE];
uint8_t *backup_block = malloc(rbyd.off);
lfs_bd_read(&lfs, NULL, &lfs.rcache, rbyd.off,
rbyd.block, 0, backup_block, rbyd.off) => 0;
@@ -7617,6 +7673,9 @@ code = '''
worst_size = lfs_max(worst_size, rbyd.off);
}
// cleanup
free(backup_block);
// next permutation using Heap's algorithm
if (stack[i] < i) {
if (i % 2 == 0) {
@@ -7649,10 +7708,13 @@ code = '''
}
'''
# NOTE if we separate physical/logical block sizes we may be able to
# use emubd's copy-on-write copy to speed this up significantly
[cases.test_rbyd_delete_traverse_permutations]
defines.N = 'range(1, 7)'
# large progs take too long for now
if = 'PROG_SIZE < 512'
in = 'lfs.c'
if = 'BLOCK_SIZE/PROG_SIZE >= N+1'
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
@@ -7722,7 +7784,7 @@ code = '''
// copy block so we can reset after each delete
lfsr_rbyd_t backup_rbyd = rbyd;
uint8_t backup_block[BLOCK_SIZE];
uint8_t *backup_block = malloc(rbyd.off);
lfs_bd_read(&lfs, NULL, &lfs.rcache, rbyd.off,
rbyd.block, 0, backup_block, rbyd.off) => 0;
@@ -7767,6 +7829,9 @@ code = '''
&tag_, &id_, &off_, &size_) => LFS_ERR_NOENT;
}
// cleanup
free(backup_block);
// next permutation using Heap's algorithm
if (stack[i] < i) {
if (i % 2 == 0) {
@@ -7787,14 +7852,14 @@ code = '''
}
'''
# NOTE if we separate physical/logical block sizes we may be able to
# use emubd's copy-on-write copy to speed this up significantly
[cases.test_rbyd_delete_traverse_range_permutations]
defines.N = 'range(1, 7)'
defines.M = 'range(1, 4)'
# large progs take too long for now
if = 'PROG_SIZE < 512'
in = 'lfs.c'
if = '''
BLOCK_SIZE/PROG_SIZE >= N+N*M+1
&& BLOCK_SIZE >= 4096
'''
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
@@ -7870,7 +7935,7 @@ code = '''
// copy block so we can reset after each delete
lfsr_rbyd_t backup_rbyd = rbyd;
uint8_t backup_block[BLOCK_SIZE];
uint8_t *backup_block = malloc(rbyd.off);
lfs_bd_read(&lfs, NULL, &lfs.rcache, rbyd.off,
rbyd.block, 0, backup_block, rbyd.off) => 0;
@@ -7930,6 +7995,9 @@ code = '''
&tag_, &id_, &off_, &size_) => LFS_ERR_NOENT;
}
// cleanup
free(backup_block);
// next permutation using Heap's algorithm
if (stack[i] < i) {
if (i % 2 == 0) {
@@ -7952,7 +8020,6 @@ code = '''
[cases.test_rbyd_delete_all]
in = 'lfs.c'
if = 'BLOCK_SIZE/PROG_SIZE >= 2'
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
@@ -8069,7 +8136,6 @@ code = '''
[cases.test_rbyd_delete_all_range]
in = 'lfs.c'
if = 'BLOCK_SIZE/PROG_SIZE >= 2'
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
@@ -8195,13 +8261,13 @@ code = '''
=> LFS_ERR_NOENT;
'''
# NOTE if we separate physical/logical block sizes we may be able to
# use emubd's copy-on-write copy to speed this up significantly
[cases.test_rbyd_delete_all_permutations]
defines.N = 'range(1, 7)'
# large progs take too long for now
if = 'PROG_SIZE < 512'
in = 'lfs.c'
if = '''
BLOCK_SIZE/PROG_SIZE >= 2*N+1
&& BLOCK_SIZE >= 1024
'''
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
@@ -8242,7 +8308,7 @@ code = '''
// copy block so we can reset after each delete
lfsr_rbyd_t backup_rbyd = rbyd;
uint8_t backup_block[BLOCK_SIZE];
uint8_t *backup_block = malloc(rbyd.off);
lfs_bd_read(&lfs, NULL, &lfs.rcache, rbyd.off,
rbyd.block, 0, backup_block, rbyd.off) => 0;
@@ -8334,6 +8400,9 @@ code = '''
}
}
// cleanup
free(backup_block);
// test that tree is self-balancing, we should be strictly bounded
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
lfs_size_t n = 1 + 2*N + 1;
@@ -8347,14 +8416,14 @@ code = '''
}
'''
# NOTE if we separate physical/logical block sizes we may be able to
# use emubd's copy-on-write copy to speed this up significantly
[cases.test_rbyd_delete_all_range_permutations]
defines.N = 'range(1, 7)'
defines.M = 'range(1, 4)'
# large progs take too long for now
if = 'PROG_SIZE < 512'
in = 'lfs.c'
if = '''
BLOCK_SIZE/PROG_SIZE >= N+N*M + N + 1+M
&& BLOCK_SIZE >= 4096
'''
code = '''
lfs_t lfs;
lfs_init(&lfs, cfg) => 0;
@@ -8401,7 +8470,7 @@ code = '''
// copy block so we can reset after each delete
lfsr_rbyd_t backup_rbyd = rbyd;
uint8_t backup_block[BLOCK_SIZE];
uint8_t *backup_block = malloc(rbyd.off);
lfs_bd_read(&lfs, NULL, &lfs.rcache, rbyd.off,
rbyd.block, 0, backup_block, rbyd.off) => 0;
@@ -8507,6 +8576,9 @@ code = '''
}
}
// cleanup
free(backup_block);
// test that tree is self-balancing, we should be strictly bounded
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
lfs_size_t n = 1 + N+N*M + N + 1+M;
@@ -8525,6 +8597,8 @@ code = '''
[cases.test_rbyd_random_create_deletes]
defines.N = 'range(1, 33)'
defines.ITER = 1000
# large progs take too long for now
if = 'PROG_SIZE < 512'
in = 'lfs.c'
code = '''
lfs_t lfs;