Files
littlefs/tests/test_dirs.toml
T
Christopher Haster bd4a5e5ab3 Tried to better budget test runtime
The main idea here is that diverse tests are better than many similar
tests.

Sure, if we throw fuzz tests at the system all day we'll eventually find
more bugs, but if a developer is in the loop that time is going to be
better spent writing specific tests targeting the fragile parts of the
system.

And don't worry, we can still throw fuzz tests at the system all day by
specifying explicit seeds with -DSEED=blah.

Changes:

- Limited dir-related powerloss fuzz testing to N <= 16.

  These tests were the biggest culprit of excessive test runtime,
  requiring O(n^2) redundant operations to recover from powerlosses
  (they just replay the full sequence on powerloss).

- As a tradeoff, bumped most fuzz tests to a minimum of 20 seeds.

  The big exception being the test_fwrite tests, which are heavily
  parameterized and already take the most time to run. Each parameter
  combination also multiplies the effective number of seeds, so
  increasing the number of base seeds will probably have diminishing
  returns.

- Limited test_fwrite_reversed to SIZE <= 4*1024*CHUNK.

  Writing a file backwards is just about the worst way you could write a
  file, since all buffering/coalescing expect writes to eventually make
  forward progress. On the flip side, because it's uncommon, writing a
  file backwards is also a great way to find bugs. But at some point a
  compromise needs to be made.

Impacted test runtimes:

  case                                otime    ntime    dtime
  test_btree_push_fuzz                  0.3      0.5     +0.2 (+60.2%)
  test_btree_push_sparse_fuzz           0.4      3.3     +2.9 (+720.4%)
  test_btree_update_fuzz                0.4      0.9     +0.6 (+141.6%)
  test_btree_update_sparse_fuzz         0.5      4.5     +4.1 (+857.4%)
  test_btree_pop_fuzz                   0.6      2.3     +1.7 (+314.7%)
  test_btree_pop_sparse_fuzz            1.2      5.7     +4.4 (+356.2%)
  test_btree_split_fuzz                 0.5      1.4     +0.8 (+150.2%)
  test_btree_split_sparse_fuzz          0.4      5.6     +5.1 (+1163.2%)
  test_btree_find_fuzz                  0.5      0.7     +0.2 (+50.7%)
  test_btree_find_sparse_fuzz           1.0      3.0     +2.0 (+189.8%)
  test_btree_traversal_fuzz             0.6      2.3     +1.6 (+260.4%)
  test_dirs_mkdir_many                  3.3      2.1     -1.3 (-37.8%)
  test_dirs_mkdir_many_backwards        3.5      2.1     -1.4 (-39.9%)
  test_dirs_mkdir_fuzz                115.3    106.4     -8.9 (-7.7%)
  test_dirs_rm_many                   283.9     76.8   -207.0 (-72.9%)
  test_dirs_rm_many_backwards         216.1     80.6   -135.5 (-62.7%)
  test_dirs_rm_fuzz                   647.0     68.5   -578.5 (-89.4%)
  test_dirs_mv_many                    14.2     15.4     +1.1 (+7.9%)
  test_dirs_mv_many_backwards          16.5     14.5     -2.1 (-12.5%)
  test_dirs_mv_fuzz                  1932.5    156.7  -1775.8 (-91.9%)
  test_dirs_general_fuzz              561.9     74.5   -487.4 (-86.7%)
  test_dread_recursive_rm             336.6     46.2   -290.4 (-86.3%)
  test_dread_recursive_mv              55.5     44.6    -11.0 (-19.8%)
  test_fsync_rrrr_fuzz                  0.4      0.3     -0.1 (-18.4%)
  test_fsync_wrrr_fuzz                  8.0     12.4     +4.5 (+56.0%)
  test_fsync_wwww_fuzz                 13.2     33.4    +20.2 (+152.6%)
  test_fsync_wwrr_fuzz                  5.4     50.9    +45.5 (+841.6%)
  test_fsync_rwrw_fuzz                  2.4      8.4     +6.0 (+253.9%)
  test_fsync_rwrw_sparse_fuzz           3.2      7.5     +4.2 (+129.9%)
  test_fsync_rwtfrwtf_sparse_fuzz       6.1      8.5     +2.4 (+39.3%)
  test_fsync_drrr_fuzz                 11.8      9.2     -2.6 (-21.8%)
  test_fsync_wddd_fuzz                  9.3     11.9     +2.6 (+28.0%)
  test_fsync_rwdrwd_fuzz                1.6     33.1    +31.5 (+1963.4%)
  test_fsync_rwdrwd_sparse_fuzz         0.3      1.8     +1.4 (+418.8%)
  test_fsync_rwtfdrwtfd_sparse_fuzz     0.3      1.1     +0.8 (+260.2%)
  test_fwrite_reversed                728.5    345.2   -383.3 (-52.6%)
  TOTAL                              7587.5   3792.3  -3795.2 (-50.0%)
2024-05-18 13:00:09 -05:00

7907 lines
260 KiB
TOML

