# 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 <= 32' reentrant = true code = ''' // format once per test lfs_t lfs; int err = lfsr_mount(&lfs, CFG); if (err) { lfsr_format(&lfs, CFG) => 0; lfsr_mount(&lfs, CFG) => 0; } // make this many directories for (lfs_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%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 <= 32' reentrant = true code = ''' // format once per test lfs_t lfs; int err = lfsr_mount(&lfs, CFG); if (err) { lfsr_format(&lfs, CFG) => 0; lfsr_mount(&lfs, CFG) => 0; } // make this many directories for (lfs_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%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(10)' # limit powerloss testing due to time if = '!TEST_PLS || N <= 64' reentrant = true code = ''' // format once per test lfs_t lfs; int err = lfsr_mount(&lfs, CFG); if (err) { lfsr_format(&lfs, CFG) => 0; lfsr_mount(&lfs, CFG) => 0; } if (PARENT) { err = lfsr_mkdir(&lfs, "pricklypear"); assert(!err || (TEST_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 <= 32', ] reentrant = true code = ''' // format once per test lfs_t lfs; int err = lfsr_mount(&lfs, CFG); if (err) { lfsr_format(&lfs, CFG) => 0; lfsr_mount(&lfs, CFG) => 0; } // make this many directories for (lfs_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%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 <= 32', ] reentrant = true code = ''' // format once per test lfs_t lfs; int err = lfsr_mount(&lfs, CFG); if (err) { lfsr_format(&lfs, CFG) => 0; lfsr_mount(&lfs, CFG) => 0; } // make this many directories for (lfs_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%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(10)' # limit powerloss testing due to time if = '!TEST_PLS || N <= 64' reentrant = true code = ''' // format once per test lfs_t lfs; int err = lfsr_mount(&lfs, CFG); if (err) { lfsr_format(&lfs, CFG) => 0; lfsr_mount(&lfs, CFG) => 0; } if (PARENT) { err = lfsr_mkdir(&lfs, "pricklypear"); assert(!err || (TEST_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 <= 32' reentrant = true code = ''' // format once per test lfs_t lfs; int err = lfsr_mount(&lfs, CFG); if (err) { lfsr_format(&lfs, CFG) => 0; lfsr_mount(&lfs, CFG) => 0; } // check if we have already started renaming, in case of powerloss struct lfs_info info; err = lfsr_stat(&lfs, ((BEFORE) ? "/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 <= 32' reentrant = true code = ''' // format once per test lfs_t lfs; int err = lfsr_mount(&lfs, CFG); if (err) { lfsr_format(&lfs, CFG) => 0; lfsr_mount(&lfs, CFG) => 0; } // check if we have already started renaming, in case of powerloss struct lfs_info info; err = lfsr_stat(&lfs, ((BEFORE) ? "/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(10)' # limit powerloss testing due to time if = '!TEST_PLS || N <= 64' reentrant = true code = ''' // format once per test lfs_t lfs; int err = lfsr_mount(&lfs, CFG); if (err) { lfsr_format(&lfs, CFG) => 0; lfsr_mount(&lfs, CFG) => 0; } if (PARENT) { err = lfsr_mkdir(&lfs, "pricklypear"); assert(!err || (TEST_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(10)' # limit powerloss testing due to time if = '!TEST_PLS || N <= 64' reentrant = true code = ''' // format once per test lfs_t lfs; int err = lfsr_mount(&lfs, CFG); if (err) { lfsr_format(&lfs, CFG) => 0; lfsr_mount(&lfs, CFG) => 0; } if (PARENT) { err = lfsr_mkdir(&lfs, "pricklypear"); assert(!err || (TEST_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; # } #''' #