3520 lines
121 KiB
TOML
3520 lines
121 KiB
TOML
|
|
# Test this inner rbyd data-structure
|
|
|
|
# test with a number of different erase values
|
|
defines.ERASE_VALUE = [0xff, 0x00, 0x1b, -1]
|
|
|
|
[cases.test_rbyd_commit]
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
|
|
// try an empty commit
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd, NULL) => 0;
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
|
|
// commit with one attribute
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4, NULL)) => 0;
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
|
|
// commit with two attributes
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4, NULL))) => 0;
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
'''
|
|
|
|
[cases.test_rbyd_multi_commit]
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
|
|
// try an empty commit
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd, NULL) => 0;
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
|
|
// commit with one attribute
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd, NULL) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4, NULL)) => 0;
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
|
|
// commit with two attributes
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4, NULL)) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4, NULL)) => 0;
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
'''
|
|
|
|
[cases.test_rbyd_commit_fetch_commit]
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
|
|
// commit with one attribute
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4, NULL)) => 0;
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
|
|
// commit with the second attribute
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4, NULL)) => 0;
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
'''
|
|
|
|
# [cases.test_rbyd_fetchmatch]
|
|
# [cases.test_rbyd_multi_fetchmatch]
|
|
|
|
# TODO we really need to test dense keys...
|
|
|
|
[cases.test_rbyd_lookup]
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
lfs_off_t off;
|
|
lfs_size_t size;
|
|
|
|
// try an empty commit
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd, NULL) => 0;
|
|
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
// commit with one attribute
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4, NULL)) => 0;
|
|
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
// commit with two attributes
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4, NULL))) => 0;
|
|
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
'''
|
|
|
|
[cases.test_rbyd_multi_lookup]
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
lfs_off_t off;
|
|
lfs_size_t size;
|
|
|
|
// try an empty commit
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd, NULL) => 0;
|
|
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
// commit with one attribute
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4, NULL)) => 0;
|
|
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
// commit with two attributes
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4, NULL)) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4, NULL)) => 0;
|
|
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
'''
|
|
|
|
[cases.test_rbyd_get]
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
uint8_t buffer[4];
|
|
|
|
// try an empty commit
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd, NULL) => 0;
|
|
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
// commit with one attribute
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4, NULL)) => 0;
|
|
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
// commit with two attributes
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4, NULL))) => 0;
|
|
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), buffer, 4)
|
|
=> 4;
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), buffer, 4)
|
|
=> 4;
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), buffer, 4)
|
|
=> 4;
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), buffer, 4)
|
|
=> 4;
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
'''
|
|
|
|
[cases.test_rbyd_multi_get]
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
uint8_t buffer[4];
|
|
|
|
// try an empty commit
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd, NULL) => 0;
|
|
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
// commit with one attribute
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4, NULL)) => 0;
|
|
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
// commit with two attributes
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4, NULL)) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4, NULL)) => 0;
|
|
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), buffer, 4)
|
|
=> 4;
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), buffer, 4)
|
|
=> 4;
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), buffer, 4)
|
|
=> 4;
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), buffer, 4)
|
|
=> 4;
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
'''
|
|
|
|
[cases.test_rbyd_traverse]
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
lfs_off_t off;
|
|
lfs_size_t size;
|
|
lfs_srtag_t tag;
|
|
|
|
// traverse requires correct biasing of the weights in the rbyd tree
|
|
// so that lookups return strictly the tag greater than or equal to
|
|
// the tag requested
|
|
rbyd = init_rbyd;
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4, NULL))) => 0;
|
|
|
|
tag = lfs_rbyd_lookup(&lfs, &rbyd, 0, &off, &size);
|
|
assert(tag == LFS_MKRTAG(UATTR, 1, 0));
|
|
tag = lfs_rbyd_lookup(&lfs, &rbyd, lfs_rtag_inc(tag), &off, &size);
|
|
assert(tag == LFS_MKRTAG(UATTR, 2, 0));
|
|
tag = lfs_rbyd_lookup(&lfs, &rbyd, lfs_rtag_inc(tag), &off, &size);
|
|
assert(tag == LFS_ERR_NOENT);
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
tag = lfs_rbyd_lookup(&lfs, &rbyd, 0, &off, &size);
|
|
assert(tag == LFS_MKRTAG(UATTR, 1, 0));
|
|
tag = lfs_rbyd_lookup(&lfs, &rbyd, lfs_rtag_inc(tag), &off, &size);
|
|
assert(tag == LFS_MKRTAG(UATTR, 2, 0));
|
|
tag = lfs_rbyd_lookup(&lfs, &rbyd, lfs_rtag_inc(tag), &off, &size);
|
|
assert(tag == LFS_ERR_NOENT);
|
|
'''
|
|
|
|
[cases.test_rbyd_multi_traverse]
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
lfs_off_t off;
|
|
lfs_size_t size;
|
|
lfs_srtag_t tag;
|
|
|
|
// traverse requires correct biasing of the weights in the rbyd tree
|
|
// so that lookups return strictly the tag greater than or equal to
|
|
// the tag requested
|
|
rbyd = init_rbyd;
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4, NULL)) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4, NULL)) => 0;
|
|
|
|
tag = lfs_rbyd_lookup(&lfs, &rbyd, 0, &off, &size);
|
|
assert(tag == LFS_MKRTAG(UATTR, 1, 0));
|
|
tag = lfs_rbyd_lookup(&lfs, &rbyd, lfs_rtag_inc(tag), &off, &size);
|
|
assert(tag == LFS_MKRTAG(UATTR, 2, 0));
|
|
tag = lfs_rbyd_lookup(&lfs, &rbyd, lfs_rtag_inc(tag), &off, &size);
|
|
assert(tag == LFS_ERR_NOENT);
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
tag = lfs_rbyd_lookup(&lfs, &rbyd, 0, &off, &size);
|
|
assert(tag == LFS_MKRTAG(UATTR, 1, 0));
|
|
tag = lfs_rbyd_lookup(&lfs, &rbyd, lfs_rtag_inc(tag), &off, &size);
|
|
assert(tag == LFS_MKRTAG(UATTR, 2, 0));
|
|
tag = lfs_rbyd_lookup(&lfs, &rbyd, lfs_rtag_inc(tag), &off, &size);
|
|
assert(tag == LFS_ERR_NOENT);
|
|
'''
|
|
|
|
[cases.test_rbyd_bifoliate]
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
lfs_off_t off;
|
|
lfs_size_t size;
|
|
|
|
// create a split in the leaves
|
|
// <b
|
|
// => .-'|
|
|
// 1 1 2
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4, NULL))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
|
|
// split the other direction
|
|
// >b
|
|
// => .-'|
|
|
// 2 2 1
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4, NULL))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
'''
|
|
|
|
[cases.test_rbyd_bflips]
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
lfs_off_t off;
|
|
lfs_size_t size;
|
|
|
|
// ignore a black edge
|
|
// <b <b
|
|
// .-'| => .----'|
|
|
// 1 2 1 2 2
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4, NULL)))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
|
|
// flip a black edge
|
|
// <b >b
|
|
// .-'| => .-'|
|
|
// 1 2 1 2 1
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4, NULL)))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
'''
|
|
|
|
[cases.test_rbyd_trifoliate]
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
lfs_off_t off;
|
|
lfs_size_t size;
|
|
|
|
// ignore a black edge
|
|
// <r
|
|
// .----'|
|
|
// <b => | <b
|
|
// .-'| | .-'|
|
|
// 1 2 1 2 3
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 3, 0, "\xcc\xcc\xcc\xcc", 4, NULL)))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 3, 0);
|
|
|
|
// flip a black edge
|
|
// >r
|
|
// .-'|
|
|
// <b => | >b
|
|
// .-'| .--|-'|
|
|
// 2 3 2 3 1
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 3, 0, "\xcc\xcc\xcc\xcc", 4,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4, NULL)))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 3, 0);
|
|
'''
|
|
|
|
|
|
[cases.test_rbyd_rflips]
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
lfs_off_t off;
|
|
lfs_size_t size;
|
|
|
|
// ignore a red edge and black edge
|
|
// <r <r
|
|
// .----'| .-------'|
|
|
// | <b => | <b
|
|
// | .-'| | .----'|
|
|
// 1 2 3 1 2 3 3
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 3, 0, "\xcc\xcc\xcc\xcc", 4,
|
|
LFS_MKRATTR(UATTR, 3, 0, "\xcc\xcc\xcc\xcc", 4, NULL))))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 3, 0);
|
|
|
|
// ignore a red edge, flip a black edge
|
|
// <r <r
|
|
// .----'| .-------'|
|
|
// | <b => | >b
|
|
// | .-'| | .-'|
|
|
// 1 2 3 1 2 3 2
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 3, 0, "\xcc\xcc\xcc\xcc", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4, NULL))))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 3, 0);
|
|
|
|
// flip a red edge and black edge
|
|
// <r >r
|
|
// .----'| .-'|
|
|
// | <b => | >b
|
|
// | .-'| .--|-'|
|
|
// 1 2 3 1 2 3 1
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 3, 0, "\xcc\xcc\xcc\xcc", 4,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4, NULL))))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 3, 0);
|
|
|
|
// flip a red edge, ignore a black edge
|
|
// <r >r
|
|
// .-'| .-------'|
|
|
// | >b => | >b
|
|
// .--|-'| | .-'|
|
|
// 3 1 2 3 1 2 1
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 3, 0, "\xcc\xcc\xcc\xcc", 4,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4, NULL))))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 3, 0);
|
|
'''
|
|
|
|
[cases.test_rbyd_quadrifoliate]
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
lfs_off_t off;
|
|
lfs_size_t size;
|
|
|
|
// ignore a red edge and black edge
|
|
// <y
|
|
// .-------'|
|
|
// <r | <r
|
|
// .----'| => | .----'|
|
|
// | <b | | <b
|
|
// | .-'| | | .-'|
|
|
// 1 2 3 1 2 3 4
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 3, 0, "\xcc\xcc\xcc\xcc", 4,
|
|
LFS_MKRATTR(UATTR, 4, 0, "\xdd\xdd\xdd\xdd", 4, NULL))))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 3, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 4, 0);
|
|
|
|
// ignore a red edge, flip a black edge
|
|
// <y >y
|
|
// .-------'| .-'|
|
|
// <r | >r | >r
|
|
// .----'| => | .-'| => .--|-'|
|
|
// | <b | | >b | | <b
|
|
// | .-'| | .--|-'| .--|--|-'|
|
|
// 1 3 4 1 3 4 2 1 3 4 2
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 3, 0, "\xcc\xcc\xcc\xcc", 4,
|
|
LFS_MKRATTR(UATTR, 4, 0, "\xdd\xdd\xdd\xdd", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4, NULL))))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 3, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 4, 0);
|
|
|
|
// flip a red edge and black edge
|
|
// >y
|
|
// .-'|
|
|
// <r | >b
|
|
// .----'| => .--|-'|
|
|
// | <b | | >b
|
|
// | .-'| .--|--|-'|
|
|
// 2 3 4 2 3 4 1
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 3, 0, "\xcc\xcc\xcc\xcc", 4,
|
|
LFS_MKRATTR(UATTR, 4, 0, "\xdd\xdd\xdd\xdd", 4,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4, NULL))))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 3, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 4, 0);
|
|
|
|
// flip a red edge, ignore a black edge
|
|
// >y
|
|
// .-------'|
|
|
// <r | >r
|
|
// .-'| => | .-'|
|
|
// | >b | | <b
|
|
// .--|-'| | .--|-'|
|
|
// 4 2 3 4 2 3 1
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 4, 0, "\xdd\xdd\xdd\xdd", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 3, 0, "\xcc\xcc\xcc\xcc", 4,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4, NULL))))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 3, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 4, 0);
|
|
'''
|
|
|
|
[cases.test_rbyd_rotations]
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
lfs_off_t off;
|
|
lfs_size_t size;
|
|
|
|
// all three the same
|
|
// <y
|
|
// .-------'|
|
|
// <r | <r
|
|
// .----'| => | .----'|
|
|
// | <b | | <b
|
|
// | .-'| | | .-'|
|
|
// 1 2 3 1 2 3 4
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 3, 0, "\xcc\xcc\xcc\xcc", 4,
|
|
LFS_MKRATTR(UATTR, 4, 0, "\xdd\xdd\xdd\xdd", 4, NULL))))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 3, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 4, 0);
|
|
|
|
// yellow and red alt the same
|
|
// <y
|
|
// .-------'|
|
|
// <r | <r
|
|
// .----'| => | .----'|
|
|
// | <b | | >b
|
|
// | .-'| | | .-'|
|
|
// 1 2 4 1 2 4 3
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 4, 0, "\xdd\xdd\xdd\xdd", 4,
|
|
LFS_MKRATTR(UATTR, 3, 0, "\xcc\xcc\xcc\xcc", 4, NULL))))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 3, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 4, 0);
|
|
|
|
// yellow and black alt the same
|
|
// <y <y
|
|
// .-------'| .-------'|
|
|
// <r | >r | <r
|
|
// .----'| => | .----'| => | .-'|
|
|
// | >b | | <b | | >b
|
|
// | .-'| | | .-'| | .--|-'|
|
|
// 1 4 2 1 4 2 3 1 4 2 3
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 4, 0, "\xdd\xdd\xdd\xdd", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 3, 0, "\xcc\xcc\xcc\xcc", 4, NULL))))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 3, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 4, 0);
|
|
|
|
// red and black alt the same
|
|
// >y <y
|
|
// .-------'| .----'|
|
|
// >r | <r | <r
|
|
// .----'| => | .----'| => | .-'|
|
|
// | <b | | <b | | >b
|
|
// | .-'| | | .-'| .--|--|-'|
|
|
// 4 1 2 4 1 2 3 4 1 2 3
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 4, 0, "\xdd\xdd\xdd\xdd", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 3, 0, "\xcc\xcc\xcc\xcc", 4, NULL))))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 3, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 4, 0);
|
|
'''
|
|
|
|
[cases.test_rbyd_ysplits]
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
lfs_off_t off;
|
|
lfs_size_t size;
|
|
|
|
// split a yellow triple, not taking any alt
|
|
// <b
|
|
// .-'|
|
|
// <y <y |
|
|
// .-------'| .-------'| |
|
|
// | <r => | <r |
|
|
// | .----'| | .----' |
|
|
// | | <b | | <b
|
|
// | | .-'| | | .----'|
|
|
// 1 2 3 4 1 2 3 4 4
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 3, 0, "\xcc\xcc\xcc\xcc", 4,
|
|
LFS_MKRATTR(UATTR, 4, 0, "\xdd\xdd\xdd\xdd", 4,
|
|
LFS_MKRATTR(UATTR, 4, 0, "\xdd\xdd\xdd\xdd", 4, NULL)))))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 3, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 4, 0);
|
|
|
|
// split a yellow triple, taking the black alt
|
|
// <b
|
|
// .-'|
|
|
// <y <y |
|
|
// .-------'| .-------'| |
|
|
// | <r => | <r |
|
|
// | .----'| | .----' |
|
|
// | | <b | | >b
|
|
// | | .-'| | | .-'|
|
|
// 1 2 3 4 1 2 3 4 3
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 3, 0, "\xcc\xcc\xcc\xcc", 4,
|
|
LFS_MKRATTR(UATTR, 4, 0, "\xdd\xdd\xdd\xdd", 4,
|
|
LFS_MKRATTR(UATTR, 3, 0, "\xcc\xcc\xcc\xcc", 4, NULL)))))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 3, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 4, 0);
|
|
|
|
// split a yellow triple, taking the red alt
|
|
// <y >b
|
|
// .-------'| .-'|
|
|
// | <r | <b
|
|
// | .----'| => .--------|-'|
|
|
// | | <b | <b |
|
|
// | | .-'| | .-'| |
|
|
// 1 2 3 4 1 2 3 4 2
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 3, 0, "\xcc\xcc\xcc\xcc", 4,
|
|
LFS_MKRATTR(UATTR, 4, 0, "\xdd\xdd\xdd\xdd", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4, NULL)))))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 3, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 4, 0);
|
|
|
|
// split a yellow triple, taking the yellow alt
|
|
// <y >b
|
|
// .-------'| .-'|
|
|
// | <r | >b
|
|
// | .----'| => .-----|-'|
|
|
// | | <b | <b |
|
|
// | | .-'| | .-'| |
|
|
// 1 2 3 4 1 2 3 4 1
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 3, 0, "\xcc\xcc\xcc\xcc", 4,
|
|
LFS_MKRATTR(UATTR, 4, 0, "\xdd\xdd\xdd\xdd", 4,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4, NULL)))))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 3, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 4, 0);
|
|
'''
|
|
|
|
[cases.test_rbyd_quintifoliate]
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
lfs_off_t off;
|
|
lfs_size_t size;
|
|
|
|
// split a yellow triple, not taking any alt
|
|
// <b
|
|
// .-'|
|
|
// <y |
|
|
// .-------'| |
|
|
// <y | <r |
|
|
// .-------'| => | .----' |
|
|
// | <r | | <r
|
|
// | .----'| | | .----'|
|
|
// | | <b | | | <b
|
|
// | | .-'| | | | .-'|
|
|
// 1 2 3 4 1 2 3 4 5
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 3, 0, "\xcc\xcc\xcc\xcc", 4,
|
|
LFS_MKRATTR(UATTR, 4, 0, "\xdd\xdd\xdd\xdd", 4,
|
|
LFS_MKRATTR(UATTR, 5, 0, "\xee\xee\xee\xee", 4, NULL)))))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 3, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 4, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 5, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 5, 0);
|
|
|
|
// split a yellow triple, taking the black alt
|
|
// <b
|
|
// .-'|
|
|
// <y |
|
|
// .-------'| |
|
|
// <y | <r |
|
|
// .-------'| => | .----' |
|
|
// | <r | | >r
|
|
// | .----'| | | .-'|
|
|
// | | <b | | | >b
|
|
// | | .-'| | | .--|-'|
|
|
// 1 2 4 5 1 2 4 5 3
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 4, 0, "\xdd\xdd\xdd\xdd", 4,
|
|
LFS_MKRATTR(UATTR, 5, 0, "\xee\xee\xee\xee", 4,
|
|
LFS_MKRATTR(UATTR, 3, 0, "\xcc\xcc\xcc\xcc", 4, NULL)))))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 3, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 4, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 5, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 5, 0);
|
|
|
|
// split a yellow triple, taking the red alt
|
|
// >b
|
|
// .-'|
|
|
// <y | <r
|
|
// .-------'| .--------|-'|
|
|
// | <r | | >b
|
|
// | .----'| => | .-----|-'|
|
|
// | | <b | | <b |
|
|
// | | .-'| | | .-'| |
|
|
// 1 3 4 5 1 3 4 5 2
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 3, 0, "\xcc\xcc\xcc\xcc", 4,
|
|
LFS_MKRATTR(UATTR, 4, 0, "\xdd\xdd\xdd\xdd", 4,
|
|
LFS_MKRATTR(UATTR, 5, 0, "\xee\xee\xee\xee", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4, NULL)))))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 3, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 4, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 5, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 5, 0);
|
|
|
|
// split a yellow triple, taking the yellow alt
|
|
// >b
|
|
// .-'|
|
|
// <y | >r
|
|
// .-------'| .-----|-'|
|
|
// | <r | | >b
|
|
// | .----'| => .--|-----|-'|
|
|
// | | <b | | <b |
|
|
// | | .-'| | | .-'| |
|
|
// 2 3 4 5 2 3 4 5 1
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 3, 0, "\xcc\xcc\xcc\xcc", 4,
|
|
LFS_MKRATTR(UATTR, 4, 0, "\xdd\xdd\xdd\xdd", 4,
|
|
LFS_MKRATTR(UATTR, 5, 0, "\xee\xee\xee\xee", 4,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4, NULL)))))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 3, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 4, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 5, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 5, 0);
|
|
'''
|
|
|
|
[cases.test_rbyd_prunes]
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
lfs_off_t off;
|
|
lfs_size_t size;
|
|
|
|
// don't prune
|
|
// <b <b
|
|
// .-'| .----'|
|
|
// <y | <y |
|
|
// .-------'| | .-------'| |
|
|
// | <r | | <r |
|
|
// | .----' | => | .----' |
|
|
// | | <r | | <r
|
|
// | | .----'| | | .-------'|
|
|
// | | | <b | | | <b
|
|
// | | | .-'| | | | .----'|
|
|
// 1 2 3 4 5 1 2 3 4 5 5
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 3, 0, "\xcc\xcc\xcc\xcc", 4,
|
|
LFS_MKRATTR(UATTR, 4, 0, "\xdd\xdd\xdd\xdd", 4,
|
|
LFS_MKRATTR(UATTR, 5, 0, "\xee\xee\xee\xee", 4,
|
|
LFS_MKRATTR(UATTR, 5, 0, "\xee\xee\xee\xee", 4, NULL))))))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 3, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 4, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 5, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 5, 0);
|
|
|
|
// prune by taking a red alt
|
|
// <b
|
|
// .-'|
|
|
// <y | >b
|
|
// .-------'| | .-'|
|
|
// | <r | | <b
|
|
// | .----' | => .-----------|-'|
|
|
// | | <r | <r |
|
|
// | | .----'| | .----'| |
|
|
// | | | <b | | <b |
|
|
// | | | .-'| | | .-'| |
|
|
// 1 2 3 4 5 1 2 3 4 5 2
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 3, 0, "\xcc\xcc\xcc\xcc", 4,
|
|
LFS_MKRATTR(UATTR, 4, 0, "\xdd\xdd\xdd\xdd", 4,
|
|
LFS_MKRATTR(UATTR, 5, 0, "\xee\xee\xee\xee", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4, NULL))))))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 3, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 4, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 5, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 5, 0);
|
|
|
|
// prune by taking a yellow alt (this needs to prune during the rflip)
|
|
// <b
|
|
// .-'|
|
|
// <y | >b
|
|
// .-------'| | .-'|
|
|
// | <r | | >b
|
|
// | .----' | => .--------|-'|
|
|
// | | <r | <r |
|
|
// | | .----'| | .----'| |
|
|
// | | | <b | | <b |
|
|
// | | | .-'| | | .-'| |
|
|
// 1 2 3 4 5 1 2 3 4 5 1
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 3, 0, "\xcc\xcc\xcc\xcc", 4,
|
|
LFS_MKRATTR(UATTR, 4, 0, "\xdd\xdd\xdd\xdd", 4,
|
|
LFS_MKRATTR(UATTR, 5, 0, "\xee\xee\xee\xee", 4,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4, NULL))))))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 3, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 4, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 5, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 5, 0);
|
|
'''
|
|
|
|
[cases.test_rbyd_sextifoliate]
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
lfs_off_t off;
|
|
lfs_size_t size;
|
|
|
|
// don't prune
|
|
// <b
|
|
// .----'|
|
|
// <b <y |
|
|
// .-'| .-------'| |
|
|
// <y | | <r |
|
|
// .-------'| | | .----' |
|
|
// | <r | | | <y
|
|
// | .----' | => | | .-------'|
|
|
// | | <r | | | <r
|
|
// | | .----'| | | | .----'|
|
|
// | | | <b | | | | <b
|
|
// | | | .-'| | | | | .-'|
|
|
// 1 2 3 4 5 1 2 3 4 5 6
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 3, 0, "\xcc\xcc\xcc\xcc", 4,
|
|
LFS_MKRATTR(UATTR, 4, 0, "\xdd\xdd\xdd\xdd", 4,
|
|
LFS_MKRATTR(UATTR, 5, 0, "\xee\xee\xee\xee", 4,
|
|
LFS_MKRATTR(UATTR, 6, 0, "\xff\xff\xff\xff", 4, NULL))))))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 3, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 4, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 5, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 5, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 6, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 6, 0);
|
|
|
|
// prune by taking a red alt
|
|
// <b >b
|
|
// .-'| .-'|
|
|
// <y | | <r
|
|
// .-------'| | .-----------|-'|
|
|
// | <r | | | >b
|
|
// | .----' | => | .--------|-'|
|
|
// | | <r | | <r |
|
|
// | | .----'| | | .----'| |
|
|
// | | | <b | | | <b |
|
|
// | | | .-'| | | | .-'| |
|
|
// 1 3 4 5 6 1 3 4 5 6 2
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 3, 0, "\xcc\xcc\xcc\xcc", 4,
|
|
LFS_MKRATTR(UATTR, 4, 0, "\xdd\xdd\xdd\xdd", 4,
|
|
LFS_MKRATTR(UATTR, 5, 0, "\xee\xee\xee\xee", 4,
|
|
LFS_MKRATTR(UATTR, 6, 0, "\xff\xff\xff\xff", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4, NULL))))))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 3, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 4, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 5, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 5, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 6, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 6, 0);
|
|
|
|
// prune by taking a yellow alt (this needs to prune during the rflip)
|
|
// <b >b
|
|
// .-'| .-'|
|
|
// <y | | >r
|
|
// .-------'| | .--------|-'|
|
|
// | <r | | | >b
|
|
// | .----' | => .--|--------|-'|
|
|
// | | <r | | <r |
|
|
// | | .----'| | | .----'| |
|
|
// | | | <b | | | <b |
|
|
// | | | .-'| | | | .-'| |
|
|
// 2 3 4 5 6 2 3 4 5 6 1
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 3, 0, "\xcc\xcc\xcc\xcc", 4,
|
|
LFS_MKRATTR(UATTR, 4, 0, "\xdd\xdd\xdd\xdd", 4,
|
|
LFS_MKRATTR(UATTR, 5, 0, "\xee\xee\xee\xee", 4,
|
|
LFS_MKRATTR(UATTR, 6, 0, "\xff\xff\xff\xff", 4,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4, NULL))))))) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 3, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 4, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 5, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 5, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 6, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 6, 0);
|
|
'''
|
|
|
|
[cases.test_rbyd_permutations]
|
|
defines.N = 'range(1, 8)'
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
lfs_off_t off;
|
|
lfs_size_t size;
|
|
|
|
// test all permutations of a given size
|
|
uint8_t perm[N];
|
|
unsigned stack[N];
|
|
for (uint8_t i = 0; i < N; i++) {
|
|
perm[i] = i;
|
|
stack[i] = 0;
|
|
}
|
|
|
|
unsigned i = 1;
|
|
while (i < N) {
|
|
// print permutation to help debugging
|
|
printf("--- permutation: [");
|
|
for (unsigned j = 0; j < N; j++) {
|
|
if (j > 0) {
|
|
printf(", ");
|
|
}
|
|
printf("%d", perm[j]+1);
|
|
}
|
|
printf("] ---\n");
|
|
|
|
// build the attribute list for the current permutation
|
|
struct lfs_rattr attrs[N];
|
|
for (unsigned j = 0; j < N; j++) {
|
|
attrs[j] = *LFS_MKRATTR(
|
|
UATTR, perm[j]+1, 0,
|
|
"\xaa\xaa\xaa\xaa", 4,
|
|
(j+1 < N) ? &attrs[j+1] : NULL);
|
|
}
|
|
|
|
// test the given permutation
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd, attrs) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
for (unsigned j = 0; j < N; j++) {
|
|
lfs_rbyd_lookup(&lfs, &rbyd,
|
|
LFS_MKRTAG(UATTR, j+1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, j+1, 0);
|
|
}
|
|
|
|
// next permutation using Heap's algorithm
|
|
if (stack[i] < i) {
|
|
if (i % 2 == 0) {
|
|
uint8_t t = perm[0];
|
|
perm[0] = perm[i];
|
|
perm[i] = t;
|
|
} else {
|
|
uint8_t t = perm[stack[i]];
|
|
perm[stack[i]] = perm[i];
|
|
perm[i] = t;
|
|
}
|
|
stack[i] += 1;
|
|
i = 1;
|
|
} else {
|
|
stack[i] = 0;
|
|
i += 1;
|
|
}
|
|
}
|
|
'''
|
|
|
|
[cases.test_rbyd_multi_permutations]
|
|
defines.N = 'range(1, 8)'
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
lfs_off_t off;
|
|
lfs_size_t size;
|
|
|
|
// test all permutations of a given size
|
|
uint8_t perm[N];
|
|
unsigned stack[N];
|
|
for (uint8_t i = 0; i < N; i++) {
|
|
perm[i] = i;
|
|
stack[i] = 0;
|
|
}
|
|
|
|
unsigned i = 1;
|
|
while (i < N) {
|
|
// print permutation to help debugging
|
|
printf("--- permutation: [");
|
|
for (unsigned j = 0; j < N; j++) {
|
|
if (j > 0) {
|
|
printf(", ");
|
|
}
|
|
printf("%d", perm[j]+1);
|
|
}
|
|
printf("] ---\n");
|
|
|
|
// test the given permutation with multiple commits
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
|
|
for (unsigned j = 0; j < N; j++) {
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, perm[j]+1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
NULL)) => 0;
|
|
}
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
for (unsigned j = 0; j < N; j++) {
|
|
lfs_rbyd_lookup(&lfs, &rbyd,
|
|
LFS_MKRTAG(UATTR, j+1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, j+1, 0);
|
|
}
|
|
|
|
// next permutation using Heap's algorithm
|
|
if (stack[i] < i) {
|
|
if (i % 2 == 0) {
|
|
uint8_t t = perm[0];
|
|
perm[0] = perm[i];
|
|
perm[i] = t;
|
|
} else {
|
|
uint8_t t = perm[stack[i]];
|
|
perm[stack[i]] = perm[i];
|
|
perm[i] = t;
|
|
}
|
|
stack[i] += 1;
|
|
i = 1;
|
|
} else {
|
|
stack[i] = 0;
|
|
i += 1;
|
|
}
|
|
}
|
|
'''
|
|
|
|
[cases.test_rbyd_large]
|
|
in = 'lfs.c'
|
|
# ORDER:
|
|
# 0 = in-order
|
|
# 1 = reverse-order
|
|
# 2 = random-order
|
|
defines.ORDER = [0, 1, 2]
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
lfs_off_t off;
|
|
lfs_size_t size;
|
|
|
|
// create the rbyd tree
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
|
|
// keep appending tags until we run out of space
|
|
//
|
|
// note, this will likely repeat tags, but that's ok
|
|
//
|
|
lfs_size_t count = 0;
|
|
uint32_t prng = 42;
|
|
for (lfs_size_t i = 0;; i++) {
|
|
uint8_t x
|
|
= (ORDER == 0) ? (uint8_t)i
|
|
: (ORDER == 1) ? (uint8_t)(((lfs_size_t)-1) - i)
|
|
: (uint8_t)TEST_PRNG(&prng);
|
|
int err = lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, x, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
NULL));
|
|
// if we can't fit an fcrc, erased is set to false, but if we can,
|
|
// lfs_rbyd_commit may error later with LFS_ERR_RANGE
|
|
if (!rbyd.erased || err == LFS_ERR_RANGE) {
|
|
break;
|
|
}
|
|
assert(err == 0);
|
|
|
|
count = i;
|
|
}
|
|
|
|
// check that we can still lookup all the tags
|
|
prng = 42;
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
for (lfs_size_t i = 0; i < count; i++) {
|
|
uint8_t x
|
|
= (ORDER == 0) ? (uint8_t)i
|
|
: (ORDER == 1) ? (uint8_t)(((lfs_size_t)-1) - i)
|
|
: (uint8_t)TEST_PRNG(&prng);
|
|
lfs_rbyd_lookup(&lfs, &rbyd,
|
|
LFS_MKRTAG(UATTR, x, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, x, 0);
|
|
}
|
|
'''
|
|
|
|
|
|
### Removal testing ###
|
|
|
|
[cases.test_rbyd_remove]
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
lfs_off_t off;
|
|
lfs_size_t size;
|
|
|
|
// add and remove one attribute
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4, NULL)) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRRMATTR(UATTR, 1, 0, NULL)) => 0;
|
|
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
// commit with two attributes, remove the first one
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4, NULL))) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRRMATTR(UATTR, 1, 0, NULL)) => 0;
|
|
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 2, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
// commit with two attributes, remove the second one
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4, NULL))) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRRMATTR(UATTR, 2, 0, NULL)) => 0;
|
|
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_MKRTAG(UATTR, 1, 0);
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
'''
|
|
|
|
[cases.test_rbyd_remove_permutations]
|
|
defines.N = 'range(1, 7)'
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
lfs_off_t off;
|
|
lfs_size_t size;
|
|
|
|
// test all permutations of a given size
|
|
uint8_t perm[N];
|
|
unsigned stack[N];
|
|
for (uint8_t i = 0; i < N; i++) {
|
|
perm[i] = i;
|
|
stack[i] = 0;
|
|
}
|
|
|
|
unsigned i = 1;
|
|
while (i < N) {
|
|
// print permutation to help debugging
|
|
printf("--- permutation: [");
|
|
for (unsigned j = 0; j < N; j++) {
|
|
if (j > 0) {
|
|
printf(", ");
|
|
}
|
|
printf("%d", perm[j]+1);
|
|
}
|
|
printf("] ---\n");
|
|
|
|
// create given permutation with multiple commits
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
|
|
for (unsigned j = 0; j < N; j++) {
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, perm[j]+1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
NULL)) => 0;
|
|
}
|
|
|
|
// copy block so we can reset after each remove
|
|
lfs_rbyd_t backup_rbyd = rbyd;
|
|
uint8_t backup_block[BLOCK_SIZE];
|
|
lfs_bd_read(&lfs, NULL, &lfs.rcache, rbyd.off,
|
|
rbyd.block, 0, backup_block, rbyd.off) => 0;
|
|
|
|
// try removing each tag
|
|
for (unsigned j = 0; j < N; j++) {
|
|
// print what we are removing to help debugging
|
|
printf("--- remove: %d ---\n", j+1);
|
|
|
|
rbyd = backup_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false,
|
|
rbyd.block, 0, backup_block, rbyd.off) => 0;
|
|
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRRMATTR(UATTR, j+1, 0, NULL)) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
for (unsigned k = 0; k < N; k++) {
|
|
lfs_srtag_t tag = lfs_rbyd_lookup(&lfs, &rbyd,
|
|
LFS_MKRTAG(UATTR, k+1, 0), &off, &size);
|
|
if (k == j) {
|
|
if (j == N-1) {
|
|
assert(tag == LFS_ERR_NOENT);
|
|
} else {
|
|
assert(tag == LFS_MKRTAG(UATTR, j+1+1, 0));
|
|
}
|
|
} else {
|
|
assert(tag == LFS_MKRTAG(UATTR, k+1, 0));
|
|
}
|
|
}
|
|
}
|
|
|
|
// next permutation using Heap's algorithm
|
|
if (stack[i] < i) {
|
|
if (i % 2 == 0) {
|
|
uint8_t t = perm[0];
|
|
perm[0] = perm[i];
|
|
perm[i] = t;
|
|
} else {
|
|
uint8_t t = perm[stack[i]];
|
|
perm[stack[i]] = perm[i];
|
|
perm[i] = t;
|
|
}
|
|
stack[i] += 1;
|
|
i = 1;
|
|
} else {
|
|
stack[i] = 0;
|
|
i += 1;
|
|
}
|
|
}
|
|
'''
|
|
|
|
[cases.test_rbyd_remove_append_permutations]
|
|
defines.N = 'range(1, 6)'
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
lfs_off_t off;
|
|
lfs_size_t size;
|
|
|
|
// test all permutations of a given size
|
|
uint8_t perm[N];
|
|
unsigned stack[N];
|
|
for (uint8_t i = 0; i < N; i++) {
|
|
perm[i] = i;
|
|
stack[i] = 0;
|
|
}
|
|
|
|
unsigned i = 1;
|
|
while (i < N) {
|
|
// print permutation to help debugging
|
|
printf("--- permutation: [");
|
|
for (unsigned j = 0; j < N; j++) {
|
|
if (j > 0) {
|
|
printf(", ");
|
|
}
|
|
printf("%d", perm[j]+1);
|
|
}
|
|
printf("] ---\n");
|
|
|
|
// create given permutation with multiple commits
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
|
|
for (unsigned j = 0; j < N; j++) {
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, perm[j]+1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
NULL)) => 0;
|
|
}
|
|
|
|
// copy block so we can reset after each remove
|
|
lfs_rbyd_t backup_rbyd = rbyd;
|
|
uint8_t backup_block[BLOCK_SIZE];
|
|
lfs_bd_read(&lfs, NULL, &lfs.rcache, rbyd.off,
|
|
rbyd.block, 0, backup_block, rbyd.off) => 0;
|
|
|
|
// try removing each tag
|
|
for (unsigned j = 0; j < N; j++) {
|
|
for (unsigned l = 0; l < N; l++) {
|
|
// print what we are removing to help debugging
|
|
printf("--- remove: %d, append: %d ---\n", j+1, l+1);
|
|
|
|
rbyd = backup_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false,
|
|
rbyd.block, 0, backup_block, rbyd.off) => 0;
|
|
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRRMATTR(UATTR, j+1, 0, NULL)) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
for (unsigned k = 0; k < N; k++) {
|
|
lfs_srtag_t tag = lfs_rbyd_lookup(&lfs, &rbyd,
|
|
LFS_MKRTAG(UATTR, k+1, 0), &off, &size);
|
|
if (k == j) {
|
|
if (j == N-1) {
|
|
assert(tag == LFS_ERR_NOENT);
|
|
} else {
|
|
assert(tag == LFS_MKRTAG(UATTR, j+1+1, 0));
|
|
}
|
|
} else {
|
|
assert(tag == LFS_MKRTAG(UATTR, k+1, 0));
|
|
assert(size == 4);
|
|
}
|
|
}
|
|
|
|
// try appending each tag to make sure the rbyd tree
|
|
// is still usable
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, l+1, 0,
|
|
"\xaa\xaa\xaa\xaa\xaa\xaa", 6,
|
|
NULL)) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
for (unsigned k = 0; k < N; k++) {
|
|
lfs_srtag_t tag = lfs_rbyd_lookup(&lfs, &rbyd,
|
|
LFS_MKRTAG(UATTR, k+1, 0), &off, &size);
|
|
if (k == l) {
|
|
assert(tag == LFS_MKRTAG(UATTR, l+1, 0));
|
|
assert(size == 6);
|
|
} else if (k == j) {
|
|
if (j == N-1) {
|
|
assert(tag == LFS_ERR_NOENT);
|
|
} else {
|
|
assert(tag == LFS_MKRTAG(UATTR, j+1+1, 0));
|
|
}
|
|
} else {
|
|
assert(tag == LFS_MKRTAG(UATTR, k+1, 0));
|
|
assert(size == 4);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// next permutation using Heap's algorithm
|
|
if (stack[i] < i) {
|
|
if (i % 2 == 0) {
|
|
uint8_t t = perm[0];
|
|
perm[0] = perm[i];
|
|
perm[i] = t;
|
|
} else {
|
|
uint8_t t = perm[stack[i]];
|
|
perm[stack[i]] = perm[i];
|
|
perm[i] = t;
|
|
}
|
|
stack[i] += 1;
|
|
i = 1;
|
|
} else {
|
|
stack[i] = 0;
|
|
i += 1;
|
|
}
|
|
}
|
|
'''
|
|
|
|
[cases.test_rbyd_remove_all]
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
lfs_off_t off;
|
|
lfs_size_t size;
|
|
|
|
// commit with one attribute, remove it
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4, NULL)) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRRMATTR(UATTR, 1, 0, NULL)) => 0;
|
|
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
// commit with two attributes, remove both
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4, NULL))) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRRMATTR(UATTR, 1, 0,
|
|
LFS_MKRRMATTR(UATTR, 2, 0, NULL))) => 0;
|
|
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
// commit with two attributes, remove both in the other order
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, 1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 2, 0, "\xbb\xbb\xbb\xbb", 4, NULL))) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRRMATTR(UATTR, 2, 0,
|
|
LFS_MKRRMATTR(UATTR, 1, 0, NULL))) => 0;
|
|
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
'''
|
|
|
|
[cases.test_rbyd_remove_all_permutations]
|
|
defines.N = 'range(1, 7)'
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
lfs_off_t off;
|
|
lfs_size_t size;
|
|
|
|
// create one consistent block
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
|
|
for (unsigned j = 0; j < N; j++) {
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(UATTR, j+1, 0, "\xaa\xaa\xaa\xaa", 4,
|
|
NULL)) => 0;
|
|
}
|
|
|
|
// copy block so we can reset after each remove
|
|
lfs_rbyd_t backup_rbyd = rbyd;
|
|
uint8_t backup_block[BLOCK_SIZE];
|
|
lfs_bd_read(&lfs, NULL, &lfs.rcache, rbyd.off,
|
|
rbyd.block, 0, backup_block, rbyd.off) => 0;
|
|
|
|
// test all permutations of a given size
|
|
uint8_t perm[N];
|
|
unsigned stack[N];
|
|
for (uint8_t i = 0; i < N; i++) {
|
|
perm[i] = i;
|
|
stack[i] = 0;
|
|
}
|
|
|
|
unsigned i = 1;
|
|
while (i < N) {
|
|
// print permutation to help debugging
|
|
printf("--- permutation: [");
|
|
for (unsigned j = 0; j < N; j++) {
|
|
if (j > 0) {
|
|
printf(", ");
|
|
}
|
|
printf("%d", perm[j]+1);
|
|
}
|
|
printf("] ---\n");
|
|
|
|
// restore backup
|
|
rbyd = backup_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false,
|
|
rbyd.block, 0, backup_block, rbyd.off) => 0;
|
|
|
|
// remove each tag in permutation order
|
|
for (unsigned j = 0; j < N; j++) {
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRRMATTR(UATTR, perm[j]+1, 0, NULL)) => 0;
|
|
}
|
|
|
|
// check that all tags are now removed
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
for (unsigned j = 0; j < N; j++) {
|
|
lfs_rbyd_lookup(&lfs, &rbyd,
|
|
LFS_MKRTAG(UATTR, j+1, 0), &off, &size)
|
|
=> LFS_ERR_NOENT;
|
|
}
|
|
|
|
// next permutation using Heap's algorithm
|
|
if (stack[i] < i) {
|
|
if (i % 2 == 0) {
|
|
uint8_t t = perm[0];
|
|
perm[0] = perm[i];
|
|
perm[i] = t;
|
|
} else {
|
|
uint8_t t = perm[stack[i]];
|
|
perm[stack[i]] = perm[i];
|
|
perm[i] = t;
|
|
}
|
|
stack[i] += 1;
|
|
i = 1;
|
|
} else {
|
|
stack[i] = 0;
|
|
i += 1;
|
|
}
|
|
}
|
|
'''
|
|
|
|
|
|
### Insertion testing ###
|
|
|
|
[cases.test_rbyd_create]
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
uint8_t buffer[4];
|
|
|
|
// try to create one id
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4, NULL)) => 0;
|
|
|
|
assert(rbyd.count == 1);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
assert(rbyd.count == 1);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
|
|
// try to create two ids
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(CREATEREG, 0, 2, "\xbb\xbb\xbb\xbb", 4, NULL))) => 0;
|
|
|
|
assert(rbyd.count == 2);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
assert(rbyd.count == 2);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
|
|
// try to create two in the other direction
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, 1, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4, NULL))) => 0;
|
|
|
|
assert(rbyd.count == 2);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
assert(rbyd.count == 2);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
|
|
// create a third to the right
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(CREATEREG, 0, 2, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(CREATEREG, 0, 3, "\xcc\xcc\xcc\xcc", 4, NULL)))) => 0;
|
|
|
|
assert(rbyd.count == 3);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0);
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
assert(rbyd.count == 3);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0);
|
|
|
|
// create a third to the left
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, 1, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(CREATEREG, 0, 2, "\xcc\xcc\xcc\xcc", 4,
|
|
LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4, NULL)))) => 0;
|
|
|
|
assert(rbyd.count == 3);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0);
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
assert(rbyd.count == 3);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0);
|
|
|
|
// create a third in the middle
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(CREATEREG, 0, 2, "\xcc\xcc\xcc\xcc", 4,
|
|
LFS_MKRATTR(CREATEREG, 0, 2, "\xbb\xbb\xbb\xbb", 4, NULL)))) => 0;
|
|
|
|
assert(rbyd.count == 3);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0);
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
assert(rbyd.count == 3);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0);
|
|
'''
|
|
|
|
[cases.test_rbyd_multi_create]
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
uint8_t buffer[4];
|
|
|
|
// try to create one id
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4, NULL)) => 0;
|
|
|
|
assert(rbyd.count == 1);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
assert(rbyd.count == 1);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
|
|
// try to create two ids
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4, NULL)) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, 2, "\xbb\xbb\xbb\xbb", 4, NULL)) => 0;
|
|
|
|
assert(rbyd.count == 2);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
assert(rbyd.count == 2);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
|
|
// try to create two in the other direction
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, 1, "\xbb\xbb\xbb\xbb", 4, NULL)) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4, NULL)) => 0;
|
|
|
|
assert(rbyd.count == 2);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
assert(rbyd.count == 2);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
|
|
// create a third to the right
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4, NULL)) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, 2, "\xbb\xbb\xbb\xbb", 4, NULL)) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, 3, "\xcc\xcc\xcc\xcc", 4, NULL)) => 0;
|
|
|
|
assert(rbyd.count == 3);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0);
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
assert(rbyd.count == 3);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0);
|
|
|
|
// create a third to the left
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, 1, "\xbb\xbb\xbb\xbb", 4, NULL)) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, 2, "\xcc\xcc\xcc\xcc", 4, NULL)) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4, NULL)) => 0;
|
|
|
|
assert(rbyd.count == 3);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0);
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
assert(rbyd.count == 3);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0);
|
|
|
|
// create a third in the middle
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4, NULL)) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, 2, "\xcc\xcc\xcc\xcc", 4, NULL)) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, 2, "\xbb\xbb\xbb\xbb", 4, NULL)) => 0;
|
|
|
|
assert(rbyd.count == 3);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0);
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
assert(rbyd.count == 3);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4) => 4;
|
|
assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0);
|
|
'''
|
|
|
|
[cases.test_rbyd_create_permutations]
|
|
defines.N = 'range(1, 8)'
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
const uint8_t names[6][4] = {
|
|
"\xaa\xaa\xaa\xaa",
|
|
"\xbb\xbb\xbb\xbb",
|
|
"\xcc\xcc\xcc\xcc",
|
|
"\xdd\xdd\xdd\xdd",
|
|
"\xee\xee\xee\xee",
|
|
"\xff\xff\xff\xff",
|
|
};
|
|
uint8_t buffer[4];
|
|
|
|
// test all permutations of a given size
|
|
uint16_t perm[N];
|
|
unsigned stack[N];
|
|
for (uint16_t i = 0; i < N; i++) {
|
|
perm[i] = i;
|
|
stack[i] = 0;
|
|
}
|
|
|
|
unsigned i = 1;
|
|
while (i < N) {
|
|
// print permutation to help debugging
|
|
printf("--- permutation: [");
|
|
for (unsigned j = 0; j < N; j++) {
|
|
if (j > 0) {
|
|
printf(", ");
|
|
}
|
|
printf("%d", perm[j]+1);
|
|
}
|
|
printf("] ---\n");
|
|
|
|
// build the attribute list for the current permutation
|
|
struct lfs_rattr attrs[N];
|
|
for (unsigned j = 0; j < N; j++) {
|
|
// adjust id based on future insertions
|
|
uint16_t id = perm[j];
|
|
for (unsigned k = j+1; k < N; k++) {
|
|
if (perm[j] > perm[k]) {
|
|
id -= 1;
|
|
}
|
|
}
|
|
|
|
attrs[j] = *LFS_MKRATTR(
|
|
CREATEREG, 0, id+1,
|
|
names[perm[j] % 6], 4,
|
|
(j+1 < N) ? &attrs[j+1] : NULL);
|
|
}
|
|
|
|
// test the given permutation
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd, attrs) => 0;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
assert(rbyd.count == N);
|
|
for (unsigned j = 0; j < N; j++) {
|
|
lfs_rbyd_get(&lfs, &rbyd,
|
|
LFS_MKRTAG(CREATEREG, 0, j+1), buffer, 4) => 4;
|
|
assert(memcmp(buffer, names[j % 6], 4) == 0);
|
|
}
|
|
|
|
// next permutation using Heap's algorithm
|
|
if (stack[i] < i) {
|
|
if (i % 2 == 0) {
|
|
uint16_t t = perm[0];
|
|
perm[0] = perm[i];
|
|
perm[i] = t;
|
|
} else {
|
|
uint16_t t = perm[stack[i]];
|
|
perm[stack[i]] = perm[i];
|
|
perm[i] = t;
|
|
}
|
|
stack[i] += 1;
|
|
i = 1;
|
|
} else {
|
|
stack[i] = 0;
|
|
i += 1;
|
|
}
|
|
}
|
|
'''
|
|
|
|
[cases.test_rbyd_multi_create_permutations]
|
|
defines.N = 'range(1, 8)'
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
const uint8_t names[6][4] = {
|
|
"\xaa\xaa\xaa\xaa",
|
|
"\xbb\xbb\xbb\xbb",
|
|
"\xcc\xcc\xcc\xcc",
|
|
"\xdd\xdd\xdd\xdd",
|
|
"\xee\xee\xee\xee",
|
|
"\xff\xff\xff\xff",
|
|
};
|
|
uint8_t buffer[4];
|
|
|
|
// test all permutations of a given size
|
|
uint16_t perm[N];
|
|
unsigned stack[N];
|
|
for (uint16_t i = 0; i < N; i++) {
|
|
perm[i] = i;
|
|
stack[i] = 0;
|
|
}
|
|
|
|
unsigned i = 1;
|
|
while (i < N) {
|
|
// print permutation to help debugging
|
|
printf("--- permutation: [");
|
|
for (unsigned j = 0; j < N; j++) {
|
|
if (j > 0) {
|
|
printf(", ");
|
|
}
|
|
printf("%d", perm[j]+1);
|
|
}
|
|
printf("] ---\n");
|
|
|
|
// test the given permutation with multiple commits
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
|
|
for (unsigned j = 0; j < N; j++) {
|
|
// adjust id based on future insertions
|
|
uint16_t id = perm[j];
|
|
for (unsigned k = j+1; k < N; k++) {
|
|
if (perm[j] > perm[k]) {
|
|
id -= 1;
|
|
}
|
|
}
|
|
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, id+1, names[perm[j] % 6], 4,
|
|
NULL)) => 0;
|
|
}
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
assert(rbyd.count == N);
|
|
for (unsigned j = 0; j < N; j++) {
|
|
lfs_rbyd_get(&lfs, &rbyd,
|
|
LFS_MKRTAG(CREATEREG, 0, j+1), buffer, 4) => 4;
|
|
assert(memcmp(buffer, names[j % 6], 4) == 0);
|
|
}
|
|
|
|
// next permutation using Heap's algorithm
|
|
if (stack[i] < i) {
|
|
if (i % 2 == 0) {
|
|
uint16_t t = perm[0];
|
|
perm[0] = perm[i];
|
|
perm[i] = t;
|
|
} else {
|
|
uint16_t t = perm[stack[i]];
|
|
perm[stack[i]] = perm[i];
|
|
perm[i] = t;
|
|
}
|
|
stack[i] += 1;
|
|
i = 1;
|
|
} else {
|
|
stack[i] = 0;
|
|
i += 1;
|
|
}
|
|
}
|
|
'''
|
|
|
|
[cases.test_rbyd_create_large]
|
|
in = 'lfs.c'
|
|
# ORDER:
|
|
# 0 = in-order
|
|
# 1 = reverse-order
|
|
# 2 = random-order
|
|
defines.ORDER = [0, 1, 2]
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
const uint8_t names[6][4] = {
|
|
"\xaa\xaa\xaa\xaa",
|
|
"\xbb\xbb\xbb\xbb",
|
|
"\xcc\xcc\xcc\xcc",
|
|
"\xdd\xdd\xdd\xdd",
|
|
"\xee\xee\xee\xee",
|
|
"\xff\xff\xff\xff",
|
|
};
|
|
|
|
// create the rbyd tree
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
|
|
// keep inserting tags until we run out of space
|
|
//
|
|
// note, the ids we create this way are both sparse and sometimes
|
|
// repeated, so we need to mod our current rbyd size to avoid invalid
|
|
// insertions
|
|
//
|
|
uint32_t prng = 42;
|
|
for (lfs_size_t i = 0;; i++) {
|
|
uint16_t x
|
|
= (ORDER == 0) ? (uint16_t)i
|
|
: (ORDER == 1) ? (uint16_t)(((lfs_size_t)-1) - i)
|
|
: (uint16_t)TEST_PRNG(&prng);
|
|
x = x % (rbyd.count+1);
|
|
|
|
int err = lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, x+1, names[x % 6], 4, NULL));
|
|
// if we can't fit an fcrc, erased is set to false, but if we can,
|
|
// lfs_rbyd_commit may error later with LFS_ERR_RANGE
|
|
if (!rbyd.erased || err == LFS_ERR_RANGE) {
|
|
break;
|
|
}
|
|
assert(err == 0);
|
|
}
|
|
|
|
// check that we can at least lookup all the tags
|
|
lfs_off_t off;
|
|
lfs_size_t size;
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
for (uint16_t x = 0; x < rbyd.count; x++) {
|
|
lfs_rbyd_lookup(&lfs, &rbyd,
|
|
LFS_MKRTAG(CREATEREG, 0, x+1), &off, &size)
|
|
=> LFS_MKRTAG(CREATEREG, 0, x+1);
|
|
}
|
|
'''
|
|
|
|
|
|
### Deletion testing ###
|
|
|
|
[cases.test_rbyd_delete]
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
uint8_t buffer[4];
|
|
|
|
// try to delete one id
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(CREATEREG, 0, 2, "\xbb\xbb\xbb\xbb", 4, NULL))) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(DELETE, 0, 2, NULL, 0, NULL)) => 0;
|
|
|
|
assert(rbyd.count == 1);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
assert(rbyd.count == 1);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
// try to delete the other id
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(CREATEREG, 0, 2, "\xbb\xbb\xbb\xbb", 4, NULL))) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(DELETE, 0, 1, NULL, 0, NULL)) => 0;
|
|
|
|
assert(rbyd.count == 1);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
assert(rbyd.count == 1);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
// try to delete the largest of three
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(CREATEREG, 0, 2, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(CREATEREG, 0, 3, "\xcc\xcc\xcc\xcc", 4, NULL)))) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(DELETE, 0, 3, NULL, 0, NULL)) => 0;
|
|
|
|
assert(rbyd.count == 2);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
assert(rbyd.count == 2);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
// try to delete the smallest of three
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(CREATEREG, 0, 2, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(CREATEREG, 0, 3, "\xcc\xcc\xcc\xcc", 4, NULL)))) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(DELETE, 0, 1, NULL, 0, NULL)) => 0;
|
|
|
|
assert(rbyd.count == 2);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
assert(rbyd.count == 2);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
// try to delete the middle
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(CREATEREG, 0, 2, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(CREATEREG, 0, 3, "\xcc\xcc\xcc\xcc", 4, NULL)))) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(DELETE, 0, 2, NULL, 0, NULL)) => 0;
|
|
|
|
assert(rbyd.count == 2);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
assert(rbyd.count == 2);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
'''
|
|
|
|
[cases.test_rbyd_delete_range]
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
uint8_t buffer[4];
|
|
|
|
// try to delete one id
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 0, 1, "\xaa\xaa", 2,
|
|
LFS_MKRATTR(CREATEREG, 0, 2, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 0, 2, "\xbb\xbb", 2, NULL))))) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(DELETE, 0, 2, NULL, 0, NULL)) => 0;
|
|
|
|
assert(rbyd.count == 1);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 1), buffer, 4)
|
|
=> 2;
|
|
assert(memcmp(buffer, "\xaa\xaa", 2) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 2), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
assert(rbyd.count == 1);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 1), buffer, 4)
|
|
=> 2;
|
|
assert(memcmp(buffer, "\xaa\xaa", 2) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 2), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
// try to delete the other id
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 0, 1, "\xaa\xaa", 2,
|
|
LFS_MKRATTR(CREATEREG, 0, 2, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 0, 2, "\xbb\xbb", 2, NULL))))) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(DELETE, 0, 1, NULL, 0, NULL)) => 0;
|
|
|
|
assert(rbyd.count == 1);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 1), buffer, 4)
|
|
=> 2;
|
|
assert(memcmp(buffer, "\xbb\xbb", 2) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 2), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
assert(rbyd.count == 1);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 1), buffer, 4)
|
|
=> 2;
|
|
assert(memcmp(buffer, "\xbb\xbb", 2) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 2), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
// try to delete the largest of three
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 0, 1, "\xaa\xaa", 2,
|
|
LFS_MKRATTR(CREATEREG, 0, 2, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 0, 2, "\xbb\xbb", 2,
|
|
LFS_MKRATTR(CREATEREG, 0, 3, "\xcc\xcc\xcc\xcc", 4,
|
|
LFS_MKRATTR(UATTR, 0, 3, "\xcc\xcc", 2, NULL))))))) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(DELETE, 0, 3, NULL, 0, NULL)) => 0;
|
|
|
|
assert(rbyd.count == 2);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 1), buffer, 4)
|
|
=> 2;
|
|
assert(memcmp(buffer, "\xaa\xaa", 2) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 2), buffer, 4)
|
|
=> 2;
|
|
assert(memcmp(buffer, "\xbb\xbb", 2) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 3), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
assert(rbyd.count == 2);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 1), buffer, 4)
|
|
=> 2;
|
|
assert(memcmp(buffer, "\xaa\xaa", 2) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 2), buffer, 4)
|
|
=> 2;
|
|
assert(memcmp(buffer, "\xbb\xbb", 2) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 3), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
// try to delete the smallest of three
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 0, 1, "\xaa\xaa", 2,
|
|
LFS_MKRATTR(CREATEREG, 0, 2, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 0, 2, "\xbb\xbb", 2,
|
|
LFS_MKRATTR(CREATEREG, 0, 3, "\xcc\xcc\xcc\xcc", 4,
|
|
LFS_MKRATTR(UATTR, 0, 3, "\xcc\xcc", 2, NULL))))))) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(DELETE, 0, 1, NULL, 0, NULL)) => 0;
|
|
|
|
assert(rbyd.count == 2);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 1), buffer, 4)
|
|
=> 2;
|
|
assert(memcmp(buffer, "\xbb\xbb", 2) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 2), buffer, 4)
|
|
=> 2;
|
|
assert(memcmp(buffer, "\xcc\xcc", 2) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 3), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
assert(rbyd.count == 2);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 1), buffer, 4)
|
|
=> 2;
|
|
assert(memcmp(buffer, "\xbb\xbb", 2) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 2), buffer, 4)
|
|
=> 2;
|
|
assert(memcmp(buffer, "\xcc\xcc", 2) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 3), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
// try to delete the middle
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4,
|
|
LFS_MKRATTR(UATTR, 0, 1, "\xaa\xaa", 2,
|
|
LFS_MKRATTR(CREATEREG, 0, 2, "\xbb\xbb\xbb\xbb", 4,
|
|
LFS_MKRATTR(UATTR, 0, 2, "\xbb\xbb", 2,
|
|
LFS_MKRATTR(CREATEREG, 0, 3, "\xcc\xcc\xcc\xcc", 4,
|
|
LFS_MKRATTR(UATTR, 0, 3, "\xcc\xcc", 2, NULL))))))) => 0;
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(DELETE, 0, 2, NULL, 0, NULL)) => 0;
|
|
|
|
assert(rbyd.count == 2);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 1), buffer, 4)
|
|
=> 2;
|
|
assert(memcmp(buffer, "\xaa\xaa", 2) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 2), buffer, 4)
|
|
=> 2;
|
|
assert(memcmp(buffer, "\xcc\xcc", 2) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 3), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
assert(rbyd.count == 2);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 1), buffer, 4)
|
|
=> 2;
|
|
assert(memcmp(buffer, "\xaa\xaa", 2) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4)
|
|
=> 4;
|
|
assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 2), buffer, 4)
|
|
=> 2;
|
|
assert(memcmp(buffer, "\xcc\xcc", 2) == 0);
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 3), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
'''
|
|
|
|
[cases.test_rbyd_delete_permutations]
|
|
defines.N = 'range(1, 7)'
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
const uint8_t names[6][4] = {
|
|
"\xaa\xaa\xaa\xaa",
|
|
"\xbb\xbb\xbb\xbb",
|
|
"\xcc\xcc\xcc\xcc",
|
|
"\xdd\xdd\xdd\xdd",
|
|
"\xee\xee\xee\xee",
|
|
"\xff\xff\xff\xff",
|
|
};
|
|
uint8_t buffer[4];
|
|
|
|
// test all permutations of a given size
|
|
uint16_t perm[N];
|
|
unsigned stack[N];
|
|
for (uint16_t i = 0; i < N; i++) {
|
|
perm[i] = i;
|
|
stack[i] = 0;
|
|
}
|
|
|
|
unsigned i = 1;
|
|
while (i < N) {
|
|
// print permutation to help debugging
|
|
printf("--- permutation: [");
|
|
for (unsigned j = 0; j < N; j++) {
|
|
if (j > 0) {
|
|
printf(", ");
|
|
}
|
|
printf("%d", perm[j]+1);
|
|
}
|
|
printf("] ---\n");
|
|
|
|
// create given permutation with multiple commits
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
|
|
for (unsigned j = 0; j < N; j++) {
|
|
// adjust id based on future insertions
|
|
uint16_t id = perm[j];
|
|
for (unsigned k = j+1; k < N; k++) {
|
|
if (perm[j] > perm[k]) {
|
|
id -= 1;
|
|
}
|
|
}
|
|
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, id+1, names[perm[j] % 6], 4,
|
|
NULL)) => 0;
|
|
}
|
|
assert(rbyd.count == N);
|
|
|
|
// copy block so we can reset after each delete
|
|
lfs_rbyd_t backup_rbyd = rbyd;
|
|
uint8_t backup_block[BLOCK_SIZE];
|
|
lfs_bd_read(&lfs, NULL, &lfs.rcache, rbyd.off,
|
|
rbyd.block, 0, backup_block, rbyd.off) => 0;
|
|
|
|
// try deleting each id
|
|
for (unsigned j = 0; j < N; j++) {
|
|
// print what we are deleting to help debugging
|
|
printf("--- delete: %d ---\n", j+1);
|
|
|
|
rbyd = backup_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false,
|
|
rbyd.block, 0, backup_block, rbyd.off) => 0;
|
|
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(DELETE, 0, j+1, NULL, 0, NULL)) => 0;
|
|
assert(rbyd.count == N-1);
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
for (unsigned k = 0; k < N-1; k++) {
|
|
lfs_rbyd_get(&lfs, &rbyd,
|
|
LFS_MKRTAG(CREATEREG, 0, k+1), buffer, 4) => 4;
|
|
if (k >= j) {
|
|
assert(memcmp(buffer, names[(k+1) % 6], 4) == 0);
|
|
} else {
|
|
assert(memcmp(buffer, names[k % 6], 4) == 0);
|
|
}
|
|
}
|
|
lfs_rbyd_get(&lfs, &rbyd,
|
|
LFS_MKRTAG(CREATEREG, 0, N-1+1), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
}
|
|
|
|
// next permutation using Heap's algorithm
|
|
if (stack[i] < i) {
|
|
if (i % 2 == 0) {
|
|
uint16_t t = perm[0];
|
|
perm[0] = perm[i];
|
|
perm[i] = t;
|
|
} else {
|
|
uint16_t t = perm[stack[i]];
|
|
perm[stack[i]] = perm[i];
|
|
perm[i] = t;
|
|
}
|
|
stack[i] += 1;
|
|
i = 1;
|
|
} else {
|
|
stack[i] = 0;
|
|
i += 1;
|
|
}
|
|
}
|
|
'''
|
|
|
|
[cases.test_rbyd_delete_range_permutations]
|
|
defines.N = 'range(1, 7)'
|
|
in = 'lfs.c'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_init(&lfs, cfg) => 0;
|
|
|
|
lfs_rbyd_t init_rbyd = {
|
|
.block = 0,
|
|
.trunk = 0,
|
|
.off = 0,
|
|
.rev = 1,
|
|
.crc = 0,
|
|
.count = 0,
|
|
.erased = true,
|
|
};
|
|
lfs_rbyd_t rbyd;
|
|
const uint8_t names[6][4] = {
|
|
"\xaa\xaa\xaa\xaa",
|
|
"\xbb\xbb\xbb\xbb",
|
|
"\xcc\xcc\xcc\xcc",
|
|
"\xdd\xdd\xdd\xdd",
|
|
"\xee\xee\xee\xee",
|
|
"\xff\xff\xff\xff",
|
|
};
|
|
uint8_t buffer[4];
|
|
|
|
// test all permutations of a given size
|
|
uint16_t perm[N];
|
|
unsigned stack[N];
|
|
for (uint16_t i = 0; i < N; i++) {
|
|
perm[i] = i;
|
|
stack[i] = 0;
|
|
}
|
|
|
|
unsigned i = 1;
|
|
while (i < N) {
|
|
// print permutation to help debugging
|
|
printf("--- permutation: [");
|
|
for (unsigned j = 0; j < N; j++) {
|
|
if (j > 0) {
|
|
printf(", ");
|
|
}
|
|
printf("%d", perm[j]+1);
|
|
}
|
|
printf("] ---\n");
|
|
|
|
// create given permutation with multiple commits
|
|
rbyd = init_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
|
|
for (unsigned j = 0; j < N; j++) {
|
|
// adjust id based on future insertions
|
|
uint16_t id = perm[j];
|
|
for (unsigned k = j+1; k < N; k++) {
|
|
if (perm[j] > perm[k]) {
|
|
id -= 1;
|
|
}
|
|
}
|
|
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(CREATEREG, 0, id+1, names[perm[j] % 6], 4,
|
|
// note uattrs have a smaller size
|
|
LFS_MKRATTR(UATTR, 0, id+1, names[perm[j] % 6], 2,
|
|
NULL))) => 0;
|
|
}
|
|
assert(rbyd.count == N);
|
|
|
|
// copy block so we can reset after each delete
|
|
lfs_rbyd_t backup_rbyd = rbyd;
|
|
uint8_t backup_block[BLOCK_SIZE];
|
|
lfs_bd_read(&lfs, NULL, &lfs.rcache, rbyd.off,
|
|
rbyd.block, 0, backup_block, rbyd.off) => 0;
|
|
|
|
// try deleting each id
|
|
for (unsigned j = 0; j < N; j++) {
|
|
// print what we are deleting to help debugging
|
|
printf("--- delete: %d ---\n", j+1);
|
|
|
|
rbyd = backup_rbyd;
|
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
|
lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false,
|
|
rbyd.block, 0, backup_block, rbyd.off) => 0;
|
|
|
|
lfs_rbyd_commit(&lfs, &rbyd,
|
|
LFS_MKRATTR(DELETE, 0, j+1, NULL, 0, NULL)) => 0;
|
|
assert(rbyd.count == N-1);
|
|
|
|
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
|
|
for (unsigned k = 0; k < N-1; k++) {
|
|
lfs_rbyd_get(&lfs, &rbyd,
|
|
LFS_MKRTAG(CREATEREG, 0, k+1), buffer, 4) => 4;
|
|
if (k >= j) {
|
|
assert(memcmp(buffer, names[(k+1) % 6], 4) == 0);
|
|
} else {
|
|
assert(memcmp(buffer, names[k % 6], 4) == 0);
|
|
}
|
|
|
|
lfs_rbyd_get(&lfs, &rbyd,
|
|
LFS_MKRTAG(UATTR, 0, k+1), buffer, 4) => 2;
|
|
if (k >= j) {
|
|
assert(memcmp(buffer, names[(k+1) % 6], 2) == 0);
|
|
} else {
|
|
assert(memcmp(buffer, names[k % 6], 2) == 0);
|
|
}
|
|
}
|
|
lfs_rbyd_get(&lfs, &rbyd,
|
|
LFS_MKRTAG(CREATEREG, 0, N-1+1), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
lfs_rbyd_get(&lfs, &rbyd,
|
|
LFS_MKRTAG(UATTR, 0, N-1+1), buffer, 4)
|
|
=> LFS_ERR_NOENT;
|
|
}
|
|
|
|
// next permutation using Heap's algorithm
|
|
if (stack[i] < i) {
|
|
if (i % 2 == 0) {
|
|
uint16_t t = perm[0];
|
|
perm[0] = perm[i];
|
|
perm[i] = t;
|
|
} else {
|
|
uint16_t t = perm[stack[i]];
|
|
perm[stack[i]] = perm[i];
|
|
perm[i] = t;
|
|
}
|
|
stack[i] += 1;
|
|
i = 1;
|
|
} else {
|
|
stack[i] = 0;
|
|
i += 1;
|
|
}
|
|
}
|
|
'''
|