edd12e1f93
This is an attempt to fix issues with dir seeking in a filesystem
undergoing changes. The problem with the previous dstart-relative
position encoding is that if we deleted/created new entries outside of
our current directory, we didn't if they were inside or outside of the
current directory, so we couldn't always update our position correctly.
Instead of using a dstart-relative position, this solution crams both
the mid and rid into a single 31-bit integer. Things get a bit tight
here, so we use the current block_size as a heuristic for how many
possible rids we can ever have in a single mdir. The idea is the larger
the rid encoding needs to be, the smaller the mid encoding needs to be,
and we should, _roughly_, approach the same encoding limitation we would
have to dstart-relative position anyways.
Making some assumptions about the maximum possible number of rids in a
block gives us at most ~block_size/8 rids per mdir.
So for 4096 byte blocks (note the exact encoding is dynamic):
sbbbbbbb bbbbbbbb bbbbbbbr rrrrrrrr
^'-----------+----------''----+---'
'------------|----------------|----- sign bit (used for errors)
'----------------|----- 22-bit metadata bid
'----- 9-bit metadata rid
Note this introduced as new, significant limitation on the number of
total mdirs in the system. Normally I would be against this solution for
that reason, however if we adopt this encoding elsewhere in the system it
may improve some RAM cost and in general simplify things by being able to
store any mid in a single integer. More work needs to be done here...
This approach needs some fleshing out and has its own issues (the
offset returned by tell quickly becomes out of date if the filesystem
is modified, but is that really a problem?), but it improves over the
previous implementation by making tell always correct at that moment.
7206 lines
232 KiB
TOML
7206 lines
232 KiB
TOML
# Directory tests
|
|
|
|
|
|
## mkdir tests
|
|
|
|
[cases.t5_dirs_mkdir]
|
|
defines.REMOUNT = [false, true]
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// make a directory
|
|
err = lfsr_mkdir(&lfs, "ardvark");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our mkdir worked with stat
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "ardvark", &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
// and with dir_read
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# test that noent errors work
|
|
[cases.t5_dirs_noent]
|
|
defines.REMOUNT = [false, true]
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
|
|
// make a directory
|
|
lfsr_mkdir(&lfs, "ardvark") => 0;
|
|
|
|
// try to read a nonsense path
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "no", &info) => LFS_ERR_NOENT;
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "no") => LFS_ERR_NOENT;
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// and check that this didn't interfere with our original directory
|
|
lfsr_stat(&lfs, "ardvark", &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# test that stat on root works
|
|
[cases.t5_dirs_stat_root]
|
|
defines.REMOUNT = [false, true]
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
|
|
// make a directory
|
|
lfsr_mkdir(&lfs, "ardvark") => 0;
|
|
|
|
// stat the root
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "/", &info) => 0;
|
|
assert(strcmp(info.name, "/") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// and check that this didn't interfere with our original directory
|
|
lfsr_stat(&lfs, "ardvark", &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# test that creating the same directory twice errors
|
|
[cases.t5_dirs_mkdir_exists]
|
|
defines.REMOUNT = [false, true]
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// make a directory
|
|
err = lfsr_mkdir(&lfs, "ardvark");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// make the same directory, should error
|
|
lfsr_mkdir(&lfs, "ardvark") => LFS_ERR_EXIST;
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// and check that this didn't interfere with our original directory
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "ardvark", &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# test what happens if we try to make root
|
|
[cases.t5_dirs_mkdir_root]
|
|
defines.REMOUNT = [false, true]
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// try to make root, which doesn't make sense
|
|
err = lfsr_mkdir(&lfs, "/");
|
|
assert(err == LFS_ERR_EXIST || err == LFS_ERR_INVAL);
|
|
|
|
// make a directory
|
|
err = lfsr_mkdir(&lfs, "ardvark");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// try to make root, which doesn't make sense
|
|
err = lfsr_mkdir(&lfs, "/");
|
|
assert(err == LFS_ERR_EXIST || err == LFS_ERR_INVAL);
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// and check that this didn't interfere with our original directory
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "ardvark", &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# test that creating a directory with an invalid path errors
|
|
[cases.t5_dirs_mkdir_noent]
|
|
defines.REMOUNT = [false, true]
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// make a directory
|
|
err = lfsr_mkdir(&lfs, "ardvark");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// make a nonsense directory, should error
|
|
lfsr_mkdir(&lfs, "no/hmm") => LFS_ERR_NOENT;
|
|
|
|
// make a nonsense child directory, should error
|
|
lfsr_mkdir(&lfs, "ardvark/no/hmm") => LFS_ERR_NOENT;
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// and check that this didn't interfere with our original directory
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "ardvark", &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_mkdir_siblings]
|
|
defines.REMOUNT = [false, true]
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// make some directories
|
|
err = lfsr_mkdir(&lfs, "ardvark");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "banana");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "cat");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our mkdir worked
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "ardvark", &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "banana", &info) => 0;
|
|
assert(strcmp(info.name, "banana") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "cat", &info) => 0;
|
|
assert(strcmp(info.name, "cat") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "banana") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "cat") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_mkdir_children]
|
|
defines.REMOUNT = [false, true]
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// make some directories
|
|
err = lfsr_mkdir(&lfs, "ardvark");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "ardvark/banana");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "ardvark/banana/cat");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our mkdirs worked
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "ardvark", &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "ardvark/banana", &info) => 0;
|
|
assert(strcmp(info.name, "banana") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "ardvark/banana/cat", &info) => 0;
|
|
assert(strcmp(info.name, "cat") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/ardvark") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "banana") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/ardvark/banana") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "cat") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_mkdir_many]
|
|
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
|
|
defines.REMOUNT = [false, true]
|
|
# limit powerloss testing due to time
|
|
if = '!TEST_PL || N <= 32'
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// make this many directories
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
err = lfsr_mkdir(&lfs, name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
}
|
|
|
|
// check that our mkdir worked
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_mkdir_many_backwards]
|
|
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
|
|
defines.REMOUNT = [false, true]
|
|
# limit powerloss testing due to time
|
|
if = '!TEST_PL || N <= 32'
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// make this many directories
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", (int)(N-1-i));
|
|
err = lfsr_mkdir(&lfs, name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
}
|
|
|
|
// check that our mkdir worked
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_mkdir_many_2layers]
|
|
defines.N = [1, 2, 4, 8, 16]
|
|
defines.REMOUNT = [false, true]
|
|
# limit powerloss testing due to time
|
|
if = '!TEST_PL || N <= 4'
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// make this many directories
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
err = lfsr_mkdir(&lfs, name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// containing this many directories
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
sprintf(name, "dir%04d/child%04d", i, j);
|
|
err = lfsr_mkdir(&lfs, name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
// check that our mkdirs worked
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d/child%04d", i, j);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
sprintf(name, "child%04d", j);
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
}
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_open(&lfs, &dir, name) => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
char name[256];
|
|
sprintf(name, "child%04d", j);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
}
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_mkdir_many_3layers]
|
|
defines.N = [1, 2, 4]
|
|
defines.REMOUNT = [false, true]
|
|
# limit powerloss testing due to time
|
|
if = '!TEST_PL || N <= 2'
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// make this many directories
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
err = lfsr_mkdir(&lfs, name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// containing this many directories
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
sprintf(name, "dir%04d/child%04d", i, j);
|
|
err = lfsr_mkdir(&lfs, name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// containing this many directories
|
|
for (lfs_size_t k = 0; k < N; k++) {
|
|
sprintf(name, "dir%04d/child%04d/grandchild%04d", i, j, k);
|
|
err = lfsr_mkdir(&lfs, name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// check that our mkdirs worked
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d/child%04d", i, j);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
sprintf(name, "child%04d", j);
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
for (lfs_size_t k = 0; k < N; k++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d/child%04d/grandchild%04d", i, j, k);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
sprintf(name, "grandchild%04d", k);
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
}
|
|
}
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_open(&lfs, &dir, name) => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
char name[256];
|
|
sprintf(name, "child%04d", j);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d/child%04d", i, j);
|
|
lfsr_dir_open(&lfs, &dir, name) => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t k = 0; k < N; k++) {
|
|
char name[256];
|
|
sprintf(name, "grandchild%04d", k);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
}
|
|
}
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_mkdir_many_linkedlist]
|
|
defines.N = [1, 2, 4, 8, 16, 32, 64]
|
|
defines.REMOUNT = [false, true]
|
|
# limit powerloss testing due to time
|
|
if = '!TEST_PL || N <= 16'
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// create this many directory in a sort of linked-list by nesting
|
|
char name[4096];
|
|
memset(name, 0, sizeof(name));
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
sprintf(&name[strlen(name)], "/dir%04d", i);
|
|
err = lfsr_mkdir(&lfs, name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
}
|
|
|
|
// check that our mkdir worked
|
|
memset(name, 0, sizeof(name));
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
sprintf(&name[strlen(name)], "/dir%04d", i);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
char name2[256];
|
|
sprintf(name2, "dir%04d", i);
|
|
assert(strcmp(info.name, name2) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
memset(name, 0, sizeof(name));
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
sprintf(&name[strlen(name)], "/dir%04d", i);
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, name) => 0;
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
if (i < N-1) {
|
|
char name2[256];
|
|
sprintf(name2, "dir%04d", i+1);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name2) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
}
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_mkdir_fuzz]
|
|
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
|
|
defines.PARENT = [false, true]
|
|
defines.REMOUNT = [false, true]
|
|
defines.SEED = 'range(10)'
|
|
# limit powerloss testing due to time
|
|
if = '!TEST_PL || N <= 64'
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
if (PARENT) {
|
|
err = lfsr_mkdir(&lfs, "pricklypear");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
}
|
|
|
|
// set up a simulation to compare against
|
|
lfs_size_t *sim = malloc(N*sizeof(lfs_size_t));
|
|
lfs_size_t sim_size = 0;
|
|
|
|
uint32_t prng = SEED;
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
// choose a pseudo-random number, truncate to 4 decimals
|
|
lfs_size_t x = TEST_PRNG(&prng) % 10000;
|
|
|
|
// insert into our sim
|
|
for (lfs_size_t j = 0;; j++) {
|
|
if (j >= sim_size || sim[j] >= x) {
|
|
// already seen?
|
|
if (j < sim_size && sim[j] == x) {
|
|
// do nothing
|
|
} else {
|
|
// insert
|
|
memmove(&sim[j+1], &sim[j],
|
|
(sim_size-j)*sizeof(lfs_size_t));
|
|
sim_size += 1;
|
|
sim[j] = x;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
// create a directory here
|
|
char name[256];
|
|
sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), x);
|
|
int err = lfsr_mkdir(&lfs, name);
|
|
assert(!err || err == LFS_ERR_EXIST);
|
|
}
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// test that our directories match our simulation
|
|
for (lfs_size_t j = 0; j < sim_size; j++) {
|
|
char name[256];
|
|
sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), sim[j]);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
char name2[256];
|
|
sprintf(name2, "dir%04d", sim[j]);
|
|
assert(strcmp(info.name, name2) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, (PARENT ? "pricklypear" : "/")) => 0;
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t j = 0; j < sim_size; j++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", sim[j]);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
// clean up sim/lfs
|
|
free(sim);
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
|
|
# test that did collisions don't cause issues
|
|
[cases.t5_dirs_did_collisions]
|
|
defines.REMOUNT = [false, true]
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
assert(lfs_crc32c(0, "a_SNmwMTHH", 10) == 0x12345678);
|
|
assert(lfs_crc32c(0, "b_skvjpWJH", 10) == 0x12345678);
|
|
assert(lfs_crc32c(0, "c_OnOQhVPH", 10) == 0x12345678);
|
|
assert(lfs_crc32c(0, "d_puMpPjRH", 10) == 0x12345678);
|
|
assert(lfs_crc32c(0, "e_LptKHkHH", 10) == 0x12345678);
|
|
assert(lfs_crc32c(0, "f_lUoVuhJH", 10) == 0x12345678);
|
|
|
|
// make directories
|
|
err = lfsr_mkdir(&lfs, "a_SNmwMTHH");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "b_skvjpWJH");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "c_OnOQhVPH");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "d_puMpPjRH");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "e_LptKHkHH");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "f_lUoVuhJH");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our mkdirs worked
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "a_SNmwMTHH", &info) => 0;
|
|
assert(strcmp(info.name, "a_SNmwMTHH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "b_skvjpWJH", &info) => 0;
|
|
assert(strcmp(info.name, "b_skvjpWJH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "c_OnOQhVPH", &info) => 0;
|
|
assert(strcmp(info.name, "c_OnOQhVPH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "d_puMpPjRH", &info) => 0;
|
|
assert(strcmp(info.name, "d_puMpPjRH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "e_LptKHkHH", &info) => 0;
|
|
assert(strcmp(info.name, "e_LptKHkHH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "f_lUoVuhJH", &info) => 0;
|
|
assert(strcmp(info.name, "f_lUoVuhJH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "a_SNmwMTHH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "b_skvjpWJH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "c_OnOQhVPH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "d_puMpPjRH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "e_LptKHkHH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "f_lUoVuhJH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# these will also collide with the root
|
|
[cases.t5_dirs_did_zero]
|
|
defines.REMOUNT = [false, true]
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
assert(lfs_crc32c(0, "a_IplRNrPH", 10) == 0x00000000);
|
|
assert(lfs_crc32c(0, "b_iUwOsqRH", 10) == 0x00000000);
|
|
assert(lfs_crc32c(0, "c_UPNtkpHH", 10) == 0x00000000);
|
|
assert(lfs_crc32c(0, "d_jKLUSLJH", 10) == 0x00000000);
|
|
assert(lfs_crc32c(0, "e_VNunKMPH", 10) == 0x00000000);
|
|
assert(lfs_crc32c(0, "f_vknsvNRH", 10) == 0x00000000);
|
|
|
|
// make directories
|
|
err = lfsr_mkdir(&lfs, "a_IplRNrPH");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "b_iUwOsqRH");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "c_UPNtkpHH");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "d_jKLUSLJH");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "e_VNunKMPH");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "f_vknsvNRH");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our mkdirs worked
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "a_IplRNrPH", &info) => 0;
|
|
assert(strcmp(info.name, "a_IplRNrPH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "b_iUwOsqRH", &info) => 0;
|
|
assert(strcmp(info.name, "b_iUwOsqRH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "c_UPNtkpHH", &info) => 0;
|
|
assert(strcmp(info.name, "c_UPNtkpHH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "d_jKLUSLJH", &info) => 0;
|
|
assert(strcmp(info.name, "d_jKLUSLJH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "e_VNunKMPH", &info) => 0;
|
|
assert(strcmp(info.name, "e_VNunKMPH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "f_vknsvNRH", &info) => 0;
|
|
assert(strcmp(info.name, "f_vknsvNRH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "a_IplRNrPH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "b_iUwOsqRH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "c_UPNtkpHH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "d_jKLUSLJH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "e_VNunKMPH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "f_vknsvNRH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# these will need to rollover from 0xffffffff -> 0x00000000 correctly
|
|
#
|
|
# note this is true even if you truncate
|
|
[cases.t5_dirs_did_ones]
|
|
defines.REMOUNT = [false, true]
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
assert(lfs_crc32c(0, "a_iomlVKPH", 10) == 0xffffffff);
|
|
assert(lfs_crc32c(0, "b_IJvqkHRH", 10) == 0xffffffff);
|
|
assert(lfs_crc32c(0, "c_uOOJsIHH", 10) == 0xffffffff);
|
|
assert(lfs_crc32c(0, "d_JTMkKuJH", 10) == 0xffffffff);
|
|
assert(lfs_crc32c(0, "e_vQtPStPH", 10) == 0xffffffff);
|
|
assert(lfs_crc32c(0, "f_VtoMnwRH", 10) == 0xffffffff);
|
|
|
|
// make directories
|
|
err = lfsr_mkdir(&lfs, "a_iomlVKPH");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "b_IJvqkHRH");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "c_uOOJsIHH");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "d_JTMkKuJH");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "e_vQtPStPH");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "f_VtoMnwRH");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our mkdirs worked
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "a_iomlVKPH", &info) => 0;
|
|
assert(strcmp(info.name, "a_iomlVKPH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "b_IJvqkHRH", &info) => 0;
|
|
assert(strcmp(info.name, "b_IJvqkHRH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "c_uOOJsIHH", &info) => 0;
|
|
assert(strcmp(info.name, "c_uOOJsIHH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "d_JTMkKuJH", &info) => 0;
|
|
assert(strcmp(info.name, "d_JTMkKuJH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "e_vQtPStPH", &info) => 0;
|
|
assert(strcmp(info.name, "e_vQtPStPH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "f_VtoMnwRH", &info) => 0;
|
|
assert(strcmp(info.name, "f_VtoMnwRH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "a_iomlVKPH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "b_IJvqkHRH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "c_uOOJsIHH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "d_JTMkKuJH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "e_vQtPStPH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "f_VtoMnwRH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# these test some boundary conditions on the underlying leb128 encoding,
|
|
# if the leb128 disk-size is not calculated correctly these can cause
|
|
# issues
|
|
[cases.t5_dirs_did_leb128_boundaries]
|
|
defines.REMOUNT = [false, true]
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
assert(lfs_crc32c(0, "a_IOtUptRH", 10) == 0x0000007f);
|
|
assert(lfs_crc32c(0, "b_nquQsKHH", 10) == 0x00000080);
|
|
assert(lfs_crc32c(0, "c_vwQtKjHH", 10) == 0x00000081);
|
|
assert(lfs_crc32c(0, "d_sVrvrWHH", 10) == 0x00003fff);
|
|
assert(lfs_crc32c(0, "e_thrRIsRH", 10) == 0x00004000);
|
|
assert(lfs_crc32c(0, "f_pNtQTPJH", 10) == 0x00004001);
|
|
|
|
// make directories
|
|
err = lfsr_mkdir(&lfs, "a_IOtUptRH");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "b_nquQsKHH");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "c_vwQtKjHH");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "d_sVrvrWHH");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "e_thrRIsRH");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "f_pNtQTPJH");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our mkdirs worked
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "a_IOtUptRH", &info) => 0;
|
|
assert(strcmp(info.name, "a_IOtUptRH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "b_nquQsKHH", &info) => 0;
|
|
assert(strcmp(info.name, "b_nquQsKHH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "c_vwQtKjHH", &info) => 0;
|
|
assert(strcmp(info.name, "c_vwQtKjHH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "d_sVrvrWHH", &info) => 0;
|
|
assert(strcmp(info.name, "d_sVrvrWHH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "e_thrRIsRH", &info) => 0;
|
|
assert(strcmp(info.name, "e_thrRIsRH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "f_pNtQTPJH", &info) => 0;
|
|
assert(strcmp(info.name, "f_pNtQTPJH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "a_IOtUptRH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "b_nquQsKHH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "c_vwQtKjHH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "d_sVrvrWHH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "e_thrRIsRH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "f_pNtQTPJH") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
|
|
## dir remove tests
|
|
|
|
[cases.t5_dirs_rm]
|
|
defines.REMOUNT = [false, true]
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// make a directory
|
|
err = lfsr_mkdir(&lfs, "ardvark");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our mkdir worked with stat
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "ardvark", &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
// and with dir_read
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
// and remove the directory
|
|
lfsr_remove(&lfs, "ardvark") => 0;
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that remove worked with stat
|
|
lfsr_stat(&lfs, "ardvark", &info) => LFS_ERR_NOENT;
|
|
|
|
// and with dir_read
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# test that noent errors work
|
|
[cases.t5_dirs_rm_noent]
|
|
defines.REMOUNT = [false, true]
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// make a directory
|
|
err = lfsr_mkdir(&lfs, "ardvark");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// try to remove a nonsense directory
|
|
lfsr_remove(&lfs, "no") => LFS_ERR_NOENT;
|
|
|
|
// try to remove a directory in a nonsense directory
|
|
lfsr_remove(&lfs, "no/ardvark") => LFS_ERR_NOENT;
|
|
|
|
// try to remove a nonsense child directory
|
|
lfsr_remove(&lfs, "ardvark/no") => LFS_ERR_NOENT;
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// and check that this didn't interfere with our original directory
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "ardvark", &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# test that we catch removing of a non-empty directory
|
|
[cases.t5_dirs_rm_notempty]
|
|
defines.REMOUNT = [false, true]
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// make a directory
|
|
err = lfsr_mkdir(&lfs, "ardvark");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// fill it with stuff
|
|
err = lfsr_mkdir(&lfs, "ardvark/banana");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// try to remove the parent directory
|
|
lfsr_remove(&lfs, "ardvark") => LFS_ERR_NOTEMPTY;
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// and check that this didn't interfere with our original directory
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "ardvark", &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "ardvark/banana", &info) => 0;
|
|
assert(strcmp(info.name, "banana") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_dir_open(&lfs, &dir, "ardvark") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "banana") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# test what happens if we try to remove root
|
|
[cases.t5_dirs_rm_root]
|
|
defines.REMOUNT = [false, true]
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// try to remove root, which doesn't really make sense
|
|
lfsr_remove(&lfs, "/") => LFS_ERR_INVAL;
|
|
|
|
// make a directory
|
|
err = lfsr_mkdir(&lfs, "ardvark");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// try to remove root, which doesn't really make sense
|
|
//
|
|
// it doesn't really matter which error returns first, so accept both
|
|
err = lfsr_remove(&lfs, "/");
|
|
assert(err == LFS_ERR_NOTEMPTY || err == LFS_ERR_INVAL);
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// and check that this didn't interfere with our original directory
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "ardvark", &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_rm_siblings]
|
|
defines.REMOUNT = [false, true]
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// make some directories
|
|
err = lfsr_mkdir(&lfs, "ardvark");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "banana");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "cat");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our mkdir worked
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "ardvark", &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "banana", &info) => 0;
|
|
assert(strcmp(info.name, "banana") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "cat", &info) => 0;
|
|
assert(strcmp(info.name, "cat") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "banana") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "cat") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
// now remove each directory
|
|
lfsr_remove(&lfs, "ardvark") => 0;
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our remove worked
|
|
lfsr_stat(&lfs, "ardvark", &info) => LFS_ERR_NOENT;
|
|
lfsr_stat(&lfs, "banana", &info) => 0;
|
|
assert(strcmp(info.name, "banana") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "cat", &info) => 0;
|
|
assert(strcmp(info.name, "cat") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "banana") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "cat") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
// remove another
|
|
lfsr_remove(&lfs, "banana") => 0;
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our remove worked
|
|
lfsr_stat(&lfs, "ardvark", &info) => LFS_ERR_NOENT;
|
|
lfsr_stat(&lfs, "banana", &info) => LFS_ERR_NOENT;
|
|
lfsr_stat(&lfs, "cat", &info) => 0;
|
|
assert(strcmp(info.name, "cat") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "cat") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
// remove another
|
|
lfsr_remove(&lfs, "cat") => 0;
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our remove worked
|
|
lfsr_stat(&lfs, "ardvark", &info) => LFS_ERR_NOENT;
|
|
lfsr_stat(&lfs, "banana", &info) => LFS_ERR_NOENT;
|
|
lfsr_stat(&lfs, "cat", &info) => LFS_ERR_NOENT;
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_rm_children]
|
|
defines.REMOUNT = [false, true]
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// make some directories
|
|
err = lfsr_mkdir(&lfs, "ardvark");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "ardvark/banana");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "ardvark/banana/cat");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our mkdirs worked
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "ardvark", &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "ardvark/banana", &info) => 0;
|
|
assert(strcmp(info.name, "banana") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "ardvark/banana/cat", &info) => 0;
|
|
assert(strcmp(info.name, "cat") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/ardvark") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "banana") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/ardvark/banana") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "cat") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
// now remove each directory
|
|
lfsr_remove(&lfs, "ardvark/banana/cat") => 0;
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our remove worked
|
|
lfsr_stat(&lfs, "ardvark", &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "ardvark/banana", &info) => 0;
|
|
assert(strcmp(info.name, "banana") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "ardvark/banana/cat", &info) => LFS_ERR_NOENT;
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/ardvark") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "banana") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/ardvark/banana") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
// remove another
|
|
lfsr_remove(&lfs, "ardvark/banana") => 0;
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our remove worked
|
|
lfsr_stat(&lfs, "ardvark", &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "ardvark/banana", &info) => LFS_ERR_NOENT;
|
|
lfsr_stat(&lfs, "ardvark/banana/cat", &info) => LFS_ERR_NOENT;
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/ardvark") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
// remove another
|
|
lfsr_remove(&lfs, "ardvark") => 0;
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our remove worked
|
|
lfsr_stat(&lfs, "ardvark", &info) => LFS_ERR_NOENT;
|
|
lfsr_stat(&lfs, "ardvark/banana", &info) => LFS_ERR_NOENT;
|
|
lfsr_stat(&lfs, "ardvark/banana/cat", &info) => LFS_ERR_NOENT;
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_rm_many]
|
|
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
|
|
defines.REMAINING = [64, 2, 1, 0]
|
|
defines.REMOUNT = [false, true]
|
|
if = [
|
|
'N > REMAINING',
|
|
# limit powerloss testing due to time
|
|
'!TEST_PL || N <= 32',
|
|
]
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// make this many directories
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
err = lfsr_mkdir(&lfs, name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
}
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our mkdir worked
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
// now remove some number of directories
|
|
for (lfs_size_t i = 0; i < N-REMAINING; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_remove(&lfs, name) => 0;
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
}
|
|
|
|
// check that our removes worked
|
|
for (lfs_size_t i = 0; i < N-REMAINING; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => LFS_ERR_NOENT;
|
|
}
|
|
for (lfs_size_t i = 0; i < REMAINING; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", (int)(N-REMAINING + i));
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t i = 0; i < REMAINING; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", (int)(N-REMAINING + i));
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_rm_many_backwards]
|
|
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
|
|
defines.REMAINING = [64, 2, 1, 0]
|
|
defines.REMOUNT = [false, true]
|
|
if = [
|
|
'N > REMAINING',
|
|
# limit powerloss testing due to time
|
|
'!TEST_PL || N <= 32',
|
|
]
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// make this many directories
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", (int)(N-1-i));
|
|
err = lfsr_mkdir(&lfs, name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
}
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our mkdir worked
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
// now remove some number of directories
|
|
for (lfs_size_t i = 0; i < N-REMAINING; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", (int)(N-1-i));
|
|
lfsr_remove(&lfs, name) => 0;
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
}
|
|
|
|
// check that our removes worked
|
|
for (lfs_size_t i = 0; i < N-REMAINING; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", (int)(N-1-i));
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => LFS_ERR_NOENT;
|
|
}
|
|
for (lfs_size_t i = 0; i < REMAINING; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t i = 0; i < REMAINING; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_rm_many_2layers]
|
|
defines.N = [1, 2, 4, 8, 16]
|
|
defines.REMAINING = [2, 1, 0]
|
|
defines.REMOUNT = [false, true]
|
|
if = [
|
|
'N > REMAINING',
|
|
# limit powerloss testing due to time
|
|
'!TEST_PL || N <= 4',
|
|
]
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// make this many directories
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
err = lfsr_mkdir(&lfs, name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// containing this many directories
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
sprintf(name, "dir%04d/child%04d", i, j);
|
|
err = lfsr_mkdir(&lfs, name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
}
|
|
}
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our mkdirs worked
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d/child%04d", i, j);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
sprintf(name, "child%04d", j);
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
}
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_open(&lfs, &dir, name) => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
char name[256];
|
|
sprintf(name, "child%04d", j);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
}
|
|
|
|
// now remove some number of directories
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
if (i < N-REMAINING || j < N-REMAINING) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d/child%04d", i, j);
|
|
lfsr_remove(&lfs, name) => 0;
|
|
}
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
}
|
|
|
|
if (i < N-REMAINING) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_remove(&lfs, name) => 0;
|
|
}
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
}
|
|
|
|
// check that our removes worked
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
struct lfs_info info;
|
|
if (i < N-REMAINING) {
|
|
lfsr_stat(&lfs, name, &info) => LFS_ERR_NOENT;
|
|
} else {
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d/child%04d", i, j);
|
|
struct lfs_info info;
|
|
if (j < N-REMAINING) {
|
|
lfsr_stat(&lfs, name, &info) => LFS_ERR_NOENT;
|
|
} else {
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
sprintf(name, "child%04d", j);
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t i = 0; i < REMAINING; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", (int)(N-REMAINING + i));
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
for (lfs_size_t i = 0; i < REMAINING; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", (int)(N-REMAINING + i));
|
|
lfsr_dir_open(&lfs, &dir, name) => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t j = 0; j < REMAINING; j++) {
|
|
char name[256];
|
|
sprintf(name, "child%04d", (int)(N-REMAINING + j));
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
}
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_rm_many_3layers]
|
|
defines.N = [1, 2, 4]
|
|
defines.REMAINING = [2, 1, 0]
|
|
defines.REMOUNT = [false, true]
|
|
if = [
|
|
'N > REMAINING',
|
|
# limit powerloss testing due to time
|
|
'!TEST_PL || N <= 2',
|
|
]
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// make this many directories
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
err = lfsr_mkdir(&lfs, name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// containing this many directories
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
sprintf(name, "dir%04d/child%04d", i, j);
|
|
err = lfsr_mkdir(&lfs, name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// containing this many directories
|
|
for (lfs_size_t k = 0; k < N; k++) {
|
|
sprintf(name, "dir%04d/child%04d/grandchild%04d", i, j, k);
|
|
err = lfsr_mkdir(&lfs, name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
}
|
|
}
|
|
}
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our mkdirs worked
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d/child%04d", i, j);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
sprintf(name, "child%04d", j);
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
for (lfs_size_t k = 0; k < N; k++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d/child%04d/grandchild%04d", i, j, k);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
sprintf(name, "grandchild%04d", k);
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
}
|
|
}
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_open(&lfs, &dir, name) => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
char name[256];
|
|
sprintf(name, "child%04d", j);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d/child%04d", i, j);
|
|
lfsr_dir_open(&lfs, &dir, name) => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t k = 0; k < N; k++) {
|
|
char name[256];
|
|
sprintf(name, "grandchild%04d", k);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
}
|
|
}
|
|
|
|
// now remove some number of directories
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
for (lfs_size_t k = 0; k < N; k++) {
|
|
if (i < N-REMAINING || j < N-REMAINING || k < N-REMAINING) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d/child%04d/grandchild%04d", i, j, k);
|
|
lfsr_remove(&lfs, name) => 0;
|
|
}
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
}
|
|
|
|
if (i < N-REMAINING || j < N-REMAINING) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d/child%04d", i, j);
|
|
lfsr_remove(&lfs, name) => 0;
|
|
}
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
}
|
|
|
|
if (i < N-REMAINING) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_remove(&lfs, name) => 0;
|
|
}
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
}
|
|
|
|
// check that our removes worked
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
struct lfs_info info;
|
|
if (i < N-REMAINING) {
|
|
lfsr_stat(&lfs, name, &info) => LFS_ERR_NOENT;
|
|
} else {
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d/child%04d", i, j);
|
|
struct lfs_info info;
|
|
if (j < N-REMAINING) {
|
|
lfsr_stat(&lfs, name, &info) => LFS_ERR_NOENT;
|
|
} else {
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
sprintf(name, "child%04d", j);
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
for (lfs_size_t k = 0; k < N; k++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d/child%04d/grandchild%04d",
|
|
i, j, k);
|
|
struct lfs_info info;
|
|
if (k < N-REMAINING) {
|
|
lfsr_stat(&lfs, name, &info) => LFS_ERR_NOENT;
|
|
} else {
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
sprintf(name, "grandchild%04d", k);
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t i = 0; i < REMAINING; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", (int)(N-REMAINING + i));
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
for (lfs_size_t i = 0; i < REMAINING; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", (int)(N-REMAINING + i));
|
|
lfsr_dir_open(&lfs, &dir, name) => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t j = 0; j < REMAINING; j++) {
|
|
char name[256];
|
|
sprintf(name, "child%04d", (int)(N-REMAINING + j));
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
}
|
|
|
|
for (lfs_size_t i = 0; i < REMAINING; i++) {
|
|
for (lfs_size_t j = 0; j < REMAINING; j++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d/child%04d",
|
|
(int)(N-REMAINING + i),
|
|
(int)(N-REMAINING + j));
|
|
lfsr_dir_open(&lfs, &dir, name) => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t k = 0; k < REMAINING; k++) {
|
|
char name[256];
|
|
sprintf(name, "grandchild%04d", (int)(N-REMAINING + k));
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
}
|
|
}
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_rm_many_linkedlist]
|
|
defines.N = [1, 2, 4, 8, 16, 32, 64]
|
|
defines.REMAINING = [16, 2, 1, 0]
|
|
defines.REMOUNT = [false, true]
|
|
if = [
|
|
'N > REMAINING',
|
|
# limit powerloss testing due to time
|
|
'!TEST_PL || N <= 16',
|
|
]
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// create this many directory in a sort of linked-list by nesting
|
|
char name[4096];
|
|
memset(name, 0, sizeof(name));
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
sprintf(&name[strlen(name)], "/dir%04d", i);
|
|
err = lfsr_mkdir(&lfs, name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
}
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our mkdir worked
|
|
memset(name, 0, sizeof(name));
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
sprintf(&name[strlen(name)], "/dir%04d", i);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
char name2[256];
|
|
sprintf(name2, "dir%04d", i);
|
|
assert(strcmp(info.name, name2) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
memset(name, 0, sizeof(name));
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
sprintf(&name[strlen(name)], "/dir%04d", i);
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, name) => 0;
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
if (i < N-1) {
|
|
char name2[256];
|
|
sprintf(name2, "dir%04d", i+1);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name2) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
}
|
|
|
|
// now remove some number of directories
|
|
for (lfs_size_t i = 0; i < N-REMAINING; i++) {
|
|
lfsr_remove(&lfs, name) => 0;
|
|
name[strlen(name) - strlen("/dir....")] = '\0';
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
}
|
|
|
|
// check that our remove worked
|
|
memset(name, 0, sizeof(name));
|
|
for (lfs_size_t i = 0; i < REMAINING; i++) {
|
|
sprintf(&name[strlen(name)], "/dir%04d", i);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
char name2[256];
|
|
sprintf(name2, "dir%04d", i);
|
|
assert(strcmp(info.name, name2) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
memset(name, 0, sizeof(name));
|
|
for (lfs_size_t i = 0; i < REMAINING; i++) {
|
|
sprintf(&name[strlen(name)], "/dir%04d", i);
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, name) => 0;
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
if (i < REMAINING-1) {
|
|
char name2[256];
|
|
sprintf(name2, "dir%04d", i+1);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name2) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
}
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_rm_fuzz]
|
|
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
|
|
defines.PARENT = [false, true]
|
|
defines.REMOUNT = [false, true]
|
|
defines.SEED = 'range(10)'
|
|
# limit powerloss testing due to time
|
|
if = '!TEST_PL || N <= 64'
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
if (PARENT) {
|
|
err = lfsr_mkdir(&lfs, "pricklypear");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
}
|
|
|
|
// set up a simulation to compare against
|
|
lfs_size_t *sim = malloc(N*sizeof(lfs_size_t));
|
|
lfs_size_t sim_size = 0;
|
|
|
|
uint32_t prng = SEED;
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
// choose a pseudo-random op, either mkdir or rmdir
|
|
uint8_t op = TEST_PRNG(&prng) % 2;
|
|
|
|
if (op == 0 || sim_size == 0) {
|
|
// choose a pseudo-random number, truncate to 4 decimals
|
|
lfs_size_t x = TEST_PRNG(&prng) % 10000;
|
|
// insert into our sim
|
|
for (lfs_size_t j = 0;; j++) {
|
|
if (j >= sim_size || sim[j] >= x) {
|
|
// already seen?
|
|
if (j < sim_size && sim[j] == x) {
|
|
// do nothing
|
|
} else {
|
|
// insert
|
|
memmove(&sim[j+1], &sim[j],
|
|
(sim_size-j)*sizeof(lfs_size_t));
|
|
sim_size += 1;
|
|
sim[j] = x;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
// create a directory here
|
|
char name[256];
|
|
sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), x);
|
|
int err = lfsr_mkdir(&lfs, name);
|
|
assert(!err || err == LFS_ERR_EXIST);
|
|
|
|
} else {
|
|
// choose a pseudo-random entry to delete
|
|
lfs_size_t j = TEST_PRNG(&prng) % sim_size;
|
|
lfs_size_t x = sim[j];
|
|
// delete from our sim
|
|
memmove(&sim[j], &sim[j+1],
|
|
(sim_size-(j+1))*sizeof(lfs_size_t));
|
|
sim_size -= 1;
|
|
|
|
// remove this directory
|
|
char name[256];
|
|
sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), x);
|
|
lfsr_remove(&lfs, name) => 0;
|
|
}
|
|
}
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// test that our directories match our simulation
|
|
for (lfs_size_t j = 0; j < sim_size; j++) {
|
|
char name[256];
|
|
sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), sim[j]);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
char name2[256];
|
|
sprintf(name2, "dir%04d", sim[j]);
|
|
assert(strcmp(info.name, name2) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, (PARENT ? "pricklypear" : "/")) => 0;
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t j = 0; j < sim_size; j++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", sim[j]);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
// clean up sim/lfs
|
|
free(sim);
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
|
|
## dir rename tests
|
|
|
|
[cases.t5_dirs_mv]
|
|
defines.REMOUNT = [false, true]
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// make a directory
|
|
err = lfsr_mkdir(&lfs, "ardvark");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// clean up interrupted renames
|
|
if (TEST_PL) {
|
|
err = lfsr_remove(&lfs, "banana");
|
|
assert(!err || err == LFS_ERR_NOENT);
|
|
}
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our mkdir worked with stat
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "ardvark", &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
// and with dir_read
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
// now rename the directory
|
|
lfsr_rename(&lfs, "ardvark", "banana") => 0;
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that rename worked with stat
|
|
lfsr_stat(&lfs, "ardvark", &info) => LFS_ERR_NOENT;
|
|
lfsr_stat(&lfs, "banana", &info) => 0;
|
|
assert(strcmp(info.name, "banana") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
// and with dir_read
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "banana") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# test that we can rename, and replace, other directories
|
|
[cases.t5_dirs_mv_replace]
|
|
defines.REMOUNT = [false, true]
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// make directories
|
|
err = lfsr_mkdir(&lfs, "ardvark");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "banana");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our mkdir worked with stat
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "ardvark", &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
// and with dir_read
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "banana") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
// now rename the directory
|
|
lfsr_rename(&lfs, "ardvark", "banana") => 0;
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that rename worked with stat
|
|
lfsr_stat(&lfs, "ardvark", &info) => LFS_ERR_NOENT;
|
|
lfsr_stat(&lfs, "banana", &info) => 0;
|
|
assert(strcmp(info.name, "banana") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
// and with dir_read
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "banana") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# test that we can rename to ourselves
|
|
[cases.t5_dirs_mv_noop]
|
|
defines.REMOUNT = [false, true]
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// make directories
|
|
err = lfsr_mkdir(&lfs, "ardvark");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our mkdir worked with stat
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "ardvark", &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
// and with dir_read
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
// now rename the directory to itself
|
|
lfsr_rename(&lfs, "ardvark", "ardvark") => 0;
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that rename worked with stat
|
|
lfsr_stat(&lfs, "ardvark", &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
// and with dir_read
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# test that we catch replacing an invalid path
|
|
[cases.t5_dirs_mv_noent]
|
|
defines.REMOUNT = [false, true]
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// make directories
|
|
err = lfsr_mkdir(&lfs, "ardvark");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// try to rename a nonsense directory
|
|
lfsr_rename(&lfs, "no", "ardvark") => LFS_ERR_NOENT;
|
|
|
|
// try to rename a directory in a nonsense directory
|
|
lfsr_rename(&lfs, "no/ardvark", "ardvark") => LFS_ERR_NOENT;
|
|
|
|
// try to rename a nonsense child directory
|
|
lfsr_rename(&lfs, "ardvark/no", "banana") => LFS_ERR_NOENT;
|
|
|
|
// try to rename to a nonense directory
|
|
lfsr_rename(&lfs, "ardvark", "no/ardvark") => LFS_ERR_NOENT;
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// and check that this didn't interfere with our original directory
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "ardvark", &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# test that we catch replacing a non-empty directory
|
|
[cases.t5_dirs_mv_notempty]
|
|
defines.REMOUNT = [false, true]
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// make directories
|
|
err = lfsr_mkdir(&lfs, "ardvark");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "banana");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
// fill dest with stuff
|
|
err = lfsr_mkdir(&lfs, "banana/cat");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// try to rename
|
|
lfsr_rename(&lfs, "ardvark", "banana") => LFS_ERR_NOTEMPTY;
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// and check that this didn't interfere with our original directory
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "ardvark", &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "banana", &info) => 0;
|
|
assert(strcmp(info.name, "banana") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "banana/cat", &info) => 0;
|
|
assert(strcmp(info.name, "cat") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "banana") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_dir_open(&lfs, &dir, "banana") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "cat") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# test what happens if we try to rename root
|
|
[cases.t5_dirs_mv_root]
|
|
defines.REMOUNT = [false, true]
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// try to rename root, which doesn't really make sense
|
|
lfsr_rename(&lfs, "/", "notroot") => LFS_ERR_INVAL;
|
|
|
|
// make a directory
|
|
err = lfsr_mkdir(&lfs, "ardvark");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// try to rename root, which doesn't really make sense
|
|
lfsr_rename(&lfs, "/", "notroot") => LFS_ERR_INVAL;
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// and check that this didn't interfere with our original directory
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "ardvark", &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_mv_siblings]
|
|
defines.REMOUNT = [false, true]
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// make some directories
|
|
err = lfsr_mkdir(&lfs, "ardvark");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "banana");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "cat");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// clean up interrupted renames
|
|
if (TEST_PL) {
|
|
err = lfsr_remove(&lfs, "disco");
|
|
assert(!err || err == LFS_ERR_NOENT);
|
|
err = lfsr_remove(&lfs, "eggplant");
|
|
assert(!err || err == LFS_ERR_NOENT);
|
|
err = lfsr_remove(&lfs, "fish");
|
|
assert(!err || err == LFS_ERR_NOENT);
|
|
}
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our mkdir worked
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "ardvark", &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "banana", &info) => 0;
|
|
assert(strcmp(info.name, "banana") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "cat", &info) => 0;
|
|
assert(strcmp(info.name, "cat") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "banana") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "cat") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
// now rename each directory
|
|
lfsr_rename(&lfs, "ardvark", "disco") => 0;
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our rename worked
|
|
lfsr_stat(&lfs, "banana", &info) => 0;
|
|
assert(strcmp(info.name, "banana") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "cat", &info) => 0;
|
|
assert(strcmp(info.name, "cat") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "disco", &info) => 0;
|
|
assert(strcmp(info.name, "disco") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "banana") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "cat") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "disco") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
// rename another
|
|
lfsr_rename(&lfs, "banana", "eggplant") => 0;
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our rename worked
|
|
lfsr_stat(&lfs, "cat", &info) => 0;
|
|
assert(strcmp(info.name, "cat") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "disco", &info) => 0;
|
|
assert(strcmp(info.name, "disco") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "eggplant", &info) => 0;
|
|
assert(strcmp(info.name, "eggplant") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "cat") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "disco") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "eggplant") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
// rename another
|
|
lfsr_rename(&lfs, "cat", "fish") => 0;
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our rename worked
|
|
lfsr_stat(&lfs, "disco", &info) => 0;
|
|
assert(strcmp(info.name, "disco") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "eggplant", &info) => 0;
|
|
assert(strcmp(info.name, "eggplant") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "fish", &info) => 0;
|
|
assert(strcmp(info.name, "fish") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "disco") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "eggplant") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "fish") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_mv_children]
|
|
defines.REMOUNT = [false, true]
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// make some directories
|
|
err = lfsr_mkdir(&lfs, "ardvark");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "ardvark/banana");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
err = lfsr_mkdir(&lfs, "ardvark/banana/cat");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// clean up interrupted renames
|
|
if (TEST_PL) {
|
|
err = lfsr_remove(&lfs, "disco/eggplant/fish");
|
|
assert(!err || err == LFS_ERR_NOENT);
|
|
err = lfsr_remove(&lfs, "disco/eggplant/cat");
|
|
assert(!err || err == LFS_ERR_NOENT);
|
|
err = lfsr_remove(&lfs, "disco/eggplant");
|
|
assert(!err || err == LFS_ERR_NOENT);
|
|
err = lfsr_remove(&lfs, "disco/banana/cat");
|
|
assert(!err || err == LFS_ERR_NOENT);
|
|
err = lfsr_remove(&lfs, "disco/banana");
|
|
assert(!err || err == LFS_ERR_NOENT);
|
|
err = lfsr_remove(&lfs, "disco");
|
|
assert(!err || err == LFS_ERR_NOENT);
|
|
}
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our mkdirs worked
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "ardvark", &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "ardvark/banana", &info) => 0;
|
|
assert(strcmp(info.name, "banana") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "ardvark/banana/cat", &info) => 0;
|
|
assert(strcmp(info.name, "cat") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/ardvark") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "banana") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/ardvark/banana") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "cat") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
// now rename each directory
|
|
lfsr_rename(&lfs, "ardvark", "disco") => 0;
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our rename worked
|
|
lfsr_stat(&lfs, "disco", &info) => 0;
|
|
assert(strcmp(info.name, "disco") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "disco/banana", &info) => 0;
|
|
assert(strcmp(info.name, "banana") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "disco/banana/cat", &info) => 0;
|
|
assert(strcmp(info.name, "cat") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "disco") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/disco") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "banana") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/disco/banana") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "cat") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
// rename another
|
|
lfsr_rename(&lfs, "disco/banana", "disco/eggplant") => 0;
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our rename worked
|
|
lfsr_stat(&lfs, "disco", &info) => 0;
|
|
assert(strcmp(info.name, "disco") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "disco/eggplant", &info) => 0;
|
|
assert(strcmp(info.name, "eggplant") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "disco/eggplant/cat", &info) => 0;
|
|
assert(strcmp(info.name, "cat") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "disco") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/disco") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "eggplant") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/disco/eggplant") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "cat") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
// rename another
|
|
lfsr_rename(&lfs, "disco/eggplant/cat", "disco/eggplant/fish") => 0;
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our rename worked
|
|
lfsr_stat(&lfs, "disco", &info) => 0;
|
|
assert(strcmp(info.name, "disco") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "disco/eggplant", &info) => 0;
|
|
assert(strcmp(info.name, "eggplant") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_stat(&lfs, "disco/eggplant/fish", &info) => 0;
|
|
assert(strcmp(info.name, "fish") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "disco") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/disco") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "eggplant") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_dir_open(&lfs, &dir, "/disco/eggplant") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "fish") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_mv_many]
|
|
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
|
|
defines.BEFORE = [false, true]
|
|
defines.REMOUNT = [false, true]
|
|
# limit powerloss testing due to time
|
|
if = '!TEST_PL || N <= 32'
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// check if we have already started renaming, in case of powerloss
|
|
struct lfs_info info;
|
|
err = lfsr_stat(&lfs, (BEFORE ? "/0mved0000" : "/mved0000"), &info);
|
|
if (err == LFS_ERR_NOENT) {
|
|
// make this many directories
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
err = lfsr_mkdir(&lfs, name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
}
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our mkdir worked
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
}
|
|
|
|
// now rename the directories
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char old_name[256];
|
|
sprintf(old_name, "dir%04d", i);
|
|
char new_name[256];
|
|
sprintf(new_name, "%smved%04d", (BEFORE ? "0" : ""), i);
|
|
int err = lfsr_rename(&lfs, old_name, new_name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_NOENT));
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
}
|
|
|
|
// check that our renames worked
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "%smved%04d", (BEFORE ? "0" : ""), i);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "%smved%04d", (BEFORE ? "0" : ""), i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_mv_many_backwards]
|
|
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
|
|
defines.BEFORE = [false, true]
|
|
defines.REMOUNT = [false, true]
|
|
# limit powerloss testing due to time
|
|
if = '!TEST_PL || N <= 32'
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// check if we have already started renaming, in case of powerloss
|
|
struct lfs_info info;
|
|
err = lfsr_stat(&lfs, (BEFORE ? "/0mved0000" : "/mved0000"), &info);
|
|
if (err == LFS_ERR_NOENT) {
|
|
// make this many directories
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", (int)(N-1-i));
|
|
err = lfsr_mkdir(&lfs, name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
}
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our mkdir worked
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
}
|
|
|
|
// now rename the directories
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char old_name[256];
|
|
sprintf(old_name, "dir%04d", i);
|
|
char new_name[256];
|
|
sprintf(new_name, "%smved%04d", (BEFORE ? "0" : ""), i);
|
|
int err = lfsr_rename(&lfs, old_name, new_name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_NOENT));
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
}
|
|
|
|
// check that our renames worked
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "%smved%04d", (BEFORE ? "0" : ""), i);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "%smved%04d", (BEFORE ? "0" : ""), i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_mv_many_2layers]
|
|
defines.N = [1, 2, 4, 8, 16]
|
|
defines.BEFORE = [false, true]
|
|
defines.REMOUNT = [false, true]
|
|
# limit powerloss testing due to time
|
|
if = '!TEST_PL || N <= 4'
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// check if we have already started renaming, in case of powerloss
|
|
struct lfs_info info;
|
|
err = lfsr_stat(&lfs, (BEFORE ? "/0mved0000" : "/mved0000"), &info);
|
|
if (err == LFS_ERR_NOENT) {
|
|
// make this many directories
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
err = lfsr_mkdir(&lfs, name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// containing this many directories
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
sprintf(name, "dir%04d/child%04d", i, j);
|
|
err = lfsr_mkdir(&lfs, name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
}
|
|
}
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our mkdirs worked
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d/child%04d", i, j);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
sprintf(name, "child%04d", j);
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
}
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_open(&lfs, &dir, name) => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
char name[256];
|
|
sprintf(name, "child%04d", j);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
}
|
|
}
|
|
|
|
// now rename our directories
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char old_name[256];
|
|
sprintf(old_name, "dir%04d", i);
|
|
char new_name[256];
|
|
sprintf(new_name, "%smved%04d", (BEFORE ? "0" : ""), i);
|
|
int err = lfsr_rename(&lfs, old_name, new_name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_NOENT));
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
char old_name[256];
|
|
sprintf(old_name, "%smved%04d/child%04d",
|
|
(BEFORE ? "0" : ""), i, j);
|
|
char new_name[256];
|
|
sprintf(new_name, "%smved%04d/%schmved%04d",
|
|
(BEFORE ? "0" : ""), i,
|
|
(BEFORE ? "0" : ""), j);
|
|
int err = lfsr_rename(&lfs, old_name, new_name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_NOENT));
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
// check that our renames worked
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "%smved%04d", (BEFORE ? "0" : ""), i);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
char name[256];
|
|
sprintf(name, "%smved%04d/%schmved%04d",
|
|
(BEFORE ? "0" : ""), i, (BEFORE ? "0" : ""), j);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
sprintf(name, "%schmved%04d", (BEFORE ? "0" : ""), j);
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
}
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "%smved%04d", (BEFORE ? "0" : ""), i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "%smved%04d", (BEFORE ? "0" : ""), i);
|
|
lfsr_dir_open(&lfs, &dir, name) => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
char name[256];
|
|
sprintf(name, "%schmved%04d", (BEFORE ? "0" : ""), j);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
}
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_mv_many_3layers]
|
|
defines.N = [1, 2, 4]
|
|
defines.BEFORE = [false, true]
|
|
defines.REMOUNT = [false, true]
|
|
# limit powerloss testing due to time
|
|
if = '!TEST_PL || N <= 2'
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// check if we have already started renaming, in case of powerloss
|
|
struct lfs_info info;
|
|
err = lfsr_stat(&lfs, (BEFORE ? "/0mved0000" : "/mved0000"), &info);
|
|
if (err == LFS_ERR_NOENT) {
|
|
// make this many directories
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
err = lfsr_mkdir(&lfs, name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// containing this many directories
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
sprintf(name, "dir%04d/child%04d", i, j);
|
|
err = lfsr_mkdir(&lfs, name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
|
|
// containing this many directories
|
|
for (lfs_size_t k = 0; k < N; k++) {
|
|
sprintf(name, "dir%04d/child%04d/grandchild%04d", i, j, k);
|
|
err = lfsr_mkdir(&lfs, name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
}
|
|
}
|
|
}
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our mkdirs worked
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d/child%04d", i, j);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
sprintf(name, "child%04d", j);
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
for (lfs_size_t k = 0; k < N; k++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d/child%04d/grandchild%04d", i, j, k);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
sprintf(name, "grandchild%04d", k);
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
}
|
|
}
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_open(&lfs, &dir, name) => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
char name[256];
|
|
sprintf(name, "child%04d", j);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d/child%04d", i, j);
|
|
lfsr_dir_open(&lfs, &dir, name) => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t k = 0; k < N; k++) {
|
|
char name[256];
|
|
sprintf(name, "grandchild%04d", k);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
// now rename our directories
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char old_name[256];
|
|
sprintf(old_name, "dir%04d", i);
|
|
char new_name[256];
|
|
sprintf(new_name, "%smved%04d", (BEFORE ? "0" : ""), i);
|
|
int err = lfsr_rename(&lfs, old_name, new_name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_NOENT));
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
char old_name[256];
|
|
sprintf(old_name, "%smved%04d/child%04d",
|
|
(BEFORE ? "0" : ""), i, j);
|
|
char new_name[256];
|
|
sprintf(new_name, "%smved%04d/%schmved%04d",
|
|
(BEFORE ? "0" : ""), i,
|
|
(BEFORE ? "0" : ""), j);
|
|
int err = lfsr_rename(&lfs, old_name, new_name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_NOENT));
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
for (lfs_size_t k = 0; k < N; k++) {
|
|
char old_name[256];
|
|
sprintf(old_name, "%smved%04d/%schmved%04d/grandchild%04d",
|
|
(BEFORE ? "0" : ""), i,
|
|
(BEFORE ? "0" : ""), j, k);
|
|
char new_name[256];
|
|
sprintf(new_name, "%smved%04d/%schmved%04d/%sgrmved%04d",
|
|
(BEFORE ? "0" : ""), i,
|
|
(BEFORE ? "0" : ""), j,
|
|
(BEFORE ? "0" : ""), k);
|
|
int err = lfsr_rename(&lfs, old_name, new_name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_NOENT));
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// check that our removes worked
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "%smved%04d", (BEFORE ? "0" : ""), i);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
char name[256];
|
|
sprintf(name, "%smved%04d/%schmved%04d",
|
|
(BEFORE ? "0" : ""), i,
|
|
(BEFORE ? "0" : ""), j);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
sprintf(name, "%schmved%04d", (BEFORE ? "0" : ""), j);
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
for (lfs_size_t k = 0; k < N; k++) {
|
|
char name[256];
|
|
sprintf(name, "%smved%04d/%schmved%04d/%sgrmved%04d",
|
|
(BEFORE ? "0" : ""), i,
|
|
(BEFORE ? "0" : ""), j,
|
|
(BEFORE ? "0" : ""), k);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
sprintf(name, "%sgrmved%04d", (BEFORE ? "0" : ""), k);
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
}
|
|
}
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "%smved%04d", (BEFORE ? "0" : ""), i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "%smved%04d", (BEFORE ? "0" : ""), i);
|
|
lfsr_dir_open(&lfs, &dir, name) => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
char name[256];
|
|
sprintf(name, "%schmved%04d", (BEFORE ? "0" : ""), j);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
for (lfs_size_t j = 0; j < N; j++) {
|
|
char name[256];
|
|
sprintf(name, "%smved%04d/%schmved%04d",
|
|
(BEFORE ? "0" : ""), i,
|
|
(BEFORE ? "0" : ""), j);
|
|
lfsr_dir_open(&lfs, &dir, name) => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t k = 0; k < N; k++) {
|
|
char name[256];
|
|
sprintf(name, "%sgrmved%04d", (BEFORE ? "0" : ""), k);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
}
|
|
}
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_mv_many_linkedlist]
|
|
defines.N = [1, 2, 4, 8, 16, 32, 64]
|
|
defines.BEFORE = [false, true]
|
|
defines.REMOUNT = [false, true]
|
|
# limit powerloss testing due to time
|
|
if = '!TEST_PL || N <= 16'
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
// check if we have already started renaming, in case of powerloss
|
|
struct lfs_info info;
|
|
err = lfsr_stat(&lfs, (BEFORE ? "/0mved0000" : "/mved0000"), &info);
|
|
if (err == LFS_ERR_NOENT) {
|
|
// create this many directory in a sort of linked-list by nesting
|
|
char name[4096];
|
|
memset(name, 0, sizeof(name));
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
sprintf(&name[strlen(name)], "/dir%04d", i);
|
|
err = lfsr_mkdir(&lfs, name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
}
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// check that our mkdir worked
|
|
memset(name, 0, sizeof(name));
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
sprintf(&name[strlen(name)], "/dir%04d", i);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
char name2[256];
|
|
sprintf(name2, "dir%04d", i);
|
|
assert(strcmp(info.name, name2) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
memset(name, 0, sizeof(name));
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
sprintf(&name[strlen(name)], "/dir%04d", i);
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, name) => 0;
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
if (i < N-1) {
|
|
char name2[256];
|
|
sprintf(name2, "dir%04d", i+1);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name2) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
}
|
|
}
|
|
|
|
// now rename our directories
|
|
char old_name[4096];
|
|
memset(old_name, 0, sizeof(old_name));
|
|
char new_name[4096];
|
|
memset(new_name, 0, sizeof(new_name));
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
sprintf(&old_name[strlen(old_name)], "/dir%04d", i);
|
|
sprintf(&new_name[strlen(new_name)], "/%smved%04d",
|
|
(BEFORE ? "0" : ""), i);
|
|
err = lfsr_rename(&lfs, old_name, new_name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_NOENT));
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// update old_name's path
|
|
memcpy(old_name, new_name, sizeof(old_name));
|
|
}
|
|
|
|
// check that our renames worked
|
|
char name[4096];
|
|
memset(name, 0, sizeof(name));
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
sprintf(&name[strlen(name)], "/%smved%04d", (BEFORE ? "0" : ""), i);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
char name2[256];
|
|
sprintf(name2, "%smved%04d", (BEFORE ? "0" : ""), i);
|
|
assert(strcmp(info.name, name2) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
memset(name, 0, sizeof(name));
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
sprintf(&name[strlen(name)], "/%smved%04d", (BEFORE ? "0" : ""), i);
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, name) => 0;
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
if (i < N-1) {
|
|
char name2[256];
|
|
sprintf(name2, "%smved%04d", (BEFORE ? "0" : ""), i+1);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name2) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
}
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_mv_fuzz]
|
|
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
|
|
defines.PARENT = [false, true]
|
|
defines.REMOUNT = [false, true]
|
|
defines.SEED = 'range(10)'
|
|
# limit powerloss testing due to time
|
|
if = '!TEST_PL || N <= 64'
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
if (PARENT) {
|
|
err = lfsr_mkdir(&lfs, "pricklypear");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
}
|
|
|
|
// set up a simulation to compare against
|
|
lfs_size_t *sim = malloc(N*sizeof(lfs_size_t));
|
|
lfs_size_t sim_size = 0;
|
|
|
|
uint32_t prng = SEED;
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
// choose a pseudo-random op, either mkdir or rename
|
|
uint8_t op = TEST_PRNG(&prng) % 2;
|
|
|
|
if (op == 0 || sim_size == 0) {
|
|
// choose a pseudo-random number, truncate to 4 decimals
|
|
lfs_size_t x = TEST_PRNG(&prng) % 10000;
|
|
// insert into our sim
|
|
for (lfs_size_t j = 0;; j++) {
|
|
if (j >= sim_size || sim[j] >= x) {
|
|
// already seen?
|
|
if (j < sim_size && sim[j] == x) {
|
|
// do nothing
|
|
} else {
|
|
// insert
|
|
memmove(&sim[j+1], &sim[j],
|
|
(sim_size-j)*sizeof(lfs_size_t));
|
|
sim_size += 1;
|
|
sim[j] = x;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
// create a directory here
|
|
char name[256];
|
|
sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), x);
|
|
int err = lfsr_mkdir(&lfs, name);
|
|
assert(!err || err == LFS_ERR_EXIST);
|
|
|
|
} else {
|
|
// choose a pseudo-random entry to rename, and a pseudo-random
|
|
// number to rename to
|
|
lfs_size_t j = TEST_PRNG(&prng) % sim_size;
|
|
lfs_size_t x = sim[j];
|
|
lfs_size_t y = TEST_PRNG(&prng) % 10000;
|
|
for (lfs_size_t k = 0;; k++) {
|
|
if (k >= sim_size || sim[k] >= y) {
|
|
// already seen and not a noop?
|
|
if (k < sim_size && sim[k] == y && x != y) {
|
|
// just delete the original entry
|
|
memmove(&sim[j], &sim[j+1],
|
|
(sim_size-(j+1))*sizeof(lfs_size_t));
|
|
sim_size -= 1;
|
|
} else {
|
|
// first delete
|
|
memmove(&sim[j], &sim[j+1],
|
|
(sim_size-(j+1))*sizeof(lfs_size_t));
|
|
if (k > j) {
|
|
k -= 1;
|
|
}
|
|
// then insert
|
|
memmove(&sim[k+1], &sim[k],
|
|
(sim_size-k)*sizeof(lfs_size_t));
|
|
sim[k] = y;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
// rename this directory
|
|
char old_name[256];
|
|
sprintf(old_name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), x);
|
|
char new_name[256];
|
|
sprintf(new_name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), y);
|
|
lfsr_rename(&lfs, old_name, new_name) => 0;
|
|
}
|
|
}
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// test that our directories match our simulation
|
|
for (lfs_size_t j = 0; j < sim_size; j++) {
|
|
char name[256];
|
|
sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), sim[j]);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
char name2[256];
|
|
sprintf(name2, "dir%04d", sim[j]);
|
|
assert(strcmp(info.name, name2) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, (PARENT ? "pricklypear" : "/")) => 0;
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t j = 0; j < sim_size; j++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", sim[j]);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
// clean up sim/lfs
|
|
free(sim);
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# test all of the operations together
|
|
[cases.t5_dirs_general_fuzz]
|
|
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
|
|
defines.PARENT = [false, true]
|
|
defines.REMOUNT = [false, true]
|
|
defines.SEED = 'range(10)'
|
|
# limit powerloss testing due to time
|
|
if = '!TEST_PL || N <= 64'
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
if (PARENT) {
|
|
err = lfsr_mkdir(&lfs, "pricklypear");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
}
|
|
|
|
// set up a simulation to compare against
|
|
lfs_size_t *sim = malloc(N*sizeof(lfs_size_t));
|
|
lfs_size_t sim_size = 0;
|
|
|
|
uint32_t prng = SEED;
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
// choose a pseudo-random op, either mkdir, remove, or rename
|
|
uint8_t op = TEST_PRNG(&prng) % 3;
|
|
|
|
if (op == 0 || sim_size == 0) {
|
|
// choose a pseudo-random number, truncate to 4 decimals
|
|
lfs_size_t x = TEST_PRNG(&prng) % 10000;
|
|
// insert into our sim
|
|
for (lfs_size_t j = 0;; j++) {
|
|
if (j >= sim_size || sim[j] >= x) {
|
|
// already seen?
|
|
if (j < sim_size && sim[j] == x) {
|
|
// do nothing
|
|
} else {
|
|
// insert
|
|
memmove(&sim[j+1], &sim[j],
|
|
(sim_size-j)*sizeof(lfs_size_t));
|
|
sim_size += 1;
|
|
sim[j] = x;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
// create a directory here
|
|
char name[256];
|
|
sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), x);
|
|
int err = lfsr_mkdir(&lfs, name);
|
|
assert(!err || err == LFS_ERR_EXIST);
|
|
|
|
} else if (op == 1) {
|
|
// choose a pseudo-random entry to delete
|
|
lfs_size_t j = TEST_PRNG(&prng) % sim_size;
|
|
lfs_size_t x = sim[j];
|
|
// delete from our sim
|
|
memmove(&sim[j], &sim[j+1],
|
|
(sim_size-(j+1))*sizeof(lfs_size_t));
|
|
sim_size -= 1;
|
|
|
|
// remove this directory
|
|
char name[256];
|
|
sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), x);
|
|
lfsr_remove(&lfs, name) => 0;
|
|
|
|
} else {
|
|
// choose a pseudo-random entry to rename, and a pseudo-random
|
|
// number to rename to
|
|
lfs_size_t j = TEST_PRNG(&prng) % sim_size;
|
|
lfs_size_t x = sim[j];
|
|
lfs_size_t y = TEST_PRNG(&prng) % 10000;
|
|
for (lfs_size_t k = 0;; k++) {
|
|
if (k >= sim_size || sim[k] >= y) {
|
|
// already seen and not a noop?
|
|
if (k < sim_size && sim[k] == y && x != y) {
|
|
// just delete the original entry
|
|
memmove(&sim[j], &sim[j+1],
|
|
(sim_size-(j+1))*sizeof(lfs_size_t));
|
|
sim_size -= 1;
|
|
} else {
|
|
// first delete
|
|
memmove(&sim[j], &sim[j+1],
|
|
(sim_size-(j+1))*sizeof(lfs_size_t));
|
|
if (k > j) {
|
|
k -= 1;
|
|
}
|
|
// then insert
|
|
memmove(&sim[k+1], &sim[k],
|
|
(sim_size-k)*sizeof(lfs_size_t));
|
|
sim[k] = y;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
// rename this directory
|
|
char old_name[256];
|
|
sprintf(old_name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), x);
|
|
char new_name[256];
|
|
sprintf(new_name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), y);
|
|
lfsr_rename(&lfs, old_name, new_name) => 0;
|
|
}
|
|
}
|
|
|
|
// remount?
|
|
if (REMOUNT) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
// grm should be zero here
|
|
assert(lfs.grm[0] == 0);
|
|
}
|
|
|
|
// test that our directories match our simulation
|
|
for (lfs_size_t j = 0; j < sim_size; j++) {
|
|
char name[256];
|
|
sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), sim[j]);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
char name2[256];
|
|
sprintf(name2, "dir%04d", sim[j]);
|
|
assert(strcmp(info.name, name2) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, (PARENT ? "pricklypear" : "/")) => 0;
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t j = 0; j < sim_size; j++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", sim[j]);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
// clean up sim/lfs
|
|
free(sim);
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
|
|
## Test seeking and stuff
|
|
|
|
[cases.t5_dirs_tell]
|
|
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
|
|
defines.PARENT = [false, true]
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
|
|
if (PARENT) {
|
|
lfsr_mkdir(&lfs, "pricklypear") => 0;
|
|
}
|
|
|
|
// make this many directories
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), i);
|
|
lfsr_mkdir(&lfs, name) => 0;
|
|
}
|
|
|
|
// read our directory
|
|
//
|
|
// we can't really make many assumptions about tell's value, so just
|
|
// check for no errors
|
|
//
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, (PARENT ? "pricklypear" : "/")) => 0;
|
|
lfs_soff_t off = lfsr_dir_tell(&lfs, &dir);
|
|
assert(off >= 0);
|
|
struct lfs_info info;
|
|
off = lfsr_dir_read(&lfs, &dir, &info);
|
|
assert(off >= 0);
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
off = lfsr_dir_tell(&lfs, &dir);
|
|
assert(off >= 0);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
off = lfsr_dir_tell(&lfs, &dir);
|
|
assert(off >= 0);
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
off = lfsr_dir_tell(&lfs, &dir);
|
|
assert(off >= 0);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
off = lfsr_dir_tell(&lfs, &dir);
|
|
assert(off >= 0);
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_rewind]
|
|
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
|
|
defines.PARENT = [false, true]
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
|
|
if (PARENT) {
|
|
lfsr_mkdir(&lfs, "pricklypear") => 0;
|
|
}
|
|
|
|
// make this many directories
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), i);
|
|
lfsr_mkdir(&lfs, name) => 0;
|
|
}
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, (PARENT ? "pricklypear" : "/")) => 0;
|
|
|
|
// read our directory once
|
|
lfs_soff_t off = lfsr_dir_tell(&lfs, &dir);
|
|
assert(off >= 0);
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
off = lfsr_dir_tell(&lfs, &dir);
|
|
assert(off >= 0);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
off = lfsr_dir_tell(&lfs, &dir);
|
|
assert(off >= 0);
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
off = lfsr_dir_tell(&lfs, &dir);
|
|
assert(off >= 0);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
off = lfsr_dir_tell(&lfs, &dir);
|
|
assert(off >= 0);
|
|
|
|
// now read it again
|
|
lfsr_dir_rewind(&lfs, &dir) => 0;
|
|
off = lfsr_dir_tell(&lfs, &dir);
|
|
assert(off >= 0);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
off = lfsr_dir_tell(&lfs, &dir);
|
|
assert(off >= 0);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
off = lfsr_dir_tell(&lfs, &dir);
|
|
assert(off >= 0);
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
off = lfsr_dir_tell(&lfs, &dir);
|
|
assert(off >= 0);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
off = lfsr_dir_tell(&lfs, &dir);
|
|
assert(off >= 0);
|
|
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_seek]
|
|
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
|
|
defines.PARENT = [false, true]
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
|
|
if (PARENT) {
|
|
lfsr_mkdir(&lfs, "pricklypear") => 0;
|
|
}
|
|
|
|
// make this many directories
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), i);
|
|
lfsr_mkdir(&lfs, name) => 0;
|
|
}
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, (PARENT ? "pricklypear" : "/")) => 0;
|
|
|
|
// read our directory once
|
|
lfs_soff_t offs[2+N+2];
|
|
offs[0] = lfsr_dir_tell(&lfs, &dir);
|
|
assert(offs[0] >= 0);
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
offs[1] = lfsr_dir_tell(&lfs, &dir);
|
|
assert(offs[1] >= 0);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
offs[2+i] = lfsr_dir_tell(&lfs, &dir);
|
|
assert(offs[2+i] >= 0);
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
offs[2+N+0] = lfsr_dir_tell(&lfs, &dir);
|
|
assert(offs[2+N+0] >= 0);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
offs[2+N+1] = lfsr_dir_tell(&lfs, &dir);
|
|
assert(offs[2+N+1] >= 0);
|
|
|
|
// now try to seek to each entry explicitly
|
|
lfsr_dir_seek(&lfs, &dir, offs[0]) => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_seek(&lfs, &dir, offs[1]) => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
lfsr_dir_seek(&lfs, &dir, offs[2+i]) => 0;
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_seek(&lfs, &dir, offs[2+N+0]) => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_seek(&lfs, &dir, offs[2+N+1]) => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_read_idempotent]
|
|
defines.PARENT = [false, true]
|
|
# bit 0x2 = left neighbor
|
|
# bit 0x1 = right neighbor
|
|
defines.NEIGHBORS = [0x0, 0x1, 0x2, 0x3]
|
|
# neighbors only make sense if we have a parent
|
|
if = 'PARENT || NEIGHBORS == 0'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
|
|
if (PARENT) {
|
|
lfsr_mkdir(&lfs, "pricklypear") => 0;
|
|
|
|
if (NEIGHBORS & 0x2) {
|
|
assert(lfs_crc32c(0, "a_IplRNrPH", 10) == 0x00000000);
|
|
lfsr_mkdir(&lfs, "a_IplRNrPH") => 0;
|
|
}
|
|
|
|
if (NEIGHBORS & 0x1) {
|
|
assert(lfs_crc32c(0, "f_VtoMnwRH", 10) == 0xffffffff);
|
|
lfsr_mkdir(&lfs, "f_VtoMnwRH") => 0;
|
|
}
|
|
}
|
|
|
|
char name[256];
|
|
sprintf(name, "%s/ardvark", (PARENT ? "pricklypear" : ""));
|
|
lfsr_mkdir(&lfs, name) => 0;
|
|
|
|
// read to the end
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, (PARENT ? "pricklypear" : "/")) => 0;
|
|
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfs_soff_t off = lfsr_dir_tell(&lfs, &dir);
|
|
assert(off >= 0);
|
|
|
|
// reading again should still return noent
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
|
|
// seeking past the end of the directory should still return noent
|
|
lfsr_dir_seek(&lfs, &dir, off) => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
|
|
lfsr_dir_seek(&lfs, &dir, off + 1000) => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
|
|
// but we should be able to read again
|
|
lfsr_dir_rewind(&lfs, &dir) => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "ardvark") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_read_with_mkdirs]
|
|
defines.N = 5
|
|
# where in the dir read do we mkdir?
|
|
defines.I = 'range(6)'
|
|
# where do we mkdir?
|
|
defines.J = 'range(6)'
|
|
defines.PARENT = [false, true]
|
|
# bit 0x2 = left neighbor
|
|
# bit 0x1 = right neighbor
|
|
defines.NEIGHBORS = [0x0, 0x1, 0x2, 0x3]
|
|
defines.SEEK = [false, true]
|
|
# neighbors only make sense if we have a parent
|
|
if = 'PARENT || NEIGHBORS == 0'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
|
|
if (PARENT) {
|
|
lfsr_mkdir(&lfs, "pricklypear") => 0;
|
|
|
|
if (NEIGHBORS & 0x2) {
|
|
assert(lfs_crc32c(0, "a_IplRNrPH", 10) == 0x00000000);
|
|
lfsr_mkdir(&lfs, "a_IplRNrPH") => 0;
|
|
}
|
|
|
|
if (NEIGHBORS & 0x1) {
|
|
assert(lfs_crc32c(0, "f_VtoMnwRH", 10) == 0xffffffff);
|
|
lfsr_mkdir(&lfs, "f_VtoMnwRH") => 0;
|
|
}
|
|
}
|
|
|
|
// create our directories
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), i+1);
|
|
lfsr_mkdir(&lfs, name) => 0;
|
|
}
|
|
|
|
// start reading
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, (PARENT ? "pricklypear" : "/")) => 0;
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
// read until I
|
|
for (lfs_size_t i = 0; i < I; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i+1);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
// make a dir at J
|
|
char name[256];
|
|
sprintf(name, "%s/dir%04d_", (PARENT ? "pricklypear" : ""), (int)J);
|
|
lfsr_mkdir(&lfs, name) => 0;
|
|
|
|
// seek after mkdir? this tests that the internal position is
|
|
// updated correctly
|
|
if (SEEK) {
|
|
lfs_ssize_t off = lfsr_dir_tell(&lfs, &dir);
|
|
assert(off >= 0);
|
|
lfsr_dir_rewind(&lfs, &dir) => 0;
|
|
lfsr_dir_seek(&lfs, &dir, off) => 0;
|
|
}
|
|
|
|
// we should be able to keep reading, though we may pick up J
|
|
for (lfs_size_t i = I + (I >= J ? 1 : 0); i < N+1; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d%s", i+1 - (i >= J ? 1 : 0), (i == J ? "_" : ""));
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_read_with_rms]
|
|
defines.N = 5
|
|
# where in the dir read do we rm?
|
|
defines.I = 'range(5)'
|
|
# where do we rm?
|
|
defines.J = 'range(5)'
|
|
defines.PARENT = [false, true]
|
|
# bit 0x2 = left neighbor
|
|
# bit 0x1 = right neighbor
|
|
defines.NEIGHBORS = [0x0, 0x1, 0x2, 0x3]
|
|
defines.SEEK = [false, true]
|
|
# neighbors only make sense if we have a parent
|
|
if = 'PARENT || NEIGHBORS == 0'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
|
|
if (PARENT) {
|
|
lfsr_mkdir(&lfs, "pricklypear") => 0;
|
|
|
|
if (NEIGHBORS & 0x2) {
|
|
assert(lfs_crc32c(0, "a_IplRNrPH", 10) == 0x00000000);
|
|
lfsr_mkdir(&lfs, "a_IplRNrPH") => 0;
|
|
}
|
|
|
|
if (NEIGHBORS & 0x1) {
|
|
assert(lfs_crc32c(0, "f_VtoMnwRH", 10) == 0xffffffff);
|
|
lfsr_mkdir(&lfs, "f_VtoMnwRH") => 0;
|
|
}
|
|
}
|
|
|
|
// create our directories
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), i);
|
|
lfsr_mkdir(&lfs, name) => 0;
|
|
}
|
|
|
|
// start reading
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, (PARENT ? "pricklypear" : "/")) => 0;
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
// read until I
|
|
for (lfs_size_t i = 0; i < I; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
// remove the dir at J
|
|
char name[256];
|
|
sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), (int)J);
|
|
lfsr_remove(&lfs, name) => 0;
|
|
|
|
// seek after remove? this tests that the internal position is
|
|
// updated correctly
|
|
if (SEEK) {
|
|
lfs_ssize_t off = lfsr_dir_tell(&lfs, &dir);
|
|
assert(off >= 0);
|
|
lfsr_dir_rewind(&lfs, &dir) => 0;
|
|
lfsr_dir_seek(&lfs, &dir, off) => 0;
|
|
}
|
|
|
|
// we should be able to keep reading
|
|
for (lfs_size_t i = I; i < N; i++) {
|
|
if (i == J) {
|
|
continue;
|
|
}
|
|
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_read_with_mvs]
|
|
defines.N = 5
|
|
# where in the dir read do we rm?
|
|
defines.I = 'range(5)'
|
|
# where do we rm?
|
|
defines.J = 'range(5)'
|
|
defines.K = 'range(5)'
|
|
defines.BEFORE = [false, true]
|
|
# 0 => no
|
|
# 1 => yes
|
|
# 2 => yes, and rename to new parent
|
|
defines.PARENT = [0, 1, 2]
|
|
# bit 0x2 = left neighbor
|
|
# bit 0x1 = right neighbor
|
|
defines.NEIGHBORS = [0x0, 0x1, 0x2, 0x3]
|
|
defines.SEEK = [false, true]
|
|
# neighbors only make sense if we have a parent
|
|
if = 'PARENT || NEIGHBORS == 0'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
|
|
if (PARENT) {
|
|
lfsr_mkdir(&lfs, "pricklypear") => 0;
|
|
if (PARENT >= 2) {
|
|
lfsr_mkdir(&lfs, "quiabentia") => 0;
|
|
}
|
|
|
|
if (NEIGHBORS & 0x2) {
|
|
assert(lfs_crc32c(0, "a_IplRNrPH", 10) == 0x00000000);
|
|
lfsr_mkdir(&lfs, "a_IplRNrPH") => 0;
|
|
}
|
|
|
|
if (NEIGHBORS & 0x1) {
|
|
assert(lfs_crc32c(0, "f_VtoMnwRH", 10) == 0xffffffff);
|
|
lfsr_mkdir(&lfs, "f_VtoMnwRH") => 0;
|
|
}
|
|
}
|
|
|
|
// create our directories
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), i);
|
|
lfsr_mkdir(&lfs, name) => 0;
|
|
}
|
|
|
|
// start reading
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, (PARENT ? "pricklypear" : "/")) => 0;
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
// read until I
|
|
for (lfs_size_t i = 0; i < I; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
// rename the dir at J
|
|
char old_name[256];
|
|
sprintf(old_name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), (int)J);
|
|
char new_name[256];
|
|
sprintf(new_name, "%s/%smved%04d",
|
|
(PARENT == 1 ? "pricklypear"
|
|
: PARENT >= 2 ? "quiabentia"
|
|
: ""),
|
|
(BEFORE ? "0" : ""),
|
|
(int)J);
|
|
lfsr_rename(&lfs, old_name, new_name) => 0;
|
|
|
|
// seek after remove? this tests that the internal position is
|
|
// updated correctly
|
|
if (SEEK) {
|
|
lfs_ssize_t off = lfsr_dir_tell(&lfs, &dir);
|
|
assert(off >= 0);
|
|
lfsr_dir_rewind(&lfs, &dir) => 0;
|
|
lfsr_dir_seek(&lfs, &dir, off) => 0;
|
|
}
|
|
|
|
// we should be able to keep reading
|
|
for (lfs_size_t i = I; i < N; i++) {
|
|
if (i == J) {
|
|
continue;
|
|
}
|
|
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
int err = lfsr_dir_read(&lfs, &dir, &info);
|
|
assert(err == LFS_ERR_NOENT || (!BEFORE && PARENT < 2));
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# dir reads with 2x ops have better chances of catching bugs that depend on
|
|
# invalid dir states
|
|
|
|
[cases.t5_dirs_read_with_2_mkdirs]
|
|
defines.N = 5
|
|
# where in the dir read do we mkdir?
|
|
defines.I = 'range(6)'
|
|
# where do we mkdir?
|
|
defines.J = 'range(6)'
|
|
defines.K = 'range(6)'
|
|
defines.PARENT = [false, true]
|
|
# bit 0x2 = left neighbor
|
|
# bit 0x1 = right neighbor
|
|
defines.NEIGHBORS = [0x0, 0x1, 0x2, 0x3]
|
|
defines.SEEK = [false, true]
|
|
if = [
|
|
'J != K',
|
|
# neighbors only make sense if we have a parent
|
|
'PARENT || NEIGHBORS == 0',
|
|
]
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
|
|
if (PARENT) {
|
|
lfsr_mkdir(&lfs, "pricklypear") => 0;
|
|
|
|
if (NEIGHBORS & 0x2) {
|
|
assert(lfs_crc32c(0, "a_IplRNrPH", 10) == 0x00000000);
|
|
lfsr_mkdir(&lfs, "a_IplRNrPH") => 0;
|
|
}
|
|
|
|
if (NEIGHBORS & 0x1) {
|
|
assert(lfs_crc32c(0, "f_VtoMnwRH", 10) == 0xffffffff);
|
|
lfsr_mkdir(&lfs, "f_VtoMnwRH") => 0;
|
|
}
|
|
}
|
|
|
|
// create our directories
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), i+1);
|
|
lfsr_mkdir(&lfs, name) => 0;
|
|
}
|
|
|
|
// start reading
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, (PARENT ? "pricklypear" : "/")) => 0;
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
// read until I
|
|
for (lfs_size_t i = 0; i < I; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i+1);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
// make a dir at J
|
|
char name[256];
|
|
sprintf(name, "%s/dir%04d_", (PARENT ? "pricklypear" : ""), (int)J);
|
|
lfsr_mkdir(&lfs, name) => 0;
|
|
|
|
// make a dir at K
|
|
sprintf(name, "%s/dir%04d_", (PARENT ? "pricklypear" : ""), (int)K);
|
|
lfsr_mkdir(&lfs, name) => 0;
|
|
|
|
// seek after mkdir? this tests that the internal position is
|
|
// updated correctly
|
|
if (SEEK) {
|
|
lfs_ssize_t off = lfsr_dir_tell(&lfs, &dir);
|
|
assert(off >= 0);
|
|
lfsr_dir_rewind(&lfs, &dir) => 0;
|
|
lfsr_dir_seek(&lfs, &dir, off) => 0;
|
|
}
|
|
|
|
// we should be able to keep reading, though we may pick up J
|
|
for (lfs_size_t i = I + (I >= J ? 1 : 0) + (I >= K ? 1 : 0); i < N+2; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d%s",
|
|
i+1 - (i >= J + (J >= K ? 1 : 0) ? 1 : 0)
|
|
- (i >= K + (K >= J ? 1 : 0) ? 1 : 0),
|
|
(i == J + (J > K ? 1 : 0) || i == K + (K > J ? 1 : 0)
|
|
? "_" : ""));
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_read_with_2_rms]
|
|
defines.N = 5
|
|
# where in the dir read do we rm?
|
|
defines.I = 'range(5)'
|
|
# where do we rm?
|
|
defines.J = 'range(5)'
|
|
defines.K = 'range(5)'
|
|
defines.PARENT = [false, true]
|
|
# bit 0x2 = left neighbor
|
|
# bit 0x1 = right neighbor
|
|
defines.NEIGHBORS = [0x0, 0x1, 0x2, 0x3]
|
|
defines.SEEK = [false, true]
|
|
if = [
|
|
'J != K',
|
|
# neighbors only make sense if we have a parent
|
|
'PARENT || NEIGHBORS == 0',
|
|
]
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
|
|
if (PARENT) {
|
|
lfsr_mkdir(&lfs, "pricklypear") => 0;
|
|
|
|
if (NEIGHBORS & 0x2) {
|
|
assert(lfs_crc32c(0, "a_IplRNrPH", 10) == 0x00000000);
|
|
lfsr_mkdir(&lfs, "a_IplRNrPH") => 0;
|
|
}
|
|
|
|
if (NEIGHBORS & 0x1) {
|
|
assert(lfs_crc32c(0, "f_VtoMnwRH", 10) == 0xffffffff);
|
|
lfsr_mkdir(&lfs, "f_VtoMnwRH") => 0;
|
|
}
|
|
}
|
|
|
|
// create our directories
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), i);
|
|
lfsr_mkdir(&lfs, name) => 0;
|
|
}
|
|
|
|
// start reading
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, (PARENT ? "pricklypear" : "/")) => 0;
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
// read until I
|
|
for (lfs_size_t i = 0; i < I; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
// remove the dir at J
|
|
char name[256];
|
|
sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), (int)J);
|
|
lfsr_remove(&lfs, name) => 0;
|
|
|
|
// remove the dir at K
|
|
sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), (int)K);
|
|
lfsr_remove(&lfs, name) => 0;
|
|
|
|
// seek after remove? this tests that the internal position is
|
|
// updated correctly
|
|
if (SEEK) {
|
|
lfs_ssize_t off = lfsr_dir_tell(&lfs, &dir);
|
|
assert(off >= 0);
|
|
lfsr_dir_rewind(&lfs, &dir) => 0;
|
|
lfsr_dir_seek(&lfs, &dir, off) => 0;
|
|
}
|
|
|
|
// we should be able to keep reading
|
|
for (lfs_size_t i = I; i < N; i++) {
|
|
if (i == J || i == K) {
|
|
continue;
|
|
}
|
|
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.t5_dirs_read_with_2_mvs]
|
|
defines.N = 5
|
|
# where in the dir read do we rm?
|
|
defines.I = 'range(5)'
|
|
# where do we rm?
|
|
defines.J = 'range(5)'
|
|
defines.K = 'range(5)'
|
|
defines.BEFORE = [false, true]
|
|
# 0 => no
|
|
# 1 => yes
|
|
# 2 => yes, and rename to new parent
|
|
defines.PARENT = [0, 1, 2]
|
|
# bit 0x2 = left neighbor
|
|
# bit 0x1 = right neighbor
|
|
defines.NEIGHBORS = [0x0, 0x1, 0x2, 0x3]
|
|
defines.SEEK = [false, true]
|
|
# neighbors only make sense if we have a parent
|
|
if = [
|
|
'J != K',
|
|
# neighbors only make sense if we have a parent
|
|
'PARENT || NEIGHBORS == 0',
|
|
]
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
|
|
if (PARENT) {
|
|
lfsr_mkdir(&lfs, "pricklypear") => 0;
|
|
if (PARENT >= 2) {
|
|
lfsr_mkdir(&lfs, "quiabentia") => 0;
|
|
}
|
|
|
|
if (NEIGHBORS & 0x2) {
|
|
assert(lfs_crc32c(0, "a_IplRNrPH", 10) == 0x00000000);
|
|
lfsr_mkdir(&lfs, "a_IplRNrPH") => 0;
|
|
}
|
|
|
|
if (NEIGHBORS & 0x1) {
|
|
assert(lfs_crc32c(0, "f_VtoMnwRH", 10) == 0xffffffff);
|
|
lfsr_mkdir(&lfs, "f_VtoMnwRH") => 0;
|
|
}
|
|
}
|
|
|
|
// create our directories
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), i);
|
|
lfsr_mkdir(&lfs, name) => 0;
|
|
}
|
|
|
|
// start reading
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, (PARENT ? "pricklypear" : "/")) => 0;
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
// read until I
|
|
for (lfs_size_t i = 0; i < I; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
// rename the dir at J
|
|
char old_name[256];
|
|
sprintf(old_name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), (int)J);
|
|
char new_name[256];
|
|
sprintf(new_name, "%s/%smved%04d",
|
|
(PARENT == 1 ? "pricklypear"
|
|
: PARENT >= 2 ? "quiabentia"
|
|
: ""),
|
|
(BEFORE ? "0" : ""),
|
|
(int)J);
|
|
lfsr_rename(&lfs, old_name, new_name) => 0;
|
|
|
|
// rename the dir at K
|
|
sprintf(old_name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), (int)K);
|
|
sprintf(new_name, "%s/%smved%04d",
|
|
(PARENT == 1 ? "pricklypear"
|
|
: PARENT >= 2 ? "quiabentia"
|
|
: ""),
|
|
(BEFORE ? "0" : ""),
|
|
(int)K);
|
|
lfsr_rename(&lfs, old_name, new_name) => 0;
|
|
|
|
// seek after remove? this tests that the internal position is
|
|
// updated correctly
|
|
if (SEEK) {
|
|
lfs_ssize_t off = lfsr_dir_tell(&lfs, &dir);
|
|
assert(off >= 0);
|
|
lfsr_dir_rewind(&lfs, &dir) => 0;
|
|
lfsr_dir_seek(&lfs, &dir, off) => 0;
|
|
}
|
|
|
|
// we should be able to keep reading
|
|
for (lfs_size_t i = I; i < N; i++) {
|
|
if (i == J || i == K) {
|
|
continue;
|
|
}
|
|
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
int err = lfsr_dir_read(&lfs, &dir, &info);
|
|
assert(err == LFS_ERR_NOENT || (!BEFORE && PARENT < 2));
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
|
|
## Recursive tests
|
|
|
|
# Recursive here just refers to removing entries in a directory while
|
|
# iterating over the directory
|
|
#
|
|
# This is a useful feature, but it's unintuitive if this should have
|
|
# well-defined behavior, so make sure to test for it
|
|
[cases.t5_dirs_rm_recursive]
|
|
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
|
|
defines.PARENT = [false, true]
|
|
defines.SEEK = [false, true]
|
|
# limit powerloss testing due to time
|
|
if = '!TEST_PL || N <= 32'
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
if (PARENT) {
|
|
err = lfsr_mkdir(&lfs, "pricklypear");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
}
|
|
|
|
// make this many directories
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), i);
|
|
err = lfsr_mkdir(&lfs, name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
}
|
|
|
|
// check that our mkdir worked
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), i);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
char name2[256];
|
|
sprintf(name2, "dir%04d", i);
|
|
assert(strcmp(info.name, name2) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, (PARENT ? "pricklypear" : "/")) => 0;
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
// now remove directories recursively
|
|
lfsr_dir_open(&lfs, &dir, (PARENT ? "pricklypear" : "/")) => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
char path[1024];
|
|
sprintf(path, "%s/%s", (PARENT ? "pricklypear" : ""), info.name);
|
|
lfsr_remove(&lfs, path) => 0;
|
|
|
|
// seek between removes? this tests that the internal position is
|
|
// updated correctly
|
|
if (SEEK) {
|
|
lfs_ssize_t off = lfsr_dir_tell(&lfs, &dir);
|
|
assert(off >= 0);
|
|
lfsr_dir_rewind(&lfs, &dir) => 0;
|
|
lfsr_dir_seek(&lfs, &dir, off) => 0;
|
|
}
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
// check that our removes worked
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), i);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => LFS_ERR_NOENT;
|
|
}
|
|
|
|
lfsr_dir_open(&lfs, &dir, (PARENT ? "pricklypear" : "/")) => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# Recursive here just refers to renaming entries in a directory while
|
|
# iterating over the directory
|
|
#
|
|
# This is a useful feature, but it's unintuitive if this should have
|
|
# well-defined behavior, so make sure to test for it
|
|
[cases.t5_dirs_mv_recursive]
|
|
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
|
|
defines.BEFORE = [false, true]
|
|
# 0 => no
|
|
# 1 => yes
|
|
# 2 => yes, and rename to new parent
|
|
defines.PARENT = [0, 1, 2]
|
|
defines.SEEK = [false, true]
|
|
# limit powerloss testing due to time
|
|
if = '!TEST_PL || N <= 32'
|
|
reentrant = true
|
|
code = '''
|
|
// format once per test
|
|
lfs_t lfs;
|
|
int err = lfsr_mount(&lfs, cfg);
|
|
if (err) {
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
}
|
|
|
|
if (PARENT) {
|
|
err = lfsr_mkdir(&lfs, "pricklypear");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
if (PARENT >= 2) {
|
|
err = lfsr_mkdir(&lfs, "quiabentia");
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
}
|
|
}
|
|
|
|
// check if we have already started renaming, in case of powerloss
|
|
struct lfs_info info;
|
|
err = lfsr_stat(&lfs,
|
|
(PARENT == 1 ? (BEFORE
|
|
? "pricklypear/0mved0000"
|
|
: "pricklypear/mved0000")
|
|
: PARENT >= 2 ? (BEFORE
|
|
? "quiabentia/0mved0000"
|
|
: "quiabentia/mved0000")
|
|
: (BEFORE
|
|
? "/0mved0000"
|
|
: "/mved0000")), &info);
|
|
if (err == LFS_ERR_NOENT) {
|
|
// make this many directories
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), i);
|
|
err = lfsr_mkdir(&lfs, name);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
|
}
|
|
|
|
// check that our mkdir worked
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), i);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
char name2[256];
|
|
sprintf(name2, "dir%04d", i);
|
|
assert(strcmp(info.name, name2) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, (PARENT ? "pricklypear" : "/")) => 0;
|
|
struct lfs_info info;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "dir%04d", i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
}
|
|
|
|
// now rename directories recursively
|
|
lfsr_dir_t dir;
|
|
lfsr_dir_open(&lfs, &dir, (PARENT ? "pricklypear" : "/")) => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t i = 0;; i++) {
|
|
int err = lfsr_dir_read(&lfs, &dir, &info);
|
|
assert(!err || err == LFS_ERR_NOENT);
|
|
// reached the end?
|
|
if (err == LFS_ERR_NOENT) {
|
|
break;
|
|
}
|
|
// skip already moved?
|
|
if (memcmp(info.name, "dir", strlen("dir")) != 0) {
|
|
continue;
|
|
}
|
|
assert(i < 2*N);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
|
|
char old_path[1024];
|
|
sprintf(old_path, "%s/%s", (PARENT ? "pricklypear" : ""), info.name);
|
|
char new_path[1024];
|
|
sprintf(new_path, "%s/%smved%s",
|
|
(PARENT == 1 ? "pricklypear"
|
|
: PARENT >= 2 ? "quiabentia"
|
|
: ""),
|
|
(BEFORE ? "0" : ""),
|
|
&info.name[strlen("dir")]);
|
|
err = lfsr_rename(&lfs, old_path, new_path);
|
|
assert(!err || (TEST_PL && err == LFS_ERR_NOENT));
|
|
|
|
// seek between renames? this tests that the internal position is
|
|
// updated correctly
|
|
if (SEEK) {
|
|
lfs_ssize_t off = lfsr_dir_tell(&lfs, &dir);
|
|
assert(off >= 0);
|
|
lfsr_dir_rewind(&lfs, &dir) => 0;
|
|
lfsr_dir_seek(&lfs, &dir, off) => 0;
|
|
}
|
|
}
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
// check that our renames worked
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), i);
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, name, &info) => LFS_ERR_NOENT;
|
|
|
|
sprintf(name, "%s/%smved%04d",
|
|
(PARENT == 1 ? "pricklypear"
|
|
: PARENT >= 2 ? "quiabentia"
|
|
: ""),
|
|
(BEFORE ? "0" : ""),
|
|
i);
|
|
lfsr_stat(&lfs, name, &info) => 0;
|
|
char name2[256];
|
|
sprintf(name2, "%smved%04d", (BEFORE ? "0" : ""), i);
|
|
assert(strcmp(info.name, name2) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
|
|
lfsr_dir_open(&lfs, &dir,
|
|
(PARENT == 1 ? "pricklypear"
|
|
: PARENT >= 2 ? "quiabentia"
|
|
: "/")) => 0;
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, ".") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, "..") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char name[256];
|
|
sprintf(name, "%smved%04d", (BEFORE ? "0" : ""), i);
|
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
assert(strcmp(info.name, name) == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
}
|
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
lfsr_dir_close(&lfs, &dir) => 0;
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[cases.test_dirs_root]
|
|
#code = '''
|
|
# lfs_t lfs;
|
|
# lfs_format(&lfs, cfg) => 0;
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_dir_t dir;
|
|
# lfs_dir_open(&lfs, &dir, "/") => 0;
|
|
# struct lfs_info info;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, ".") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, "..") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 0;
|
|
# lfs_dir_close(&lfs, &dir) => 0;
|
|
# lfs_unmount(&lfs) => 0;
|
|
#'''
|
|
#
|
|
#[cases.test_dirs_many_creation]
|
|
#defines.N = 'range(3, 100, 3)'
|
|
#if = 'N < BLOCK_COUNT/2'
|
|
#code = '''
|
|
# lfs_t lfs;
|
|
# lfs_format(&lfs, cfg) => 0;
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# for (int i = 0; i < N; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "dir%03d", i);
|
|
# lfs_mkdir(&lfs, path) => 0;
|
|
# }
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_dir_t dir;
|
|
# lfs_dir_open(&lfs, &dir, "/") => 0;
|
|
# struct lfs_info info;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, ".") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, "..") == 0);
|
|
# for (int i = 0; i < N; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "dir%03d", i);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, path) == 0);
|
|
# }
|
|
# lfs_dir_read(&lfs, &dir, &info) => 0;
|
|
# lfs_dir_close(&lfs, &dir) => 0;
|
|
# lfs_unmount(&lfs) => 0;
|
|
#'''
|
|
#
|
|
#[cases.test_dirs_many_removal]
|
|
#defines.N = 'range(3, 100, 11)'
|
|
#if = 'N < BLOCK_COUNT/2'
|
|
#code = '''
|
|
# lfs_t lfs;
|
|
# lfs_format(&lfs, cfg) => 0;
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# for (int i = 0; i < N; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "removeme%03d", i);
|
|
# lfs_mkdir(&lfs, path) => 0;
|
|
# }
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_dir_t dir;
|
|
# lfs_dir_open(&lfs, &dir, "/") => 0;
|
|
# struct lfs_info info;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, ".") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, "..") == 0);
|
|
# for (int i = 0; i < N; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "removeme%03d", i);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, path) == 0);
|
|
# }
|
|
# lfs_dir_read(&lfs, &dir, &info) => 0;
|
|
# lfs_dir_close(&lfs, &dir) => 0;
|
|
# lfs_unmount(&lfs);
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# for (int i = 0; i < N; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "removeme%03d", i);
|
|
# lfs_remove(&lfs, path) => 0;
|
|
# }
|
|
# lfs_unmount(&lfs);
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_dir_open(&lfs, &dir, "/") => 0;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, ".") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, "..") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 0;
|
|
# lfs_dir_close(&lfs, &dir) => 0;
|
|
# lfs_unmount(&lfs) => 0;
|
|
#'''
|
|
#
|
|
#[cases.test_dirs_many_rename]
|
|
#defines.N = 'range(3, 100, 11)'
|
|
#if = 'N < BLOCK_COUNT/2'
|
|
#code = '''
|
|
# lfs_t lfs;
|
|
# lfs_format(&lfs, cfg) => 0;
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# for (int i = 0; i < N; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "test%03d", i);
|
|
# lfs_mkdir(&lfs, path) => 0;
|
|
# }
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_dir_t dir;
|
|
# lfs_dir_open(&lfs, &dir, "/") => 0;
|
|
# struct lfs_info info;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, ".") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, "..") == 0);
|
|
# for (int i = 0; i < N; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "test%03d", i);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, path) == 0);
|
|
# }
|
|
# lfs_dir_read(&lfs, &dir, &info) => 0;
|
|
# lfs_dir_close(&lfs, &dir) => 0;
|
|
# lfs_unmount(&lfs);
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# for (int i = 0; i < N; i++) {
|
|
# char oldpath[128];
|
|
# char newpath[128];
|
|
# sprintf(oldpath, "test%03d", i);
|
|
# sprintf(newpath, "tedd%03d", i);
|
|
# lfs_rename(&lfs, oldpath, newpath) => 0;
|
|
# }
|
|
# lfs_unmount(&lfs);
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_dir_open(&lfs, &dir, "/") => 0;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, ".") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, "..") == 0);
|
|
# for (int i = 0; i < N; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "tedd%03d", i);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, path) == 0);
|
|
# }
|
|
# lfs_dir_read(&lfs, &dir, &info) => 0;
|
|
# lfs_dir_close(&lfs, &dir) => 0;
|
|
# lfs_unmount(&lfs);
|
|
#'''
|
|
#
|
|
#[cases.test_dirs_many_reentrant]
|
|
#defines.N = [5, 11]
|
|
#if = 'BLOCK_COUNT >= 4*N'
|
|
#reentrant = true
|
|
#code = '''
|
|
# lfs_t lfs;
|
|
# int err = lfs_mount(&lfs, cfg);
|
|
# if (err) {
|
|
# lfs_format(&lfs, cfg) => 0;
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# }
|
|
#
|
|
# for (int i = 0; i < N; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "hi%03d", i);
|
|
# err = lfs_mkdir(&lfs, path);
|
|
# assert(err == 0 || err == LFS_ERR_EXIST);
|
|
# }
|
|
#
|
|
# for (int i = 0; i < N; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "hello%03d", i);
|
|
# err = lfs_remove(&lfs, path);
|
|
# assert(err == 0 || err == LFS_ERR_NOENT);
|
|
# }
|
|
#
|
|
# lfs_dir_t dir;
|
|
# lfs_dir_open(&lfs, &dir, "/") => 0;
|
|
# struct lfs_info info;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, ".") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, "..") == 0);
|
|
# for (int i = 0; i < N; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "hi%03d", i);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, path) == 0);
|
|
# }
|
|
# lfs_dir_read(&lfs, &dir, &info) => 0;
|
|
# lfs_dir_close(&lfs, &dir) => 0;
|
|
#
|
|
# for (int i = 0; i < N; i++) {
|
|
# char oldpath[128];
|
|
# char newpath[128];
|
|
# sprintf(oldpath, "hi%03d", i);
|
|
# sprintf(newpath, "hello%03d", i);
|
|
# // YES this can overwrite an existing newpath
|
|
# lfs_rename(&lfs, oldpath, newpath) => 0;
|
|
# }
|
|
#
|
|
# lfs_dir_open(&lfs, &dir, "/") => 0;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, ".") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, "..") == 0);
|
|
# for (int i = 0; i < N; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "hello%03d", i);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, path) == 0);
|
|
# }
|
|
# lfs_dir_read(&lfs, &dir, &info) => 0;
|
|
# lfs_dir_close(&lfs, &dir) => 0;
|
|
#
|
|
# for (int i = 0; i < N; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "hello%03d", i);
|
|
# lfs_remove(&lfs, path) => 0;
|
|
# }
|
|
#
|
|
# lfs_dir_open(&lfs, &dir, "/") => 0;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, ".") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, "..") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 0;
|
|
# lfs_dir_close(&lfs, &dir) => 0;
|
|
# lfs_unmount(&lfs) => 0;
|
|
#'''
|
|
#
|
|
#[cases.test_dirs_file_creation]
|
|
#defines.N = 'range(3, 100, 11)'
|
|
#if = 'N < BLOCK_COUNT/2'
|
|
#code = '''
|
|
# lfs_t lfs;
|
|
# lfs_format(&lfs, cfg) => 0;
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# for (int i = 0; i < N; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "file%03d", i);
|
|
# lfs_file_t file;
|
|
# lfs_file_open(&lfs, &file, path,
|
|
# LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
|
# lfs_file_close(&lfs, &file) => 0;
|
|
# }
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_dir_t dir;
|
|
# lfs_dir_open(&lfs, &dir, "/") => 0;
|
|
# struct lfs_info info;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, ".") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, "..") == 0);
|
|
# for (int i = 0; i < N; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "file%03d", i);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_REG);
|
|
# assert(strcmp(info.name, path) == 0);
|
|
# }
|
|
# lfs_dir_read(&lfs, &dir, &info) => 0;
|
|
# lfs_dir_close(&lfs, &dir) => 0;
|
|
# lfs_unmount(&lfs);
|
|
#'''
|
|
#
|
|
#[cases.test_dirs_file_removal]
|
|
#defines.N = 'range(3, 100, 11)'
|
|
#if = 'N < BLOCK_COUNT/2'
|
|
#code = '''
|
|
# lfs_t lfs;
|
|
# lfs_format(&lfs, cfg) => 0;
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# for (int i = 0; i < N; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "removeme%03d", i);
|
|
# lfs_file_t file;
|
|
# lfs_file_open(&lfs, &file, path,
|
|
# LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
|
# lfs_file_close(&lfs, &file) => 0;
|
|
# }
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_dir_t dir;
|
|
# lfs_dir_open(&lfs, &dir, "/") => 0;
|
|
# struct lfs_info info;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, ".") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, "..") == 0);
|
|
# for (int i = 0; i < N; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "removeme%03d", i);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_REG);
|
|
# assert(strcmp(info.name, path) == 0);
|
|
# }
|
|
# lfs_dir_read(&lfs, &dir, &info) => 0;
|
|
# lfs_dir_close(&lfs, &dir) => 0;
|
|
# lfs_unmount(&lfs);
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# for (int i = 0; i < N; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "removeme%03d", i);
|
|
# lfs_remove(&lfs, path) => 0;
|
|
# }
|
|
# lfs_unmount(&lfs);
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_dir_open(&lfs, &dir, "/") => 0;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, ".") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, "..") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 0;
|
|
# lfs_dir_close(&lfs, &dir) => 0;
|
|
# lfs_unmount(&lfs) => 0;
|
|
#'''
|
|
#
|
|
#[cases.test_dirs_file_rename]
|
|
#defines.N = 'range(3, 100, 11)'
|
|
#if = 'N < BLOCK_COUNT/2'
|
|
#code = '''
|
|
# lfs_t lfs;
|
|
# lfs_format(&lfs, cfg) => 0;
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# for (int i = 0; i < N; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "test%03d", i);
|
|
# lfs_file_t file;
|
|
# lfs_file_open(&lfs, &file, path,
|
|
# LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
|
# lfs_file_close(&lfs, &file) => 0;
|
|
# }
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_dir_t dir;
|
|
# lfs_dir_open(&lfs, &dir, "/") => 0;
|
|
# struct lfs_info info;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, ".") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, "..") == 0);
|
|
# for (int i = 0; i < N; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "test%03d", i);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_REG);
|
|
# assert(strcmp(info.name, path) == 0);
|
|
# }
|
|
# lfs_dir_read(&lfs, &dir, &info) => 0;
|
|
# lfs_dir_close(&lfs, &dir) => 0;
|
|
# lfs_unmount(&lfs);
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# for (int i = 0; i < N; i++) {
|
|
# char oldpath[128];
|
|
# char newpath[128];
|
|
# sprintf(oldpath, "test%03d", i);
|
|
# sprintf(newpath, "tedd%03d", i);
|
|
# lfs_rename(&lfs, oldpath, newpath) => 0;
|
|
# }
|
|
# lfs_unmount(&lfs);
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_dir_open(&lfs, &dir, "/") => 0;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, ".") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, "..") == 0);
|
|
# for (int i = 0; i < N; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "tedd%03d", i);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_REG);
|
|
# assert(strcmp(info.name, path) == 0);
|
|
# }
|
|
# lfs_dir_read(&lfs, &dir, &info) => 0;
|
|
# lfs_dir_close(&lfs, &dir) => 0;
|
|
# lfs_unmount(&lfs);
|
|
#'''
|
|
#
|
|
#[cases.test_dirs_file_reentrant]
|
|
#defines.N = [5, 25]
|
|
#if = 'N < BLOCK_COUNT/2'
|
|
#reentrant = true
|
|
#code = '''
|
|
# lfs_t lfs;
|
|
# int err = lfs_mount(&lfs, cfg);
|
|
# if (err) {
|
|
# lfs_format(&lfs, cfg) => 0;
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# }
|
|
#
|
|
# for (int i = 0; i < N; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "hi%03d", i);
|
|
# lfs_file_t file;
|
|
# lfs_file_open(&lfs, &file, path, LFS_O_CREAT | LFS_O_WRONLY) => 0;
|
|
# lfs_file_close(&lfs, &file) => 0;
|
|
# }
|
|
#
|
|
# for (int i = 0; i < N; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "hello%03d", i);
|
|
# err = lfs_remove(&lfs, path);
|
|
# assert(err == 0 || err == LFS_ERR_NOENT);
|
|
# }
|
|
#
|
|
# lfs_dir_t dir;
|
|
# lfs_dir_open(&lfs, &dir, "/") => 0;
|
|
# struct lfs_info info;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, ".") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, "..") == 0);
|
|
# for (int i = 0; i < N; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "hi%03d", i);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_REG);
|
|
# assert(strcmp(info.name, path) == 0);
|
|
# }
|
|
# lfs_dir_read(&lfs, &dir, &info) => 0;
|
|
# lfs_dir_close(&lfs, &dir) => 0;
|
|
#
|
|
# for (int i = 0; i < N; i++) {
|
|
# char oldpath[128];
|
|
# char newpath[128];
|
|
# sprintf(oldpath, "hi%03d", i);
|
|
# sprintf(newpath, "hello%03d", i);
|
|
# // YES this can overwrite an existing newpath
|
|
# lfs_rename(&lfs, oldpath, newpath) => 0;
|
|
# }
|
|
#
|
|
# lfs_dir_open(&lfs, &dir, "/") => 0;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, ".") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, "..") == 0);
|
|
# for (int i = 0; i < N; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "hello%03d", i);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_REG);
|
|
# assert(strcmp(info.name, path) == 0);
|
|
# }
|
|
# lfs_dir_read(&lfs, &dir, &info) => 0;
|
|
# lfs_dir_close(&lfs, &dir) => 0;
|
|
#
|
|
# for (int i = 0; i < N; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "hello%03d", i);
|
|
# lfs_remove(&lfs, path) => 0;
|
|
# }
|
|
#
|
|
# lfs_dir_open(&lfs, &dir, "/") => 0;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, ".") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, "..") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 0;
|
|
# lfs_dir_close(&lfs, &dir) => 0;
|
|
# lfs_unmount(&lfs) => 0;
|
|
#'''
|
|
#
|
|
#[cases.test_dirs_nested]
|
|
#code = '''
|
|
# lfs_t lfs;
|
|
# lfs_format(&lfs, cfg) => 0;
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_mkdir(&lfs, "potato") => 0;
|
|
# lfs_file_t file;
|
|
# lfs_file_open(&lfs, &file, "burito",
|
|
# LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
|
# lfs_file_close(&lfs, &file) => 0;
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_mkdir(&lfs, "potato/baked") => 0;
|
|
# lfs_mkdir(&lfs, "potato/sweet") => 0;
|
|
# lfs_mkdir(&lfs, "potato/fried") => 0;
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_dir_t dir;
|
|
# lfs_dir_open(&lfs, &dir, "potato") => 0;
|
|
# struct lfs_info info;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(strcmp(info.name, ".") == 0);
|
|
# info.type => LFS_TYPE_DIR;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(strcmp(info.name, "..") == 0);
|
|
# info.type => LFS_TYPE_DIR;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(strcmp(info.name, "baked") == 0);
|
|
# info.type => LFS_TYPE_DIR;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(strcmp(info.name, "fried") == 0);
|
|
# info.type => LFS_TYPE_DIR;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(strcmp(info.name, "sweet") == 0);
|
|
# info.type => LFS_TYPE_DIR;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 0;
|
|
# lfs_dir_close(&lfs, &dir) => 0;
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# // try removing?
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_remove(&lfs, "potato") => LFS_ERR_NOTEMPTY;
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# // try renaming?
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_rename(&lfs, "potato", "coldpotato") => 0;
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_rename(&lfs, "coldpotato", "warmpotato") => 0;
|
|
# lfs_rename(&lfs, "warmpotato", "hotpotato") => 0;
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_remove(&lfs, "potato") => LFS_ERR_NOENT;
|
|
# lfs_remove(&lfs, "coldpotato") => LFS_ERR_NOENT;
|
|
# lfs_remove(&lfs, "warmpotato") => LFS_ERR_NOENT;
|
|
# lfs_remove(&lfs, "hotpotato") => LFS_ERR_NOTEMPTY;
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# // try cross-directory renaming
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_mkdir(&lfs, "coldpotato") => 0;
|
|
# lfs_rename(&lfs, "hotpotato/baked", "coldpotato/baked") => 0;
|
|
# lfs_rename(&lfs, "coldpotato", "hotpotato") => LFS_ERR_NOTEMPTY;
|
|
# lfs_remove(&lfs, "coldpotato") => LFS_ERR_NOTEMPTY;
|
|
# lfs_remove(&lfs, "hotpotato") => LFS_ERR_NOTEMPTY;
|
|
# lfs_rename(&lfs, "hotpotato/fried", "coldpotato/fried") => 0;
|
|
# lfs_rename(&lfs, "coldpotato", "hotpotato") => LFS_ERR_NOTEMPTY;
|
|
# lfs_remove(&lfs, "coldpotato") => LFS_ERR_NOTEMPTY;
|
|
# lfs_remove(&lfs, "hotpotato") => LFS_ERR_NOTEMPTY;
|
|
# lfs_rename(&lfs, "hotpotato/sweet", "coldpotato/sweet") => 0;
|
|
# lfs_rename(&lfs, "coldpotato", "hotpotato") => 0;
|
|
# lfs_remove(&lfs, "coldpotato") => LFS_ERR_NOENT;
|
|
# lfs_remove(&lfs, "hotpotato") => LFS_ERR_NOTEMPTY;
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_dir_open(&lfs, &dir, "hotpotato") => 0;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(strcmp(info.name, ".") == 0);
|
|
# info.type => LFS_TYPE_DIR;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(strcmp(info.name, "..") == 0);
|
|
# info.type => LFS_TYPE_DIR;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(strcmp(info.name, "baked") == 0);
|
|
# info.type => LFS_TYPE_DIR;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(strcmp(info.name, "fried") == 0);
|
|
# info.type => LFS_TYPE_DIR;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(strcmp(info.name, "sweet") == 0);
|
|
# info.type => LFS_TYPE_DIR;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 0;
|
|
# lfs_dir_close(&lfs, &dir) => 0;
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# // final remove
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_remove(&lfs, "hotpotato") => LFS_ERR_NOTEMPTY;
|
|
# lfs_remove(&lfs, "hotpotato/baked") => 0;
|
|
# lfs_remove(&lfs, "hotpotato") => LFS_ERR_NOTEMPTY;
|
|
# lfs_remove(&lfs, "hotpotato/fried") => 0;
|
|
# lfs_remove(&lfs, "hotpotato") => LFS_ERR_NOTEMPTY;
|
|
# lfs_remove(&lfs, "hotpotato/sweet") => 0;
|
|
# lfs_remove(&lfs, "hotpotato") => 0;
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_dir_open(&lfs, &dir, "/") => 0;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(strcmp(info.name, ".") == 0);
|
|
# info.type => LFS_TYPE_DIR;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(strcmp(info.name, "..") == 0);
|
|
# info.type => LFS_TYPE_DIR;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(strcmp(info.name, "burito") == 0);
|
|
# info.type => LFS_TYPE_REG;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 0;
|
|
# lfs_dir_close(&lfs, &dir) => 0;
|
|
# lfs_unmount(&lfs) => 0;
|
|
#'''
|
|
#
|
|
#[cases.test_dirs_recursive_remove]
|
|
#defines.N = [10, 100]
|
|
#if = 'N < BLOCK_COUNT/2'
|
|
#code = '''
|
|
# lfs_t lfs;
|
|
# lfs_format(&lfs, cfg) => 0;
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_mkdir(&lfs, "prickly-pear") => 0;
|
|
# for (int i = 0; i < N; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "prickly-pear/cactus%03d", i);
|
|
# lfs_mkdir(&lfs, path) => 0;
|
|
# }
|
|
# lfs_dir_t dir;
|
|
# lfs_dir_open(&lfs, &dir, "prickly-pear") => 0;
|
|
# struct lfs_info info;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, ".") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, "..") == 0);
|
|
# for (int i = 0; i < N; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "cactus%03d", i);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, path) == 0);
|
|
# }
|
|
# lfs_dir_read(&lfs, &dir, &info) => 0;
|
|
# lfs_dir_close(&lfs, &dir) => 0;
|
|
# lfs_unmount(&lfs);
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_remove(&lfs, "prickly-pear") => LFS_ERR_NOTEMPTY;
|
|
#
|
|
# lfs_dir_open(&lfs, &dir, "prickly-pear") => 0;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, ".") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, "..") == 0);
|
|
# for (int i = 0; i < N; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "cactus%03d", i);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, path) == 0);
|
|
# sprintf(path, "prickly-pear/%s", info.name);
|
|
# lfs_remove(&lfs, path) => 0;
|
|
# }
|
|
# lfs_dir_read(&lfs, &dir, &info) => 0;
|
|
# lfs_dir_close(&lfs, &dir) => 0;
|
|
#
|
|
# lfs_remove(&lfs, "prickly-pear") => 0;
|
|
# lfs_remove(&lfs, "prickly-pear") => LFS_ERR_NOENT;
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_remove(&lfs, "prickly-pear") => LFS_ERR_NOENT;
|
|
# lfs_unmount(&lfs) => 0;
|
|
#'''
|
|
#
|
|
#[cases.test_dirs_other_errors]
|
|
#code = '''
|
|
# lfs_t lfs;
|
|
# lfs_format(&lfs, cfg) => 0;
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_mkdir(&lfs, "potato") => 0;
|
|
# lfs_file_t file;
|
|
# lfs_file_open(&lfs, &file, "burito",
|
|
# LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
|
# lfs_file_close(&lfs, &file) => 0;
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
#
|
|
# lfs_mkdir(&lfs, "potato") => LFS_ERR_EXIST;
|
|
# lfs_mkdir(&lfs, "burito") => LFS_ERR_EXIST;
|
|
# lfs_file_open(&lfs, &file, "burito",
|
|
# LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST;
|
|
# lfs_file_open(&lfs, &file, "potato",
|
|
# LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST;
|
|
# lfs_dir_t dir;
|
|
# lfs_dir_open(&lfs, &dir, "tomato") => LFS_ERR_NOENT;
|
|
# lfs_dir_open(&lfs, &dir, "burito") => LFS_ERR_NOTDIR;
|
|
# lfs_file_open(&lfs, &file, "tomato", LFS_O_RDONLY) => LFS_ERR_NOENT;
|
|
# lfs_file_open(&lfs, &file, "potato", LFS_O_RDONLY) => LFS_ERR_ISDIR;
|
|
# lfs_file_open(&lfs, &file, "tomato", LFS_O_WRONLY) => LFS_ERR_NOENT;
|
|
# lfs_file_open(&lfs, &file, "potato", LFS_O_WRONLY) => LFS_ERR_ISDIR;
|
|
# lfs_file_open(&lfs, &file, "potato",
|
|
# LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR;
|
|
#
|
|
# lfs_mkdir(&lfs, "/") => LFS_ERR_EXIST;
|
|
# lfs_file_open(&lfs, &file, "/",
|
|
# LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST;
|
|
# lfs_file_open(&lfs, &file, "/", LFS_O_RDONLY) => LFS_ERR_ISDIR;
|
|
# lfs_file_open(&lfs, &file, "/", LFS_O_WRONLY) => LFS_ERR_ISDIR;
|
|
# lfs_file_open(&lfs, &file, "/",
|
|
# LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR;
|
|
#
|
|
# // check that errors did not corrupt directory
|
|
# lfs_dir_open(&lfs, &dir, "/") => 0;
|
|
# struct lfs_info info;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, ".") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, "..") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_REG);
|
|
# assert(strcmp(info.name, "burito") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, "potato") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 0;
|
|
# lfs_dir_close(&lfs, &dir) => 0;
|
|
#
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# // or on disk
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_dir_open(&lfs, &dir, "/") => 0;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, ".") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, "..") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_REG);
|
|
# assert(strcmp(info.name, "burito") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# assert(strcmp(info.name, "potato") == 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 0;
|
|
# lfs_dir_close(&lfs, &dir) => 0;
|
|
# lfs_unmount(&lfs) => 0;
|
|
#'''
|
|
#
|
|
#[cases.test_dirs_seek]
|
|
#defines.COUNT = [4, 128, 132]
|
|
#if = 'COUNT < BLOCK_COUNT/2'
|
|
#code = '''
|
|
# lfs_t lfs;
|
|
# lfs_format(&lfs, cfg) => 0;
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_mkdir(&lfs, "hello") => 0;
|
|
# for (int i = 0; i < COUNT; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "hello/kitty%03d", i);
|
|
# lfs_mkdir(&lfs, path) => 0;
|
|
# }
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# for (int j = 2; j < COUNT; j++) {
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_dir_t dir;
|
|
# lfs_dir_open(&lfs, &dir, "hello") => 0;
|
|
# struct lfs_info info;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(strcmp(info.name, ".") == 0);
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(strcmp(info.name, "..") == 0);
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
#
|
|
# lfs_soff_t pos;
|
|
# for (int i = 0; i < j; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "kitty%03d", i);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(strcmp(info.name, path) == 0);
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# pos = lfs_dir_tell(&lfs, &dir);
|
|
# assert(pos >= 0);
|
|
# }
|
|
#
|
|
# lfs_dir_seek(&lfs, &dir, pos) => 0;
|
|
# char path[1024];
|
|
# sprintf(path, "kitty%03d", j);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(strcmp(info.name, path) == 0);
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
#
|
|
# lfs_dir_rewind(&lfs, &dir) => 0;
|
|
# sprintf(path, "kitty%03u", 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(strcmp(info.name, ".") == 0);
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(strcmp(info.name, "..") == 0);
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(strcmp(info.name, path) == 0);
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
#
|
|
# lfs_dir_seek(&lfs, &dir, pos) => 0;
|
|
# sprintf(path, "kitty%03d", j);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(strcmp(info.name, path) == 0);
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
#
|
|
# lfs_dir_close(&lfs, &dir) => 0;
|
|
# lfs_unmount(&lfs) => 0;
|
|
# }
|
|
#'''
|
|
#
|
|
#[cases.test_dirs_toot_seek]
|
|
#defines.COUNT = [4, 128, 132]
|
|
#if = 'COUNT < BLOCK_COUNT/2'
|
|
#code = '''
|
|
# lfs_t lfs;
|
|
# lfs_format(&lfs, cfg) => 0;
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# for (int i = 0; i < COUNT; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "hi%03d", i);
|
|
# lfs_mkdir(&lfs, path) => 0;
|
|
# }
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# for (int j = 2; j < COUNT; j++) {
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_dir_t dir;
|
|
# lfs_dir_open(&lfs, &dir, "/") => 0;
|
|
# struct lfs_info info;
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(strcmp(info.name, ".") == 0);
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(strcmp(info.name, "..") == 0);
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
#
|
|
# lfs_soff_t pos;
|
|
# for (int i = 0; i < j; i++) {
|
|
# char path[1024];
|
|
# sprintf(path, "hi%03d", i);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(strcmp(info.name, path) == 0);
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# pos = lfs_dir_tell(&lfs, &dir);
|
|
# assert(pos >= 0);
|
|
# }
|
|
#
|
|
# lfs_dir_seek(&lfs, &dir, pos) => 0;
|
|
# char path[1024];
|
|
# sprintf(path, "hi%03d", j);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(strcmp(info.name, path) == 0);
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
#
|
|
# lfs_dir_rewind(&lfs, &dir) => 0;
|
|
# sprintf(path, "hi%03u", 0);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(strcmp(info.name, ".") == 0);
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(strcmp(info.name, "..") == 0);
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(strcmp(info.name, path) == 0);
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
#
|
|
# lfs_dir_seek(&lfs, &dir, pos) => 0;
|
|
# sprintf(path, "hi%03d", j);
|
|
# lfs_dir_read(&lfs, &dir, &info) => 1;
|
|
# assert(strcmp(info.name, path) == 0);
|
|
# assert(info.type == LFS_TYPE_DIR);
|
|
#
|
|
# lfs_dir_close(&lfs, &dir) => 0;
|
|
# lfs_unmount(&lfs) => 0;
|
|
# }
|
|
#'''
|
|
#
|