Files
littlefs/tests/test_dirs.toml
Christopher Haster bc9562c64e tests: Accidentally found a couple buffer overruns
- Off-by-one in test_btree_find_general[_sparse]_fuzz

  Because we can only create named btrees via splitting, these always
  start with one entry. If all operations are randomly selected to be
  splits, this can lead to an overflow of the sim buffer (sounds
  unlikely, but relatively easily for small N).

  The fix is to use a `for (lfs3_size_t i = 1; i < N; i++)` loop to
  account for the initial entry. Note we already use this in the
  test_btree_split_* tests.

  An alternative is allocating space for N+1 entries, but this seems
  unintuitive with N usually being associated with the upper bound on
  btree size.

- Off-by-one in our sim rename pattern

  When renaming, we don't bother to update sim_size, because after the
  rename the sim_size size will be unchanged. But this means the
  sim_size is out-of-date during the memmove that reinserts the renamed
  entry. Buffer overflow!

  To fix we just need to use sim_size-1 to account for the temporarily
  deleted entry.

  This is messy C code, so not surprised it went unnoticed, even though
  this pattern ended up in quite a few tests.

Found while running with HEAP=1. This was just intended to test HEAP=1,
but I guess the injected heap hooks result in a more fragile heap? They
increase all allocations by one word, and maybe this reduces alignment
padding? Not exactly sure.

But it's a good argument for maybe adding heap canaries in the future.
Previously we ran Valgrind on all tests, but it's unclear if this will
still be reasonable with the number of tests we have now.
2026-02-19 12:39:20 -06:00

6955 lines
240 KiB
TOML

