Files
littlefs/tests/test_dirs.toml
T
Christopher Haster 7d45ca0892 tests: Big test cleanup!
Removing the vestiges of v2 tests.
2025-05-27 21:05:53 -05:00

6955 lines
237 KiB
TOML

# Test directory operations
after = 'test_mtree'
## mkdir tests
[cases.test_dirs_mkdir]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// make a directory
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[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);
assert(info.size == 0);
// 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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.test_dirs_noent]
code = '''
lfs_t lfs;
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, 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;
lfsr_unmount(&lfs) => 0;
'''
# test that stat on root works
[cases.test_dirs_stat_root]
code = '''
lfs_t lfs;
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, 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);
assert(info.size == 0);
lfsr_unmount(&lfs) => 0;
'''
# test that creating the same directory twice errors
[cases.test_dirs_mkdir_exists]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// make a directory
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// make the same directory, should error
lfsr_mkdir(&lfs, "ardvark") => LFS_ERR_EXIST;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[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);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
lfsr_unmount(&lfs) => 0;
'''
# test that dir existance is the same before/after mkconsistent
[cases.test_dirs_mkdir_consistent]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// check if dir exists before mkconsistent
struct lfs_info info;
err = lfsr_stat(&lfs, "ardvark", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool exists = !err;
// 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// make a directory
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == exists);
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[0] == 0);
// check that our mkdir worked with stat
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
// 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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.test_dirs_mkdir_root]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// try to make root, which doesn't make sense
lfsr_mkdir(&lfs, "/") => LFS_ERR_EXIST;
// make a directory
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// try to make root, which doesn't make sense
lfsr_mkdir(&lfs, "/") => LFS_ERR_EXIST;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[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);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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.test_dirs_mkdir_noent]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// make a directory
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && 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;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[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);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_mkdir_siblings]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// check if dirs exist before mkconsistent
struct lfs_info info;
err = lfsr_stat(&lfs, "ardvark", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfsr_stat(&lfs, "banana", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
err = lfsr_stat(&lfs, "cat", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool c_exists = !err;
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (b_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (c_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// make some directories
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == a_exists);
err = lfsr_mkdir(&lfs, "banana");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == b_exists);
err = lfsr_mkdir(&lfs, "cat");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == c_exists);
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[0] == 0);
// check that our mkdir worked
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_dir_open(&lfs, &dir, "cat") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_mkdir_children]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// check if dirs exist before mkconsistent
struct lfs_info info;
err = lfsr_stat(&lfs, "ardvark", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfsr_stat(&lfs, "ardvark/banana", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
err = lfsr_stat(&lfs, "ardvark/banana/cat", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool c_exists = !err;
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
err = lfsr_dir_open(&lfs, &dir, "/ardvark");
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
assert(!err == a_exists);
if (a_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (b_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
err = lfsr_dir_open(&lfs, &dir, "/ardvark/banana");
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
assert(!err == b_exists);
if (b_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (c_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
// make some directories
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == a_exists);
err = lfsr_mkdir(&lfs, "ardvark/banana");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == b_exists);
err = lfsr_mkdir(&lfs, "ardvark/banana/cat");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == c_exists);
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[0] == 0);
// check that our mkdirs worked
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "ardvark/banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "ardvark/banana/cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_dir_open(&lfs, &dir, "/ardvark/banana/cat") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_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_PLS || N <= 16'
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// make this many directories
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[0] == 0);
// check that our mkdir worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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%03x", 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_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_PLS || N <= 16'
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// make this many directories
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", (int)(N-1-i));
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[0] == 0);
// check that our mkdir worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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%03x", 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_mkdir_many_2layers]
defines.N = [1, 2, 4, 8, 16]
defines.REMOUNT = [false, true]
# limit powerloss testing due to time
if = '!TEST_PLS || N <= 4'
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// make this many directories
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// containing this many directories
for (lfs_size_t j = 0; j < N; j++) {
sprintf(name, "dir%03x/child%03x", i, j);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[0] == 0);
// check that our mkdirs worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
sprintf(name, "child%03x", j);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
}
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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%03x", 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "child%03x", j);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
for (lfs_size_t i = 0; i < N; i++) {
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
}
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_mkdir_many_3layers]
defines.N = [1, 2, 4]
defines.REMOUNT = [false, true]
# limit powerloss testing due to time
if = '!TEST_PLS || N <= 2'
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// make this many directories
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// containing this many directories
for (lfs_size_t j = 0; j < N; j++) {
sprintf(name, "dir%03x/child%03x", i, j);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// containing this many directories
for (lfs_size_t k = 0; k < N; k++) {
sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
}
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[0] == 0);
// check that our mkdirs worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
sprintf(name, "child%03x", j);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t k = 0; k < N; k++) {
char name[256];
sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
sprintf(name, "grandchild%03x", k);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
}
}
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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%03x", 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "child%03x", j);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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%03x/child%03x", 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t k = 0; k < N; k++) {
char name[256];
sprintf(name, "grandchild%03x", k);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
}
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++) {
char name[256];
sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
}
}
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_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_PLS || N <= 16'
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, 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%03x", i);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[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%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
char name2[256];
sprintf(name2, "dir%03x", i);
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
memset(name, 0, sizeof(name));
for (lfs_size_t i = 0; i < N; i++) {
sprintf(&name[strlen(name)], "/dir%03x", 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (i < N-1) {
char name2[256];
sprintf(name2, "dir%03x", i+1);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_mkdir_fuzz]
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256]
# do more ops than dirs to encourage rename collisions
defines.OPS = '2*N'
defines.PARENT = [false, true]
defines.SEED = 'range(20)'
fuzz = 'SEED'
# limit powerloss testing due to time
if = '!TEST_PLS || N <= 8'
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
if (PARENT) {
err = lfsr_mkdir(&lfs, "pricklypear");
assert(!err || (TEST_PLS && 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 < OPS; i++) {
// choose a pseudo-random number
lfs_size_t x = TEST_PRNG(&prng) % N;
// 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%03x", ((PARENT) ? "pricklypear" : ""), x);
int err = lfsr_mkdir(&lfs, name);
assert(!err || err == LFS_ERR_EXIST);
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[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%03x",
((PARENT) ? "pricklypear" : ""),
sim[j]);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
char name2[256];
sprintf(name2, "dir%03x", sim[j]);
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < sim_size; j++) {
char name[256];
sprintf(name, "dir%03x", sim[j]);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
for (lfs_size_t j = 0; j < sim_size; j++) {
char name[256];
sprintf(name, "%s/dir%03x",
((PARENT) ? "pricklypear" : ""),
sim[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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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 some common ordering mistakes
[cases.test_dirs_ordering]
# ORDER=0 => inorder
# ORDER=1 => reversed
# ORDER=2 => random
defines.ORDER = [0, 1, 2]
code = '''
lfs_t lfs;
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
if (ORDER == 0) {
lfsr_mkdir(&lfs, "a") => 0;
lfsr_mkdir(&lfs, "b") => 0;
lfsr_mkdir(&lfs, "c") => 0;
lfsr_mkdir(&lfs, "d") => 0;
lfsr_mkdir(&lfs, "e") => 0;
lfsr_mkdir(&lfs, "f") => 0;
} else if (ORDER == 1) {
lfsr_mkdir(&lfs, "f") => 0;
lfsr_mkdir(&lfs, "e") => 0;
lfsr_mkdir(&lfs, "d") => 0;
lfsr_mkdir(&lfs, "c") => 0;
lfsr_mkdir(&lfs, "b") => 0;
lfsr_mkdir(&lfs, "a") => 0;
} else if (ORDER == 2) {
// "random", trust me
lfsr_mkdir(&lfs, "e") => 0;
lfsr_mkdir(&lfs, "c") => 0;
lfsr_mkdir(&lfs, "b") => 0;
lfsr_mkdir(&lfs, "d") => 0;
lfsr_mkdir(&lfs, "f") => 0;
lfsr_mkdir(&lfs, "a") => 0;
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[0] == 0);
// check that our mkdirs worked
struct lfs_info info;
lfsr_stat(&lfs, "a", &info) => 0;
assert(strcmp(info.name, "a") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "b", &info) => 0;
assert(strcmp(info.name, "b") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "c", &info) => 0;
assert(strcmp(info.name, "c") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "d", &info) => 0;
assert(strcmp(info.name, "d") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "e", &info) => 0;
assert(strcmp(info.name, "e") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "f", &info) => 0;
assert(strcmp(info.name, "f") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
// check the directory order
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "a") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "b") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "c") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "d") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "e") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "f") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_ordering_length]
# ORDER=0 => inorder
# ORDER=1 => reversed
# ORDER=2 => random
defines.ORDER = [0, 1, 2]
code = '''
lfs_t lfs;
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
if (ORDER == 0) {
lfsr_mkdir(&lfs, "a") => 0;
lfsr_mkdir(&lfs, "aa") => 0;
lfsr_mkdir(&lfs, "aaa") => 0;
lfsr_mkdir(&lfs, "aaaa") => 0;
lfsr_mkdir(&lfs, "aaaaa") => 0;
lfsr_mkdir(&lfs, "aaaaaa") => 0;
} else if (ORDER == 1) {
lfsr_mkdir(&lfs, "aaaaaa") => 0;
lfsr_mkdir(&lfs, "aaaaa") => 0;
lfsr_mkdir(&lfs, "aaaa") => 0;
lfsr_mkdir(&lfs, "aaa") => 0;
lfsr_mkdir(&lfs, "aa") => 0;
lfsr_mkdir(&lfs, "a") => 0;
} else if (ORDER == 2) {
// "random", trust me
lfsr_mkdir(&lfs, "aaaaa") => 0;
lfsr_mkdir(&lfs, "aaa") => 0;
lfsr_mkdir(&lfs, "aa") => 0;
lfsr_mkdir(&lfs, "aaaa") => 0;
lfsr_mkdir(&lfs, "aaaaaa") => 0;
lfsr_mkdir(&lfs, "a") => 0;
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[0] == 0);
// check that our mkdirs worked
struct lfs_info info;
lfsr_stat(&lfs, "a", &info) => 0;
assert(strcmp(info.name, "a") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "aa", &info) => 0;
assert(strcmp(info.name, "aa") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "aaa", &info) => 0;
assert(strcmp(info.name, "aaa") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "aaaa", &info) => 0;
assert(strcmp(info.name, "aaaa") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "aaaaa", &info) => 0;
assert(strcmp(info.name, "aaaaa") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "aaaaaa", &info) => 0;
assert(strcmp(info.name, "aaaaaa") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
// check the directory order
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "a") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "aa") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "aaa") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "aaaa") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "aaaaa") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "aaaaaa") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
lfsr_unmount(&lfs) => 0;
'''
# test that did collisions don't cause issues
[cases.test_dirs_did_collisions]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, 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);
// check if dirs exist before mkconsistent
struct lfs_info info;
err = lfsr_stat(&lfs, "a_SNmwMTHH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfsr_stat(&lfs, "b_skvjpWJH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
err = lfsr_stat(&lfs, "c_OnOQhVPH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool c_exists = !err;
err = lfsr_stat(&lfs, "d_puMpPjRH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool d_exists = !err;
err = lfsr_stat(&lfs, "e_LptKHkHH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool e_exists = !err;
err = lfsr_stat(&lfs, "f_lUoVuhJH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool f_exists = !err;
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "a_SNmwMTHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (b_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "b_skvjpWJH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (c_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "c_OnOQhVPH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (d_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "d_puMpPjRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (e_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "e_LptKHkHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (f_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "f_lUoVuhJH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// make directories
err = lfsr_mkdir(&lfs, "a_SNmwMTHH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == a_exists);
err = lfsr_mkdir(&lfs, "b_skvjpWJH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == b_exists);
err = lfsr_mkdir(&lfs, "c_OnOQhVPH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == c_exists);
err = lfsr_mkdir(&lfs, "d_puMpPjRH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == d_exists);
err = lfsr_mkdir(&lfs, "e_LptKHkHH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == e_exists);
err = lfsr_mkdir(&lfs, "f_lUoVuhJH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == f_exists);
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[0] == 0);
// check that our mkdirs worked
lfsr_stat(&lfs, "a_SNmwMTHH", &info) => 0;
assert(strcmp(info.name, "a_SNmwMTHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "b_skvjpWJH", &info) => 0;
assert(strcmp(info.name, "b_skvjpWJH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "c_OnOQhVPH", &info) => 0;
assert(strcmp(info.name, "c_OnOQhVPH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "d_puMpPjRH", &info) => 0;
assert(strcmp(info.name, "d_puMpPjRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "e_LptKHkHH", &info) => 0;
assert(strcmp(info.name, "e_LptKHkHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "f_lUoVuhJH", &info) => 0;
assert(strcmp(info.name, "f_lUoVuhJH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "a_SNmwMTHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "b_skvjpWJH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "c_OnOQhVPH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "d_puMpPjRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "e_LptKHkHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "f_lUoVuhJH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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.test_dirs_did_zero]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, 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);
// check if dirs exist before mkconsistent
struct lfs_info info;
err = lfsr_stat(&lfs, "a_IplRNrPH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfsr_stat(&lfs, "b_iUwOsqRH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
err = lfsr_stat(&lfs, "c_UPNtkpHH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool c_exists = !err;
err = lfsr_stat(&lfs, "d_jKLUSLJH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool d_exists = !err;
err = lfsr_stat(&lfs, "e_VNunKMPH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool e_exists = !err;
err = lfsr_stat(&lfs, "f_vknsvNRH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool f_exists = !err;
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "a_IplRNrPH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (b_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "b_iUwOsqRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (c_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "c_UPNtkpHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (d_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "d_jKLUSLJH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (e_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "e_VNunKMPH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (f_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "f_vknsvNRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// make directories
err = lfsr_mkdir(&lfs, "a_IplRNrPH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == a_exists);
err = lfsr_mkdir(&lfs, "b_iUwOsqRH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == b_exists);
err = lfsr_mkdir(&lfs, "c_UPNtkpHH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == c_exists);
err = lfsr_mkdir(&lfs, "d_jKLUSLJH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == d_exists);
err = lfsr_mkdir(&lfs, "e_VNunKMPH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == e_exists);
err = lfsr_mkdir(&lfs, "f_vknsvNRH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == f_exists);
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[0] == 0);
// check that our mkdirs worked
lfsr_stat(&lfs, "a_IplRNrPH", &info) => 0;
assert(strcmp(info.name, "a_IplRNrPH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "b_iUwOsqRH", &info) => 0;
assert(strcmp(info.name, "b_iUwOsqRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "c_UPNtkpHH", &info) => 0;
assert(strcmp(info.name, "c_UPNtkpHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "d_jKLUSLJH", &info) => 0;
assert(strcmp(info.name, "d_jKLUSLJH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "e_VNunKMPH", &info) => 0;
assert(strcmp(info.name, "e_VNunKMPH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "f_vknsvNRH", &info) => 0;
assert(strcmp(info.name, "f_vknsvNRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "a_IplRNrPH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "b_iUwOsqRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "c_UPNtkpHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "d_jKLUSLJH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "e_VNunKMPH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "f_vknsvNRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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.test_dirs_did_ones]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, 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);
// check if dirs exist before mkconsistent
struct lfs_info info;
err = lfsr_stat(&lfs, "a_iomlVKPH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfsr_stat(&lfs, "b_IJvqkHRH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
err = lfsr_stat(&lfs, "c_uOOJsIHH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool c_exists = !err;
err = lfsr_stat(&lfs, "d_JTMkKuJH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool d_exists = !err;
err = lfsr_stat(&lfs, "e_vQtPStPH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool e_exists = !err;
err = lfsr_stat(&lfs, "f_VtoMnwRH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool f_exists = !err;
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "a_iomlVKPH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (b_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "b_IJvqkHRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (c_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "c_uOOJsIHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (d_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "d_JTMkKuJH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (e_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "e_vQtPStPH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (f_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "f_VtoMnwRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// make directories
err = lfsr_mkdir(&lfs, "a_iomlVKPH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == a_exists);
err = lfsr_mkdir(&lfs, "b_IJvqkHRH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == b_exists);
err = lfsr_mkdir(&lfs, "c_uOOJsIHH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == c_exists);
err = lfsr_mkdir(&lfs, "d_JTMkKuJH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == d_exists);
err = lfsr_mkdir(&lfs, "e_vQtPStPH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == e_exists);
err = lfsr_mkdir(&lfs, "f_VtoMnwRH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == f_exists);
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[0] == 0);
// check that our mkdirs worked
lfsr_stat(&lfs, "a_iomlVKPH", &info) => 0;
assert(strcmp(info.name, "a_iomlVKPH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "b_IJvqkHRH", &info) => 0;
assert(strcmp(info.name, "b_IJvqkHRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "c_uOOJsIHH", &info) => 0;
assert(strcmp(info.name, "c_uOOJsIHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "d_JTMkKuJH", &info) => 0;
assert(strcmp(info.name, "d_JTMkKuJH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "e_vQtPStPH", &info) => 0;
assert(strcmp(info.name, "e_vQtPStPH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "f_VtoMnwRH", &info) => 0;
assert(strcmp(info.name, "f_VtoMnwRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "a_iomlVKPH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "b_IJvqkHRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "c_uOOJsIHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "d_JTMkKuJH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "e_vQtPStPH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "f_VtoMnwRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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.test_dirs_did_leb128_boundaries]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// make a directory
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 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);
assert(info.size == 0);
// 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// and remove the directory
lfsr_remove(&lfs, "ardvark") => 0;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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.test_dirs_rm_noent]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// make a directory
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && 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;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[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);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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.test_dirs_rm_notempty]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// make a directory
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// fill it with stuff
err = lfsr_mkdir(&lfs, "ardvark/banana");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// try to remove the parent directory
lfsr_remove(&lfs, "ardvark") => LFS_ERR_NOTEMPTY;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[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);
assert(info.size == 0);
lfsr_stat(&lfs, "ardvark/banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
lfsr_unmount(&lfs) => 0;
'''
# test that dir existance is the same before/after mkconsistent
[cases.test_dirs_rm_consistent]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// check if dir exists before mkconsistent
struct lfs_info info;
err = lfsr_stat(&lfs, "ardvark", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool exists = !err;
// 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// make a directory
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == exists);
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// check that our mkdir worked with stat
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
// 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// and remove the directory
lfsr_remove(&lfs, "ardvark") => 0;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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.test_dirs_rm_root]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, 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_PLS && 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);
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[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);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_rm_siblings]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// check if dirs exist before mkconsistent
struct lfs_info info;
err = lfsr_stat(&lfs, "ardvark", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfsr_stat(&lfs, "banana", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
err = lfsr_stat(&lfs, "cat", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool c_exists = !err;
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (b_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (c_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// make some directories
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == a_exists);
err = lfsr_mkdir(&lfs, "banana");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == b_exists);
err = lfsr_mkdir(&lfs, "cat");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == c_exists);
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// check that our mkdir worked
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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, LFS_M_RDWR, CFG) => 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);
assert(info.size == 0);
lfsr_stat(&lfs, "cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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, LFS_M_RDWR, CFG) => 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);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// remove another
lfsr_remove(&lfs, "cat") => 0;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_rm_children]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// check if dirs exist before mkconsistent
struct lfs_info info;
err = lfsr_stat(&lfs, "ardvark", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfsr_stat(&lfs, "ardvark/banana", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
err = lfsr_stat(&lfs, "ardvark/banana/cat", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool c_exists = !err;
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
err = lfsr_dir_open(&lfs, &dir, "/ardvark");
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
assert(!err == a_exists);
if (a_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (b_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
err = lfsr_dir_open(&lfs, &dir, "/ardvark/banana");
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
assert(!err == b_exists);
if (b_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (c_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
// make some directories
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == a_exists);
err = lfsr_mkdir(&lfs, "ardvark/banana");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == b_exists);
err = lfsr_mkdir(&lfs, "ardvark/banana/cat");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == c_exists);
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// check that our mkdirs worked
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "ardvark/banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "ardvark/banana/cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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, LFS_M_RDWR, CFG) => 0;
}
// check that our remove worked
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "ardvark/banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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, LFS_M_RDWR, CFG) => 0;
}
// check that our remove worked
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// remove another
lfsr_remove(&lfs, "ardvark") => 0;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_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_PLS || N <= 16',
]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// make this many directories
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// check that our mkdir worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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%03x", i);
lfsr_remove(&lfs, name) => 0;
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[0] == 0);
// check that our removes worked
for (lfs_size_t i = 0; i < N-REMAINING; i++) {
char name[256];
sprintf(name, "dir%03x", 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%03x", (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);
assert(info.size == 0);
}
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < REMAINING; i++) {
char name[256];
sprintf(name, "dir%03x", (int)(N-REMAINING + i));
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_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_PLS || N <= 16',
]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// make this many directories
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", (int)(N-1-i));
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// check that our mkdir worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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%03x", (int)(N-1-i));
lfsr_remove(&lfs, name) => 0;
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[0] == 0);
// check that our removes worked
for (lfs_size_t i = 0; i < N-REMAINING; i++) {
char name[256];
sprintf(name, "dir%03x", (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%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < REMAINING; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_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_PLS || N <= 4',
# TODO fix this case, it's failing because a mkdir is lining up with an
# mdir split, and the chosen split name makes it so our did should have
# ended up in the previous mdir
'!(TEST_PLS && N == 4)',
]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// make this many directories
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// containing this many directories
for (lfs_size_t j = 0; j < N; j++) {
sprintf(name, "dir%03x/child%03x", i, j);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
}
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// check that our mkdirs worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
sprintf(name, "child%03x", j);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
}
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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%03x", 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "child%03x", j);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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%03x/child%03x", i, j);
lfsr_remove(&lfs, name) => 0;
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
}
if (i < N-REMAINING) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_remove(&lfs, name) => 0;
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[0] == 0);
// check that our removes worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", 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);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", 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%03x", j);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
}
}
}
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < REMAINING; i++) {
char name[256];
sprintf(name, "dir%03x", (int)(N-REMAINING + i));
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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%03x", (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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < REMAINING; j++) {
char name[256];
sprintf(name, "child%03x", (int)(N-REMAINING + j));
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_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_PLS || N <= 2',
]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// make this many directories
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// containing this many directories
for (lfs_size_t j = 0; j < N; j++) {
sprintf(name, "dir%03x/child%03x", i, j);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// containing this many directories
for (lfs_size_t k = 0; k < N; k++) {
sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
}
}
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// check that our mkdirs worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
sprintf(name, "child%03x", j);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t k = 0; k < N; k++) {
char name[256];
sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
sprintf(name, "grandchild%03x", k);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
}
}
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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%03x", 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "child%03x", j);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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%03x/child%03x", 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t k = 0; k < N; k++) {
char name[256];
sprintf(name, "grandchild%03x", k);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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%03x/child%03x/grandchild%03x", i, j, k);
lfsr_remove(&lfs, name) => 0;
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
}
if (i < N-REMAINING || j < N-REMAINING) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
lfsr_remove(&lfs, name) => 0;
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
}
if (i < N-REMAINING) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_remove(&lfs, name) => 0;
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[0] == 0);
// check that our removes worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", 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);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", 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%03x", j);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t k = 0; k < N; k++) {
char name[256];
sprintf(name, "dir%03x/child%03x/grandchild%03x",
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%03x", k);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
}
}
}
}
}
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < REMAINING; i++) {
char name[256];
sprintf(name, "dir%03x", (int)(N-REMAINING + i));
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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%03x", (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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < REMAINING; j++) {
char name[256];
sprintf(name, "child%03x", (int)(N-REMAINING + j));
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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%03x/child%03x",
(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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t k = 0; k < REMAINING; k++) {
char name[256];
sprintf(name, "grandchild%03x", (int)(N-REMAINING + k));
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
}
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_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_PLS || N <= 16',
]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, 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%03x", i);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 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%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
char name2[256];
sprintf(name2, "dir%03x", i);
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
memset(name, 0, sizeof(name));
for (lfs_size_t i = 0; i < N; i++) {
sprintf(&name[strlen(name)], "/dir%03x", 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (i < N-1) {
char name2[256];
sprintf(name2, "dir%03x", i+1);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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, LFS_M_RDWR, CFG) => 0;
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[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%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
char name2[256];
sprintf(name2, "dir%03x", i);
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
memset(name, 0, sizeof(name));
for (lfs_size_t i = 0; i < REMAINING; i++) {
sprintf(&name[strlen(name)], "/dir%03x", 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (i < REMAINING-1) {
char name2[256];
sprintf(name2, "dir%03x", i+1);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_rm_fuzz]
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256]
# do more ops than dirs to encourage rename collisions
defines.OPS = '2*N'
defines.PARENT = [false, true]
defines.SEED = 'range(20)'
fuzz = 'SEED'
# limit powerloss testing due to time
if = '!TEST_PLS || N <= 8'
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
if (PARENT) {
err = lfsr_mkdir(&lfs, "pricklypear");
assert(!err || (TEST_PLS && 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 < OPS; 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
lfs_size_t x = TEST_PRNG(&prng) % N;
// 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%03x", ((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%03x", ((PARENT) ? "pricklypear" : ""), x);
lfsr_remove(&lfs, name) => 0;
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[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%03x",
((PARENT) ? "pricklypear" : ""),
sim[j]);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
char name2[256];
sprintf(name2, "dir%03x", sim[j]);
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < sim_size; j++) {
char name[256];
sprintf(name, "dir%03x", sim[j]);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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.test_dirs_mv]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// make a directory
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// clean up interrupted renames
if (TEST_PLS) {
err = lfsr_remove(&lfs, "banana");
assert(!err || err == LFS_ERR_NOENT);
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 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);
assert(info.size == 0);
// 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[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);
assert(info.size == 0);
// 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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.test_dirs_mv_replace]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// make directories
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
err = lfsr_mkdir(&lfs, "banana");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 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);
assert(info.size == 0);
// 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[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);
assert(info.size == 0);
// 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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.test_dirs_mv_noop]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// make directories
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 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);
assert(info.size == 0);
// 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[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);
assert(info.size == 0);
// 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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.test_dirs_mv_noent]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// make directories
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && 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;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[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);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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.test_dirs_mv_notempty]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// make directories
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
err = lfsr_mkdir(&lfs, "banana");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// fill dest with stuff
err = lfsr_mkdir(&lfs, "banana/cat");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// try to rename
lfsr_rename(&lfs, "ardvark", "banana") => LFS_ERR_NOTEMPTY;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[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);
assert(info.size == 0);
lfsr_stat(&lfs, "banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "banana/cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
lfsr_unmount(&lfs) => 0;
'''
# test that dir existance is the same before/after mkconsistent
[cases.test_dirs_mv_consistent]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// check if dirs exist before mkconsistent
struct lfs_info info;
err = lfsr_stat(&lfs, "ardvark", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfsr_stat(&lfs, "banana", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
// 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (b_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// make a directory
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == a_exists);
// clean up interrupted renames
if (TEST_PLS) {
err = lfsr_remove(&lfs, "banana");
assert(!err || err == LFS_ERR_NOENT);
assert(!err == b_exists);
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// check that our mkdir worked with stat
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
// 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[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);
assert(info.size == 0);
// 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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.test_dirs_mv_root]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, 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_PLS && err == LFS_ERR_EXIST));
// try to rename root, which doesn't really make sense
lfsr_rename(&lfs, "/", "notroot") => LFS_ERR_INVAL;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[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);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_mv_siblings]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// check if dirs exist before mkconsistent
struct lfs_info info;
err = lfsr_stat(&lfs, "ardvark", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfsr_stat(&lfs, "banana", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
err = lfsr_stat(&lfs, "cat", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool c_exists = !err;
err = lfsr_stat(&lfs, "disco", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool d_exists = !err;
err = lfsr_stat(&lfs, "eggplant", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool e_exists = !err;
err = lfsr_stat(&lfs, "fish", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool f_exists = !err;
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (b_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (c_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (d_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (e_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "eggplant") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (f_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "fish") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// make some directories
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == a_exists);
err = lfsr_mkdir(&lfs, "banana");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == b_exists);
err = lfsr_mkdir(&lfs, "cat");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == c_exists);
// clean up interrupted renames
if (TEST_PLS) {
err = lfsr_remove(&lfs, "disco");
assert(!err || err == LFS_ERR_NOENT);
assert(!err == d_exists);
err = lfsr_remove(&lfs, "eggplant");
assert(!err || err == LFS_ERR_NOENT);
assert(!err == e_exists);
err = lfsr_remove(&lfs, "fish");
assert(!err || err == LFS_ERR_NOENT);
assert(!err == f_exists);
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// check that our mkdir worked
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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, LFS_M_RDWR, CFG) => 0;
}
// check that our rename worked
lfsr_stat(&lfs, "banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "disco", &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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, LFS_M_RDWR, CFG) => 0;
}
// check that our rename worked
lfsr_stat(&lfs, "cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "disco", &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "eggplant", &info) => 0;
assert(strcmp(info.name, "eggplant") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "eggplant") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// rename another
lfsr_rename(&lfs, "cat", "fish") => 0;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[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);
assert(info.size == 0);
lfsr_stat(&lfs, "eggplant", &info) => 0;
assert(strcmp(info.name, "eggplant") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "fish", &info) => 0;
assert(strcmp(info.name, "fish") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "eggplant") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "fish") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_mv_children]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// check if dirs exist before mkconsistent
struct lfs_info info;
err = lfsr_stat(&lfs, "ardvark", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfsr_stat(&lfs, "ardvark/banana", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
err = lfsr_stat(&lfs, "ardvark/banana/cat", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool c_exists = !err;
err = lfsr_stat(&lfs, "disco", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool d_exists = !err;
err = lfsr_stat(&lfs, "disco/eggplant", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool e_exists = !err;
err = lfsr_stat(&lfs, "disco/eggplant/fish", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool f_exists = !err;
err = lfsr_stat(&lfs, "disco/banana", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool db_exists = !err;
err = lfsr_stat(&lfs, "disco/banana/cat", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool dbc_exists = !err;
err = lfsr_stat(&lfs, "disco/eggplant/cat", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool dec_exists = !err;
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (d_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
err = lfsr_dir_open(&lfs, &dir, "/ardvark");
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
assert(!err == a_exists);
if (a_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (b_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
err = lfsr_dir_open(&lfs, &dir, "/ardvark/banana");
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
assert(!err == b_exists);
if (b_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (c_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
err = lfsr_dir_open(&lfs, &dir, "/disco");
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
assert(!err == d_exists);
if (d_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (db_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (e_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "eggplant") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
err = lfsr_dir_open(&lfs, &dir, "/disco/eggplant");
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
assert(!err == e_exists);
if (e_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (dec_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (f_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "fish") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
// make some directories
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == a_exists);
err = lfsr_mkdir(&lfs, "ardvark/banana");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == b_exists);
err = lfsr_mkdir(&lfs, "ardvark/banana/cat");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == c_exists);
// clean up interrupted renames
if (TEST_PLS) {
err = lfsr_remove(&lfs, "disco/eggplant/fish");
assert(!err || err == LFS_ERR_NOENT);
assert(!err == f_exists);
err = lfsr_remove(&lfs, "disco/eggplant/cat");
assert(!err || err == LFS_ERR_NOENT);
assert(!err == dec_exists);
err = lfsr_remove(&lfs, "disco/eggplant");
assert(!err || err == LFS_ERR_NOENT);
assert(!err == e_exists);
err = lfsr_remove(&lfs, "disco/banana/cat");
assert(!err || err == LFS_ERR_NOENT);
assert(!err == dbc_exists);
err = lfsr_remove(&lfs, "disco/banana");
assert(!err || err == LFS_ERR_NOENT);
assert(!err == db_exists);
err = lfsr_remove(&lfs, "disco");
assert(!err || err == LFS_ERR_NOENT);
assert(!err == d_exists);
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// check that our mkdirs worked
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "ardvark/banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "ardvark/banana/cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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, LFS_M_RDWR, CFG) => 0;
}
// check that our rename worked
lfsr_stat(&lfs, "disco", &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "disco/banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "disco/banana/cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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, LFS_M_RDWR, CFG) => 0;
}
// check that our rename worked
lfsr_stat(&lfs, "disco", &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "disco/eggplant", &info) => 0;
assert(strcmp(info.name, "eggplant") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "disco/eggplant/cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "eggplant") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[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);
assert(info.size == 0);
lfsr_stat(&lfs, "disco/eggplant", &info) => 0;
assert(strcmp(info.name, "eggplant") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "disco/eggplant/fish", &info) => 0;
assert(strcmp(info.name, "fish") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "eggplant") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "fish") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_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_PLS || N <= 16'
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// check if we have already started renaming, in case of powerloss
struct lfs_info info;
err = lfsr_stat(&lfs, ((BEFORE) ? "/0mved000" : "/mved000"), &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%03x", i);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// check that our mkdir worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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%03x", i);
char new_name[256];
sprintf(new_name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
int err = lfsr_rename(&lfs, old_name, new_name);
assert(!err || (TEST_PLS && err == LFS_ERR_NOENT));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[0] == 0);
// check that our renames worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "%smved%03x", ((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);
assert(info.size == 0);
}
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_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_PLS || N <= 16'
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// check if we have already started renaming, in case of powerloss
struct lfs_info info;
err = lfsr_stat(&lfs, ((BEFORE) ? "/0mved000" : "/mved000"), &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%03x", (int)(N-1-i));
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// check that our mkdir worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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%03x", i);
char new_name[256];
sprintf(new_name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
int err = lfsr_rename(&lfs, old_name, new_name);
assert(!err || (TEST_PLS && err == LFS_ERR_NOENT));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[0] == 0);
// check that our renames worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "%smved%03x", ((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);
assert(info.size == 0);
}
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_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_PLS || N <= 4'
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// check if we have already started renaming, in case of powerloss
struct lfs_info info;
err = lfsr_stat(&lfs, ((BEFORE) ? "/0mved000" : "/mved000"), &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%03x", i);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// containing this many directories
for (lfs_size_t j = 0; j < N; j++) {
sprintf(name, "dir%03x/child%03x", i, j);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
}
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// check that our mkdirs worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
sprintf(name, "child%03x", j);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
}
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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%03x", 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "child%03x", j);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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%03x", i);
char new_name[256];
sprintf(new_name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
int err = lfsr_rename(&lfs, old_name, new_name);
assert(!err || (TEST_PLS && err == LFS_ERR_NOENT));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
for (lfs_size_t j = 0; j < N; j++) {
char old_name[256];
sprintf(old_name, "%smved%03x/child%03x",
((BEFORE) ? "0" : ""), i, j);
char new_name[256];
sprintf(new_name, "%smved%03x/%schmved%03x",
((BEFORE) ? "0" : ""), i,
((BEFORE) ? "0" : ""), j);
int err = lfsr_rename(&lfs, old_name, new_name);
assert(!err || (TEST_PLS && err == LFS_ERR_NOENT));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[0] == 0);
// check that our renames worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "%smved%03x", ((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);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "%smved%03x/%schmved%03x",
((BEFORE) ? "0" : ""), i, ((BEFORE) ? "0" : ""), j);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
sprintf(name, "%schmved%03x", ((BEFORE) ? "0" : ""), j);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
}
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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%03x", ((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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "%schmved%03x", ((BEFORE) ? "0" : ""), j);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_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_PLS || N <= 2'
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// check if we have already started renaming, in case of powerloss
struct lfs_info info;
err = lfsr_stat(&lfs, ((BEFORE) ? "/0mved000" : "/mved000"), &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%03x", i);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// containing this many directories
for (lfs_size_t j = 0; j < N; j++) {
sprintf(name, "dir%03x/child%03x", i, j);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// containing this many directories
for (lfs_size_t k = 0; k < N; k++) {
sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
}
}
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// check that our mkdirs worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
sprintf(name, "child%03x", j);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t k = 0; k < N; k++) {
char name[256];
sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
sprintf(name, "grandchild%03x", k);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
}
}
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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%03x", 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "child%03x", j);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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%03x/child%03x", 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t k = 0; k < N; k++) {
char name[256];
sprintf(name, "grandchild%03x", k);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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%03x", i);
char new_name[256];
sprintf(new_name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
int err = lfsr_rename(&lfs, old_name, new_name);
assert(!err || (TEST_PLS && err == LFS_ERR_NOENT));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
for (lfs_size_t j = 0; j < N; j++) {
char old_name[256];
sprintf(old_name, "%smved%03x/child%03x",
((BEFORE) ? "0" : ""), i, j);
char new_name[256];
sprintf(new_name, "%smved%03x/%schmved%03x",
((BEFORE) ? "0" : ""), i,
((BEFORE) ? "0" : ""), j);
int err = lfsr_rename(&lfs, old_name, new_name);
assert(!err || (TEST_PLS && err == LFS_ERR_NOENT));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
for (lfs_size_t k = 0; k < N; k++) {
char old_name[256];
sprintf(old_name, "%smved%03x/%schmved%03x/grandchild%03x",
((BEFORE) ? "0" : ""), i,
((BEFORE) ? "0" : ""), j, k);
char new_name[256];
sprintf(new_name, "%smved%03x/%schmved%03x/%sgrmved%03x",
((BEFORE) ? "0" : ""), i,
((BEFORE) ? "0" : ""), j,
((BEFORE) ? "0" : ""), k);
int err = lfsr_rename(&lfs, old_name, new_name);
assert(!err || (TEST_PLS && err == LFS_ERR_NOENT));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
}
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[0] == 0);
// check that our removes worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "%smved%03x", ((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);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "%smved%03x/%schmved%03x",
((BEFORE) ? "0" : ""), i,
((BEFORE) ? "0" : ""), j);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
sprintf(name, "%schmved%03x", ((BEFORE) ? "0" : ""), j);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t k = 0; k < N; k++) {
char name[256];
sprintf(name, "%smved%03x/%schmved%03x/%sgrmved%03x",
((BEFORE) ? "0" : ""), i,
((BEFORE) ? "0" : ""), j,
((BEFORE) ? "0" : ""), k);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
sprintf(name, "%sgrmved%03x", ((BEFORE) ? "0" : ""), k);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
}
}
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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%03x", ((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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "%schmved%03x", ((BEFORE) ? "0" : ""), j);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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%03x/%schmved%03x",
((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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t k = 0; k < N; k++) {
char name[256];
sprintf(name, "%sgrmved%03x", ((BEFORE) ? "0" : ""), k);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
}
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_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_PLS || N <= 16'
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// check if we have already started renaming, in case of powerloss
struct lfs_info info;
err = lfsr_stat(&lfs, ((BEFORE) ? "/0mved000" : "/mved000"), &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%03x", i);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 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%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
char name2[256];
sprintf(name2, "dir%03x", i);
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
memset(name, 0, sizeof(name));
for (lfs_size_t i = 0; i < N; i++) {
sprintf(&name[strlen(name)], "/dir%03x", 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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (i < N-1) {
char name2[256];
sprintf(name2, "dir%03x", i+1);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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%03x", i);
sprintf(&new_name[strlen(new_name)], "/%smved%03x",
((BEFORE) ? "0" : ""), i);
err = lfsr_rename(&lfs, old_name, new_name);
assert(!err || (TEST_PLS && err == LFS_ERR_NOENT));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// update old_name's path
memcpy(old_name, new_name, sizeof(old_name));
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[0] == 0);
// 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%03x",
((BEFORE) ? "0" : ""),
i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
char name2[256];
sprintf(name2, "%smved%03x", ((BEFORE) ? "0" : ""), i);
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
memset(name, 0, sizeof(name));
for (lfs_size_t i = 0; i < N; i++) {
sprintf(&name[strlen(name)], "/%smved%03x",
((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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (i < N-1) {
char name2[256];
sprintf(name2, "%smved%03x", ((BEFORE) ? "0" : ""), i+1);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_mv_fuzz]
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256]
# do more ops than dirs to encourage rename collisions
defines.OPS = '2*N'
defines.PARENT = [false, true]
defines.SEED = 'range(20)'
fuzz = 'SEED'
# limit powerloss testing due to time
if = '!TEST_PLS || N <= 8'
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
if (PARENT) {
err = lfsr_mkdir(&lfs, "pricklypear");
assert(!err || (TEST_PLS && 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 < OPS; 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
lfs_size_t x = TEST_PRNG(&prng) % N;
// 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%03x", ((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) % N;
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%03x", ((PARENT) ? "pricklypear" : ""), x);
char new_name[256];
sprintf(new_name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), y);
lfsr_rename(&lfs, old_name, new_name) => 0;
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[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%03x",
((PARENT) ? "pricklypear" : ""),
sim[j]);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
char name2[256];
sprintf(name2, "dir%03x", sim[j]);
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < sim_size; j++) {
char name[256];
sprintf(name, "dir%03x", sim[j]);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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.test_dirs_mvrm_fuzz]
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256]
# do more ops than dirs to encourage rename collisions
defines.OPS = '2*N'
defines.PARENT = [false, true]
defines.SEED = 'range(20)'
fuzz = 'SEED'
# limit powerloss testing due to time
if = '!TEST_PLS || N <= 8'
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, LFS_M_RDWR, CFG);
if (err) {
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
if (PARENT) {
err = lfsr_mkdir(&lfs, "pricklypear");
assert(!err || (TEST_PLS && 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 < OPS; 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
lfs_size_t x = TEST_PRNG(&prng) % N;
// 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%03x", ((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%03x", ((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) % N;
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%03x", ((PARENT) ? "pricklypear" : ""), x);
char new_name[256];
sprintf(new_name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), y);
lfsr_rename(&lfs, old_name, new_name) => 0;
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs.grm_p[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%03x",
((PARENT) ? "pricklypear" : ""),
sim[j]);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
char name2[256];
sprintf(name2, "dir%03x", sim[j]);
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < sim_size; j++) {
char name[256];
sprintf(name, "dir%03x", sim[j]);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
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;
'''