# Test directory operations
after = 'test_mtree'
## mkdir tests
[cases.test_dirs_mkdir]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// make a directory
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our mkdir worked with stat
struct lfs_info info;
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
// and with dir_read
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_dir_open(&lfs, &dir, "ardvark") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
# test that noent errors work
[cases.test_dirs_noent]
code = '''
lfs_t lfs;
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
// make a directory
lfsr_mkdir(&lfs, "ardvark") => 0;
// try to read a nonsense path
struct lfs_info info;
lfsr_stat(&lfs, "no", &info) => LFS_ERR_NOENT;
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "no") => LFS_ERR_NOENT;
lfsr_unmount(&lfs) => 0;
'''
# test that stat on root works
[cases.test_dirs_stat_root]
code = '''
lfs_t lfs;
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
// make a directory
lfsr_mkdir(&lfs, "ardvark") => 0;
// stat the root
struct lfs_info info;
lfsr_stat(&lfs, "/", &info) => 0;
assert(strcmp(info.name, "/") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_unmount(&lfs) => 0;
'''
# test that creating the same directory twice errors
[cases.test_dirs_mkdir_exists]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// make a directory
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// make the same directory, should error
lfsr_mkdir(&lfs, "ardvark") => LFS_ERR_EXIST;
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// and check that this didn't interfere with our original directory
struct lfs_info info;
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_dir_open(&lfs, &dir, "ardvark") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
# test that dir existance is the same before/after mkconsistent
[cases.test_dirs_mkdir_consistent]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// check if dir exists before mkconsistent
struct lfs_info info;
err = lfsr_stat(&lfs, "ardvark", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool exists = !err;
// and with dir_read
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// make a directory
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == exists);
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our mkdir worked with stat
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
// and with dir_read
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_dir_open(&lfs, &dir, "ardvark") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
# test what happens if we try to make root
[cases.test_dirs_mkdir_root]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// try to make root, which doesn't make sense
lfsr_mkdir(&lfs, "/") => LFS_ERR_INVAL;
// make a directory
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// try to make root, which doesn't make sense
lfsr_mkdir(&lfs, "/") => LFS_ERR_INVAL;
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// and check that this didn't interfere with our original directory
struct lfs_info info;
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_dir_open(&lfs, &dir, "ardvark") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
# test that creating a directory with an invalid path errors
[cases.test_dirs_mkdir_noent]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// make a directory
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// make a nonsense directory, should error
lfsr_mkdir(&lfs, "no/hmm") => LFS_ERR_NOENT;
// make a nonsense child directory, should error
lfsr_mkdir(&lfs, "ardvark/no/hmm") => LFS_ERR_NOENT;
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// and check that this didn't interfere with our original directory
struct lfs_info info;
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_dir_open(&lfs, &dir, "ardvark") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_mkdir_siblings]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// check if dirs exist before mkconsistent
struct lfs_info info;
err = lfsr_stat(&lfs, "ardvark", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfsr_stat(&lfs, "banana", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
err = lfsr_stat(&lfs, "cat", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool c_exists = !err;
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (b_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (c_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// make some directories
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == a_exists);
err = lfsr_mkdir(&lfs, "banana");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == b_exists);
err = lfsr_mkdir(&lfs, "cat");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == c_exists);
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our mkdir worked
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_dir_open(&lfs, &dir, "ardvark") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_dir_open(&lfs, &dir, "banana") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_dir_open(&lfs, &dir, "cat") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_mkdir_children]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// check if dirs exist before mkconsistent
struct lfs_info info;
err = lfsr_stat(&lfs, "ardvark", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfsr_stat(&lfs, "ardvark/banana", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
err = lfsr_stat(&lfs, "ardvark/banana/cat", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool c_exists = !err;
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
err = lfsr_dir_open(&lfs, &dir, "/ardvark");
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
assert(!err == a_exists);
if (a_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (b_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
err = lfsr_dir_open(&lfs, &dir, "/ardvark/banana");
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
assert(!err == b_exists);
if (b_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (c_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
// make some directories
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == a_exists);
err = lfsr_mkdir(&lfs, "ardvark/banana");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == b_exists);
err = lfsr_mkdir(&lfs, "ardvark/banana/cat");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == c_exists);
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our mkdirs worked
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "ardvark/banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "ardvark/banana/cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_dir_open(&lfs, &dir, "/ardvark") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_dir_open(&lfs, &dir, "/ardvark/banana") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_dir_open(&lfs, &dir, "/ardvark/banana/cat") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_mkdir_many]
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
defines.REMOUNT = [false, true]
# limit powerloss testing due to time
if = '!TEST_PLS || N <= 16'
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// make this many directories
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
}
// check that our mkdir worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
struct lfs_info info;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_open(&lfs, &dir, name) => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_mkdir_many_backwards]
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
defines.REMOUNT = [false, true]
# limit powerloss testing due to time
if = '!TEST_PLS || N <= 16'
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// make this many directories
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", (int)(N-1-i));
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
}
// check that our mkdir worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
struct lfs_info info;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_open(&lfs, &dir, name) => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_mkdir_many_2layers]
defines.N = [1, 2, 4, 8, 16]
defines.REMOUNT = [false, true]
# limit powerloss testing due to time
if = '!TEST_PLS || N <= 4'
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// make this many directories
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// containing this many directories
for (lfs_size_t j = 0; j < N; j++) {
sprintf(name, "dir%03x/child%03x", i, j);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
}
}
// check that our mkdirs worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
sprintf(name, "child%03x", j);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
}
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
struct lfs_info info;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_open(&lfs, &dir, name) => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "child%03x", j);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
for (lfs_size_t i = 0; i < N; i++) {
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
lfsr_dir_open(&lfs, &dir, name) => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_mkdir_many_3layers]
defines.N = [1, 2, 4]
defines.REMOUNT = [false, true]
# limit powerloss testing due to time
if = '!TEST_PLS || N <= 2'
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// make this many directories
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// containing this many directories
for (lfs_size_t j = 0; j < N; j++) {
sprintf(name, "dir%03x/child%03x", i, j);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// containing this many directories
for (lfs_size_t k = 0; k < N; k++) {
sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
}
}
}
// check that our mkdirs worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
sprintf(name, "child%03x", j);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t k = 0; k < N; k++) {
char name[256];
sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
sprintf(name, "grandchild%03x", k);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
}
}
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
struct lfs_info info;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_open(&lfs, &dir, name) => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "child%03x", j);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
lfsr_dir_open(&lfs, &dir, name) => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t k = 0; k < N; k++) {
char name[256];
sprintf(name, "grandchild%03x", k);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
}
for (lfs_size_t i = 0; i < N; i++) {
for (lfs_size_t j = 0; j < N; j++) {
for (lfs_size_t k = 0; k < N; k++) {
char name[256];
sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k);
lfsr_dir_open(&lfs, &dir, name) => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
}
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_mkdir_many_linkedlist]
defines.N = [1, 2, 4, 8, 16, 32, 64]
defines.REMOUNT = [false, true]
# limit powerloss testing due to time
if = '!TEST_PLS || N <= 16'
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// create this many directory in a sort of linked-list by nesting
char name[4096];
memset(name, 0, sizeof(name));
for (lfs_size_t i = 0; i < N; i++) {
sprintf(&name[strlen(name)], "/dir%03x", i);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
}
// check that our mkdir worked
memset(name, 0, sizeof(name));
for (lfs_size_t i = 0; i < N; i++) {
sprintf(&name[strlen(name)], "/dir%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
char name2[256];
sprintf(name2, "dir%03x", i);
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
memset(name, 0, sizeof(name));
for (lfs_size_t i = 0; i < N; i++) {
sprintf(&name[strlen(name)], "/dir%03x", i);
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, name) => 0;
struct lfs_info info;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (i < N-1) {
char name2[256];
sprintf(name2, "dir%03x", i+1);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_mkdir_fuzz]
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
defines.PARENT = [false, true]
defines.REMOUNT = [false, true]
defines.SEED = 'range(20)'
# limit powerloss testing due to time
if = '!TEST_PLS || N <= 16'
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
if (PARENT) {
err = lfsr_mkdir(&lfs, "pricklypear");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
}
// set up a simulation to compare against
lfs_size_t *sim = malloc(N*sizeof(lfs_size_t));
lfs_size_t sim_size = 0;
uint32_t prng = SEED;
for (lfs_size_t i = 0; i < N; i++) {
// choose a pseudo-random number, truncate to 3 hexadecimals
lfs_size_t x = TEST_PRNG(&prng) % 0x1000;
// insert into our sim
for (lfs_size_t j = 0;; j++) {
if (j >= sim_size || sim[j] >= x) {
// already seen?
if (j < sim_size && sim[j] == x) {
// do nothing
} else {
// insert
memmove(&sim[j+1], &sim[j],
(sim_size-j)*sizeof(lfs_size_t));
sim_size += 1;
sim[j] = x;
}
break;
}
}
// create a directory here
char name[256];
sprintf(name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), x);
int err = lfsr_mkdir(&lfs, name);
assert(!err || err == LFS_ERR_EXIST);
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// test that our directories match our simulation
for (lfs_size_t j = 0; j < sim_size; j++) {
char name[256];
sprintf(name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), sim[j]);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
char name2[256];
sprintf(name2, "dir%03x", sim[j]);
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, ((PARENT) ? "pricklypear" : "/")) => 0;
struct lfs_info info;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < sim_size; j++) {
char name[256];
sprintf(name, "dir%03x", sim[j]);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
for (lfs_size_t j = 0; j < sim_size; j++) {
char name[256];
sprintf(name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), sim[j]);
lfsr_dir_open(&lfs, &dir, name) => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
// clean up sim/lfs
free(sim);
lfsr_unmount(&lfs) => 0;
'''
# test some common ordering mistakes
[cases.test_dirs_ordering]
# ORDER=0 => inorder
# ORDER=1 => reversed
# ORDER=2 => random
defines.ORDER = [0, 1, 2]
defines.REMOUNT = [false, true]
code = '''
lfs_t lfs;
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
if (ORDER == 0) {
lfsr_mkdir(&lfs, "a") => 0;
lfsr_mkdir(&lfs, "b") => 0;
lfsr_mkdir(&lfs, "c") => 0;
lfsr_mkdir(&lfs, "d") => 0;
lfsr_mkdir(&lfs, "e") => 0;
lfsr_mkdir(&lfs, "f") => 0;
} else if (ORDER == 1) {
lfsr_mkdir(&lfs, "f") => 0;
lfsr_mkdir(&lfs, "e") => 0;
lfsr_mkdir(&lfs, "d") => 0;
lfsr_mkdir(&lfs, "c") => 0;
lfsr_mkdir(&lfs, "b") => 0;
lfsr_mkdir(&lfs, "a") => 0;
} else if (ORDER == 2) {
// "random", trust me
lfsr_mkdir(&lfs, "e") => 0;
lfsr_mkdir(&lfs, "c") => 0;
lfsr_mkdir(&lfs, "b") => 0;
lfsr_mkdir(&lfs, "d") => 0;
lfsr_mkdir(&lfs, "f") => 0;
lfsr_mkdir(&lfs, "a") => 0;
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our mkdirs worked
struct lfs_info info;
lfsr_stat(&lfs, "a", &info) => 0;
assert(strcmp(info.name, "a") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "b", &info) => 0;
assert(strcmp(info.name, "b") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "c", &info) => 0;
assert(strcmp(info.name, "c") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "d", &info) => 0;
assert(strcmp(info.name, "d") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "e", &info) => 0;
assert(strcmp(info.name, "e") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "f", &info) => 0;
assert(strcmp(info.name, "f") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
// check the directory order
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "a") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "b") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "c") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "d") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "e") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "f") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_ordering_length]
# ORDER=0 => inorder
# ORDER=1 => reversed
# ORDER=2 => random
defines.ORDER = [0, 1, 2]
defines.REMOUNT = [false, true]
code = '''
lfs_t lfs;
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
if (ORDER == 0) {
lfsr_mkdir(&lfs, "a") => 0;
lfsr_mkdir(&lfs, "aa") => 0;
lfsr_mkdir(&lfs, "aaa") => 0;
lfsr_mkdir(&lfs, "aaaa") => 0;
lfsr_mkdir(&lfs, "aaaaa") => 0;
lfsr_mkdir(&lfs, "aaaaaa") => 0;
} else if (ORDER == 1) {
lfsr_mkdir(&lfs, "aaaaaa") => 0;
lfsr_mkdir(&lfs, "aaaaa") => 0;
lfsr_mkdir(&lfs, "aaaa") => 0;
lfsr_mkdir(&lfs, "aaa") => 0;
lfsr_mkdir(&lfs, "aa") => 0;
lfsr_mkdir(&lfs, "a") => 0;
} else if (ORDER == 2) {
// "random", trust me
lfsr_mkdir(&lfs, "aaaaa") => 0;
lfsr_mkdir(&lfs, "aaa") => 0;
lfsr_mkdir(&lfs, "aa") => 0;
lfsr_mkdir(&lfs, "aaaa") => 0;
lfsr_mkdir(&lfs, "aaaaaa") => 0;
lfsr_mkdir(&lfs, "a") => 0;
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our mkdirs worked
struct lfs_info info;
lfsr_stat(&lfs, "a", &info) => 0;
assert(strcmp(info.name, "a") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "aa", &info) => 0;
assert(strcmp(info.name, "aa") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "aaa", &info) => 0;
assert(strcmp(info.name, "aaa") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "aaaa", &info) => 0;
assert(strcmp(info.name, "aaaa") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "aaaaa", &info) => 0;
assert(strcmp(info.name, "aaaaa") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "aaaaaa", &info) => 0;
assert(strcmp(info.name, "aaaaaa") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
// check the directory order
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "a") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "aa") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "aaa") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "aaaa") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "aaaaa") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "aaaaaa") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
# test that did collisions don't cause issues
[cases.test_dirs_did_collisions]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
assert(lfs_crc32c(0, "a_SNmwMTHH", 10) == 0x12345678);
assert(lfs_crc32c(0, "b_skvjpWJH", 10) == 0x12345678);
assert(lfs_crc32c(0, "c_OnOQhVPH", 10) == 0x12345678);
assert(lfs_crc32c(0, "d_puMpPjRH", 10) == 0x12345678);
assert(lfs_crc32c(0, "e_LptKHkHH", 10) == 0x12345678);
assert(lfs_crc32c(0, "f_lUoVuhJH", 10) == 0x12345678);
// check if dirs exist before mkconsistent
struct lfs_info info;
err = lfsr_stat(&lfs, "a_SNmwMTHH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfsr_stat(&lfs, "b_skvjpWJH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
err = lfsr_stat(&lfs, "c_OnOQhVPH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool c_exists = !err;
err = lfsr_stat(&lfs, "d_puMpPjRH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool d_exists = !err;
err = lfsr_stat(&lfs, "e_LptKHkHH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool e_exists = !err;
err = lfsr_stat(&lfs, "f_lUoVuhJH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool f_exists = !err;
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "a_SNmwMTHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (b_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "b_skvjpWJH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (c_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "c_OnOQhVPH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (d_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "d_puMpPjRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (e_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "e_LptKHkHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (f_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "f_lUoVuhJH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// make directories
err = lfsr_mkdir(&lfs, "a_SNmwMTHH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == a_exists);
err = lfsr_mkdir(&lfs, "b_skvjpWJH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == b_exists);
err = lfsr_mkdir(&lfs, "c_OnOQhVPH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == c_exists);
err = lfsr_mkdir(&lfs, "d_puMpPjRH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == d_exists);
err = lfsr_mkdir(&lfs, "e_LptKHkHH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == e_exists);
err = lfsr_mkdir(&lfs, "f_lUoVuhJH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == f_exists);
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our mkdirs worked
lfsr_stat(&lfs, "a_SNmwMTHH", &info) => 0;
assert(strcmp(info.name, "a_SNmwMTHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "b_skvjpWJH", &info) => 0;
assert(strcmp(info.name, "b_skvjpWJH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "c_OnOQhVPH", &info) => 0;
assert(strcmp(info.name, "c_OnOQhVPH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "d_puMpPjRH", &info) => 0;
assert(strcmp(info.name, "d_puMpPjRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "e_LptKHkHH", &info) => 0;
assert(strcmp(info.name, "e_LptKHkHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "f_lUoVuhJH", &info) => 0;
assert(strcmp(info.name, "f_lUoVuhJH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "a_SNmwMTHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "b_skvjpWJH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "c_OnOQhVPH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "d_puMpPjRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "e_LptKHkHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "f_lUoVuhJH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
# these will also collide with the root
[cases.test_dirs_did_zero]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
assert(lfs_crc32c(0, "a_IplRNrPH", 10) == 0x00000000);
assert(lfs_crc32c(0, "b_iUwOsqRH", 10) == 0x00000000);
assert(lfs_crc32c(0, "c_UPNtkpHH", 10) == 0x00000000);
assert(lfs_crc32c(0, "d_jKLUSLJH", 10) == 0x00000000);
assert(lfs_crc32c(0, "e_VNunKMPH", 10) == 0x00000000);
assert(lfs_crc32c(0, "f_vknsvNRH", 10) == 0x00000000);
// check if dirs exist before mkconsistent
struct lfs_info info;
err = lfsr_stat(&lfs, "a_IplRNrPH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfsr_stat(&lfs, "b_iUwOsqRH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
err = lfsr_stat(&lfs, "c_UPNtkpHH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool c_exists = !err;
err = lfsr_stat(&lfs, "d_jKLUSLJH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool d_exists = !err;
err = lfsr_stat(&lfs, "e_VNunKMPH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool e_exists = !err;
err = lfsr_stat(&lfs, "f_vknsvNRH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool f_exists = !err;
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "a_IplRNrPH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (b_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "b_iUwOsqRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (c_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "c_UPNtkpHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (d_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "d_jKLUSLJH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (e_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "e_VNunKMPH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (f_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "f_vknsvNRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// make directories
err = lfsr_mkdir(&lfs, "a_IplRNrPH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == a_exists);
err = lfsr_mkdir(&lfs, "b_iUwOsqRH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == b_exists);
err = lfsr_mkdir(&lfs, "c_UPNtkpHH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == c_exists);
err = lfsr_mkdir(&lfs, "d_jKLUSLJH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == d_exists);
err = lfsr_mkdir(&lfs, "e_VNunKMPH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == e_exists);
err = lfsr_mkdir(&lfs, "f_vknsvNRH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == f_exists);
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our mkdirs worked
lfsr_stat(&lfs, "a_IplRNrPH", &info) => 0;
assert(strcmp(info.name, "a_IplRNrPH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "b_iUwOsqRH", &info) => 0;
assert(strcmp(info.name, "b_iUwOsqRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "c_UPNtkpHH", &info) => 0;
assert(strcmp(info.name, "c_UPNtkpHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "d_jKLUSLJH", &info) => 0;
assert(strcmp(info.name, "d_jKLUSLJH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "e_VNunKMPH", &info) => 0;
assert(strcmp(info.name, "e_VNunKMPH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "f_vknsvNRH", &info) => 0;
assert(strcmp(info.name, "f_vknsvNRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "a_IplRNrPH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "b_iUwOsqRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "c_UPNtkpHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "d_jKLUSLJH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "e_VNunKMPH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "f_vknsvNRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
# these will need to rollover from 0xffffffff -> 0x00000000 correctly
#
# note this is true even if you truncate
[cases.test_dirs_did_ones]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
assert(lfs_crc32c(0, "a_iomlVKPH", 10) == 0xffffffff);
assert(lfs_crc32c(0, "b_IJvqkHRH", 10) == 0xffffffff);
assert(lfs_crc32c(0, "c_uOOJsIHH", 10) == 0xffffffff);
assert(lfs_crc32c(0, "d_JTMkKuJH", 10) == 0xffffffff);
assert(lfs_crc32c(0, "e_vQtPStPH", 10) == 0xffffffff);
assert(lfs_crc32c(0, "f_VtoMnwRH", 10) == 0xffffffff);
// check if dirs exist before mkconsistent
struct lfs_info info;
err = lfsr_stat(&lfs, "a_iomlVKPH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfsr_stat(&lfs, "b_IJvqkHRH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
err = lfsr_stat(&lfs, "c_uOOJsIHH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool c_exists = !err;
err = lfsr_stat(&lfs, "d_JTMkKuJH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool d_exists = !err;
err = lfsr_stat(&lfs, "e_vQtPStPH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool e_exists = !err;
err = lfsr_stat(&lfs, "f_VtoMnwRH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool f_exists = !err;
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "a_iomlVKPH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (b_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "b_IJvqkHRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (c_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "c_uOOJsIHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (d_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "d_JTMkKuJH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (e_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "e_vQtPStPH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (f_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "f_VtoMnwRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// make directories
err = lfsr_mkdir(&lfs, "a_iomlVKPH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == a_exists);
err = lfsr_mkdir(&lfs, "b_IJvqkHRH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == b_exists);
err = lfsr_mkdir(&lfs, "c_uOOJsIHH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == c_exists);
err = lfsr_mkdir(&lfs, "d_JTMkKuJH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == d_exists);
err = lfsr_mkdir(&lfs, "e_vQtPStPH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == e_exists);
err = lfsr_mkdir(&lfs, "f_VtoMnwRH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == f_exists);
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our mkdirs worked
lfsr_stat(&lfs, "a_iomlVKPH", &info) => 0;
assert(strcmp(info.name, "a_iomlVKPH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "b_IJvqkHRH", &info) => 0;
assert(strcmp(info.name, "b_IJvqkHRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "c_uOOJsIHH", &info) => 0;
assert(strcmp(info.name, "c_uOOJsIHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "d_JTMkKuJH", &info) => 0;
assert(strcmp(info.name, "d_JTMkKuJH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "e_vQtPStPH", &info) => 0;
assert(strcmp(info.name, "e_vQtPStPH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "f_VtoMnwRH", &info) => 0;
assert(strcmp(info.name, "f_VtoMnwRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "a_iomlVKPH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "b_IJvqkHRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "c_uOOJsIHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "d_JTMkKuJH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "e_vQtPStPH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "f_VtoMnwRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
# these test some boundary conditions on the underlying leb128 encoding,
# if the leb128 disk-size is not calculated correctly these can cause
# issues
[cases.test_dirs_did_leb128_boundaries]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
assert(lfs_crc32c(0, "a_IOtUptRH", 10) == 0x0000007f);
assert(lfs_crc32c(0, "b_nquQsKHH", 10) == 0x00000080);
assert(lfs_crc32c(0, "c_vwQtKjHH", 10) == 0x00000081);
assert(lfs_crc32c(0, "d_sVrvrWHH", 10) == 0x00003fff);
assert(lfs_crc32c(0, "e_thrRIsRH", 10) == 0x00004000);
assert(lfs_crc32c(0, "f_pNtQTPJH", 10) == 0x00004001);
// check if dirs exist before mkconsistent
struct lfs_info info;
err = lfsr_stat(&lfs, "a_IOtUptRH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfsr_stat(&lfs, "b_nquQsKHH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
err = lfsr_stat(&lfs, "c_vwQtKjHH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool c_exists = !err;
err = lfsr_stat(&lfs, "d_sVrvrWHH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool d_exists = !err;
err = lfsr_stat(&lfs, "e_thrRIsRH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool e_exists = !err;
err = lfsr_stat(&lfs, "f_pNtQTPJH", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool f_exists = !err;
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "a_IOtUptRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (b_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "b_nquQsKHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (c_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "c_vwQtKjHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (d_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "d_sVrvrWHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (e_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "e_thrRIsRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (f_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "f_pNtQTPJH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// make directories
err = lfsr_mkdir(&lfs, "a_IOtUptRH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == a_exists);
err = lfsr_mkdir(&lfs, "b_nquQsKHH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == b_exists);
err = lfsr_mkdir(&lfs, "c_vwQtKjHH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == c_exists);
err = lfsr_mkdir(&lfs, "d_sVrvrWHH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == d_exists);
err = lfsr_mkdir(&lfs, "e_thrRIsRH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == e_exists);
err = lfsr_mkdir(&lfs, "f_pNtQTPJH");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == f_exists);
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our mkdirs worked
lfsr_stat(&lfs, "a_IOtUptRH", &info) => 0;
assert(strcmp(info.name, "a_IOtUptRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "b_nquQsKHH", &info) => 0;
assert(strcmp(info.name, "b_nquQsKHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "c_vwQtKjHH", &info) => 0;
assert(strcmp(info.name, "c_vwQtKjHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "d_sVrvrWHH", &info) => 0;
assert(strcmp(info.name, "d_sVrvrWHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "e_thrRIsRH", &info) => 0;
assert(strcmp(info.name, "e_thrRIsRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "f_pNtQTPJH", &info) => 0;
assert(strcmp(info.name, "f_pNtQTPJH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "a_IOtUptRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "b_nquQsKHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "c_vwQtKjHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "d_sVrvrWHH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "e_thrRIsRH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "f_pNtQTPJH") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
## dir remove tests
[cases.test_dirs_rm]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// make a directory
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our mkdir worked with stat
struct lfs_info info;
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
// and with dir_read
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// and remove the directory
lfsr_remove(&lfs, "ardvark") => 0;
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that remove worked with stat
lfsr_stat(&lfs, "ardvark", &info) => LFS_ERR_NOENT;
// and with dir_read
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
# test that noent errors work
[cases.test_dirs_rm_noent]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// make a directory
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// try to remove a nonsense directory
lfsr_remove(&lfs, "no") => LFS_ERR_NOENT;
// try to remove a directory in a nonsense directory
lfsr_remove(&lfs, "no/ardvark") => LFS_ERR_NOENT;
// try to remove a nonsense child directory
lfsr_remove(&lfs, "ardvark/no") => LFS_ERR_NOENT;
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// and check that this didn't interfere with our original directory
struct lfs_info info;
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
# test that we catch removing of a non-empty directory
[cases.test_dirs_rm_notempty]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// make a directory
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// fill it with stuff
err = lfsr_mkdir(&lfs, "ardvark/banana");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// try to remove the parent directory
lfsr_remove(&lfs, "ardvark") => LFS_ERR_NOTEMPTY;
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// and check that this didn't interfere with our original directory
struct lfs_info info;
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "ardvark/banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_dir_open(&lfs, &dir, "ardvark") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
# test that dir existance is the same before/after mkconsistent
[cases.test_dirs_rm_consistent]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// check if dir exists before mkconsistent
struct lfs_info info;
err = lfsr_stat(&lfs, "ardvark", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool exists = !err;
// and with dir_read
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// make a directory
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == exists);
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our mkdir worked with stat
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
// and with dir_read
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// and remove the directory
lfsr_remove(&lfs, "ardvark") => 0;
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that remove worked with stat
lfsr_stat(&lfs, "ardvark", &info) => LFS_ERR_NOENT;
// and with dir_read
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
# test what happens if we try to remove root
[cases.test_dirs_rm_root]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// try to remove root, which doesn't really make sense
lfsr_remove(&lfs, "/") => LFS_ERR_INVAL;
// make a directory
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// try to remove root, which doesn't really make sense
//
// it doesn't really matter which error returns first, so accept both
err = lfsr_remove(&lfs, "/");
assert(err == LFS_ERR_NOTEMPTY || err == LFS_ERR_INVAL);
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// and check that this didn't interfere with our original directory
struct lfs_info info;
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_rm_siblings]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// check if dirs exist before mkconsistent
struct lfs_info info;
err = lfsr_stat(&lfs, "ardvark", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfsr_stat(&lfs, "banana", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
err = lfsr_stat(&lfs, "cat", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool c_exists = !err;
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (b_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (c_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// make some directories
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == a_exists);
err = lfsr_mkdir(&lfs, "banana");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == b_exists);
err = lfsr_mkdir(&lfs, "cat");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == c_exists);
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our mkdir worked
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// now remove each directory
lfsr_remove(&lfs, "ardvark") => 0;
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our remove worked
lfsr_stat(&lfs, "ardvark", &info) => LFS_ERR_NOENT;
lfsr_stat(&lfs, "banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// remove another
lfsr_remove(&lfs, "banana") => 0;
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our remove worked
lfsr_stat(&lfs, "ardvark", &info) => LFS_ERR_NOENT;
lfsr_stat(&lfs, "banana", &info) => LFS_ERR_NOENT;
lfsr_stat(&lfs, "cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// remove another
lfsr_remove(&lfs, "cat") => 0;
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our remove worked
lfsr_stat(&lfs, "ardvark", &info) => LFS_ERR_NOENT;
lfsr_stat(&lfs, "banana", &info) => LFS_ERR_NOENT;
lfsr_stat(&lfs, "cat", &info) => LFS_ERR_NOENT;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_rm_children]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// check if dirs exist before mkconsistent
struct lfs_info info;
err = lfsr_stat(&lfs, "ardvark", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfsr_stat(&lfs, "ardvark/banana", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
err = lfsr_stat(&lfs, "ardvark/banana/cat", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool c_exists = !err;
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
err = lfsr_dir_open(&lfs, &dir, "/ardvark");
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
assert(!err == a_exists);
if (a_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (b_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
err = lfsr_dir_open(&lfs, &dir, "/ardvark/banana");
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
assert(!err == b_exists);
if (b_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (c_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
// make some directories
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == a_exists);
err = lfsr_mkdir(&lfs, "ardvark/banana");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == b_exists);
err = lfsr_mkdir(&lfs, "ardvark/banana/cat");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == c_exists);
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our mkdirs worked
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "ardvark/banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "ardvark/banana/cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_dir_open(&lfs, &dir, "/ardvark") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_dir_open(&lfs, &dir, "/ardvark/banana") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// now remove each directory
lfsr_remove(&lfs, "ardvark/banana/cat") => 0;
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our remove worked
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "ardvark/banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "ardvark/banana/cat", &info) => LFS_ERR_NOENT;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_dir_open(&lfs, &dir, "/ardvark") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_dir_open(&lfs, &dir, "/ardvark/banana") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// remove another
lfsr_remove(&lfs, "ardvark/banana") => 0;
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our remove worked
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "ardvark/banana", &info) => LFS_ERR_NOENT;
lfsr_stat(&lfs, "ardvark/banana/cat", &info) => LFS_ERR_NOENT;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_dir_open(&lfs, &dir, "/ardvark") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// remove another
lfsr_remove(&lfs, "ardvark") => 0;
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our remove worked
lfsr_stat(&lfs, "ardvark", &info) => LFS_ERR_NOENT;
lfsr_stat(&lfs, "ardvark/banana", &info) => LFS_ERR_NOENT;
lfsr_stat(&lfs, "ardvark/banana/cat", &info) => LFS_ERR_NOENT;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_rm_many]
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
defines.REMAINING = [64, 2, 1, 0]
defines.REMOUNT = [false, true]
if = [
'N > REMAINING',
# limit powerloss testing due to time
'!TEST_PLS || N <= 16',
]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// make this many directories
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our mkdir worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
struct lfs_info info;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// now remove some number of directories
for (lfs_size_t i = 0; i < N-REMAINING; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_remove(&lfs, name) => 0;
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
}
// check that our removes worked
for (lfs_size_t i = 0; i < N-REMAINING; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => LFS_ERR_NOENT;
}
for (lfs_size_t i = 0; i < REMAINING; i++) {
char name[256];
sprintf(name, "dir%03x", (int)(N-REMAINING + i));
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < REMAINING; i++) {
char name[256];
sprintf(name, "dir%03x", (int)(N-REMAINING + i));
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_rm_many_backwards]
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
defines.REMAINING = [64, 2, 1, 0]
defines.REMOUNT = [false, true]
if = [
'N > REMAINING',
# limit powerloss testing due to time
'!TEST_PLS || N <= 16',
]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// make this many directories
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", (int)(N-1-i));
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our mkdir worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
struct lfs_info info;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// now remove some number of directories
for (lfs_size_t i = 0; i < N-REMAINING; i++) {
char name[256];
sprintf(name, "dir%03x", (int)(N-1-i));
lfsr_remove(&lfs, name) => 0;
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
}
// check that our removes worked
for (lfs_size_t i = 0; i < N-REMAINING; i++) {
char name[256];
sprintf(name, "dir%03x", (int)(N-1-i));
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => LFS_ERR_NOENT;
}
for (lfs_size_t i = 0; i < REMAINING; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < REMAINING; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_rm_many_2layers]
defines.N = [1, 2, 4, 8, 16]
defines.REMAINING = [2, 1, 0]
defines.REMOUNT = [false, true]
if = [
'N > REMAINING',
# limit powerloss testing due to time
'!TEST_PLS || N <= 4',
# TODO fix this case, it's failing because a mkdir is lining up with an
# mdir split, and the chosen split name makes it so our did should have
# ended up in the previous mdir
'!(TEST_PLS && N == 4)',
]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// make this many directories
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// containing this many directories
for (lfs_size_t j = 0; j < N; j++) {
sprintf(name, "dir%03x/child%03x", i, j);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
}
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our mkdirs worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
sprintf(name, "child%03x", j);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
}
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
struct lfs_info info;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_open(&lfs, &dir, name) => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "child%03x", j);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
// now remove some number of directories
for (lfs_size_t i = 0; i < N; i++) {
for (lfs_size_t j = 0; j < N; j++) {
if (i < N-REMAINING || j < N-REMAINING) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
lfsr_remove(&lfs, name) => 0;
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
}
if (i < N-REMAINING) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_remove(&lfs, name) => 0;
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
}
// check that our removes worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs_info info;
if (i < N-REMAINING) {
lfsr_stat(&lfs, name, &info) => LFS_ERR_NOENT;
} else {
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
struct lfs_info info;
if (j < N-REMAINING) {
lfsr_stat(&lfs, name, &info) => LFS_ERR_NOENT;
} else {
lfsr_stat(&lfs, name, &info) => 0;
sprintf(name, "child%03x", j);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
}
}
}
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < REMAINING; i++) {
char name[256];
sprintf(name, "dir%03x", (int)(N-REMAINING + i));
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
for (lfs_size_t i = 0; i < REMAINING; i++) {
char name[256];
sprintf(name, "dir%03x", (int)(N-REMAINING + i));
lfsr_dir_open(&lfs, &dir, name) => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < REMAINING; j++) {
char name[256];
sprintf(name, "child%03x", (int)(N-REMAINING + j));
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_rm_many_3layers]
defines.N = [1, 2, 4]
defines.REMAINING = [2, 1, 0]
defines.REMOUNT = [false, true]
if = [
'N > REMAINING',
# limit powerloss testing due to time
'!TEST_PLS || N <= 2',
]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// make this many directories
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// containing this many directories
for (lfs_size_t j = 0; j < N; j++) {
sprintf(name, "dir%03x/child%03x", i, j);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// containing this many directories
for (lfs_size_t k = 0; k < N; k++) {
sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
}
}
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our mkdirs worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
sprintf(name, "child%03x", j);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t k = 0; k < N; k++) {
char name[256];
sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
sprintf(name, "grandchild%03x", k);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
}
}
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
struct lfs_info info;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_open(&lfs, &dir, name) => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "child%03x", j);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
lfsr_dir_open(&lfs, &dir, name) => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t k = 0; k < N; k++) {
char name[256];
sprintf(name, "grandchild%03x", k);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
}
// now remove some number of directories
for (lfs_size_t i = 0; i < N; i++) {
for (lfs_size_t j = 0; j < N; j++) {
for (lfs_size_t k = 0; k < N; k++) {
if (i < N-REMAINING || j < N-REMAINING || k < N-REMAINING) {
char name[256];
sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k);
lfsr_remove(&lfs, name) => 0;
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
}
if (i < N-REMAINING || j < N-REMAINING) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
lfsr_remove(&lfs, name) => 0;
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
}
if (i < N-REMAINING) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_remove(&lfs, name) => 0;
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
}
// check that our removes worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs_info info;
if (i < N-REMAINING) {
lfsr_stat(&lfs, name, &info) => LFS_ERR_NOENT;
} else {
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
struct lfs_info info;
if (j < N-REMAINING) {
lfsr_stat(&lfs, name, &info) => LFS_ERR_NOENT;
} else {
lfsr_stat(&lfs, name, &info) => 0;
sprintf(name, "child%03x", j);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t k = 0; k < N; k++) {
char name[256];
sprintf(name, "dir%03x/child%03x/grandchild%03x",
i, j, k);
struct lfs_info info;
if (k < N-REMAINING) {
lfsr_stat(&lfs, name, &info) => LFS_ERR_NOENT;
} else {
lfsr_stat(&lfs, name, &info) => 0;
sprintf(name, "grandchild%03x", k);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
}
}
}
}
}
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < REMAINING; i++) {
char name[256];
sprintf(name, "dir%03x", (int)(N-REMAINING + i));
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
for (lfs_size_t i = 0; i < REMAINING; i++) {
char name[256];
sprintf(name, "dir%03x", (int)(N-REMAINING + i));
lfsr_dir_open(&lfs, &dir, name) => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < REMAINING; j++) {
char name[256];
sprintf(name, "child%03x", (int)(N-REMAINING + j));
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
for (lfs_size_t i = 0; i < REMAINING; i++) {
for (lfs_size_t j = 0; j < REMAINING; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x",
(int)(N-REMAINING + i),
(int)(N-REMAINING + j));
lfsr_dir_open(&lfs, &dir, name) => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t k = 0; k < REMAINING; k++) {
char name[256];
sprintf(name, "grandchild%03x", (int)(N-REMAINING + k));
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_rm_many_linkedlist]
defines.N = [1, 2, 4, 8, 16, 32, 64]
defines.REMAINING = [16, 2, 1, 0]
defines.REMOUNT = [false, true]
if = [
'N > REMAINING',
# limit powerloss testing due to time
'!TEST_PLS || N <= 16',
]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// create this many directory in a sort of linked-list by nesting
char name[4096];
memset(name, 0, sizeof(name));
for (lfs_size_t i = 0; i < N; i++) {
sprintf(&name[strlen(name)], "/dir%03x", i);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our mkdir worked
memset(name, 0, sizeof(name));
for (lfs_size_t i = 0; i < N; i++) {
sprintf(&name[strlen(name)], "/dir%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
char name2[256];
sprintf(name2, "dir%03x", i);
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
memset(name, 0, sizeof(name));
for (lfs_size_t i = 0; i < N; i++) {
sprintf(&name[strlen(name)], "/dir%03x", i);
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, name) => 0;
struct lfs_info info;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (i < N-1) {
char name2[256];
sprintf(name2, "dir%03x", i+1);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
// now remove some number of directories
for (lfs_size_t i = 0; i < N-REMAINING; i++) {
lfsr_remove(&lfs, name) => 0;
name[strlen(name) - strlen("/dir...")] = '\0';
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
}
// check that our remove worked
memset(name, 0, sizeof(name));
for (lfs_size_t i = 0; i < REMAINING; i++) {
sprintf(&name[strlen(name)], "/dir%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
char name2[256];
sprintf(name2, "dir%03x", i);
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
memset(name, 0, sizeof(name));
for (lfs_size_t i = 0; i < REMAINING; i++) {
sprintf(&name[strlen(name)], "/dir%03x", i);
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, name) => 0;
struct lfs_info info;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (i < REMAINING-1) {
char name2[256];
sprintf(name2, "dir%03x", i+1);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_rm_fuzz]
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
defines.PARENT = [false, true]
defines.REMOUNT = [false, true]
defines.SEED = 'range(20)'
# limit powerloss testing due to time
if = '!TEST_PLS || N <= 16'
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
if (PARENT) {
err = lfsr_mkdir(&lfs, "pricklypear");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
}
// set up a simulation to compare against
lfs_size_t *sim = malloc(N*sizeof(lfs_size_t));
lfs_size_t sim_size = 0;
uint32_t prng = SEED;
for (lfs_size_t i = 0; i < N; i++) {
// choose a pseudo-random op, either mkdir or rmdir
uint8_t op = TEST_PRNG(&prng) % 2;
if (op == 0 || sim_size == 0) {
// choose a pseudo-random number, truncate to 3 hexadecimals
lfs_size_t x = TEST_PRNG(&prng) % 0x1000;
// insert into our sim
for (lfs_size_t j = 0;; j++) {
if (j >= sim_size || sim[j] >= x) {
// already seen?
if (j < sim_size && sim[j] == x) {
// do nothing
} else {
// insert
memmove(&sim[j+1], &sim[j],
(sim_size-j)*sizeof(lfs_size_t));
sim_size += 1;
sim[j] = x;
}
break;
}
}
// create a directory here
char name[256];
sprintf(name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), x);
int err = lfsr_mkdir(&lfs, name);
assert(!err || err == LFS_ERR_EXIST);
} else {
// choose a pseudo-random entry to delete
lfs_size_t j = TEST_PRNG(&prng) % sim_size;
lfs_size_t x = sim[j];
// delete from our sim
memmove(&sim[j], &sim[j+1],
(sim_size-(j+1))*sizeof(lfs_size_t));
sim_size -= 1;
// remove this directory
char name[256];
sprintf(name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), x);
lfsr_remove(&lfs, name) => 0;
}
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// test that our directories match our simulation
for (lfs_size_t j = 0; j < sim_size; j++) {
char name[256];
sprintf(name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), sim[j]);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
char name2[256];
sprintf(name2, "dir%03x", sim[j]);
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, ((PARENT) ? "pricklypear" : "/")) => 0;
struct lfs_info info;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < sim_size; j++) {
char name[256];
sprintf(name, "dir%03x", sim[j]);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// clean up sim/lfs
free(sim);
lfsr_unmount(&lfs) => 0;
'''
## dir rename tests
[cases.test_dirs_mv]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// make a directory
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// clean up interrupted renames
if (TEST_PLS) {
err = lfsr_remove(&lfs, "banana");
assert(!err || err == LFS_ERR_NOENT);
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our mkdir worked with stat
struct lfs_info info;
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
// and with dir_read
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// now rename the directory
lfsr_rename(&lfs, "ardvark", "banana") => 0;
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that rename worked with stat
lfsr_stat(&lfs, "ardvark", &info) => LFS_ERR_NOENT;
lfsr_stat(&lfs, "banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
// and with dir_read
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
# test that we can rename, and replace, other directories
[cases.test_dirs_mv_replace]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// make directories
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
err = lfsr_mkdir(&lfs, "banana");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our mkdir worked with stat
struct lfs_info info;
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
// and with dir_read
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// now rename the directory
lfsr_rename(&lfs, "ardvark", "banana") => 0;
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that rename worked with stat
lfsr_stat(&lfs, "ardvark", &info) => LFS_ERR_NOENT;
lfsr_stat(&lfs, "banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
// and with dir_read
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
# test that we can rename to ourselves
[cases.test_dirs_mv_noop]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// make directories
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our mkdir worked with stat
struct lfs_info info;
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
// and with dir_read
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// now rename the directory to itself
lfsr_rename(&lfs, "ardvark", "ardvark") => 0;
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that rename worked with stat
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
// and with dir_read
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
# test that we catch replacing an invalid path
[cases.test_dirs_mv_noent]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// make directories
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// try to rename a nonsense directory
lfsr_rename(&lfs, "no", "ardvark") => LFS_ERR_NOENT;
// try to rename a directory in a nonsense directory
lfsr_rename(&lfs, "no/ardvark", "ardvark") => LFS_ERR_NOENT;
// try to rename a nonsense child directory
lfsr_rename(&lfs, "ardvark/no", "banana") => LFS_ERR_NOENT;
// try to rename to a nonense directory
lfsr_rename(&lfs, "ardvark", "no/ardvark") => LFS_ERR_NOENT;
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// and check that this didn't interfere with our original directory
struct lfs_info info;
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
# test that we catch replacing a non-empty directory
[cases.test_dirs_mv_notempty]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// make directories
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
err = lfsr_mkdir(&lfs, "banana");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// fill dest with stuff
err = lfsr_mkdir(&lfs, "banana/cat");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// try to rename
lfsr_rename(&lfs, "ardvark", "banana") => LFS_ERR_NOTEMPTY;
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// and check that this didn't interfere with our original directory
struct lfs_info info;
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "banana/cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_dir_open(&lfs, &dir, "banana") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
# test that dir existance is the same before/after mkconsistent
[cases.test_dirs_mv_consistent]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// check if dirs exist before mkconsistent
struct lfs_info info;
err = lfsr_stat(&lfs, "ardvark", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfsr_stat(&lfs, "banana", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
// and with dir_read
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (b_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// make a directory
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == a_exists);
// clean up interrupted renames
if (TEST_PLS) {
err = lfsr_remove(&lfs, "banana");
assert(!err || err == LFS_ERR_NOENT);
assert(!err == b_exists);
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our mkdir worked with stat
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
// and with dir_read
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// now rename the directory
lfsr_rename(&lfs, "ardvark", "banana") => 0;
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that rename worked with stat
lfsr_stat(&lfs, "ardvark", &info) => LFS_ERR_NOENT;
lfsr_stat(&lfs, "banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
// and with dir_read
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
# test what happens if we try to rename root
[cases.test_dirs_mv_root]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// try to rename root, which doesn't really make sense
lfsr_rename(&lfs, "/", "notroot") => LFS_ERR_INVAL;
// make a directory
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// try to rename root, which doesn't really make sense
lfsr_rename(&lfs, "/", "notroot") => LFS_ERR_INVAL;
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// and check that this didn't interfere with our original directory
struct lfs_info info;
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_mv_siblings]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// check if dirs exist before mkconsistent
struct lfs_info info;
err = lfsr_stat(&lfs, "ardvark", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfsr_stat(&lfs, "banana", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
err = lfsr_stat(&lfs, "cat", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool c_exists = !err;
err = lfsr_stat(&lfs, "disco", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool d_exists = !err;
err = lfsr_stat(&lfs, "eggplant", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool e_exists = !err;
err = lfsr_stat(&lfs, "fish", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool f_exists = !err;
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (b_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (c_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (d_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (e_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "eggplant") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (f_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "fish") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// make some directories
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == a_exists);
err = lfsr_mkdir(&lfs, "banana");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == b_exists);
err = lfsr_mkdir(&lfs, "cat");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == c_exists);
// clean up interrupted renames
if (TEST_PLS) {
err = lfsr_remove(&lfs, "disco");
assert(!err || err == LFS_ERR_NOENT);
assert(!err == d_exists);
err = lfsr_remove(&lfs, "eggplant");
assert(!err || err == LFS_ERR_NOENT);
assert(!err == e_exists);
err = lfsr_remove(&lfs, "fish");
assert(!err || err == LFS_ERR_NOENT);
assert(!err == f_exists);
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our mkdir worked
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// now rename each directory
lfsr_rename(&lfs, "ardvark", "disco") => 0;
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our rename worked
lfsr_stat(&lfs, "banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "disco", &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// rename another
lfsr_rename(&lfs, "banana", "eggplant") => 0;
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our rename worked
lfsr_stat(&lfs, "cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "disco", &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "eggplant", &info) => 0;
assert(strcmp(info.name, "eggplant") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "eggplant") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// rename another
lfsr_rename(&lfs, "cat", "fish") => 0;
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our rename worked
lfsr_stat(&lfs, "disco", &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "eggplant", &info) => 0;
assert(strcmp(info.name, "eggplant") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "fish", &info) => 0;
assert(strcmp(info.name, "fish") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "eggplant") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "fish") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_mv_children]
defines.REMOUNT = [false, true]
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// check if dirs exist before mkconsistent
struct lfs_info info;
err = lfsr_stat(&lfs, "ardvark", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool a_exists = !err;
err = lfsr_stat(&lfs, "ardvark/banana", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool b_exists = !err;
err = lfsr_stat(&lfs, "ardvark/banana/cat", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool c_exists = !err;
err = lfsr_stat(&lfs, "disco", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool d_exists = !err;
err = lfsr_stat(&lfs, "disco/eggplant", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool e_exists = !err;
err = lfsr_stat(&lfs, "disco/eggplant/fish", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool f_exists = !err;
err = lfsr_stat(&lfs, "disco/banana", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool db_exists = !err;
err = lfsr_stat(&lfs, "disco/banana/cat", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool dbc_exists = !err;
err = lfsr_stat(&lfs, "disco/eggplant/cat", &info);
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
bool dec_exists = !err;
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (a_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (d_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
err = lfsr_dir_open(&lfs, &dir, "/ardvark");
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
assert(!err == a_exists);
if (a_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (b_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
err = lfsr_dir_open(&lfs, &dir, "/ardvark/banana");
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
assert(!err == b_exists);
if (b_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (c_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
err = lfsr_dir_open(&lfs, &dir, "/disco");
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
assert(!err == d_exists);
if (d_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (db_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (e_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "eggplant") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
err = lfsr_dir_open(&lfs, &dir, "/disco/eggplant");
assert(err == LFS_ERR_NOENT || (TEST_PLS && !err));
assert(!err == e_exists);
if (e_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (dec_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
if (f_exists) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "fish") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
// make some directories
err = lfsr_mkdir(&lfs, "ardvark");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == a_exists);
err = lfsr_mkdir(&lfs, "ardvark/banana");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == b_exists);
err = lfsr_mkdir(&lfs, "ardvark/banana/cat");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
assert((err == LFS_ERR_EXIST) == c_exists);
// clean up interrupted renames
if (TEST_PLS) {
err = lfsr_remove(&lfs, "disco/eggplant/fish");
assert(!err || err == LFS_ERR_NOENT);
assert(!err == f_exists);
err = lfsr_remove(&lfs, "disco/eggplant/cat");
assert(!err || err == LFS_ERR_NOENT);
assert(!err == dec_exists);
err = lfsr_remove(&lfs, "disco/eggplant");
assert(!err || err == LFS_ERR_NOENT);
assert(!err == e_exists);
err = lfsr_remove(&lfs, "disco/banana/cat");
assert(!err || err == LFS_ERR_NOENT);
assert(!err == dbc_exists);
err = lfsr_remove(&lfs, "disco/banana");
assert(!err || err == LFS_ERR_NOENT);
assert(!err == db_exists);
err = lfsr_remove(&lfs, "disco");
assert(!err || err == LFS_ERR_NOENT);
assert(!err == d_exists);
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our mkdirs worked
lfsr_stat(&lfs, "ardvark", &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "ardvark/banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "ardvark/banana/cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "ardvark") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_dir_open(&lfs, &dir, "/ardvark") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_dir_open(&lfs, &dir, "/ardvark/banana") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// now rename each directory
lfsr_rename(&lfs, "ardvark", "disco") => 0;
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our rename worked
lfsr_stat(&lfs, "disco", &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "disco/banana", &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "disco/banana/cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_dir_open(&lfs, &dir, "/disco") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "banana") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_dir_open(&lfs, &dir, "/disco/banana") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// rename another
lfsr_rename(&lfs, "disco/banana", "disco/eggplant") => 0;
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our rename worked
lfsr_stat(&lfs, "disco", &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "disco/eggplant", &info) => 0;
assert(strcmp(info.name, "eggplant") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "disco/eggplant/cat", &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_dir_open(&lfs, &dir, "/disco") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "eggplant") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_dir_open(&lfs, &dir, "/disco/eggplant") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "cat") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// rename another
lfsr_rename(&lfs, "disco/eggplant/cat", "disco/eggplant/fish") => 0;
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our rename worked
lfsr_stat(&lfs, "disco", &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "disco/eggplant", &info) => 0;
assert(strcmp(info.name, "eggplant") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_stat(&lfs, "disco/eggplant/fish", &info) => 0;
assert(strcmp(info.name, "fish") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "disco") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_dir_open(&lfs, &dir, "/disco") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "eggplant") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_dir_open(&lfs, &dir, "/disco/eggplant") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "fish") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_mv_many]
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
defines.BEFORE = [false, true]
defines.REMOUNT = [false, true]
# limit powerloss testing due to time
if = '!TEST_PLS || N <= 16'
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// check if we have already started renaming, in case of powerloss
struct lfs_info info;
err = lfsr_stat(&lfs, ((BEFORE) ? "/0mved000" : "/mved000"), &info);
if (err == LFS_ERR_NOENT) {
// make this many directories
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our mkdir worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
struct lfs_info info;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
// now rename the directories
for (lfs_size_t i = 0; i < N; i++) {
char old_name[256];
sprintf(old_name, "dir%03x", i);
char new_name[256];
sprintf(new_name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
int err = lfsr_rename(&lfs, old_name, new_name);
assert(!err || (TEST_PLS && err == LFS_ERR_NOENT));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
}
// check that our renames worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_mv_many_backwards]
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
defines.BEFORE = [false, true]
defines.REMOUNT = [false, true]
# limit powerloss testing due to time
if = '!TEST_PLS || N <= 16'
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// check if we have already started renaming, in case of powerloss
struct lfs_info info;
err = lfsr_stat(&lfs, ((BEFORE) ? "/0mved000" : "/mved000"), &info);
if (err == LFS_ERR_NOENT) {
// make this many directories
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", (int)(N-1-i));
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our mkdir worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
struct lfs_info info;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
// now rename the directories
for (lfs_size_t i = 0; i < N; i++) {
char old_name[256];
sprintf(old_name, "dir%03x", i);
char new_name[256];
sprintf(new_name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
int err = lfsr_rename(&lfs, old_name, new_name);
assert(!err || (TEST_PLS && err == LFS_ERR_NOENT));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
}
// check that our renames worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_mv_many_2layers]
defines.N = [1, 2, 4, 8, 16]
defines.BEFORE = [false, true]
defines.REMOUNT = [false, true]
# limit powerloss testing due to time
if = '!TEST_PLS || N <= 4'
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// check if we have already started renaming, in case of powerloss
struct lfs_info info;
err = lfsr_stat(&lfs, ((BEFORE) ? "/0mved000" : "/mved000"), &info);
if (err == LFS_ERR_NOENT) {
// make this many directories
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// containing this many directories
for (lfs_size_t j = 0; j < N; j++) {
sprintf(name, "dir%03x/child%03x", i, j);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
}
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our mkdirs worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
sprintf(name, "child%03x", j);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
}
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
struct lfs_info info;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_open(&lfs, &dir, name) => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "child%03x", j);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
}
// now rename our directories
for (lfs_size_t i = 0; i < N; i++) {
char old_name[256];
sprintf(old_name, "dir%03x", i);
char new_name[256];
sprintf(new_name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
int err = lfsr_rename(&lfs, old_name, new_name);
assert(!err || (TEST_PLS && err == LFS_ERR_NOENT));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
for (lfs_size_t j = 0; j < N; j++) {
char old_name[256];
sprintf(old_name, "%smved%03x/child%03x",
((BEFORE) ? "0" : ""), i, j);
char new_name[256];
sprintf(new_name, "%smved%03x/%schmved%03x",
((BEFORE) ? "0" : ""), i,
((BEFORE) ? "0" : ""), j);
int err = lfsr_rename(&lfs, old_name, new_name);
assert(!err || (TEST_PLS && err == LFS_ERR_NOENT));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
}
}
// check that our renames worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "%smved%03x/%schmved%03x",
((BEFORE) ? "0" : ""), i, ((BEFORE) ? "0" : ""), j);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
sprintf(name, "%schmved%03x", ((BEFORE) ? "0" : ""), j);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
}
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
lfsr_dir_open(&lfs, &dir, name) => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "%schmved%03x", ((BEFORE) ? "0" : ""), j);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_mv_many_3layers]
defines.N = [1, 2, 4]
defines.BEFORE = [false, true]
defines.REMOUNT = [false, true]
# limit powerloss testing due to time
if = '!TEST_PLS || N <= 2'
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// check if we have already started renaming, in case of powerloss
struct lfs_info info;
err = lfsr_stat(&lfs, ((BEFORE) ? "/0mved000" : "/mved000"), &info);
if (err == LFS_ERR_NOENT) {
// make this many directories
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// containing this many directories
for (lfs_size_t j = 0; j < N; j++) {
sprintf(name, "dir%03x/child%03x", i, j);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
// containing this many directories
for (lfs_size_t k = 0; k < N; k++) {
sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
}
}
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our mkdirs worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
sprintf(name, "child%03x", j);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t k = 0; k < N; k++) {
char name[256];
sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
sprintf(name, "grandchild%03x", k);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
}
}
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
struct lfs_info info;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "dir%03x", i);
lfsr_dir_open(&lfs, &dir, name) => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "child%03x", j);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "dir%03x/child%03x", i, j);
lfsr_dir_open(&lfs, &dir, name) => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t k = 0; k < N; k++) {
char name[256];
sprintf(name, "grandchild%03x", k);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
}
}
// now rename our directories
for (lfs_size_t i = 0; i < N; i++) {
char old_name[256];
sprintf(old_name, "dir%03x", i);
char new_name[256];
sprintf(new_name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
int err = lfsr_rename(&lfs, old_name, new_name);
assert(!err || (TEST_PLS && err == LFS_ERR_NOENT));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
for (lfs_size_t j = 0; j < N; j++) {
char old_name[256];
sprintf(old_name, "%smved%03x/child%03x",
((BEFORE) ? "0" : ""), i, j);
char new_name[256];
sprintf(new_name, "%smved%03x/%schmved%03x",
((BEFORE) ? "0" : ""), i,
((BEFORE) ? "0" : ""), j);
int err = lfsr_rename(&lfs, old_name, new_name);
assert(!err || (TEST_PLS && err == LFS_ERR_NOENT));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
for (lfs_size_t k = 0; k < N; k++) {
char old_name[256];
sprintf(old_name, "%smved%03x/%schmved%03x/grandchild%03x",
((BEFORE) ? "0" : ""), i,
((BEFORE) ? "0" : ""), j, k);
char new_name[256];
sprintf(new_name, "%smved%03x/%schmved%03x/%sgrmved%03x",
((BEFORE) ? "0" : ""), i,
((BEFORE) ? "0" : ""), j,
((BEFORE) ? "0" : ""), k);
int err = lfsr_rename(&lfs, old_name, new_name);
assert(!err || (TEST_PLS && err == LFS_ERR_NOENT));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
}
}
}
// check that our removes worked
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "%smved%03x/%schmved%03x",
((BEFORE) ? "0" : ""), i,
((BEFORE) ? "0" : ""), j);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
sprintf(name, "%schmved%03x", ((BEFORE) ? "0" : ""), j);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t k = 0; k < N; k++) {
char name[256];
sprintf(name, "%smved%03x/%schmved%03x/%sgrmved%03x",
((BEFORE) ? "0" : ""), i,
((BEFORE) ? "0" : ""), j,
((BEFORE) ? "0" : ""), k);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
sprintf(name, "%sgrmved%03x", ((BEFORE) ? "0" : ""), k);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
}
}
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
for (lfs_size_t i = 0; i < N; i++) {
char name[256];
sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i);
lfsr_dir_open(&lfs, &dir, name) => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "%schmved%03x", ((BEFORE) ? "0" : ""), j);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
for (lfs_size_t j = 0; j < N; j++) {
char name[256];
sprintf(name, "%smved%03x/%schmved%03x",
((BEFORE) ? "0" : ""), i,
((BEFORE) ? "0" : ""), j);
lfsr_dir_open(&lfs, &dir, name) => 0;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t k = 0; k < N; k++) {
char name[256];
sprintf(name, "%sgrmved%03x", ((BEFORE) ? "0" : ""), k);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_mv_many_linkedlist]
defines.N = [1, 2, 4, 8, 16, 32, 64]
defines.BEFORE = [false, true]
defines.REMOUNT = [false, true]
# limit powerloss testing due to time
if = '!TEST_PLS || N <= 16'
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
// check if we have already started renaming, in case of powerloss
struct lfs_info info;
err = lfsr_stat(&lfs, ((BEFORE) ? "/0mved000" : "/mved000"), &info);
if (err == LFS_ERR_NOENT) {
// create this many directory in a sort of linked-list by nesting
char name[4096];
memset(name, 0, sizeof(name));
for (lfs_size_t i = 0; i < N; i++) {
sprintf(&name[strlen(name)], "/dir%03x", i);
err = lfsr_mkdir(&lfs, name);
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// check that our mkdir worked
memset(name, 0, sizeof(name));
for (lfs_size_t i = 0; i < N; i++) {
sprintf(&name[strlen(name)], "/dir%03x", i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
char name2[256];
sprintf(name2, "dir%03x", i);
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
memset(name, 0, sizeof(name));
for (lfs_size_t i = 0; i < N; i++) {
sprintf(&name[strlen(name)], "/dir%03x", i);
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, name) => 0;
struct lfs_info info;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (i < N-1) {
char name2[256];
sprintf(name2, "dir%03x", i+1);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
}
// now rename our directories
char old_name[4096];
memset(old_name, 0, sizeof(old_name));
char new_name[4096];
memset(new_name, 0, sizeof(new_name));
for (lfs_size_t i = 0; i < N; i++) {
sprintf(&old_name[strlen(old_name)], "/dir%03x", i);
sprintf(&new_name[strlen(new_name)], "/%smved%03x",
((BEFORE) ? "0" : ""), i);
err = lfsr_rename(&lfs, old_name, new_name);
assert(!err || (TEST_PLS && err == LFS_ERR_NOENT));
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// update old_name's path
memcpy(old_name, new_name, sizeof(old_name));
}
// check that our renames worked
char name[4096];
memset(name, 0, sizeof(name));
for (lfs_size_t i = 0; i < N; i++) {
sprintf(&name[strlen(name)], "/%smved%03x", ((BEFORE) ? "0" : ""), i);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
char name2[256];
sprintf(name2, "%smved%03x", ((BEFORE) ? "0" : ""), i);
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
memset(name, 0, sizeof(name));
for (lfs_size_t i = 0; i < N; i++) {
sprintf(&name[strlen(name)], "/%smved%03x", ((BEFORE) ? "0" : ""), i);
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, name) => 0;
struct lfs_info info;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
if (i < N-1) {
char name2[256];
sprintf(name2, "%smved%03x", ((BEFORE) ? "0" : ""), i+1);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
lfsr_unmount(&lfs) => 0;
'''
[cases.test_dirs_mv_fuzz]
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
defines.PARENT = [false, true]
defines.REMOUNT = [false, true]
defines.SEED = 'range(20)'
# limit powerloss testing due to time
if = '!TEST_PLS || N <= 16'
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
if (PARENT) {
err = lfsr_mkdir(&lfs, "pricklypear");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
}
// set up a simulation to compare against
lfs_size_t *sim = malloc(N*sizeof(lfs_size_t));
lfs_size_t sim_size = 0;
uint32_t prng = SEED;
for (lfs_size_t i = 0; i < N; i++) {
// choose a pseudo-random op, either mkdir or rename
uint8_t op = TEST_PRNG(&prng) % 2;
if (op == 0 || sim_size == 0) {
// choose a pseudo-random number, truncate to 3 hexadecimals
lfs_size_t x = TEST_PRNG(&prng) % 0x1000;
// insert into our sim
for (lfs_size_t j = 0;; j++) {
if (j >= sim_size || sim[j] >= x) {
// already seen?
if (j < sim_size && sim[j] == x) {
// do nothing
} else {
// insert
memmove(&sim[j+1], &sim[j],
(sim_size-j)*sizeof(lfs_size_t));
sim_size += 1;
sim[j] = x;
}
break;
}
}
// create a directory here
char name[256];
sprintf(name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), x);
int err = lfsr_mkdir(&lfs, name);
assert(!err || err == LFS_ERR_EXIST);
} else {
// choose a pseudo-random entry to rename, and a pseudo-random
// number to rename to
lfs_size_t j = TEST_PRNG(&prng) % sim_size;
lfs_size_t x = sim[j];
lfs_size_t y = TEST_PRNG(&prng) % 0x1000;
for (lfs_size_t k = 0;; k++) {
if (k >= sim_size || sim[k] >= y) {
// already seen and not a noop?
if (k < sim_size && sim[k] == y && x != y) {
// just delete the original entry
memmove(&sim[j], &sim[j+1],
(sim_size-(j+1))*sizeof(lfs_size_t));
sim_size -= 1;
} else {
// first delete
memmove(&sim[j], &sim[j+1],
(sim_size-(j+1))*sizeof(lfs_size_t));
if (k > j) {
k -= 1;
}
// then insert
memmove(&sim[k+1], &sim[k],
(sim_size-k)*sizeof(lfs_size_t));
sim[k] = y;
}
break;
}
}
// rename this directory
char old_name[256];
sprintf(old_name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), x);
char new_name[256];
sprintf(new_name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), y);
lfsr_rename(&lfs, old_name, new_name) => 0;
}
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// test that our directories match our simulation
for (lfs_size_t j = 0; j < sim_size; j++) {
char name[256];
sprintf(name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), sim[j]);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
char name2[256];
sprintf(name2, "dir%03x", sim[j]);
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, ((PARENT) ? "pricklypear" : "/")) => 0;
struct lfs_info info;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < sim_size; j++) {
char name[256];
sprintf(name, "dir%03x", sim[j]);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// clean up sim/lfs
free(sim);
lfsr_unmount(&lfs) => 0;
'''
# test all of the operations together
[cases.test_dirs_general_fuzz]
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
defines.PARENT = [false, true]
defines.REMOUNT = [false, true]
defines.SEED = 'range(20)'
# limit powerloss testing due to time
if = '!TEST_PLS || N <= 16'
reentrant = true
code = '''
// format once per test
lfs_t lfs;
int err = lfsr_mount(&lfs, CFG);
if (err) {
lfsr_format(&lfs, CFG) => 0;
lfsr_mount(&lfs, CFG) => 0;
}
if (PARENT) {
err = lfsr_mkdir(&lfs, "pricklypear");
assert(!err || (TEST_PLS && err == LFS_ERR_EXIST));
}
// set up a simulation to compare against
lfs_size_t *sim = malloc(N*sizeof(lfs_size_t));
lfs_size_t sim_size = 0;
uint32_t prng = SEED;
for (lfs_size_t i = 0; i < N; i++) {
// choose a pseudo-random op, either mkdir, remove, or rename
uint8_t op = TEST_PRNG(&prng) % 3;
if (op == 0 || sim_size == 0) {
// choose a pseudo-random number, truncate to 3 hexadecimals
lfs_size_t x = TEST_PRNG(&prng) % 0x1000;
// insert into our sim
for (lfs_size_t j = 0;; j++) {
if (j >= sim_size || sim[j] >= x) {
// already seen?
if (j < sim_size && sim[j] == x) {
// do nothing
} else {
// insert
memmove(&sim[j+1], &sim[j],
(sim_size-j)*sizeof(lfs_size_t));
sim_size += 1;
sim[j] = x;
}
break;
}
}
// create a directory here
char name[256];
sprintf(name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), x);
int err = lfsr_mkdir(&lfs, name);
assert(!err || err == LFS_ERR_EXIST);
} else if (op == 1) {
// choose a pseudo-random entry to delete
lfs_size_t j = TEST_PRNG(&prng) % sim_size;
lfs_size_t x = sim[j];
// delete from our sim
memmove(&sim[j], &sim[j+1],
(sim_size-(j+1))*sizeof(lfs_size_t));
sim_size -= 1;
// remove this directory
char name[256];
sprintf(name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), x);
lfsr_remove(&lfs, name) => 0;
} else {
// choose a pseudo-random entry to rename, and a pseudo-random
// number to rename to
lfs_size_t j = TEST_PRNG(&prng) % sim_size;
lfs_size_t x = sim[j];
lfs_size_t y = TEST_PRNG(&prng) % 0x1000;
for (lfs_size_t k = 0;; k++) {
if (k >= sim_size || sim[k] >= y) {
// already seen and not a noop?
if (k < sim_size && sim[k] == y && x != y) {
// just delete the original entry
memmove(&sim[j], &sim[j+1],
(sim_size-(j+1))*sizeof(lfs_size_t));
sim_size -= 1;
} else {
// first delete
memmove(&sim[j], &sim[j+1],
(sim_size-(j+1))*sizeof(lfs_size_t));
if (k > j) {
k -= 1;
}
// then insert
memmove(&sim[k+1], &sim[k],
(sim_size-k)*sizeof(lfs_size_t));
sim[k] = y;
}
break;
}
}
// rename this directory
char old_name[256];
sprintf(old_name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), x);
char new_name[256];
sprintf(new_name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), y);
lfsr_rename(&lfs, old_name, new_name) => 0;
}
}
// remount?
if (REMOUNT) {
lfsr_unmount(&lfs) => 0;
lfsr_mount(&lfs, CFG) => 0;
// grm should be zero here
assert(lfs.grm_g[0] == 0);
}
// test that our directories match our simulation
for (lfs_size_t j = 0; j < sim_size; j++) {
char name[256];
sprintf(name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), sim[j]);
struct lfs_info info;
lfsr_stat(&lfs, name, &info) => 0;
char name2[256];
sprintf(name2, "dir%03x", sim[j]);
assert(strcmp(info.name, name2) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, ((PARENT) ? "pricklypear" : "/")) => 0;
struct lfs_info info;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t j = 0; j < sim_size; j++) {
char name[256];
sprintf(name, "dir%03x", sim[j]);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// clean up sim/lfs
free(sim);
lfsr_unmount(&lfs) => 0;
'''
#[cases.test_dirs_root]
#code = '''
# lfs_t lfs;
# lfs_format(&lfs, cfg) => 0;
# lfs_mount(&lfs, cfg) => 0;
# lfs_dir_t dir;
# lfs_dir_open(&lfs, &dir, "/") => 0;
# struct lfs_info info;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, ".") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, "..") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 0;
# lfs_dir_close(&lfs, &dir) => 0;
# lfs_unmount(&lfs) => 0;
#'''
#
#[cases.test_dirs_many_creation]
#defines.N = 'range(3, 100, 3)'
#if = 'N < BLOCK_COUNT/2'
#code = '''
# lfs_t lfs;
# lfs_format(&lfs, cfg) => 0;
#
# lfs_mount(&lfs, cfg) => 0;
# for (int i = 0; i < N; i++) {
# char path[1024];
# sprintf(path, "dir%03d", i);
# lfs_mkdir(&lfs, path) => 0;
# }
# lfs_unmount(&lfs) => 0;
#
# lfs_mount(&lfs, cfg) => 0;
# lfs_dir_t dir;
# lfs_dir_open(&lfs, &dir, "/") => 0;
# struct lfs_info info;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, ".") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, "..") == 0);
# for (int i = 0; i < N; i++) {
# char path[1024];
# sprintf(path, "dir%03d", i);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, path) == 0);
# }
# lfs_dir_read(&lfs, &dir, &info) => 0;
# lfs_dir_close(&lfs, &dir) => 0;
# lfs_unmount(&lfs) => 0;
#'''
#
#[cases.test_dirs_many_removal]
#defines.N = 'range(3, 100, 11)'
#if = 'N < BLOCK_COUNT/2'
#code = '''
# lfs_t lfs;
# lfs_format(&lfs, cfg) => 0;
#
# lfs_mount(&lfs, cfg) => 0;
# for (int i = 0; i < N; i++) {
# char path[1024];
# sprintf(path, "removeme%03d", i);
# lfs_mkdir(&lfs, path) => 0;
# }
# lfs_unmount(&lfs) => 0;
#
# lfs_mount(&lfs, cfg) => 0;
# lfs_dir_t dir;
# lfs_dir_open(&lfs, &dir, "/") => 0;
# struct lfs_info info;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, ".") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, "..") == 0);
# for (int i = 0; i < N; i++) {
# char path[1024];
# sprintf(path, "removeme%03d", i);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, path) == 0);
# }
# lfs_dir_read(&lfs, &dir, &info) => 0;
# lfs_dir_close(&lfs, &dir) => 0;
# lfs_unmount(&lfs);
#
# lfs_mount(&lfs, cfg) => 0;
# for (int i = 0; i < N; i++) {
# char path[1024];
# sprintf(path, "removeme%03d", i);
# lfs_remove(&lfs, path) => 0;
# }
# lfs_unmount(&lfs);
#
# lfs_mount(&lfs, cfg) => 0;
# lfs_dir_open(&lfs, &dir, "/") => 0;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, ".") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, "..") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 0;
# lfs_dir_close(&lfs, &dir) => 0;
# lfs_unmount(&lfs) => 0;
#'''
#
#[cases.test_dirs_many_rename]
#defines.N = 'range(3, 100, 11)'
#if = 'N < BLOCK_COUNT/2'
#code = '''
# lfs_t lfs;
# lfs_format(&lfs, cfg) => 0;
#
# lfs_mount(&lfs, cfg) => 0;
# for (int i = 0; i < N; i++) {
# char path[1024];
# sprintf(path, "test%03d", i);
# lfs_mkdir(&lfs, path) => 0;
# }
# lfs_unmount(&lfs) => 0;
#
# lfs_mount(&lfs, cfg) => 0;
# lfs_dir_t dir;
# lfs_dir_open(&lfs, &dir, "/") => 0;
# struct lfs_info info;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, ".") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, "..") == 0);
# for (int i = 0; i < N; i++) {
# char path[1024];
# sprintf(path, "test%03d", i);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, path) == 0);
# }
# lfs_dir_read(&lfs, &dir, &info) => 0;
# lfs_dir_close(&lfs, &dir) => 0;
# lfs_unmount(&lfs);
#
# lfs_mount(&lfs, cfg) => 0;
# for (int i = 0; i < N; i++) {
# char oldpath[128];
# char newpath[128];
# sprintf(oldpath, "test%03d", i);
# sprintf(newpath, "tedd%03d", i);
# lfs_rename(&lfs, oldpath, newpath) => 0;
# }
# lfs_unmount(&lfs);
#
# lfs_mount(&lfs, cfg) => 0;
# lfs_dir_open(&lfs, &dir, "/") => 0;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, ".") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, "..") == 0);
# for (int i = 0; i < N; i++) {
# char path[1024];
# sprintf(path, "tedd%03d", i);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, path) == 0);
# }
# lfs_dir_read(&lfs, &dir, &info) => 0;
# lfs_dir_close(&lfs, &dir) => 0;
# lfs_unmount(&lfs);
#'''
#
#[cases.test_dirs_many_reentrant]
#defines.N = [5, 11]
#if = 'BLOCK_COUNT >= 4*N'
#reentrant = true
#code = '''
# lfs_t lfs;
# int err = lfs_mount(&lfs, cfg);
# if (err) {
# lfs_format(&lfs, cfg) => 0;
# lfs_mount(&lfs, cfg) => 0;
# }
#
# for (int i = 0; i < N; i++) {
# char path[1024];
# sprintf(path, "hi%03d", i);
# err = lfs_mkdir(&lfs, path);
# assert(err == 0 || err == LFS_ERR_EXIST);
# }
#
# for (int i = 0; i < N; i++) {
# char path[1024];
# sprintf(path, "hello%03d", i);
# err = lfs_remove(&lfs, path);
# assert(err == 0 || err == LFS_ERR_NOENT);
# }
#
# lfs_dir_t dir;
# lfs_dir_open(&lfs, &dir, "/") => 0;
# struct lfs_info info;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, ".") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, "..") == 0);
# for (int i = 0; i < N; i++) {
# char path[1024];
# sprintf(path, "hi%03d", i);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, path) == 0);
# }
# lfs_dir_read(&lfs, &dir, &info) => 0;
# lfs_dir_close(&lfs, &dir) => 0;
#
# for (int i = 0; i < N; i++) {
# char oldpath[128];
# char newpath[128];
# sprintf(oldpath, "hi%03d", i);
# sprintf(newpath, "hello%03d", i);
# // YES this can overwrite an existing newpath
# lfs_rename(&lfs, oldpath, newpath) => 0;
# }
#
# lfs_dir_open(&lfs, &dir, "/") => 0;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, ".") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, "..") == 0);
# for (int i = 0; i < N; i++) {
# char path[1024];
# sprintf(path, "hello%03d", i);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, path) == 0);
# }
# lfs_dir_read(&lfs, &dir, &info) => 0;
# lfs_dir_close(&lfs, &dir) => 0;
#
# for (int i = 0; i < N; i++) {
# char path[1024];
# sprintf(path, "hello%03d", i);
# lfs_remove(&lfs, path) => 0;
# }
#
# lfs_dir_open(&lfs, &dir, "/") => 0;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, ".") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, "..") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 0;
# lfs_dir_close(&lfs, &dir) => 0;
# lfs_unmount(&lfs) => 0;
#'''
#
#[cases.test_dirs_file_creation]
#defines.N = 'range(3, 100, 11)'
#if = 'N < BLOCK_COUNT/2'
#code = '''
# lfs_t lfs;
# lfs_format(&lfs, cfg) => 0;
#
# lfs_mount(&lfs, cfg) => 0;
# for (int i = 0; i < N; i++) {
# char path[1024];
# sprintf(path, "file%03d", i);
# lfs_file_t file;
# lfs_file_open(&lfs, &file, path,
# LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
# lfs_file_close(&lfs, &file) => 0;
# }
# lfs_unmount(&lfs) => 0;
#
# lfs_mount(&lfs, cfg) => 0;
# lfs_dir_t dir;
# lfs_dir_open(&lfs, &dir, "/") => 0;
# struct lfs_info info;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, ".") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, "..") == 0);
# for (int i = 0; i < N; i++) {
# char path[1024];
# sprintf(path, "file%03d", i);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_REG);
# assert(strcmp(info.name, path) == 0);
# }
# lfs_dir_read(&lfs, &dir, &info) => 0;
# lfs_dir_close(&lfs, &dir) => 0;
# lfs_unmount(&lfs);
#'''
#
#[cases.test_dirs_file_removal]
#defines.N = 'range(3, 100, 11)'
#if = 'N < BLOCK_COUNT/2'
#code = '''
# lfs_t lfs;
# lfs_format(&lfs, cfg) => 0;
#
# lfs_mount(&lfs, cfg) => 0;
# for (int i = 0; i < N; i++) {
# char path[1024];
# sprintf(path, "removeme%03d", i);
# lfs_file_t file;
# lfs_file_open(&lfs, &file, path,
# LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
# lfs_file_close(&lfs, &file) => 0;
# }
# lfs_unmount(&lfs) => 0;
#
# lfs_mount(&lfs, cfg) => 0;
# lfs_dir_t dir;
# lfs_dir_open(&lfs, &dir, "/") => 0;
# struct lfs_info info;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, ".") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, "..") == 0);
# for (int i = 0; i < N; i++) {
# char path[1024];
# sprintf(path, "removeme%03d", i);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_REG);
# assert(strcmp(info.name, path) == 0);
# }
# lfs_dir_read(&lfs, &dir, &info) => 0;
# lfs_dir_close(&lfs, &dir) => 0;
# lfs_unmount(&lfs);
#
# lfs_mount(&lfs, cfg) => 0;
# for (int i = 0; i < N; i++) {
# char path[1024];
# sprintf(path, "removeme%03d", i);
# lfs_remove(&lfs, path) => 0;
# }
# lfs_unmount(&lfs);
#
# lfs_mount(&lfs, cfg) => 0;
# lfs_dir_open(&lfs, &dir, "/") => 0;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, ".") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, "..") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 0;
# lfs_dir_close(&lfs, &dir) => 0;
# lfs_unmount(&lfs) => 0;
#'''
#
#[cases.test_dirs_file_rename]
#defines.N = 'range(3, 100, 11)'
#if = 'N < BLOCK_COUNT/2'
#code = '''
# lfs_t lfs;
# lfs_format(&lfs, cfg) => 0;
#
# lfs_mount(&lfs, cfg) => 0;
# for (int i = 0; i < N; i++) {
# char path[1024];
# sprintf(path, "test%03d", i);
# lfs_file_t file;
# lfs_file_open(&lfs, &file, path,
# LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
# lfs_file_close(&lfs, &file) => 0;
# }
# lfs_unmount(&lfs) => 0;
#
# lfs_mount(&lfs, cfg) => 0;
# lfs_dir_t dir;
# lfs_dir_open(&lfs, &dir, "/") => 0;
# struct lfs_info info;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, ".") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, "..") == 0);
# for (int i = 0; i < N; i++) {
# char path[1024];
# sprintf(path, "test%03d", i);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_REG);
# assert(strcmp(info.name, path) == 0);
# }
# lfs_dir_read(&lfs, &dir, &info) => 0;
# lfs_dir_close(&lfs, &dir) => 0;
# lfs_unmount(&lfs);
#
# lfs_mount(&lfs, cfg) => 0;
# for (int i = 0; i < N; i++) {
# char oldpath[128];
# char newpath[128];
# sprintf(oldpath, "test%03d", i);
# sprintf(newpath, "tedd%03d", i);
# lfs_rename(&lfs, oldpath, newpath) => 0;
# }
# lfs_unmount(&lfs);
#
# lfs_mount(&lfs, cfg) => 0;
# lfs_dir_open(&lfs, &dir, "/") => 0;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, ".") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, "..") == 0);
# for (int i = 0; i < N; i++) {
# char path[1024];
# sprintf(path, "tedd%03d", i);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_REG);
# assert(strcmp(info.name, path) == 0);
# }
# lfs_dir_read(&lfs, &dir, &info) => 0;
# lfs_dir_close(&lfs, &dir) => 0;
# lfs_unmount(&lfs);
#'''
#
#[cases.test_dirs_file_reentrant]
#defines.N = [5, 25]
#if = 'N < BLOCK_COUNT/2'
#reentrant = true
#code = '''
# lfs_t lfs;
# int err = lfs_mount(&lfs, cfg);
# if (err) {
# lfs_format(&lfs, cfg) => 0;
# lfs_mount(&lfs, cfg) => 0;
# }
#
# for (int i = 0; i < N; i++) {
# char path[1024];
# sprintf(path, "hi%03d", i);
# lfs_file_t file;
# lfs_file_open(&lfs, &file, path, LFS_O_CREAT | LFS_O_WRONLY) => 0;
# lfs_file_close(&lfs, &file) => 0;
# }
#
# for (int i = 0; i < N; i++) {
# char path[1024];
# sprintf(path, "hello%03d", i);
# err = lfs_remove(&lfs, path);
# assert(err == 0 || err == LFS_ERR_NOENT);
# }
#
# lfs_dir_t dir;
# lfs_dir_open(&lfs, &dir, "/") => 0;
# struct lfs_info info;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, ".") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, "..") == 0);
# for (int i = 0; i < N; i++) {
# char path[1024];
# sprintf(path, "hi%03d", i);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_REG);
# assert(strcmp(info.name, path) == 0);
# }
# lfs_dir_read(&lfs, &dir, &info) => 0;
# lfs_dir_close(&lfs, &dir) => 0;
#
# for (int i = 0; i < N; i++) {
# char oldpath[128];
# char newpath[128];
# sprintf(oldpath, "hi%03d", i);
# sprintf(newpath, "hello%03d", i);
# // YES this can overwrite an existing newpath
# lfs_rename(&lfs, oldpath, newpath) => 0;
# }
#
# lfs_dir_open(&lfs, &dir, "/") => 0;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, ".") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, "..") == 0);
# for (int i = 0; i < N; i++) {
# char path[1024];
# sprintf(path, "hello%03d", i);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_REG);
# assert(strcmp(info.name, path) == 0);
# }
# lfs_dir_read(&lfs, &dir, &info) => 0;
# lfs_dir_close(&lfs, &dir) => 0;
#
# for (int i = 0; i < N; i++) {
# char path[1024];
# sprintf(path, "hello%03d", i);
# lfs_remove(&lfs, path) => 0;
# }
#
# lfs_dir_open(&lfs, &dir, "/") => 0;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, ".") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, "..") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 0;
# lfs_dir_close(&lfs, &dir) => 0;
# lfs_unmount(&lfs) => 0;
#'''
#
#[cases.test_dirs_nested]
#code = '''
# lfs_t lfs;
# lfs_format(&lfs, cfg) => 0;
# lfs_mount(&lfs, cfg) => 0;
# lfs_mkdir(&lfs, "potato") => 0;
# lfs_file_t file;
# lfs_file_open(&lfs, &file, "burito",
# LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
# lfs_file_close(&lfs, &file) => 0;
# lfs_unmount(&lfs) => 0;
#
# lfs_mount(&lfs, cfg) => 0;
# lfs_mkdir(&lfs, "potato/baked") => 0;
# lfs_mkdir(&lfs, "potato/sweet") => 0;
# lfs_mkdir(&lfs, "potato/fried") => 0;
# lfs_unmount(&lfs) => 0;
#
# lfs_mount(&lfs, cfg) => 0;
# lfs_dir_t dir;
# lfs_dir_open(&lfs, &dir, "potato") => 0;
# struct lfs_info info;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(strcmp(info.name, ".") == 0);
# info.type => LFS_TYPE_DIR;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(strcmp(info.name, "..") == 0);
# info.type => LFS_TYPE_DIR;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(strcmp(info.name, "baked") == 0);
# info.type => LFS_TYPE_DIR;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(strcmp(info.name, "fried") == 0);
# info.type => LFS_TYPE_DIR;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(strcmp(info.name, "sweet") == 0);
# info.type => LFS_TYPE_DIR;
# lfs_dir_read(&lfs, &dir, &info) => 0;
# lfs_dir_close(&lfs, &dir) => 0;
# lfs_unmount(&lfs) => 0;
#
# // try removing?
# lfs_mount(&lfs, cfg) => 0;
# lfs_remove(&lfs, "potato") => LFS_ERR_NOTEMPTY;
# lfs_unmount(&lfs) => 0;
#
# // try renaming?
# lfs_mount(&lfs, cfg) => 0;
# lfs_rename(&lfs, "potato", "coldpotato") => 0;
# lfs_unmount(&lfs) => 0;
#
# lfs_mount(&lfs, cfg) => 0;
# lfs_rename(&lfs, "coldpotato", "warmpotato") => 0;
# lfs_rename(&lfs, "warmpotato", "hotpotato") => 0;
# lfs_unmount(&lfs) => 0;
#
# lfs_mount(&lfs, cfg) => 0;
# lfs_remove(&lfs, "potato") => LFS_ERR_NOENT;
# lfs_remove(&lfs, "coldpotato") => LFS_ERR_NOENT;
# lfs_remove(&lfs, "warmpotato") => LFS_ERR_NOENT;
# lfs_remove(&lfs, "hotpotato") => LFS_ERR_NOTEMPTY;
# lfs_unmount(&lfs) => 0;
#
# // try cross-directory renaming
# lfs_mount(&lfs, cfg) => 0;
# lfs_mkdir(&lfs, "coldpotato") => 0;
# lfs_rename(&lfs, "hotpotato/baked", "coldpotato/baked") => 0;
# lfs_rename(&lfs, "coldpotato", "hotpotato") => LFS_ERR_NOTEMPTY;
# lfs_remove(&lfs, "coldpotato") => LFS_ERR_NOTEMPTY;
# lfs_remove(&lfs, "hotpotato") => LFS_ERR_NOTEMPTY;
# lfs_rename(&lfs, "hotpotato/fried", "coldpotato/fried") => 0;
# lfs_rename(&lfs, "coldpotato", "hotpotato") => LFS_ERR_NOTEMPTY;
# lfs_remove(&lfs, "coldpotato") => LFS_ERR_NOTEMPTY;
# lfs_remove(&lfs, "hotpotato") => LFS_ERR_NOTEMPTY;
# lfs_rename(&lfs, "hotpotato/sweet", "coldpotato/sweet") => 0;
# lfs_rename(&lfs, "coldpotato", "hotpotato") => 0;
# lfs_remove(&lfs, "coldpotato") => LFS_ERR_NOENT;
# lfs_remove(&lfs, "hotpotato") => LFS_ERR_NOTEMPTY;
# lfs_unmount(&lfs) => 0;
#
# lfs_mount(&lfs, cfg) => 0;
# lfs_dir_open(&lfs, &dir, "hotpotato") => 0;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(strcmp(info.name, ".") == 0);
# info.type => LFS_TYPE_DIR;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(strcmp(info.name, "..") == 0);
# info.type => LFS_TYPE_DIR;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(strcmp(info.name, "baked") == 0);
# info.type => LFS_TYPE_DIR;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(strcmp(info.name, "fried") == 0);
# info.type => LFS_TYPE_DIR;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(strcmp(info.name, "sweet") == 0);
# info.type => LFS_TYPE_DIR;
# lfs_dir_read(&lfs, &dir, &info) => 0;
# lfs_dir_close(&lfs, &dir) => 0;
# lfs_unmount(&lfs) => 0;
#
# // final remove
# lfs_mount(&lfs, cfg) => 0;
# lfs_remove(&lfs, "hotpotato") => LFS_ERR_NOTEMPTY;
# lfs_remove(&lfs, "hotpotato/baked") => 0;
# lfs_remove(&lfs, "hotpotato") => LFS_ERR_NOTEMPTY;
# lfs_remove(&lfs, "hotpotato/fried") => 0;
# lfs_remove(&lfs, "hotpotato") => LFS_ERR_NOTEMPTY;
# lfs_remove(&lfs, "hotpotato/sweet") => 0;
# lfs_remove(&lfs, "hotpotato") => 0;
# lfs_unmount(&lfs) => 0;
#
# lfs_mount(&lfs, cfg) => 0;
# lfs_dir_open(&lfs, &dir, "/") => 0;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(strcmp(info.name, ".") == 0);
# info.type => LFS_TYPE_DIR;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(strcmp(info.name, "..") == 0);
# info.type => LFS_TYPE_DIR;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(strcmp(info.name, "burito") == 0);
# info.type => LFS_TYPE_REG;
# lfs_dir_read(&lfs, &dir, &info) => 0;
# lfs_dir_close(&lfs, &dir) => 0;
# lfs_unmount(&lfs) => 0;
#'''
#
#[cases.test_dirs_recursive_remove]
#defines.N = [10, 100]
#if = 'N < BLOCK_COUNT/2'
#code = '''
# lfs_t lfs;
# lfs_format(&lfs, cfg) => 0;
# lfs_mount(&lfs, cfg) => 0;
# lfs_mkdir(&lfs, "prickly-pear") => 0;
# for (int i = 0; i < N; i++) {
# char path[1024];
# sprintf(path, "prickly-pear/cactus%03d", i);
# lfs_mkdir(&lfs, path) => 0;
# }
# lfs_dir_t dir;
# lfs_dir_open(&lfs, &dir, "prickly-pear") => 0;
# struct lfs_info info;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, ".") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, "..") == 0);
# for (int i = 0; i < N; i++) {
# char path[1024];
# sprintf(path, "cactus%03d", i);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, path) == 0);
# }
# lfs_dir_read(&lfs, &dir, &info) => 0;
# lfs_dir_close(&lfs, &dir) => 0;
# lfs_unmount(&lfs);
#
# lfs_mount(&lfs, cfg) => 0;
# lfs_remove(&lfs, "prickly-pear") => LFS_ERR_NOTEMPTY;
#
# lfs_dir_open(&lfs, &dir, "prickly-pear") => 0;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, ".") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, "..") == 0);
# for (int i = 0; i < N; i++) {
# char path[1024];
# sprintf(path, "cactus%03d", i);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, path) == 0);
# sprintf(path, "prickly-pear/%s", info.name);
# lfs_remove(&lfs, path) => 0;
# }
# lfs_dir_read(&lfs, &dir, &info) => 0;
# lfs_dir_close(&lfs, &dir) => 0;
#
# lfs_remove(&lfs, "prickly-pear") => 0;
# lfs_remove(&lfs, "prickly-pear") => LFS_ERR_NOENT;
# lfs_unmount(&lfs) => 0;
#
# lfs_mount(&lfs, cfg) => 0;
# lfs_remove(&lfs, "prickly-pear") => LFS_ERR_NOENT;
# lfs_unmount(&lfs) => 0;
#'''
#
#[cases.test_dirs_other_errors]
#code = '''
# lfs_t lfs;
# lfs_format(&lfs, cfg) => 0;
# lfs_mount(&lfs, cfg) => 0;
# lfs_mkdir(&lfs, "potato") => 0;
# lfs_file_t file;
# lfs_file_open(&lfs, &file, "burito",
# LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
# lfs_file_close(&lfs, &file) => 0;
# lfs_unmount(&lfs) => 0;
#
# lfs_mount(&lfs, cfg) => 0;
#
# lfs_mkdir(&lfs, "potato") => LFS_ERR_EXIST;
# lfs_mkdir(&lfs, "burito") => LFS_ERR_EXIST;
# lfs_file_open(&lfs, &file, "burito",
# LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST;
# lfs_file_open(&lfs, &file, "potato",
# LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST;
# lfs_dir_t dir;
# lfs_dir_open(&lfs, &dir, "tomato") => LFS_ERR_NOENT;
# lfs_dir_open(&lfs, &dir, "burito") => LFS_ERR_NOTDIR;
# lfs_file_open(&lfs, &file, "tomato", LFS_O_RDONLY) => LFS_ERR_NOENT;
# lfs_file_open(&lfs, &file, "potato", LFS_O_RDONLY) => LFS_ERR_ISDIR;
# lfs_file_open(&lfs, &file, "tomato", LFS_O_WRONLY) => LFS_ERR_NOENT;
# lfs_file_open(&lfs, &file, "potato", LFS_O_WRONLY) => LFS_ERR_ISDIR;
# lfs_file_open(&lfs, &file, "potato",
# LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR;
#
# lfs_mkdir(&lfs, "/") => LFS_ERR_EXIST;
# lfs_file_open(&lfs, &file, "/",
# LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST;
# lfs_file_open(&lfs, &file, "/", LFS_O_RDONLY) => LFS_ERR_ISDIR;
# lfs_file_open(&lfs, &file, "/", LFS_O_WRONLY) => LFS_ERR_ISDIR;
# lfs_file_open(&lfs, &file, "/",
# LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR;
#
# // check that errors did not corrupt directory
# lfs_dir_open(&lfs, &dir, "/") => 0;
# struct lfs_info info;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, ".") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, "..") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_REG);
# assert(strcmp(info.name, "burito") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, "potato") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 0;
# lfs_dir_close(&lfs, &dir) => 0;
#
# lfs_unmount(&lfs) => 0;
#
# // or on disk
# lfs_mount(&lfs, cfg) => 0;
# lfs_dir_open(&lfs, &dir, "/") => 0;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, ".") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, "..") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_REG);
# assert(strcmp(info.name, "burito") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(info.type == LFS_TYPE_DIR);
# assert(strcmp(info.name, "potato") == 0);
# lfs_dir_read(&lfs, &dir, &info) => 0;
# lfs_dir_close(&lfs, &dir) => 0;
# lfs_unmount(&lfs) => 0;
#'''
#
#[cases.test_dirs_seek]
#defines.COUNT = [4, 128, 132]
#if = 'COUNT < BLOCK_COUNT/2'
#code = '''
# lfs_t lfs;
# lfs_format(&lfs, cfg) => 0;
# lfs_mount(&lfs, cfg) => 0;
# lfs_mkdir(&lfs, "hello") => 0;
# for (int i = 0; i < COUNT; i++) {
# char path[1024];
# sprintf(path, "hello/kitty%03d", i);
# lfs_mkdir(&lfs, path) => 0;
# }
# lfs_unmount(&lfs) => 0;
#
# for (int j = 2; j < COUNT; j++) {
# lfs_mount(&lfs, cfg) => 0;
# lfs_dir_t dir;
# lfs_dir_open(&lfs, &dir, "hello") => 0;
# struct lfs_info info;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(strcmp(info.name, ".") == 0);
# assert(info.type == LFS_TYPE_DIR);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(strcmp(info.name, "..") == 0);
# assert(info.type == LFS_TYPE_DIR);
#
# lfs_soff_t pos;
# for (int i = 0; i < j; i++) {
# char path[1024];
# sprintf(path, "kitty%03d", i);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(strcmp(info.name, path) == 0);
# assert(info.type == LFS_TYPE_DIR);
# pos = lfs_dir_tell(&lfs, &dir);
# assert(pos >= 0);
# }
#
# lfs_dir_seek(&lfs, &dir, pos) => 0;
# char path[1024];
# sprintf(path, "kitty%03d", j);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(strcmp(info.name, path) == 0);
# assert(info.type == LFS_TYPE_DIR);
#
# lfs_dir_rewind(&lfs, &dir) => 0;
# sprintf(path, "kitty%03u", 0);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(strcmp(info.name, ".") == 0);
# assert(info.type == LFS_TYPE_DIR);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(strcmp(info.name, "..") == 0);
# assert(info.type == LFS_TYPE_DIR);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(strcmp(info.name, path) == 0);
# assert(info.type == LFS_TYPE_DIR);
#
# lfs_dir_seek(&lfs, &dir, pos) => 0;
# sprintf(path, "kitty%03d", j);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(strcmp(info.name, path) == 0);
# assert(info.type == LFS_TYPE_DIR);
#
# lfs_dir_close(&lfs, &dir) => 0;
# lfs_unmount(&lfs) => 0;
# }
#'''
#
#[cases.test_dirs_toot_seek]
#defines.COUNT = [4, 128, 132]
#if = 'COUNT < BLOCK_COUNT/2'
#code = '''
# lfs_t lfs;
# lfs_format(&lfs, cfg) => 0;
# lfs_mount(&lfs, cfg) => 0;
# for (int i = 0; i < COUNT; i++) {
# char path[1024];
# sprintf(path, "hi%03d", i);
# lfs_mkdir(&lfs, path) => 0;
# }
# lfs_unmount(&lfs) => 0;
#
# for (int j = 2; j < COUNT; j++) {
# lfs_mount(&lfs, cfg) => 0;
# lfs_dir_t dir;
# lfs_dir_open(&lfs, &dir, "/") => 0;
# struct lfs_info info;
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(strcmp(info.name, ".") == 0);
# assert(info.type == LFS_TYPE_DIR);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(strcmp(info.name, "..") == 0);
# assert(info.type == LFS_TYPE_DIR);
#
# lfs_soff_t pos;
# for (int i = 0; i < j; i++) {
# char path[1024];
# sprintf(path, "hi%03d", i);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(strcmp(info.name, path) == 0);
# assert(info.type == LFS_TYPE_DIR);
# pos = lfs_dir_tell(&lfs, &dir);
# assert(pos >= 0);
# }
#
# lfs_dir_seek(&lfs, &dir, pos) => 0;
# char path[1024];
# sprintf(path, "hi%03d", j);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(strcmp(info.name, path) == 0);
# assert(info.type == LFS_TYPE_DIR);
#
# lfs_dir_rewind(&lfs, &dir) => 0;
# sprintf(path, "hi%03u", 0);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(strcmp(info.name, ".") == 0);
# assert(info.type == LFS_TYPE_DIR);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(strcmp(info.name, "..") == 0);
# assert(info.type == LFS_TYPE_DIR);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(strcmp(info.name, path) == 0);
# assert(info.type == LFS_TYPE_DIR);
#
# lfs_dir_seek(&lfs, &dir, pos) => 0;
# sprintf(path, "hi%03d", j);
# lfs_dir_read(&lfs, &dir, &info) => 1;
# assert(strcmp(info.name, path) == 0);
# assert(info.type == LFS_TYPE_DIR);
#
# lfs_dir_close(&lfs, &dir) => 0;
# lfs_unmount(&lfs) => 0;
# }
#'''
#