# Test directory operations
after = 'test_mtree'
## mkdir tests
[cases.test_dirs_mkdir]
reentrant = true
code = '''
// format once per test
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// make a directory
err = lfs3_mkdir(&lfs3, "ardvark");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that our mkdir worked with stat
struct lfs3_info info;
lfs3_stat(&lfs3, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
// and with dir_read
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
lfs3_dir_open(&lfs3, &dir, "ardvark") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 0;
'''
# test that noent errors work
[cases.test_dirs_noent]
code = '''
lfs3_t lfs3;
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
// make a directory
lfs3_mkdir(&lfs3, "ardvark") => 0;
// try to read a nonsense path
struct lfs3_info info;
lfs3_stat(&lfs3, "no", &info) => LFS3_ERR_NOENT;
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "no") => LFS3_ERR_NOENT;
lfs3_unmount(&lfs3) => 0;
'''
# test that stat on root works
[cases.test_dirs_stat_root]
code = '''
lfs3_t lfs3;
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
// make a directory
lfs3_mkdir(&lfs3, "ardvark") => 0;
// stat the root
struct lfs3_info info;
lfs3_stat(&lfs3, "/", &info) => 0;
assert(strcmp(info.name, "/") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_unmount(&lfs3) => 0;
'''
# test that creating the same directory twice errors
[cases.test_dirs_mkdir_exists]
reentrant = true
code = '''
// format once per test
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// make a directory
err = lfs3_mkdir(&lfs3, "ardvark");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
// make the same directory, should error
lfs3_mkdir(&lfs3, "ardvark") => LFS3_ERR_EXIST;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// and check that this didn't interfere with our original directory
struct lfs3_info info;
lfs3_stat(&lfs3, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
lfs3_dir_open(&lfs3, &dir, "ardvark") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 0;
'''
# test that dir existance is the same before/after mkconsistent
[cases.test_dirs_mkdir_consistent]
reentrant = true
code = '''
// format once per test
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check if dir exists before mkconsistent
struct lfs3_info info;
err = lfs3_stat(&lfs3, "ardvark", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool exists = !err;
// and with dir_read
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
if (exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
// make a directory
err = lfs3_mkdir(&lfs3, "ardvark");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == exists);
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that our mkdir worked with stat
lfs3_stat(&lfs3, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
// and with dir_read
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
lfs3_dir_open(&lfs3, &dir, "ardvark") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 0;
'''
# test what happens if we try to make root
[cases.test_dirs_mkdir_root]
reentrant = true
code = '''
// format once per test
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// try to make root, which doesn't make sense
lfs3_mkdir(&lfs3, "/") => LFS3_ERR_EXIST;
// make a directory
err = lfs3_mkdir(&lfs3, "ardvark");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
// try to make root, which doesn't make sense
lfs3_mkdir(&lfs3, "/") => LFS3_ERR_EXIST;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// and check that this didn't interfere with our original directory
struct lfs3_info info;
lfs3_stat(&lfs3, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
lfs3_dir_open(&lfs3, &dir, "ardvark") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 0;
'''
# test that creating a directory with an invalid path errors
[cases.test_dirs_mkdir_noent]
reentrant = true
code = '''
// format once per test
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// make a directory
err = lfs3_mkdir(&lfs3, "ardvark");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
// make a nonsense directory, should error
lfs3_mkdir(&lfs3, "no/hmm") => LFS3_ERR_NOENT;
// make a nonsense child directory, should error
lfs3_mkdir(&lfs3, "ardvark/no/hmm") => LFS3_ERR_NOENT;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// and check that this didn't interfere with our original directory
struct lfs3_info info;
lfs3_stat(&lfs3, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
lfs3_dir_open(&lfs3, &dir, "ardvark") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 0;
'''
[cases.test_dirs_mkdir_siblings]
reentrant = true
code = '''
// format once per test
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check if dirs exist before mkconsistent
struct lfs3_info info;
err = lfs3_stat(&lfs3, "ardvark", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfs3_stat(&lfs3, "banana", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
err = lfs3_stat(&lfs3, "cat", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool c_exists = !err;
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
if (b_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
if (c_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
// make some directories
err = lfs3_mkdir(&lfs3, "ardvark");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == a_exists);
err = lfs3_mkdir(&lfs3, "banana");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == b_exists);
err = lfs3_mkdir(&lfs3, "cat");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == c_exists);
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that our mkdir worked
lfs3_stat(&lfs3, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
lfs3_dir_open(&lfs3, &dir, "ardvark") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
lfs3_dir_open(&lfs3, &dir, "banana") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
lfs3_dir_open(&lfs3, &dir, "cat") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 0;
'''
[cases.test_dirs_mkdir_children]
reentrant = true
code = '''
// format once per test
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check if dirs exist before mkconsistent
struct lfs3_info info;
err = lfs3_stat(&lfs3, "ardvark", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfs3_stat(&lfs3, "ardvark/banana", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
err = lfs3_stat(&lfs3, "ardvark/banana/cat", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool c_exists = !err;
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
err = lfs3_dir_open(&lfs3, &dir, "/ardvark");
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
assert(!err == a_exists);
if (a_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
if (b_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
err = lfs3_dir_open(&lfs3, &dir, "/ardvark/banana");
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
assert(!err == b_exists);
if (b_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
if (c_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
// make some directories
err = lfs3_mkdir(&lfs3, "ardvark");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == a_exists);
err = lfs3_mkdir(&lfs3, "ardvark/banana");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == b_exists);
err = lfs3_mkdir(&lfs3, "ardvark/banana/cat");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == c_exists);
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that our mkdirs worked
lfs3_stat(&lfs3, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "ardvark/banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "ardvark/banana/cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
lfs3_dir_open(&lfs3, &dir, "/ardvark") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
lfs3_dir_open(&lfs3, &dir, "/ardvark/banana") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
lfs3_dir_open(&lfs3, &dir, "/ardvark/banana/cat") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 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
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// make this many directories
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
err = lfs3_mkdir(&lfs3, name);
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that our mkdir worked
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
struct lfs3_info info;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfs3_dir_open(&lfs3, &dir, name) => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
}
lfs3_unmount(&lfs3) => 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
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// make this many directories
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", (int)(N-1-i));
err = lfs3_mkdir(&lfs3, name);
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that our mkdir worked
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
struct lfs3_info info;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfs3_dir_open(&lfs3, &dir, name) => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
}
lfs3_unmount(&lfs3) => 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
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// make this many directories
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
err = lfs3_mkdir(&lfs3, name);
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
// containing this many directories
for (lfs3_size_t j = 0; j < N; j++) {
sprintf(name, "dir%03x/child%03x", i, j);
err = lfs3_mkdir(&lfs3, name);
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that our mkdirs worked
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
sprintf(name, "child%03x", j);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
}
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
struct lfs3_info info;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfs3_dir_open(&lfs3, &dir, name) => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "child%03x", j);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
for (lfs3_size_t i = 0; i < N; i++) {
for (lfs3_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
lfs3_dir_open(&lfs3, &dir, name) => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
}
}
lfs3_unmount(&lfs3) => 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
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// make this many directories
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
err = lfs3_mkdir(&lfs3, name);
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
// containing this many directories
for (lfs3_size_t j = 0; j < N; j++) {
sprintf(name, "dir%03x/child%03x", i, j);
err = lfs3_mkdir(&lfs3, name);
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
// containing this many directories
for (lfs3_size_t k = 0; k < N; k++) {
sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k);
err = lfs3_mkdir(&lfs3, name);
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
}
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that our mkdirs worked
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
sprintf(name, "child%03x", j);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t k = 0; k < N; k++) {
char name[256];
sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
sprintf(name, "grandchild%03x", k);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
}
}
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
struct lfs3_info info;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfs3_dir_open(&lfs3, &dir, name) => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "child%03x", j);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
for (lfs3_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
lfs3_dir_open(&lfs3, &dir, name) => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t k = 0; k < N; k++) {
char name[256];
sprintf(name, "grandchild%03x", k);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
}
for (lfs3_size_t i = 0; i < N; i++) {
for (lfs3_size_t j = 0; j < N; j++) {
for (lfs3_size_t k = 0; k < N; k++) {
char name[256];
sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k);
lfs3_dir_open(&lfs3, &dir, name) => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
}
}
}
lfs3_unmount(&lfs3) => 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
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_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 (lfs3_size_t i = 0; i < N; i++) {
sprintf(&name[strlen(name)], "/dir%03x", i);
err = lfs3_mkdir(&lfs3, name);
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that our mkdir worked
memset(name, 0, sizeof(name));
for (lfs3_size_t i = 0; i < N; i++) {
sprintf(&name[strlen(name)], "/dir%03x", i);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
char name2[256];
sprintf(name2, "dir%03x", i);
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
memset(name, 0, sizeof(name));
for (lfs3_size_t i = 0; i < N; i++) {
sprintf(&name[strlen(name)], "/dir%03x", i);
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, name) => 0;
struct lfs3_info info;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
if (i < N-1) {
char name2[256];
sprintf(name2, "dir%03x", i+1);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
}
lfs3_unmount(&lfs3) => 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
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
if (PARENT) {
err = lfs3_mkdir(&lfs3, "pricklypear");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
}
// set up a simulation to compare against
lfs3_size_t *sim = malloc(N*sizeof(lfs3_size_t));
lfs3_size_t sim_size = 0;
uint32_t prng = SEED;
for (lfs3_size_t i = 0; i < OPS; i++) {
// choose a pseudo-random number
lfs3_size_t x = TEST_PRNG(&prng) % N;
// insert into our sim
for (lfs3_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(lfs3_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 = lfs3_mkdir(&lfs3, name);
assert(!err || err == LFS3_ERR_EXIST);
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// test that our directories match our simulation
for (lfs3_size_t j = 0; j < sim_size; j++) {
char name[256];
sprintf(name, "%s/dir%03x",
((PARENT) ? "pricklypear" : ""),
sim[j]);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
char name2[256];
sprintf(name2, "dir%03x", sim[j]);
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, ((PARENT) ? "pricklypear" : "/")) => 0;
struct lfs3_info info;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t j = 0; j < sim_size; j++) {
char name[256];
sprintf(name, "dir%03x", sim[j]);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
for (lfs3_size_t j = 0; j < sim_size; j++) {
char name[256];
sprintf(name, "%s/dir%03x",
((PARENT) ? "pricklypear" : ""),
sim[j]);
lfs3_dir_open(&lfs3, &dir, name) => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
}
// clean up sim/lfs3
free(sim);
lfs3_unmount(&lfs3) => 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 = '''
lfs3_t lfs3;
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
if (ORDER == 0) {
lfs3_mkdir(&lfs3, "a") => 0;
lfs3_mkdir(&lfs3, "b") => 0;
lfs3_mkdir(&lfs3, "c") => 0;
lfs3_mkdir(&lfs3, "d") => 0;
lfs3_mkdir(&lfs3, "e") => 0;
lfs3_mkdir(&lfs3, "f") => 0;
} else if (ORDER == 1) {
lfs3_mkdir(&lfs3, "f") => 0;
lfs3_mkdir(&lfs3, "e") => 0;
lfs3_mkdir(&lfs3, "d") => 0;
lfs3_mkdir(&lfs3, "c") => 0;
lfs3_mkdir(&lfs3, "b") => 0;
lfs3_mkdir(&lfs3, "a") => 0;
} else if (ORDER == 2) {
// "random", trust me
lfs3_mkdir(&lfs3, "e") => 0;
lfs3_mkdir(&lfs3, "c") => 0;
lfs3_mkdir(&lfs3, "b") => 0;
lfs3_mkdir(&lfs3, "d") => 0;
lfs3_mkdir(&lfs3, "f") => 0;
lfs3_mkdir(&lfs3, "a") => 0;
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that our mkdirs worked
struct lfs3_info info;
lfs3_stat(&lfs3, "a", &info) => 0;
assert(strcmp(info.name, "a") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "b", &info) => 0;
assert(strcmp(info.name, "b") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "c", &info) => 0;
assert(strcmp(info.name, "c") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "d", &info) => 0;
assert(strcmp(info.name, "d") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "e", &info) => 0;
assert(strcmp(info.name, "e") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "f", &info) => 0;
assert(strcmp(info.name, "f") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
// check the directory order
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "a") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "b") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "c") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "d") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "e") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "f") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 0;
'''
[cases.test_dirs_ordering_length]
# ORDER=0 => inorder
# ORDER=1 => reversed
# ORDER=2 => random
defines.ORDER = [0, 1, 2]
code = '''
lfs3_t lfs3;
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
if (ORDER == 0) {
lfs3_mkdir(&lfs3, "a") => 0;
lfs3_mkdir(&lfs3, "aa") => 0;
lfs3_mkdir(&lfs3, "aaa") => 0;
lfs3_mkdir(&lfs3, "aaaa") => 0;
lfs3_mkdir(&lfs3, "aaaaa") => 0;
lfs3_mkdir(&lfs3, "aaaaaa") => 0;
} else if (ORDER == 1) {
lfs3_mkdir(&lfs3, "aaaaaa") => 0;
lfs3_mkdir(&lfs3, "aaaaa") => 0;
lfs3_mkdir(&lfs3, "aaaa") => 0;
lfs3_mkdir(&lfs3, "aaa") => 0;
lfs3_mkdir(&lfs3, "aa") => 0;
lfs3_mkdir(&lfs3, "a") => 0;
} else if (ORDER == 2) {
// "random", trust me
lfs3_mkdir(&lfs3, "aaaaa") => 0;
lfs3_mkdir(&lfs3, "aaa") => 0;
lfs3_mkdir(&lfs3, "aa") => 0;
lfs3_mkdir(&lfs3, "aaaa") => 0;
lfs3_mkdir(&lfs3, "aaaaaa") => 0;
lfs3_mkdir(&lfs3, "a") => 0;
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that our mkdirs worked
struct lfs3_info info;
lfs3_stat(&lfs3, "a", &info) => 0;
assert(strcmp(info.name, "a") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "aa", &info) => 0;
assert(strcmp(info.name, "aa") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "aaa", &info) => 0;
assert(strcmp(info.name, "aaa") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "aaaa", &info) => 0;
assert(strcmp(info.name, "aaaa") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "aaaaa", &info) => 0;
assert(strcmp(info.name, "aaaaa") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "aaaaaa", &info) => 0;
assert(strcmp(info.name, "aaaaaa") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
// check the directory order
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "a") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "aa") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "aaa") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "aaaa") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "aaaaa") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "aaaaaa") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 0;
'''
# test that did collisions don't cause issues
[cases.test_dirs_did_collisions]
reentrant = true
code = '''
// format once per test
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
assert(lfs3_crc32c(0, "a_SNmwMTHH", 10) == 0x12345678);
assert(lfs3_crc32c(0, "b_skvjpWJH", 10) == 0x12345678);
assert(lfs3_crc32c(0, "c_OnOQhVPH", 10) == 0x12345678);
assert(lfs3_crc32c(0, "d_puMpPjRH", 10) == 0x12345678);
assert(lfs3_crc32c(0, "e_LptKHkHH", 10) == 0x12345678);
assert(lfs3_crc32c(0, "f_lUoVuhJH", 10) == 0x12345678);
// check if dirs exist before mkconsistent
struct lfs3_info info;
err = lfs3_stat(&lfs3, "a_SNmwMTHH", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfs3_stat(&lfs3, "b_skvjpWJH", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
err = lfs3_stat(&lfs3, "c_OnOQhVPH", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool c_exists = !err;
err = lfs3_stat(&lfs3, "d_puMpPjRH", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool d_exists = !err;
err = lfs3_stat(&lfs3, "e_LptKHkHH", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool e_exists = !err;
err = lfs3_stat(&lfs3, "f_lUoVuhJH", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool f_exists = !err;
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "a_SNmwMTHH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
if (b_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "b_skvjpWJH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
if (c_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "c_OnOQhVPH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
if (d_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "d_puMpPjRH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
if (e_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "e_LptKHkHH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
if (f_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "f_lUoVuhJH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
// make directories
err = lfs3_mkdir(&lfs3, "a_SNmwMTHH");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == a_exists);
err = lfs3_mkdir(&lfs3, "b_skvjpWJH");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == b_exists);
err = lfs3_mkdir(&lfs3, "c_OnOQhVPH");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == c_exists);
err = lfs3_mkdir(&lfs3, "d_puMpPjRH");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == d_exists);
err = lfs3_mkdir(&lfs3, "e_LptKHkHH");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == e_exists);
err = lfs3_mkdir(&lfs3, "f_lUoVuhJH");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == f_exists);
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that our mkdirs worked
lfs3_stat(&lfs3, "a_SNmwMTHH", &info) => 0;
assert(strcmp(info.name, "a_SNmwMTHH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "b_skvjpWJH", &info) => 0;
assert(strcmp(info.name, "b_skvjpWJH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "c_OnOQhVPH", &info) => 0;
assert(strcmp(info.name, "c_OnOQhVPH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "d_puMpPjRH", &info) => 0;
assert(strcmp(info.name, "d_puMpPjRH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "e_LptKHkHH", &info) => 0;
assert(strcmp(info.name, "e_LptKHkHH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "f_lUoVuhJH", &info) => 0;
assert(strcmp(info.name, "f_lUoVuhJH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "a_SNmwMTHH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "b_skvjpWJH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "c_OnOQhVPH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "d_puMpPjRH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "e_LptKHkHH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "f_lUoVuhJH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 0;
'''
# these will also collide with the root
[cases.test_dirs_did_zero]
reentrant = true
code = '''
// format once per test
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
assert(lfs3_crc32c(0, "a_IplRNrPH", 10) == 0x00000000);
assert(lfs3_crc32c(0, "b_iUwOsqRH", 10) == 0x00000000);
assert(lfs3_crc32c(0, "c_UPNtkpHH", 10) == 0x00000000);
assert(lfs3_crc32c(0, "d_jKLUSLJH", 10) == 0x00000000);
assert(lfs3_crc32c(0, "e_VNunKMPH", 10) == 0x00000000);
assert(lfs3_crc32c(0, "f_vknsvNRH", 10) == 0x00000000);
// check if dirs exist before mkconsistent
struct lfs3_info info;
err = lfs3_stat(&lfs3, "a_IplRNrPH", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfs3_stat(&lfs3, "b_iUwOsqRH", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
err = lfs3_stat(&lfs3, "c_UPNtkpHH", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool c_exists = !err;
err = lfs3_stat(&lfs3, "d_jKLUSLJH", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool d_exists = !err;
err = lfs3_stat(&lfs3, "e_VNunKMPH", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool e_exists = !err;
err = lfs3_stat(&lfs3, "f_vknsvNRH", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool f_exists = !err;
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "a_IplRNrPH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
if (b_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "b_iUwOsqRH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
if (c_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "c_UPNtkpHH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
if (d_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "d_jKLUSLJH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
if (e_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "e_VNunKMPH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
if (f_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "f_vknsvNRH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
// make directories
err = lfs3_mkdir(&lfs3, "a_IplRNrPH");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == a_exists);
err = lfs3_mkdir(&lfs3, "b_iUwOsqRH");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == b_exists);
err = lfs3_mkdir(&lfs3, "c_UPNtkpHH");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == c_exists);
err = lfs3_mkdir(&lfs3, "d_jKLUSLJH");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == d_exists);
err = lfs3_mkdir(&lfs3, "e_VNunKMPH");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == e_exists);
err = lfs3_mkdir(&lfs3, "f_vknsvNRH");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == f_exists);
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that our mkdirs worked
lfs3_stat(&lfs3, "a_IplRNrPH", &info) => 0;
assert(strcmp(info.name, "a_IplRNrPH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "b_iUwOsqRH", &info) => 0;
assert(strcmp(info.name, "b_iUwOsqRH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "c_UPNtkpHH", &info) => 0;
assert(strcmp(info.name, "c_UPNtkpHH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "d_jKLUSLJH", &info) => 0;
assert(strcmp(info.name, "d_jKLUSLJH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "e_VNunKMPH", &info) => 0;
assert(strcmp(info.name, "e_VNunKMPH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "f_vknsvNRH", &info) => 0;
assert(strcmp(info.name, "f_vknsvNRH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "a_IplRNrPH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "b_iUwOsqRH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "c_UPNtkpHH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "d_jKLUSLJH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "e_VNunKMPH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "f_vknsvNRH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 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
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
assert(lfs3_crc32c(0, "a_iomlVKPH", 10) == 0xffffffff);
assert(lfs3_crc32c(0, "b_IJvqkHRH", 10) == 0xffffffff);
assert(lfs3_crc32c(0, "c_uOOJsIHH", 10) == 0xffffffff);
assert(lfs3_crc32c(0, "d_JTMkKuJH", 10) == 0xffffffff);
assert(lfs3_crc32c(0, "e_vQtPStPH", 10) == 0xffffffff);
assert(lfs3_crc32c(0, "f_VtoMnwRH", 10) == 0xffffffff);
// check if dirs exist before mkconsistent
struct lfs3_info info;
err = lfs3_stat(&lfs3, "a_iomlVKPH", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfs3_stat(&lfs3, "b_IJvqkHRH", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
err = lfs3_stat(&lfs3, "c_uOOJsIHH", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool c_exists = !err;
err = lfs3_stat(&lfs3, "d_JTMkKuJH", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool d_exists = !err;
err = lfs3_stat(&lfs3, "e_vQtPStPH", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool e_exists = !err;
err = lfs3_stat(&lfs3, "f_VtoMnwRH", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool f_exists = !err;
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "a_iomlVKPH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
if (b_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "b_IJvqkHRH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
if (c_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "c_uOOJsIHH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
if (d_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "d_JTMkKuJH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
if (e_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "e_vQtPStPH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
if (f_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "f_VtoMnwRH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
// make directories
err = lfs3_mkdir(&lfs3, "a_iomlVKPH");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == a_exists);
err = lfs3_mkdir(&lfs3, "b_IJvqkHRH");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == b_exists);
err = lfs3_mkdir(&lfs3, "c_uOOJsIHH");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == c_exists);
err = lfs3_mkdir(&lfs3, "d_JTMkKuJH");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == d_exists);
err = lfs3_mkdir(&lfs3, "e_vQtPStPH");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == e_exists);
err = lfs3_mkdir(&lfs3, "f_VtoMnwRH");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == f_exists);
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that our mkdirs worked
lfs3_stat(&lfs3, "a_iomlVKPH", &info) => 0;
assert(strcmp(info.name, "a_iomlVKPH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "b_IJvqkHRH", &info) => 0;
assert(strcmp(info.name, "b_IJvqkHRH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "c_uOOJsIHH", &info) => 0;
assert(strcmp(info.name, "c_uOOJsIHH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "d_JTMkKuJH", &info) => 0;
assert(strcmp(info.name, "d_JTMkKuJH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "e_vQtPStPH", &info) => 0;
assert(strcmp(info.name, "e_vQtPStPH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "f_VtoMnwRH", &info) => 0;
assert(strcmp(info.name, "f_VtoMnwRH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "a_iomlVKPH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "b_IJvqkHRH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "c_uOOJsIHH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "d_JTMkKuJH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "e_vQtPStPH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "f_VtoMnwRH") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 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
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// make a directory
err = lfs3_mkdir(&lfs3, "ardvark");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check that our mkdir worked with stat
struct lfs3_info info;
lfs3_stat(&lfs3, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
// and with dir_read
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
// and remove the directory
lfs3_remove(&lfs3, "ardvark") => 0;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that remove worked with stat
lfs3_stat(&lfs3, "ardvark", &info) => LFS3_ERR_NOENT;
// and with dir_read
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 0;
'''
# test that noent errors work
[cases.test_dirs_rm_noent]
reentrant = true
code = '''
// format once per test
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// make a directory
err = lfs3_mkdir(&lfs3, "ardvark");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
// try to remove a nonsense directory
lfs3_remove(&lfs3, "no") => LFS3_ERR_NOENT;
// try to remove a directory in a nonsense directory
lfs3_remove(&lfs3, "no/ardvark") => LFS3_ERR_NOENT;
// try to remove a nonsense child directory
lfs3_remove(&lfs3, "ardvark/no") => LFS3_ERR_NOENT;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// and check that this didn't interfere with our original directory
struct lfs3_info info;
lfs3_stat(&lfs3, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 0;
'''
# test that we catch removing of a non-empty directory
[cases.test_dirs_rm_notempty]
reentrant = true
code = '''
// format once per test
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// make a directory
err = lfs3_mkdir(&lfs3, "ardvark");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
// fill it with stuff
err = lfs3_mkdir(&lfs3, "ardvark/banana");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
// try to remove the parent directory
lfs3_remove(&lfs3, "ardvark") => LFS3_ERR_NOTEMPTY;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// and check that this didn't interfere with our original directory
struct lfs3_info info;
lfs3_stat(&lfs3, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "ardvark/banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
lfs3_dir_open(&lfs3, &dir, "ardvark") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 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
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check if dir exists before mkconsistent
struct lfs3_info info;
err = lfs3_stat(&lfs3, "ardvark", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool exists = !err;
// and with dir_read
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
if (exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
// make a directory
err = lfs3_mkdir(&lfs3, "ardvark");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == exists);
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check that our mkdir worked with stat
lfs3_stat(&lfs3, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
// and with dir_read
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
// and remove the directory
lfs3_remove(&lfs3, "ardvark") => 0;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that remove worked with stat
lfs3_stat(&lfs3, "ardvark", &info) => LFS3_ERR_NOENT;
// and with dir_read
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 0;
'''
# test what happens if we try to remove root
[cases.test_dirs_rm_root]
reentrant = true
code = '''
// format once per test
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// try to remove root, which doesn't really make sense
lfs3_remove(&lfs3, "/") => LFS3_ERR_BUSY;
// make a directory
err = lfs3_mkdir(&lfs3, "ardvark");
assert(!err || (TEST_PLS && err == LFS3_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 = lfs3_remove(&lfs3, "/");
assert(err == LFS3_ERR_NOTEMPTY || err == LFS3_ERR_BUSY);
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// and check that this didn't interfere with our original directory
struct lfs3_info info;
lfs3_stat(&lfs3, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 0;
'''
[cases.test_dirs_rm_siblings]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check if dirs exist before mkconsistent
struct lfs3_info info;
err = lfs3_stat(&lfs3, "ardvark", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfs3_stat(&lfs3, "banana", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
err = lfs3_stat(&lfs3, "cat", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool c_exists = !err;
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
if (b_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
if (c_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
// make some directories
err = lfs3_mkdir(&lfs3, "ardvark");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == a_exists);
err = lfs3_mkdir(&lfs3, "banana");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == b_exists);
err = lfs3_mkdir(&lfs3, "cat");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == c_exists);
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check that our mkdir worked
lfs3_stat(&lfs3, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
// now remove each directory
lfs3_remove(&lfs3, "ardvark") => 0;
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check that our remove worked
lfs3_stat(&lfs3, "ardvark", &info) => LFS3_ERR_NOENT;
lfs3_stat(&lfs3, "banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
// remove another
lfs3_remove(&lfs3, "banana") => 0;
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check that our remove worked
lfs3_stat(&lfs3, "ardvark", &info) => LFS3_ERR_NOENT;
lfs3_stat(&lfs3, "banana", &info) => LFS3_ERR_NOENT;
lfs3_stat(&lfs3, "cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
// remove another
lfs3_remove(&lfs3, "cat") => 0;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that our remove worked
lfs3_stat(&lfs3, "ardvark", &info) => LFS3_ERR_NOENT;
lfs3_stat(&lfs3, "banana", &info) => LFS3_ERR_NOENT;
lfs3_stat(&lfs3, "cat", &info) => LFS3_ERR_NOENT;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 0;
'''
[cases.test_dirs_rm_children]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check if dirs exist before mkconsistent
struct lfs3_info info;
err = lfs3_stat(&lfs3, "ardvark", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfs3_stat(&lfs3, "ardvark/banana", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
err = lfs3_stat(&lfs3, "ardvark/banana/cat", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool c_exists = !err;
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
err = lfs3_dir_open(&lfs3, &dir, "/ardvark");
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
assert(!err == a_exists);
if (a_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
if (b_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
err = lfs3_dir_open(&lfs3, &dir, "/ardvark/banana");
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
assert(!err == b_exists);
if (b_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
if (c_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
// make some directories
err = lfs3_mkdir(&lfs3, "ardvark");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == a_exists);
err = lfs3_mkdir(&lfs3, "ardvark/banana");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == b_exists);
err = lfs3_mkdir(&lfs3, "ardvark/banana/cat");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == c_exists);
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check that our mkdirs worked
lfs3_stat(&lfs3, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "ardvark/banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "ardvark/banana/cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
lfs3_dir_open(&lfs3, &dir, "/ardvark") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
lfs3_dir_open(&lfs3, &dir, "/ardvark/banana") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
// now remove each directory
lfs3_remove(&lfs3, "ardvark/banana/cat") => 0;
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check that our remove worked
lfs3_stat(&lfs3, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "ardvark/banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "ardvark/banana/cat", &info) => LFS3_ERR_NOENT;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
lfs3_dir_open(&lfs3, &dir, "/ardvark") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
lfs3_dir_open(&lfs3, &dir, "/ardvark/banana") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
// remove another
lfs3_remove(&lfs3, "ardvark/banana") => 0;
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check that our remove worked
lfs3_stat(&lfs3, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "ardvark/banana", &info) => LFS3_ERR_NOENT;
lfs3_stat(&lfs3, "ardvark/banana/cat", &info) => LFS3_ERR_NOENT;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
lfs3_dir_open(&lfs3, &dir, "/ardvark") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
// remove another
lfs3_remove(&lfs3, "ardvark") => 0;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that our remove worked
lfs3_stat(&lfs3, "ardvark", &info) => LFS3_ERR_NOENT;
lfs3_stat(&lfs3, "ardvark/banana", &info) => LFS3_ERR_NOENT;
lfs3_stat(&lfs3, "ardvark/banana/cat", &info) => LFS3_ERR_NOENT;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 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
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// make this many directories
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
err = lfs3_mkdir(&lfs3, name);
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
}
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check that our mkdir worked
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
struct lfs3_info info;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
// now remove some number of directories
for (lfs3_size_t i = 0; i < N-REMAINING; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfs3_remove(&lfs3, name) => 0;
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that our removes worked
for (lfs3_size_t i = 0; i < N-REMAINING; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => LFS3_ERR_NOENT;
}
for (lfs3_size_t i = 0; i < REMAINING; i++) {
char name[256];
sprintf(name, "dir%03x", (int)(N-REMAINING + i));
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t i = 0; i < REMAINING; i++) {
char name[256];
sprintf(name, "dir%03x", (int)(N-REMAINING + i));
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 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
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// make this many directories
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", (int)(N-1-i));
err = lfs3_mkdir(&lfs3, name);
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
}
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check that our mkdir worked
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
struct lfs3_info info;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
// now remove some number of directories
for (lfs3_size_t i = 0; i < N-REMAINING; i++) {
char name[256];
sprintf(name, "dir%03x", (int)(N-1-i));
lfs3_remove(&lfs3, name) => 0;
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that our removes worked
for (lfs3_size_t i = 0; i < N-REMAINING; i++) {
char name[256];
sprintf(name, "dir%03x", (int)(N-1-i));
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => LFS3_ERR_NOENT;
}
for (lfs3_size_t i = 0; i < REMAINING; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t i = 0; i < REMAINING; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 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
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// make this many directories
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
err = lfs3_mkdir(&lfs3, name);
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
// containing this many directories
for (lfs3_size_t j = 0; j < N; j++) {
sprintf(name, "dir%03x/child%03x", i, j);
err = lfs3_mkdir(&lfs3, name);
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
}
}
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check that our mkdirs worked
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
sprintf(name, "child%03x", j);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
}
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
struct lfs3_info info;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfs3_dir_open(&lfs3, &dir, name) => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "child%03x", j);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
// now remove some number of directories
for (lfs3_size_t i = 0; i < N; i++) {
for (lfs3_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);
lfs3_remove(&lfs3, name) => 0;
}
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
}
if (i < N-REMAINING) {
char name[256];
sprintf(name, "dir%03x", i);
lfs3_remove(&lfs3, name) => 0;
}
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that our removes worked
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs3_info info;
if (i < N-REMAINING) {
lfs3_stat(&lfs3, name, &info) => LFS3_ERR_NOENT;
} else {
lfs3_stat(&lfs3, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
struct lfs3_info info;
if (j < N-REMAINING) {
lfs3_stat(&lfs3, name, &info) => LFS3_ERR_NOENT;
} else {
lfs3_stat(&lfs3, name, &info) => 0;
sprintf(name, "child%03x", j);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
}
}
}
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t i = 0; i < REMAINING; i++) {
char name[256];
sprintf(name, "dir%03x", (int)(N-REMAINING + i));
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
for (lfs3_size_t i = 0; i < REMAINING; i++) {
char name[256];
sprintf(name, "dir%03x", (int)(N-REMAINING + i));
lfs3_dir_open(&lfs3, &dir, name) => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t j = 0; j < REMAINING; j++) {
char name[256];
sprintf(name, "child%03x", (int)(N-REMAINING + j));
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
}
lfs3_unmount(&lfs3) => 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
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// make this many directories
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
err = lfs3_mkdir(&lfs3, name);
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
// containing this many directories
for (lfs3_size_t j = 0; j < N; j++) {
sprintf(name, "dir%03x/child%03x", i, j);
err = lfs3_mkdir(&lfs3, name);
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
// containing this many directories
for (lfs3_size_t k = 0; k < N; k++) {
sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k);
err = lfs3_mkdir(&lfs3, name);
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
}
}
}
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check that our mkdirs worked
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
sprintf(name, "child%03x", j);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t k = 0; k < N; k++) {
char name[256];
sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
sprintf(name, "grandchild%03x", k);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
}
}
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
struct lfs3_info info;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfs3_dir_open(&lfs3, &dir, name) => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "child%03x", j);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
for (lfs3_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
lfs3_dir_open(&lfs3, &dir, name) => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t k = 0; k < N; k++) {
char name[256];
sprintf(name, "grandchild%03x", k);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
}
// now remove some number of directories
for (lfs3_size_t i = 0; i < N; i++) {
for (lfs3_size_t j = 0; j < N; j++) {
for (lfs3_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);
lfs3_remove(&lfs3, name) => 0;
}
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
}
if (i < N-REMAINING || j < N-REMAINING) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
lfs3_remove(&lfs3, name) => 0;
}
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
}
if (i < N-REMAINING) {
char name[256];
sprintf(name, "dir%03x", i);
lfs3_remove(&lfs3, name) => 0;
}
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that our removes worked
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs3_info info;
if (i < N-REMAINING) {
lfs3_stat(&lfs3, name, &info) => LFS3_ERR_NOENT;
} else {
lfs3_stat(&lfs3, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
struct lfs3_info info;
if (j < N-REMAINING) {
lfs3_stat(&lfs3, name, &info) => LFS3_ERR_NOENT;
} else {
lfs3_stat(&lfs3, name, &info) => 0;
sprintf(name, "child%03x", j);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t k = 0; k < N; k++) {
char name[256];
sprintf(name, "dir%03x/child%03x/grandchild%03x",
i, j, k);
struct lfs3_info info;
if (k < N-REMAINING) {
lfs3_stat(&lfs3, name, &info) => LFS3_ERR_NOENT;
} else {
lfs3_stat(&lfs3, name, &info) => 0;
sprintf(name, "grandchild%03x", k);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
}
}
}
}
}
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t i = 0; i < REMAINING; i++) {
char name[256];
sprintf(name, "dir%03x", (int)(N-REMAINING + i));
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
for (lfs3_size_t i = 0; i < REMAINING; i++) {
char name[256];
sprintf(name, "dir%03x", (int)(N-REMAINING + i));
lfs3_dir_open(&lfs3, &dir, name) => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t j = 0; j < REMAINING; j++) {
char name[256];
sprintf(name, "child%03x", (int)(N-REMAINING + j));
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
for (lfs3_size_t i = 0; i < REMAINING; i++) {
for (lfs3_size_t j = 0; j < REMAINING; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x",
(int)(N-REMAINING + i),
(int)(N-REMAINING + j));
lfs3_dir_open(&lfs3, &dir, name) => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t k = 0; k < REMAINING; k++) {
char name[256];
sprintf(name, "grandchild%03x", (int)(N-REMAINING + k));
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
}
}
lfs3_unmount(&lfs3) => 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
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_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 (lfs3_size_t i = 0; i < N; i++) {
sprintf(&name[strlen(name)], "/dir%03x", i);
err = lfs3_mkdir(&lfs3, name);
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
}
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check that our mkdir worked
memset(name, 0, sizeof(name));
for (lfs3_size_t i = 0; i < N; i++) {
sprintf(&name[strlen(name)], "/dir%03x", i);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
char name2[256];
sprintf(name2, "dir%03x", i);
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
memset(name, 0, sizeof(name));
for (lfs3_size_t i = 0; i < N; i++) {
sprintf(&name[strlen(name)], "/dir%03x", i);
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, name) => 0;
struct lfs3_info info;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
if (i < N-1) {
char name2[256];
sprintf(name2, "dir%03x", i+1);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
// now remove some number of directories
for (lfs3_size_t i = 0; i < N-REMAINING; i++) {
lfs3_remove(&lfs3, name) => 0;
name[strlen(name) - strlen("/dir...")] = '\0';
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that our remove worked
memset(name, 0, sizeof(name));
for (lfs3_size_t i = 0; i < REMAINING; i++) {
sprintf(&name[strlen(name)], "/dir%03x", i);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
char name2[256];
sprintf(name2, "dir%03x", i);
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
memset(name, 0, sizeof(name));
for (lfs3_size_t i = 0; i < REMAINING; i++) {
sprintf(&name[strlen(name)], "/dir%03x", i);
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, name) => 0;
struct lfs3_info info;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
if (i < REMAINING-1) {
char name2[256];
sprintf(name2, "dir%03x", i+1);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
}
lfs3_unmount(&lfs3) => 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
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
if (PARENT) {
err = lfs3_mkdir(&lfs3, "pricklypear");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
}
// set up a simulation to compare against
lfs3_size_t *sim = malloc(N*sizeof(lfs3_size_t));
lfs3_size_t sim_size = 0;
uint32_t prng = SEED;
for (lfs3_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
lfs3_size_t x = TEST_PRNG(&prng) % N;
// insert into our sim
for (lfs3_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(lfs3_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 = lfs3_mkdir(&lfs3, name);
assert(!err || err == LFS3_ERR_EXIST);
} else {
// choose a pseudo-random entry to delete
lfs3_size_t j = TEST_PRNG(&prng) % sim_size;
lfs3_size_t x = sim[j];
// delete from our sim
memmove(&sim[j], &sim[j+1],
(sim_size-(j+1))*sizeof(lfs3_size_t));
sim_size -= 1;
// remove this directory
char name[256];
sprintf(name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), x);
lfs3_remove(&lfs3, name) => 0;
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// test that our directories match our simulation
for (lfs3_size_t j = 0; j < sim_size; j++) {
char name[256];
sprintf(name, "%s/dir%03x",
((PARENT) ? "pricklypear" : ""),
sim[j]);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
char name2[256];
sprintf(name2, "dir%03x", sim[j]);
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, ((PARENT) ? "pricklypear" : "/")) => 0;
struct lfs3_info info;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t j = 0; j < sim_size; j++) {
char name[256];
sprintf(name, "dir%03x", sim[j]);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
// clean up sim/lfs3
free(sim);
lfs3_unmount(&lfs3) => 0;
'''
## dir rename tests
[cases.test_dirs_mv]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// make a directory
err = lfs3_mkdir(&lfs3, "ardvark");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
// clean up interrupted renames
if (TEST_PLS) {
err = lfs3_remove(&lfs3, "banana");
assert(!err || err == LFS3_ERR_NOENT);
}
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check that our mkdir worked with stat
struct lfs3_info info;
lfs3_stat(&lfs3, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
// and with dir_read
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
// now rename the directory
lfs3_rename(&lfs3, "ardvark", "banana") => 0;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that rename worked with stat
lfs3_stat(&lfs3, "ardvark", &info) => LFS3_ERR_NOENT;
lfs3_stat(&lfs3, "banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
// and with dir_read
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 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
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// make directories
err = lfs3_mkdir(&lfs3, "ardvark");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
err = lfs3_mkdir(&lfs3, "banana");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check that our mkdir worked with stat
struct lfs3_info info;
lfs3_stat(&lfs3, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
// and with dir_read
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
// now rename the directory
lfs3_rename(&lfs3, "ardvark", "banana") => 0;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that rename worked with stat
lfs3_stat(&lfs3, "ardvark", &info) => LFS3_ERR_NOENT;
lfs3_stat(&lfs3, "banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
// and with dir_read
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 0;
'''
# test that we can rename to ourselves
[cases.test_dirs_mv_noop]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// make directories
err = lfs3_mkdir(&lfs3, "ardvark");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check that our mkdir worked with stat
struct lfs3_info info;
lfs3_stat(&lfs3, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
// and with dir_read
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
// now rename the directory to itself
lfs3_rename(&lfs3, "ardvark", "ardvark") => 0;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that rename worked with stat
lfs3_stat(&lfs3, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
// and with dir_read
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 0;
'''
# test that we catch replacing an invalid path
[cases.test_dirs_mv_noent]
reentrant = true
code = '''
// format once per test
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// make directories
err = lfs3_mkdir(&lfs3, "ardvark");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
// try to rename a nonsense directory
lfs3_rename(&lfs3, "no", "ardvark") => LFS3_ERR_NOENT;
// try to rename a directory in a nonsense directory
lfs3_rename(&lfs3, "no/ardvark", "ardvark") => LFS3_ERR_NOENT;
// try to rename a nonsense child directory
lfs3_rename(&lfs3, "ardvark/no", "banana") => LFS3_ERR_NOENT;
// try to rename to a nonense directory
lfs3_rename(&lfs3, "ardvark", "no/ardvark") => LFS3_ERR_NOENT;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// and check that this didn't interfere with our original directory
struct lfs3_info info;
lfs3_stat(&lfs3, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 0;
'''
# test that we catch replacing a non-empty directory
[cases.test_dirs_mv_notempty]
reentrant = true
code = '''
// format once per test
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// make directories
err = lfs3_mkdir(&lfs3, "ardvark");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
err = lfs3_mkdir(&lfs3, "banana");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
// fill dest with stuff
err = lfs3_mkdir(&lfs3, "banana/cat");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
// try to rename
lfs3_rename(&lfs3, "ardvark", "banana") => LFS3_ERR_NOTEMPTY;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// and check that this didn't interfere with our original directory
struct lfs3_info info;
lfs3_stat(&lfs3, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "banana/cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
lfs3_dir_open(&lfs3, &dir, "banana") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 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
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check if dirs exist before mkconsistent
struct lfs3_info info;
err = lfs3_stat(&lfs3, "ardvark", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfs3_stat(&lfs3, "banana", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
// and with dir_read
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
if (b_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
// make a directory
err = lfs3_mkdir(&lfs3, "ardvark");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == a_exists);
// clean up interrupted renames
if (TEST_PLS) {
err = lfs3_remove(&lfs3, "banana");
assert(!err || err == LFS3_ERR_NOENT);
assert(!err == b_exists);
}
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check that our mkdir worked with stat
lfs3_stat(&lfs3, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
// and with dir_read
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
// now rename the directory
lfs3_rename(&lfs3, "ardvark", "banana") => 0;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that rename worked with stat
lfs3_stat(&lfs3, "ardvark", &info) => LFS3_ERR_NOENT;
lfs3_stat(&lfs3, "banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
// and with dir_read
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 0;
'''
# test what happens if we try to rename root
[cases.test_dirs_mv_root]
reentrant = true
code = '''
// format once per test
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// try to rename root, which doesn't really make sense
lfs3_rename(&lfs3, "/", "notroot") => LFS3_ERR_BUSY;
// make a directory
err = lfs3_mkdir(&lfs3, "ardvark");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
// try to rename root, which doesn't really make sense
lfs3_rename(&lfs3, "/", "notroot") => LFS3_ERR_BUSY;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// and check that this didn't interfere with our original directory
struct lfs3_info info;
lfs3_stat(&lfs3, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 0;
'''
[cases.test_dirs_mv_siblings]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check if dirs exist before mkconsistent
struct lfs3_info info;
err = lfs3_stat(&lfs3, "ardvark", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfs3_stat(&lfs3, "banana", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
err = lfs3_stat(&lfs3, "cat", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool c_exists = !err;
err = lfs3_stat(&lfs3, "disco", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool d_exists = !err;
err = lfs3_stat(&lfs3, "eggplant", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool e_exists = !err;
err = lfs3_stat(&lfs3, "fish", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool f_exists = !err;
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
if (b_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
if (c_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
if (d_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
if (e_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "eggplant") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
if (f_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "fish") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
// make some directories
err = lfs3_mkdir(&lfs3, "ardvark");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == a_exists);
err = lfs3_mkdir(&lfs3, "banana");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == b_exists);
err = lfs3_mkdir(&lfs3, "cat");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == c_exists);
// clean up interrupted renames
if (TEST_PLS) {
err = lfs3_remove(&lfs3, "disco");
assert(!err || err == LFS3_ERR_NOENT);
assert(!err == d_exists);
err = lfs3_remove(&lfs3, "eggplant");
assert(!err || err == LFS3_ERR_NOENT);
assert(!err == e_exists);
err = lfs3_remove(&lfs3, "fish");
assert(!err || err == LFS3_ERR_NOENT);
assert(!err == f_exists);
}
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check that our mkdir worked
lfs3_stat(&lfs3, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
// now rename each directory
lfs3_rename(&lfs3, "ardvark", "disco") => 0;
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check that our rename worked
lfs3_stat(&lfs3, "banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "disco", &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
// rename another
lfs3_rename(&lfs3, "banana", "eggplant") => 0;
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check that our rename worked
lfs3_stat(&lfs3, "cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "disco", &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "eggplant", &info) => 0;
assert(strcmp(info.name, "eggplant") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "eggplant") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
// rename another
lfs3_rename(&lfs3, "cat", "fish") => 0;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that our rename worked
lfs3_stat(&lfs3, "disco", &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "eggplant", &info) => 0;
assert(strcmp(info.name, "eggplant") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "fish", &info) => 0;
assert(strcmp(info.name, "fish") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "eggplant") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "fish") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 0;
'''
[cases.test_dirs_mv_children]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check if dirs exist before mkconsistent
struct lfs3_info info;
err = lfs3_stat(&lfs3, "ardvark", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfs3_stat(&lfs3, "ardvark/banana", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
err = lfs3_stat(&lfs3, "ardvark/banana/cat", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool c_exists = !err;
err = lfs3_stat(&lfs3, "disco", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool d_exists = !err;
err = lfs3_stat(&lfs3, "disco/eggplant", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool e_exists = !err;
err = lfs3_stat(&lfs3, "disco/eggplant/fish", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool f_exists = !err;
err = lfs3_stat(&lfs3, "disco/banana", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool db_exists = !err;
err = lfs3_stat(&lfs3, "disco/banana/cat", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool dbc_exists = !err;
err = lfs3_stat(&lfs3, "disco/eggplant/cat", &info);
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
bool dec_exists = !err;
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
if (d_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
err = lfs3_dir_open(&lfs3, &dir, "/ardvark");
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
assert(!err == a_exists);
if (a_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
if (b_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
err = lfs3_dir_open(&lfs3, &dir, "/ardvark/banana");
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
assert(!err == b_exists);
if (b_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
if (c_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
err = lfs3_dir_open(&lfs3, &dir, "/disco");
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
assert(!err == d_exists);
if (d_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
if (db_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
if (e_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "eggplant") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
err = lfs3_dir_open(&lfs3, &dir, "/disco/eggplant");
assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err));
assert(!err == e_exists);
if (e_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
if (dec_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
if (f_exists) {
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "fish") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
// make some directories
err = lfs3_mkdir(&lfs3, "ardvark");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == a_exists);
err = lfs3_mkdir(&lfs3, "ardvark/banana");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == b_exists);
err = lfs3_mkdir(&lfs3, "ardvark/banana/cat");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
assert((err == LFS3_ERR_EXIST) == c_exists);
// clean up interrupted renames
if (TEST_PLS) {
err = lfs3_remove(&lfs3, "disco/eggplant/fish");
assert(!err || err == LFS3_ERR_NOENT);
assert(!err == f_exists);
err = lfs3_remove(&lfs3, "disco/eggplant/cat");
assert(!err || err == LFS3_ERR_NOENT);
assert(!err == dec_exists);
err = lfs3_remove(&lfs3, "disco/eggplant");
assert(!err || err == LFS3_ERR_NOENT);
assert(!err == e_exists);
err = lfs3_remove(&lfs3, "disco/banana/cat");
assert(!err || err == LFS3_ERR_NOENT);
assert(!err == dbc_exists);
err = lfs3_remove(&lfs3, "disco/banana");
assert(!err || err == LFS3_ERR_NOENT);
assert(!err == db_exists);
err = lfs3_remove(&lfs3, "disco");
assert(!err || err == LFS3_ERR_NOENT);
assert(!err == d_exists);
}
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check that our mkdirs worked
lfs3_stat(&lfs3, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "ardvark/banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "ardvark/banana/cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
lfs3_dir_open(&lfs3, &dir, "/ardvark") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
lfs3_dir_open(&lfs3, &dir, "/ardvark/banana") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
// now rename each directory
lfs3_rename(&lfs3, "ardvark", "disco") => 0;
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check that our rename worked
lfs3_stat(&lfs3, "disco", &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "disco/banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "disco/banana/cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
lfs3_dir_open(&lfs3, &dir, "/disco") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
lfs3_dir_open(&lfs3, &dir, "/disco/banana") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
// rename another
lfs3_rename(&lfs3, "disco/banana", "disco/eggplant") => 0;
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check that our rename worked
lfs3_stat(&lfs3, "disco", &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "disco/eggplant", &info) => 0;
assert(strcmp(info.name, "eggplant") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "disco/eggplant/cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
lfs3_dir_open(&lfs3, &dir, "/disco") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "eggplant") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
lfs3_dir_open(&lfs3, &dir, "/disco/eggplant") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
// rename another
lfs3_rename(&lfs3, "disco/eggplant/cat", "disco/eggplant/fish") => 0;
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that our rename worked
lfs3_stat(&lfs3, "disco", &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "disco/eggplant", &info) => 0;
assert(strcmp(info.name, "eggplant") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_stat(&lfs3, "disco/eggplant/fish", &info) => 0;
assert(strcmp(info.name, "fish") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
lfs3_dir_open(&lfs3, &dir, "/disco") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "eggplant") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
lfs3_dir_open(&lfs3, &dir, "/disco/eggplant") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "fish") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 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
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check if we have already started renaming, in case of powerloss
struct lfs3_info info;
err = lfs3_stat(&lfs3, ((BEFORE) ? "/0mved000" : "/mved000"), &info);
if (err == LFS3_ERR_NOENT) {
// make this many directories
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
err = lfs3_mkdir(&lfs3, name);
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
}
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check that our mkdir worked
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
struct lfs3_info info;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
// now rename the directories
for (lfs3_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 = lfs3_rename(&lfs3, old_name, new_name);
assert(!err || (TEST_PLS && err == LFS3_ERR_NOENT));
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that our renames worked
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 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
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check if we have already started renaming, in case of powerloss
struct lfs3_info info;
err = lfs3_stat(&lfs3, ((BEFORE) ? "/0mved000" : "/mved000"), &info);
if (err == LFS3_ERR_NOENT) {
// make this many directories
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", (int)(N-1-i));
err = lfs3_mkdir(&lfs3, name);
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
}
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check that our mkdir worked
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
struct lfs3_info info;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
// now rename the directories
for (lfs3_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 = lfs3_rename(&lfs3, old_name, new_name);
assert(!err || (TEST_PLS && err == LFS3_ERR_NOENT));
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that our renames worked
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
lfs3_unmount(&lfs3) => 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
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check if we have already started renaming, in case of powerloss
struct lfs3_info info;
err = lfs3_stat(&lfs3, ((BEFORE) ? "/0mved000" : "/mved000"), &info);
if (err == LFS3_ERR_NOENT) {
// make this many directories
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
err = lfs3_mkdir(&lfs3, name);
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
// containing this many directories
for (lfs3_size_t j = 0; j < N; j++) {
sprintf(name, "dir%03x/child%03x", i, j);
err = lfs3_mkdir(&lfs3, name);
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
}
}
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check that our mkdirs worked
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
sprintf(name, "child%03x", j);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
}
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
struct lfs3_info info;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfs3_dir_open(&lfs3, &dir, name) => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "child%03x", j);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
}
// now rename our directories
for (lfs3_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 = lfs3_rename(&lfs3, old_name, new_name);
assert(!err || (TEST_PLS && err == LFS3_ERR_NOENT));
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
for (lfs3_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 = lfs3_rename(&lfs3, old_name, new_name);
assert(!err || (TEST_PLS && err == LFS3_ERR_NOENT));
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that our renames worked
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "%smved%03x/%schmved%03x",
((BEFORE) ? "0" : ""), i, ((BEFORE) ? "0" : ""), j);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
sprintf(name, "%schmved%03x", ((BEFORE) ? "0" : ""), j);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
}
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
lfs3_dir_open(&lfs3, &dir, name) => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "%schmved%03x", ((BEFORE) ? "0" : ""), j);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
}
lfs3_unmount(&lfs3) => 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
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check if we have already started renaming, in case of powerloss
struct lfs3_info info;
err = lfs3_stat(&lfs3, ((BEFORE) ? "/0mved000" : "/mved000"), &info);
if (err == LFS3_ERR_NOENT) {
// make this many directories
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
err = lfs3_mkdir(&lfs3, name);
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
// containing this many directories
for (lfs3_size_t j = 0; j < N; j++) {
sprintf(name, "dir%03x/child%03x", i, j);
err = lfs3_mkdir(&lfs3, name);
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
// containing this many directories
for (lfs3_size_t k = 0; k < N; k++) {
sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k);
err = lfs3_mkdir(&lfs3, name);
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
}
}
}
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check that our mkdirs worked
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
sprintf(name, "child%03x", j);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t k = 0; k < N; k++) {
char name[256];
sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
sprintf(name, "grandchild%03x", k);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
}
}
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
struct lfs3_info info;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfs3_dir_open(&lfs3, &dir, name) => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "child%03x", j);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
for (lfs3_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
lfs3_dir_open(&lfs3, &dir, name) => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t k = 0; k < N; k++) {
char name[256];
sprintf(name, "grandchild%03x", k);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
}
}
// now rename our directories
for (lfs3_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 = lfs3_rename(&lfs3, old_name, new_name);
assert(!err || (TEST_PLS && err == LFS3_ERR_NOENT));
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
for (lfs3_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 = lfs3_rename(&lfs3, old_name, new_name);
assert(!err || (TEST_PLS && err == LFS3_ERR_NOENT));
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
for (lfs3_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 = lfs3_rename(&lfs3, old_name, new_name);
assert(!err || (TEST_PLS && err == LFS3_ERR_NOENT));
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
}
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that our removes worked
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "%smved%03x/%schmved%03x",
((BEFORE) ? "0" : ""), i,
((BEFORE) ? "0" : ""), j);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
sprintf(name, "%schmved%03x", ((BEFORE) ? "0" : ""), j);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_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 lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
sprintf(name, "%sgrmved%03x", ((BEFORE) ? "0" : ""), k);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
}
}
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, "/") => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
for (lfs3_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
lfs3_dir_open(&lfs3, &dir, name) => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "%schmved%03x", ((BEFORE) ? "0" : ""), j);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
for (lfs3_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "%smved%03x/%schmved%03x",
((BEFORE) ? "0" : ""), i,
((BEFORE) ? "0" : ""), j);
lfs3_dir_open(&lfs3, &dir, name) => 0;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t k = 0; k < N; k++) {
char name[256];
sprintf(name, "%sgrmved%03x", ((BEFORE) ? "0" : ""), k);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
}
}
lfs3_unmount(&lfs3) => 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
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check if we have already started renaming, in case of powerloss
struct lfs3_info info;
err = lfs3_stat(&lfs3, ((BEFORE) ? "/0mved000" : "/mved000"), &info);
if (err == LFS3_ERR_NOENT) {
// create this many directory in a sort of linked-list by nesting
char name[4096];
memset(name, 0, sizeof(name));
for (lfs3_size_t i = 0; i < N; i++) {
sprintf(&name[strlen(name)], "/dir%03x", i);
err = lfs3_mkdir(&lfs3, name);
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
}
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// check that our mkdir worked
memset(name, 0, sizeof(name));
for (lfs3_size_t i = 0; i < N; i++) {
sprintf(&name[strlen(name)], "/dir%03x", i);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
char name2[256];
sprintf(name2, "dir%03x", i);
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
memset(name, 0, sizeof(name));
for (lfs3_size_t i = 0; i < N; i++) {
sprintf(&name[strlen(name)], "/dir%03x", i);
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, name) => 0;
struct lfs3_info info;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
if (i < N-1) {
char name2[256];
sprintf(name2, "dir%03x", i+1);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &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 (lfs3_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 = lfs3_rename(&lfs3, old_name, new_name);
assert(!err || (TEST_PLS && err == LFS3_ERR_NOENT));
// remount?
if (REMOUNT) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_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) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// check that our renames worked
char name[4096];
memset(name, 0, sizeof(name));
for (lfs3_size_t i = 0; i < N; i++) {
sprintf(&name[strlen(name)], "/%smved%03x",
((BEFORE) ? "0" : ""),
i);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
char name2[256];
sprintf(name2, "%smved%03x", ((BEFORE) ? "0" : ""), i);
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
memset(name, 0, sizeof(name));
for (lfs3_size_t i = 0; i < N; i++) {
sprintf(&name[strlen(name)], "/%smved%03x",
((BEFORE) ? "0" : ""),
i);
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, name) => 0;
struct lfs3_info info;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
if (i < N-1) {
char name2[256];
sprintf(name2, "%smved%03x", ((BEFORE) ? "0" : ""), i+1);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
}
lfs3_unmount(&lfs3) => 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
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
if (PARENT) {
err = lfs3_mkdir(&lfs3, "pricklypear");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
}
// set up a simulation to compare against
lfs3_size_t *sim = malloc(N*sizeof(lfs3_size_t));
lfs3_size_t sim_size = 0;
uint32_t prng = SEED;
for (lfs3_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
lfs3_size_t x = TEST_PRNG(&prng) % N;
// insert into our sim
for (lfs3_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(lfs3_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 = lfs3_mkdir(&lfs3, name);
assert(!err || err == LFS3_ERR_EXIST);
} else {
// choose a pseudo-random entry to rename, and a pseudo-random
// number to rename to
lfs3_size_t j = TEST_PRNG(&prng) % sim_size;
lfs3_size_t x = sim[j];
lfs3_size_t y = TEST_PRNG(&prng) % N;
for (lfs3_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(lfs3_size_t));
sim_size -= 1;
} else {
// first delete
memmove(&sim[j], &sim[j+1],
(sim_size-(j+1))*sizeof(lfs3_size_t));
if (k > j) {
k -= 1;
}
// then insert
memmove(&sim[k+1], &sim[k],
(sim_size-1-k)*sizeof(lfs3_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);
lfs3_rename(&lfs3, old_name, new_name) => 0;
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// test that our directories match our simulation
for (lfs3_size_t j = 0; j < sim_size; j++) {
char name[256];
sprintf(name, "%s/dir%03x",
((PARENT) ? "pricklypear" : ""),
sim[j]);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
char name2[256];
sprintf(name2, "dir%03x", sim[j]);
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, ((PARENT) ? "pricklypear" : "/")) => 0;
struct lfs3_info info;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t j = 0; j < sim_size; j++) {
char name[256];
sprintf(name, "dir%03x", sim[j]);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
// clean up sim/lfs3
free(sim);
lfs3_unmount(&lfs3) => 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
lfs3_t lfs3;
int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG);
if (err) {
lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
if (PARENT) {
err = lfs3_mkdir(&lfs3, "pricklypear");
assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST));
}
// set up a simulation to compare against
lfs3_size_t *sim = malloc(N*sizeof(lfs3_size_t));
lfs3_size_t sim_size = 0;
uint32_t prng = SEED;
for (lfs3_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
lfs3_size_t x = TEST_PRNG(&prng) % N;
// insert into our sim
for (lfs3_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(lfs3_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 = lfs3_mkdir(&lfs3, name);
assert(!err || err == LFS3_ERR_EXIST);
} else if (op == 1) {
// choose a pseudo-random entry to delete
lfs3_size_t j = TEST_PRNG(&prng) % sim_size;
lfs3_size_t x = sim[j];
// delete from our sim
memmove(&sim[j], &sim[j+1],
(sim_size-(j+1))*sizeof(lfs3_size_t));
sim_size -= 1;
// remove this directory
char name[256];
sprintf(name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), x);
lfs3_remove(&lfs3, name) => 0;
} else {
// choose a pseudo-random entry to rename, and a pseudo-random
// number to rename to
lfs3_size_t j = TEST_PRNG(&prng) % sim_size;
lfs3_size_t x = sim[j];
lfs3_size_t y = TEST_PRNG(&prng) % N;
for (lfs3_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(lfs3_size_t));
sim_size -= 1;
} else {
// first delete
memmove(&sim[j], &sim[j+1],
(sim_size-(j+1))*sizeof(lfs3_size_t));
if (k > j) {
k -= 1;
}
// then insert
memmove(&sim[k+1], &sim[k],
(sim_size-1-k)*sizeof(lfs3_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);
lfs3_rename(&lfs3, old_name, new_name) => 0;
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0;
}
// grm should be zero here
assert(lfs3.grm_p[0] == 0);
// test that our directories match our simulation
for (lfs3_size_t j = 0; j < sim_size; j++) {
char name[256];
sprintf(name, "%s/dir%03x",
((PARENT) ? "pricklypear" : ""),
sim[j]);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
char name2[256];
sprintf(name2, "dir%03x", sim[j]);
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_t dir;
lfs3_dir_open(&lfs3, &dir, ((PARENT) ? "pricklypear" : "/")) => 0;
struct lfs3_info info;
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
for (lfs3_size_t j = 0; j < sim_size; j++) {
char name[256];
sprintf(name, "dir%03x", sim[j]);
lfs3_dir_read(&lfs3, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_DIR);
assert(info.size == 0);
}
lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT;
lfs3_dir_close(&lfs3, &dir) => 0;
}
// clean up sim/lfs3
free(sim);
lfs3_unmount(&lfs3) => 0;
'''