4ff7c1f771
This makes it easier to evaluate the code/stack/etc sizes and run tests without bringing in all of the outdated code. I guess this officially makes this branch more-or-less a full rewrite, though the benefit of commenting vs deleting this code is that it can be easily pulled back in when useful.
130 lines
4.5 KiB
TOML
130 lines
4.5 KiB
TOML
#[cases.test_orphans_normal]
|
|
#in = "lfs.c"
|
|
#if = 'PROG_SIZE <= 0x3fe' # only works with one crc per commit
|
|
#code = '''
|
|
# lfs_t lfs;
|
|
# lfs_format(&lfs, cfg) => 0;
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_mkdir(&lfs, "parent") => 0;
|
|
# lfs_mkdir(&lfs, "parent/orphan") => 0;
|
|
# lfs_mkdir(&lfs, "parent/child") => 0;
|
|
# lfs_remove(&lfs, "parent/orphan") => 0;
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# // corrupt the child's most recent commit, this should be the update
|
|
# // to the linked-list entry, which should orphan the orphan. Note this
|
|
# // makes a lot of assumptions about the remove operation.
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_dir_t dir;
|
|
# lfs_dir_open(&lfs, &dir, "parent/child") => 0;
|
|
# lfs_block_t block = dir.m.pair[0];
|
|
# lfs_dir_close(&lfs, &dir) => 0;
|
|
# lfs_unmount(&lfs) => 0;
|
|
# uint8_t buffer[BLOCK_SIZE];
|
|
# cfg->read(cfg, block, 0, buffer, BLOCK_SIZE) => 0;
|
|
# int off = BLOCK_SIZE-1;
|
|
# while (off >= 0 && buffer[off] == ERASE_VALUE) {
|
|
# off -= 1;
|
|
# }
|
|
# memset(&buffer[off-3], BLOCK_SIZE, 3);
|
|
# cfg->erase(cfg, block) => 0;
|
|
# cfg->prog(cfg, block, 0, buffer, BLOCK_SIZE) => 0;
|
|
# cfg->sync(cfg) => 0;
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# struct lfs_info info;
|
|
# lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERR_NOENT;
|
|
# lfs_stat(&lfs, "parent/child", &info) => 0;
|
|
# lfs_fs_size(&lfs) => 8;
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERR_NOENT;
|
|
# lfs_stat(&lfs, "parent/child", &info) => 0;
|
|
# lfs_fs_size(&lfs) => 8;
|
|
# // this mkdir should both create a dir and deorphan, so size
|
|
# // should be unchanged
|
|
# lfs_mkdir(&lfs, "parent/otherchild") => 0;
|
|
# lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERR_NOENT;
|
|
# lfs_stat(&lfs, "parent/child", &info) => 0;
|
|
# lfs_stat(&lfs, "parent/otherchild", &info) => 0;
|
|
# lfs_fs_size(&lfs) => 8;
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERR_NOENT;
|
|
# lfs_stat(&lfs, "parent/child", &info) => 0;
|
|
# lfs_stat(&lfs, "parent/otherchild", &info) => 0;
|
|
# lfs_fs_size(&lfs) => 8;
|
|
# lfs_unmount(&lfs) => 0;
|
|
#'''
|
|
#
|
|
## reentrant testing for orphans, basically just spam mkdir/remove
|
|
#[cases.test_orphans_reentrant]
|
|
#reentrant = true
|
|
## TODO fix this case, caused by non-DAG trees
|
|
#if = '!(DEPTH == 3 && CACHE_SIZE != 64)'
|
|
#defines = [
|
|
# {FILES=6, DEPTH=1, CYCLES=20},
|
|
# {FILES=26, DEPTH=1, CYCLES=20},
|
|
# {FILES=3, DEPTH=3, CYCLES=20},
|
|
#]
|
|
#code = '''
|
|
# lfs_t lfs;
|
|
# int err = lfs_mount(&lfs, cfg);
|
|
# if (err) {
|
|
# lfs_format(&lfs, cfg) => 0;
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# }
|
|
#
|
|
# uint32_t prng = 1;
|
|
# const char alpha[] = "abcdefghijklmnopqrstuvwxyz";
|
|
# for (unsigned i = 0; i < CYCLES; i++) {
|
|
# // create random path
|
|
# char full_path[256];
|
|
# for (unsigned d = 0; d < DEPTH; d++) {
|
|
# sprintf(&full_path[2*d], "/%c", alpha[TEST_PRNG(&prng) % FILES]);
|
|
# }
|
|
#
|
|
# // if it does not exist, we create it, else we destroy
|
|
# struct lfs_info info;
|
|
# int res = lfs_stat(&lfs, full_path, &info);
|
|
# if (res == LFS_ERR_NOENT) {
|
|
# // create each directory in turn, ignore if dir already exists
|
|
# for (unsigned d = 0; d < DEPTH; d++) {
|
|
# char path[1024];
|
|
# strcpy(path, full_path);
|
|
# path[2*d+2] = '\0';
|
|
# err = lfs_mkdir(&lfs, path);
|
|
# assert(!err || err == LFS_ERR_EXIST);
|
|
# }
|
|
#
|
|
# for (unsigned d = 0; d < DEPTH; d++) {
|
|
# char path[1024];
|
|
# strcpy(path, full_path);
|
|
# path[2*d+2] = '\0';
|
|
# lfs_stat(&lfs, path, &info) => 0;
|
|
# assert(strcmp(info.name, &path[2*d+1]) == 0);
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# }
|
|
# } else {
|
|
# // is valid dir?
|
|
# assert(strcmp(info.name, &full_path[2*(DEPTH-1)+1]) == 0);
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
#
|
|
# // try to delete path in reverse order, ignore if dir is not empty
|
|
# for (int d = DEPTH-1; d >= 0; d--) {
|
|
# char path[1024];
|
|
# strcpy(path, full_path);
|
|
# path[2*d+2] = '\0';
|
|
# err = lfs_remove(&lfs, path);
|
|
# assert(!err || err == LFS_ERR_NOTEMPTY);
|
|
# }
|
|
#
|
|
# lfs_stat(&lfs, full_path, &info) => LFS_ERR_NOENT;
|
|
# }
|
|
# }
|
|
# lfs_unmount(&lfs) => 0;
|
|
#'''
|
|
#
|