# Test directory operations after = 'test_mtree' ## mkdir tests [cases.test_dirs_mkdir] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // make a directory err = lfs3_mkdir(&lfs3, "ardvark"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that our mkdir worked with stat struct lfs3_info info; lfs3_stat(&lfs3, "ardvark", &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); // and with dir_read lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; lfs3_dir_open(&lfs3, &dir, "ardvark") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' # test that noent errors work [cases.test_dirs_noent] code = ''' lfs3_t lfs3; lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; // make a directory lfs3_mkdir(&lfs3, "ardvark") => 0; // try to read a nonsense path struct lfs3_info info; lfs3_stat(&lfs3, "no", &info) => LFS3_ERR_NOENT; lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "no") => LFS3_ERR_NOENT; lfs3_unmount(&lfs3) => 0; ''' # test that stat on root works [cases.test_dirs_stat_root] code = ''' lfs3_t lfs3; lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; // make a directory lfs3_mkdir(&lfs3, "ardvark") => 0; // stat the root struct lfs3_info info; lfs3_stat(&lfs3, "/", &info) => 0; assert(strcmp(info.name, "/") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_unmount(&lfs3) => 0; ''' # test that creating the same directory twice errors [cases.test_dirs_mkdir_exists] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // make a directory err = lfs3_mkdir(&lfs3, "ardvark"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); // make the same directory, should error lfs3_mkdir(&lfs3, "ardvark") => LFS3_ERR_EXIST; for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // and check that this didn't interfere with our original directory struct lfs3_info info; lfs3_stat(&lfs3, "ardvark", &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; lfs3_dir_open(&lfs3, &dir, "ardvark") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' # test that dir existance is the same before/after mkconsistent [cases.test_dirs_mkdir_consistent] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check if dir exists before mkconsistent struct lfs3_info info; err = lfs3_stat(&lfs3, "ardvark", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool exists = !err; // and with dir_read lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); if (exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; // make a directory err = lfs3_mkdir(&lfs3, "ardvark"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == exists); for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that our mkdir worked with stat lfs3_stat(&lfs3, "ardvark", &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); // and with dir_read lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; lfs3_dir_open(&lfs3, &dir, "ardvark") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' # test what happens if we try to make root [cases.test_dirs_mkdir_root] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // try to make root, which doesn't make sense lfs3_mkdir(&lfs3, "/") => LFS3_ERR_EXIST; // make a directory err = lfs3_mkdir(&lfs3, "ardvark"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); // try to make root, which doesn't make sense lfs3_mkdir(&lfs3, "/") => LFS3_ERR_EXIST; for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // and check that this didn't interfere with our original directory struct lfs3_info info; lfs3_stat(&lfs3, "ardvark", &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; lfs3_dir_open(&lfs3, &dir, "ardvark") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' # test that creating a directory with an invalid path errors [cases.test_dirs_mkdir_noent] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // make a directory err = lfs3_mkdir(&lfs3, "ardvark"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); // make a nonsense directory, should error lfs3_mkdir(&lfs3, "no/hmm") => LFS3_ERR_NOENT; // make a nonsense child directory, should error lfs3_mkdir(&lfs3, "ardvark/no/hmm") => LFS3_ERR_NOENT; for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // and check that this didn't interfere with our original directory struct lfs3_info info; lfs3_stat(&lfs3, "ardvark", &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; lfs3_dir_open(&lfs3, &dir, "ardvark") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' [cases.test_dirs_mkdir_siblings] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check if dirs exist before mkconsistent struct lfs3_info info; err = lfs3_stat(&lfs3, "ardvark", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool a_exists = !err; err = lfs3_stat(&lfs3, "banana", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool b_exists = !err; err = lfs3_stat(&lfs3, "cat", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool c_exists = !err; lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); if (a_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } if (b_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } if (c_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; // make some directories err = lfs3_mkdir(&lfs3, "ardvark"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == a_exists); err = lfs3_mkdir(&lfs3, "banana"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == b_exists); err = lfs3_mkdir(&lfs3, "cat"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == c_exists); for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that our mkdir worked lfs3_stat(&lfs3, "ardvark", &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "banana", &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "cat", &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; lfs3_dir_open(&lfs3, &dir, "ardvark") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; lfs3_dir_open(&lfs3, &dir, "banana") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; lfs3_dir_open(&lfs3, &dir, "cat") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' [cases.test_dirs_mkdir_children] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check if dirs exist before mkconsistent struct lfs3_info info; err = lfs3_stat(&lfs3, "ardvark", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool a_exists = !err; err = lfs3_stat(&lfs3, "ardvark/banana", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool b_exists = !err; err = lfs3_stat(&lfs3, "ardvark/banana/cat", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool c_exists = !err; lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); if (a_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; err = lfs3_dir_open(&lfs3, &dir, "/ardvark"); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); assert(!err == a_exists); if (a_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); if (b_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } err = lfs3_dir_open(&lfs3, &dir, "/ardvark/banana"); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); assert(!err == b_exists); if (b_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); if (c_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } // make some directories err = lfs3_mkdir(&lfs3, "ardvark"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == a_exists); err = lfs3_mkdir(&lfs3, "ardvark/banana"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == b_exists); err = lfs3_mkdir(&lfs3, "ardvark/banana/cat"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == c_exists); for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that our mkdirs worked lfs3_stat(&lfs3, "ardvark", &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "ardvark/banana", &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "ardvark/banana/cat", &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; lfs3_dir_open(&lfs3, &dir, "/ardvark") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; lfs3_dir_open(&lfs3, &dir, "/ardvark/banana") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; lfs3_dir_open(&lfs3, &dir, "/ardvark/banana/cat") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' [cases.test_dirs_mkdir_many] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] defines.REMOUNT = [false, true] # limit powerloss testing due to time if = '!TEST_PLS || N <= 16' reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // make this many directories for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); err = lfs3_mkdir(&lfs3, name); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } } for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that our mkdir worked for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; struct lfs3_info info; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); lfs3_dir_open(&lfs3, &dir, name) => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } } lfs3_unmount(&lfs3) => 0; ''' [cases.test_dirs_mkdir_many_backwards] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] defines.REMOUNT = [false, true] # limit powerloss testing due to time if = '!TEST_PLS || N <= 16' reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // make this many directories for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", (int)(N-1-i)); err = lfs3_mkdir(&lfs3, name); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } } for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that our mkdir worked for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; struct lfs3_info info; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); lfs3_dir_open(&lfs3, &dir, name) => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } } lfs3_unmount(&lfs3) => 0; ''' [cases.test_dirs_mkdir_many_2layers] defines.N = [1, 2, 4, 8, 16] defines.REMOUNT = [false, true] # limit powerloss testing due to time if = '!TEST_PLS || N <= 4' reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // make this many directories for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); err = lfs3_mkdir(&lfs3, name); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); // containing this many directories for (lfs3_size_t j = 0; j < N; j++) { sprintf(name, "dir%03x/child%03x", i, j); err = lfs3_mkdir(&lfs3, name); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } } } for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that our mkdirs worked for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t j = 0; j < N; j++) { char name[256]; sprintf(name, "dir%03x/child%03x", i, j); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; sprintf(name, "child%03x", j); assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } } lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; struct lfs3_info info; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); lfs3_dir_open(&lfs3, &dir, name) => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t j = 0; j < N; j++) { char name[256]; sprintf(name, "child%03x", j); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } for (lfs3_size_t i = 0; i < N; i++) { for (lfs3_size_t j = 0; j < N; j++) { char name[256]; sprintf(name, "dir%03x/child%03x", i, j); lfs3_dir_open(&lfs3, &dir, name) => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } } } lfs3_unmount(&lfs3) => 0; ''' [cases.test_dirs_mkdir_many_3layers] defines.N = [1, 2, 4] defines.REMOUNT = [false, true] # limit powerloss testing due to time if = '!TEST_PLS || N <= 2' reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // make this many directories for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); err = lfs3_mkdir(&lfs3, name); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); // containing this many directories for (lfs3_size_t j = 0; j < N; j++) { sprintf(name, "dir%03x/child%03x", i, j); err = lfs3_mkdir(&lfs3, name); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); // containing this many directories for (lfs3_size_t k = 0; k < N; k++) { sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k); err = lfs3_mkdir(&lfs3, name); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } } } } for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that our mkdirs worked for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t j = 0; j < N; j++) { char name[256]; sprintf(name, "dir%03x/child%03x", i, j); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; sprintf(name, "child%03x", j); assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t k = 0; k < N; k++) { char name[256]; sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; sprintf(name, "grandchild%03x", k); assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } } } lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; struct lfs3_info info; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); lfs3_dir_open(&lfs3, &dir, name) => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t j = 0; j < N; j++) { char name[256]; sprintf(name, "child%03x", j); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; for (lfs3_size_t j = 0; j < N; j++) { char name[256]; sprintf(name, "dir%03x/child%03x", i, j); lfs3_dir_open(&lfs3, &dir, name) => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t k = 0; k < N; k++) { char name[256]; sprintf(name, "grandchild%03x", k); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } } for (lfs3_size_t i = 0; i < N; i++) { for (lfs3_size_t j = 0; j < N; j++) { for (lfs3_size_t k = 0; k < N; k++) { char name[256]; sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k); lfs3_dir_open(&lfs3, &dir, name) => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } } } } lfs3_unmount(&lfs3) => 0; ''' [cases.test_dirs_mkdir_many_linkedlist] defines.N = [1, 2, 4, 8, 16, 32, 64] defines.REMOUNT = [false, true] # limit powerloss testing due to time if = '!TEST_PLS || N <= 16' reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // create this many directory in a sort of linked-list by nesting char name[4096]; memset(name, 0, sizeof(name)); for (lfs3_size_t i = 0; i < N; i++) { sprintf(&name[strlen(name)], "/dir%03x", i); err = lfs3_mkdir(&lfs3, name); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } } for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that our mkdir worked memset(name, 0, sizeof(name)); for (lfs3_size_t i = 0; i < N; i++) { sprintf(&name[strlen(name)], "/dir%03x", i); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; char name2[256]; sprintf(name2, "dir%03x", i); assert(strcmp(info.name, name2) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } memset(name, 0, sizeof(name)); for (lfs3_size_t i = 0; i < N; i++) { sprintf(&name[strlen(name)], "/dir%03x", i); lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, name) => 0; struct lfs3_info info; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); if (i < N-1) { char name2[256]; sprintf(name2, "dir%03x", i+1); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name2) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } } lfs3_unmount(&lfs3) => 0; ''' [cases.test_dirs_mkdir_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256] # do more ops than dirs to encourage rename collisions defines.OPS = '2*N' defines.PARENT = [false, true] defines.SEED = 'range(20)' fuzz = 'SEED' # limit powerloss testing due to time if = '!TEST_PLS || N <= 8' reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } if (PARENT) { err = lfs3_mkdir(&lfs3, "pricklypear"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); } // set up a simulation to compare against lfs3_size_t *sim = malloc(N*sizeof(lfs3_size_t)); lfs3_size_t sim_size = 0; uint32_t prng = SEED; for (lfs3_size_t i = 0; i < OPS; i++) { // choose a pseudo-random number lfs3_size_t x = TEST_PRNG(&prng) % N; // insert into our sim for (lfs3_size_t j = 0;; j++) { if (j >= sim_size || sim[j] >= x) { // already seen? if (j < sim_size && sim[j] == x) { // do nothing } else { // insert memmove(&sim[j+1], &sim[j], (sim_size-j)*sizeof(lfs3_size_t)); sim_size += 1; sim[j] = x; } break; } } // create a directory here char name[256]; sprintf(name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), x); int err = lfs3_mkdir(&lfs3, name); assert(!err || err == LFS3_ERR_EXIST); } for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // test that our directories match our simulation for (lfs3_size_t j = 0; j < sim_size; j++) { char name[256]; sprintf(name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), sim[j]); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; char name2[256]; sprintf(name2, "dir%03x", sim[j]); assert(strcmp(info.name, name2) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, ((PARENT) ? "pricklypear" : "/")) => 0; struct lfs3_info info; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t j = 0; j < sim_size; j++) { char name[256]; sprintf(name, "dir%03x", sim[j]); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; for (lfs3_size_t j = 0; j < sim_size; j++) { char name[256]; sprintf(name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), sim[j]); lfs3_dir_open(&lfs3, &dir, name) => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } } // clean up sim/lfs3 free(sim); lfs3_unmount(&lfs3) => 0; ''' # test some common ordering mistakes [cases.test_dirs_ordering] # ORDER=0 => inorder # ORDER=1 => reversed # ORDER=2 => random defines.ORDER = [0, 1, 2] code = ''' lfs3_t lfs3; lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; if (ORDER == 0) { lfs3_mkdir(&lfs3, "a") => 0; lfs3_mkdir(&lfs3, "b") => 0; lfs3_mkdir(&lfs3, "c") => 0; lfs3_mkdir(&lfs3, "d") => 0; lfs3_mkdir(&lfs3, "e") => 0; lfs3_mkdir(&lfs3, "f") => 0; } else if (ORDER == 1) { lfs3_mkdir(&lfs3, "f") => 0; lfs3_mkdir(&lfs3, "e") => 0; lfs3_mkdir(&lfs3, "d") => 0; lfs3_mkdir(&lfs3, "c") => 0; lfs3_mkdir(&lfs3, "b") => 0; lfs3_mkdir(&lfs3, "a") => 0; } else if (ORDER == 2) { // "random", trust me lfs3_mkdir(&lfs3, "e") => 0; lfs3_mkdir(&lfs3, "c") => 0; lfs3_mkdir(&lfs3, "b") => 0; lfs3_mkdir(&lfs3, "d") => 0; lfs3_mkdir(&lfs3, "f") => 0; lfs3_mkdir(&lfs3, "a") => 0; } for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that our mkdirs worked struct lfs3_info info; lfs3_stat(&lfs3, "a", &info) => 0; assert(strcmp(info.name, "a") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "b", &info) => 0; assert(strcmp(info.name, "b") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "c", &info) => 0; assert(strcmp(info.name, "c") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "d", &info) => 0; assert(strcmp(info.name, "d") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "e", &info) => 0; assert(strcmp(info.name, "e") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "f", &info) => 0; assert(strcmp(info.name, "f") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); // check the directory order lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "a") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "b") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "c") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "d") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "e") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "f") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' [cases.test_dirs_ordering_length] # ORDER=0 => inorder # ORDER=1 => reversed # ORDER=2 => random defines.ORDER = [0, 1, 2] code = ''' lfs3_t lfs3; lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; if (ORDER == 0) { lfs3_mkdir(&lfs3, "a") => 0; lfs3_mkdir(&lfs3, "aa") => 0; lfs3_mkdir(&lfs3, "aaa") => 0; lfs3_mkdir(&lfs3, "aaaa") => 0; lfs3_mkdir(&lfs3, "aaaaa") => 0; lfs3_mkdir(&lfs3, "aaaaaa") => 0; } else if (ORDER == 1) { lfs3_mkdir(&lfs3, "aaaaaa") => 0; lfs3_mkdir(&lfs3, "aaaaa") => 0; lfs3_mkdir(&lfs3, "aaaa") => 0; lfs3_mkdir(&lfs3, "aaa") => 0; lfs3_mkdir(&lfs3, "aa") => 0; lfs3_mkdir(&lfs3, "a") => 0; } else if (ORDER == 2) { // "random", trust me lfs3_mkdir(&lfs3, "aaaaa") => 0; lfs3_mkdir(&lfs3, "aaa") => 0; lfs3_mkdir(&lfs3, "aa") => 0; lfs3_mkdir(&lfs3, "aaaa") => 0; lfs3_mkdir(&lfs3, "aaaaaa") => 0; lfs3_mkdir(&lfs3, "a") => 0; } for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that our mkdirs worked struct lfs3_info info; lfs3_stat(&lfs3, "a", &info) => 0; assert(strcmp(info.name, "a") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "aa", &info) => 0; assert(strcmp(info.name, "aa") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "aaa", &info) => 0; assert(strcmp(info.name, "aaa") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "aaaa", &info) => 0; assert(strcmp(info.name, "aaaa") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "aaaaa", &info) => 0; assert(strcmp(info.name, "aaaaa") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "aaaaaa", &info) => 0; assert(strcmp(info.name, "aaaaaa") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); // check the directory order lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "a") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "aa") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "aaa") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "aaaa") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "aaaaa") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "aaaaaa") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' # test that did collisions don't cause issues [cases.test_dirs_did_collisions] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } assert(lfs3_crc32c(0, "a_SNmwMTHH", 10) == 0x12345678); assert(lfs3_crc32c(0, "b_skvjpWJH", 10) == 0x12345678); assert(lfs3_crc32c(0, "c_OnOQhVPH", 10) == 0x12345678); assert(lfs3_crc32c(0, "d_puMpPjRH", 10) == 0x12345678); assert(lfs3_crc32c(0, "e_LptKHkHH", 10) == 0x12345678); assert(lfs3_crc32c(0, "f_lUoVuhJH", 10) == 0x12345678); // check if dirs exist before mkconsistent struct lfs3_info info; err = lfs3_stat(&lfs3, "a_SNmwMTHH", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool a_exists = !err; err = lfs3_stat(&lfs3, "b_skvjpWJH", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool b_exists = !err; err = lfs3_stat(&lfs3, "c_OnOQhVPH", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool c_exists = !err; err = lfs3_stat(&lfs3, "d_puMpPjRH", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool d_exists = !err; err = lfs3_stat(&lfs3, "e_LptKHkHH", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool e_exists = !err; err = lfs3_stat(&lfs3, "f_lUoVuhJH", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool f_exists = !err; lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); if (a_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "a_SNmwMTHH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } if (b_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "b_skvjpWJH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } if (c_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "c_OnOQhVPH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } if (d_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "d_puMpPjRH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } if (e_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "e_LptKHkHH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } if (f_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "f_lUoVuhJH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; // make directories err = lfs3_mkdir(&lfs3, "a_SNmwMTHH"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == a_exists); err = lfs3_mkdir(&lfs3, "b_skvjpWJH"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == b_exists); err = lfs3_mkdir(&lfs3, "c_OnOQhVPH"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == c_exists); err = lfs3_mkdir(&lfs3, "d_puMpPjRH"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == d_exists); err = lfs3_mkdir(&lfs3, "e_LptKHkHH"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == e_exists); err = lfs3_mkdir(&lfs3, "f_lUoVuhJH"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == f_exists); for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that our mkdirs worked lfs3_stat(&lfs3, "a_SNmwMTHH", &info) => 0; assert(strcmp(info.name, "a_SNmwMTHH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "b_skvjpWJH", &info) => 0; assert(strcmp(info.name, "b_skvjpWJH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "c_OnOQhVPH", &info) => 0; assert(strcmp(info.name, "c_OnOQhVPH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "d_puMpPjRH", &info) => 0; assert(strcmp(info.name, "d_puMpPjRH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "e_LptKHkHH", &info) => 0; assert(strcmp(info.name, "e_LptKHkHH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "f_lUoVuhJH", &info) => 0; assert(strcmp(info.name, "f_lUoVuhJH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "a_SNmwMTHH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "b_skvjpWJH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "c_OnOQhVPH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "d_puMpPjRH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "e_LptKHkHH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "f_lUoVuhJH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' # these will also collide with the root [cases.test_dirs_did_zero] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } assert(lfs3_crc32c(0, "a_IplRNrPH", 10) == 0x00000000); assert(lfs3_crc32c(0, "b_iUwOsqRH", 10) == 0x00000000); assert(lfs3_crc32c(0, "c_UPNtkpHH", 10) == 0x00000000); assert(lfs3_crc32c(0, "d_jKLUSLJH", 10) == 0x00000000); assert(lfs3_crc32c(0, "e_VNunKMPH", 10) == 0x00000000); assert(lfs3_crc32c(0, "f_vknsvNRH", 10) == 0x00000000); // check if dirs exist before mkconsistent struct lfs3_info info; err = lfs3_stat(&lfs3, "a_IplRNrPH", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool a_exists = !err; err = lfs3_stat(&lfs3, "b_iUwOsqRH", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool b_exists = !err; err = lfs3_stat(&lfs3, "c_UPNtkpHH", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool c_exists = !err; err = lfs3_stat(&lfs3, "d_jKLUSLJH", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool d_exists = !err; err = lfs3_stat(&lfs3, "e_VNunKMPH", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool e_exists = !err; err = lfs3_stat(&lfs3, "f_vknsvNRH", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool f_exists = !err; lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); if (a_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "a_IplRNrPH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } if (b_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "b_iUwOsqRH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } if (c_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "c_UPNtkpHH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } if (d_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "d_jKLUSLJH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } if (e_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "e_VNunKMPH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } if (f_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "f_vknsvNRH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; // make directories err = lfs3_mkdir(&lfs3, "a_IplRNrPH"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == a_exists); err = lfs3_mkdir(&lfs3, "b_iUwOsqRH"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == b_exists); err = lfs3_mkdir(&lfs3, "c_UPNtkpHH"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == c_exists); err = lfs3_mkdir(&lfs3, "d_jKLUSLJH"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == d_exists); err = lfs3_mkdir(&lfs3, "e_VNunKMPH"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == e_exists); err = lfs3_mkdir(&lfs3, "f_vknsvNRH"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == f_exists); for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that our mkdirs worked lfs3_stat(&lfs3, "a_IplRNrPH", &info) => 0; assert(strcmp(info.name, "a_IplRNrPH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "b_iUwOsqRH", &info) => 0; assert(strcmp(info.name, "b_iUwOsqRH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "c_UPNtkpHH", &info) => 0; assert(strcmp(info.name, "c_UPNtkpHH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "d_jKLUSLJH", &info) => 0; assert(strcmp(info.name, "d_jKLUSLJH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "e_VNunKMPH", &info) => 0; assert(strcmp(info.name, "e_VNunKMPH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "f_vknsvNRH", &info) => 0; assert(strcmp(info.name, "f_vknsvNRH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "a_IplRNrPH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "b_iUwOsqRH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "c_UPNtkpHH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "d_jKLUSLJH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "e_VNunKMPH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "f_vknsvNRH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' # these will need to rollover from 0xffffffff -> 0x00000000 correctly # # note this is true even if you truncate [cases.test_dirs_did_ones] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } assert(lfs3_crc32c(0, "a_iomlVKPH", 10) == 0xffffffff); assert(lfs3_crc32c(0, "b_IJvqkHRH", 10) == 0xffffffff); assert(lfs3_crc32c(0, "c_uOOJsIHH", 10) == 0xffffffff); assert(lfs3_crc32c(0, "d_JTMkKuJH", 10) == 0xffffffff); assert(lfs3_crc32c(0, "e_vQtPStPH", 10) == 0xffffffff); assert(lfs3_crc32c(0, "f_VtoMnwRH", 10) == 0xffffffff); // check if dirs exist before mkconsistent struct lfs3_info info; err = lfs3_stat(&lfs3, "a_iomlVKPH", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool a_exists = !err; err = lfs3_stat(&lfs3, "b_IJvqkHRH", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool b_exists = !err; err = lfs3_stat(&lfs3, "c_uOOJsIHH", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool c_exists = !err; err = lfs3_stat(&lfs3, "d_JTMkKuJH", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool d_exists = !err; err = lfs3_stat(&lfs3, "e_vQtPStPH", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool e_exists = !err; err = lfs3_stat(&lfs3, "f_VtoMnwRH", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool f_exists = !err; lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); if (a_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "a_iomlVKPH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } if (b_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "b_IJvqkHRH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } if (c_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "c_uOOJsIHH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } if (d_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "d_JTMkKuJH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } if (e_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "e_vQtPStPH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } if (f_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "f_VtoMnwRH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; // make directories err = lfs3_mkdir(&lfs3, "a_iomlVKPH"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == a_exists); err = lfs3_mkdir(&lfs3, "b_IJvqkHRH"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == b_exists); err = lfs3_mkdir(&lfs3, "c_uOOJsIHH"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == c_exists); err = lfs3_mkdir(&lfs3, "d_JTMkKuJH"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == d_exists); err = lfs3_mkdir(&lfs3, "e_vQtPStPH"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == e_exists); err = lfs3_mkdir(&lfs3, "f_VtoMnwRH"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == f_exists); for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that our mkdirs worked lfs3_stat(&lfs3, "a_iomlVKPH", &info) => 0; assert(strcmp(info.name, "a_iomlVKPH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "b_IJvqkHRH", &info) => 0; assert(strcmp(info.name, "b_IJvqkHRH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "c_uOOJsIHH", &info) => 0; assert(strcmp(info.name, "c_uOOJsIHH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "d_JTMkKuJH", &info) => 0; assert(strcmp(info.name, "d_JTMkKuJH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "e_vQtPStPH", &info) => 0; assert(strcmp(info.name, "e_vQtPStPH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "f_VtoMnwRH", &info) => 0; assert(strcmp(info.name, "f_VtoMnwRH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "a_iomlVKPH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "b_IJvqkHRH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "c_uOOJsIHH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "d_JTMkKuJH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "e_vQtPStPH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "f_VtoMnwRH") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' # these test some boundary conditions on the underlying leb128 encoding, # if the leb128 disk-size is not calculated correctly these can cause # issues [cases.test_dirs_did_leb128_boundaries] defines.REMOUNT = [false, true] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // make a directory err = lfs3_mkdir(&lfs3, "ardvark"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check that our mkdir worked with stat struct lfs3_info info; lfs3_stat(&lfs3, "ardvark", &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); // and with dir_read lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; // and remove the directory lfs3_remove(&lfs3, "ardvark") => 0; for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that remove worked with stat lfs3_stat(&lfs3, "ardvark", &info) => LFS3_ERR_NOENT; // and with dir_read lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' # test that noent errors work [cases.test_dirs_rm_noent] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // make a directory err = lfs3_mkdir(&lfs3, "ardvark"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); // try to remove a nonsense directory lfs3_remove(&lfs3, "no") => LFS3_ERR_NOENT; // try to remove a directory in a nonsense directory lfs3_remove(&lfs3, "no/ardvark") => LFS3_ERR_NOENT; // try to remove a nonsense child directory lfs3_remove(&lfs3, "ardvark/no") => LFS3_ERR_NOENT; for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // and check that this didn't interfere with our original directory struct lfs3_info info; lfs3_stat(&lfs3, "ardvark", &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' # test that we catch removing of a non-empty directory [cases.test_dirs_rm_notempty] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // make a directory err = lfs3_mkdir(&lfs3, "ardvark"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); // fill it with stuff err = lfs3_mkdir(&lfs3, "ardvark/banana"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); // try to remove the parent directory lfs3_remove(&lfs3, "ardvark") => LFS3_ERR_NOTEMPTY; for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // and check that this didn't interfere with our original directory struct lfs3_info info; lfs3_stat(&lfs3, "ardvark", &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "ardvark/banana", &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; lfs3_dir_open(&lfs3, &dir, "ardvark") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' # test that dir existance is the same before/after mkconsistent [cases.test_dirs_rm_consistent] defines.REMOUNT = [false, true] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check if dir exists before mkconsistent struct lfs3_info info; err = lfs3_stat(&lfs3, "ardvark", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool exists = !err; // and with dir_read lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); if (exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; // make a directory err = lfs3_mkdir(&lfs3, "ardvark"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == exists); // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check that our mkdir worked with stat lfs3_stat(&lfs3, "ardvark", &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); // and with dir_read lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; // and remove the directory lfs3_remove(&lfs3, "ardvark") => 0; for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that remove worked with stat lfs3_stat(&lfs3, "ardvark", &info) => LFS3_ERR_NOENT; // and with dir_read lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' # test what happens if we try to remove root [cases.test_dirs_rm_root] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // try to remove root, which doesn't really make sense lfs3_remove(&lfs3, "/") => LFS3_ERR_BUSY; // make a directory err = lfs3_mkdir(&lfs3, "ardvark"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); // try to remove root, which doesn't really make sense // // it doesn't really matter which error returns first, so accept both err = lfs3_remove(&lfs3, "/"); assert(err == LFS3_ERR_NOTEMPTY || err == LFS3_ERR_BUSY); for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // and check that this didn't interfere with our original directory struct lfs3_info info; lfs3_stat(&lfs3, "ardvark", &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' [cases.test_dirs_rm_siblings] defines.REMOUNT = [false, true] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check if dirs exist before mkconsistent struct lfs3_info info; err = lfs3_stat(&lfs3, "ardvark", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool a_exists = !err; err = lfs3_stat(&lfs3, "banana", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool b_exists = !err; err = lfs3_stat(&lfs3, "cat", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool c_exists = !err; lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); if (a_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } if (b_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } if (c_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; // make some directories err = lfs3_mkdir(&lfs3, "ardvark"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == a_exists); err = lfs3_mkdir(&lfs3, "banana"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == b_exists); err = lfs3_mkdir(&lfs3, "cat"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == c_exists); // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check that our mkdir worked lfs3_stat(&lfs3, "ardvark", &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "banana", &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "cat", &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; // now remove each directory lfs3_remove(&lfs3, "ardvark") => 0; // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check that our remove worked lfs3_stat(&lfs3, "ardvark", &info) => LFS3_ERR_NOENT; lfs3_stat(&lfs3, "banana", &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "cat", &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; // remove another lfs3_remove(&lfs3, "banana") => 0; // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check that our remove worked lfs3_stat(&lfs3, "ardvark", &info) => LFS3_ERR_NOENT; lfs3_stat(&lfs3, "banana", &info) => LFS3_ERR_NOENT; lfs3_stat(&lfs3, "cat", &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; // remove another lfs3_remove(&lfs3, "cat") => 0; for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that our remove worked lfs3_stat(&lfs3, "ardvark", &info) => LFS3_ERR_NOENT; lfs3_stat(&lfs3, "banana", &info) => LFS3_ERR_NOENT; lfs3_stat(&lfs3, "cat", &info) => LFS3_ERR_NOENT; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' [cases.test_dirs_rm_children] defines.REMOUNT = [false, true] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check if dirs exist before mkconsistent struct lfs3_info info; err = lfs3_stat(&lfs3, "ardvark", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool a_exists = !err; err = lfs3_stat(&lfs3, "ardvark/banana", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool b_exists = !err; err = lfs3_stat(&lfs3, "ardvark/banana/cat", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool c_exists = !err; lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); if (a_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; err = lfs3_dir_open(&lfs3, &dir, "/ardvark"); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); assert(!err == a_exists); if (a_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); if (b_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } err = lfs3_dir_open(&lfs3, &dir, "/ardvark/banana"); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); assert(!err == b_exists); if (b_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); if (c_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } // make some directories err = lfs3_mkdir(&lfs3, "ardvark"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == a_exists); err = lfs3_mkdir(&lfs3, "ardvark/banana"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == b_exists); err = lfs3_mkdir(&lfs3, "ardvark/banana/cat"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == c_exists); // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check that our mkdirs worked lfs3_stat(&lfs3, "ardvark", &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "ardvark/banana", &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "ardvark/banana/cat", &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; lfs3_dir_open(&lfs3, &dir, "/ardvark") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; lfs3_dir_open(&lfs3, &dir, "/ardvark/banana") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; // now remove each directory lfs3_remove(&lfs3, "ardvark/banana/cat") => 0; // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check that our remove worked lfs3_stat(&lfs3, "ardvark", &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "ardvark/banana", &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "ardvark/banana/cat", &info) => LFS3_ERR_NOENT; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; lfs3_dir_open(&lfs3, &dir, "/ardvark") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; lfs3_dir_open(&lfs3, &dir, "/ardvark/banana") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; // remove another lfs3_remove(&lfs3, "ardvark/banana") => 0; // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check that our remove worked lfs3_stat(&lfs3, "ardvark", &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "ardvark/banana", &info) => LFS3_ERR_NOENT; lfs3_stat(&lfs3, "ardvark/banana/cat", &info) => LFS3_ERR_NOENT; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; lfs3_dir_open(&lfs3, &dir, "/ardvark") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; // remove another lfs3_remove(&lfs3, "ardvark") => 0; for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that our remove worked lfs3_stat(&lfs3, "ardvark", &info) => LFS3_ERR_NOENT; lfs3_stat(&lfs3, "ardvark/banana", &info) => LFS3_ERR_NOENT; lfs3_stat(&lfs3, "ardvark/banana/cat", &info) => LFS3_ERR_NOENT; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' [cases.test_dirs_rm_many] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] defines.REMAINING = [64, 2, 1, 0] defines.REMOUNT = [false, true] if = [ 'N > REMAINING', # limit powerloss testing due to time '!TEST_PLS || N <= 16', ] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // make this many directories for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); err = lfs3_mkdir(&lfs3, name); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); } // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check that our mkdir worked for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; struct lfs3_info info; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; // now remove some number of directories for (lfs3_size_t i = 0; i < N-REMAINING; i++) { char name[256]; sprintf(name, "dir%03x", i); lfs3_remove(&lfs3, name) => 0; // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } } for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that our removes worked for (lfs3_size_t i = 0; i < N-REMAINING; i++) { char name[256]; sprintf(name, "dir%03x", i); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => LFS3_ERR_NOENT; } for (lfs3_size_t i = 0; i < REMAINING; i++) { char name[256]; sprintf(name, "dir%03x", (int)(N-REMAINING + i)); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t i = 0; i < REMAINING; i++) { char name[256]; sprintf(name, "dir%03x", (int)(N-REMAINING + i)); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' [cases.test_dirs_rm_many_backwards] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] defines.REMAINING = [64, 2, 1, 0] defines.REMOUNT = [false, true] if = [ 'N > REMAINING', # limit powerloss testing due to time '!TEST_PLS || N <= 16', ] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // make this many directories for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", (int)(N-1-i)); err = lfs3_mkdir(&lfs3, name); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); } // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check that our mkdir worked for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; struct lfs3_info info; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; // now remove some number of directories for (lfs3_size_t i = 0; i < N-REMAINING; i++) { char name[256]; sprintf(name, "dir%03x", (int)(N-1-i)); lfs3_remove(&lfs3, name) => 0; // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } } for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that our removes worked for (lfs3_size_t i = 0; i < N-REMAINING; i++) { char name[256]; sprintf(name, "dir%03x", (int)(N-1-i)); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => LFS3_ERR_NOENT; } for (lfs3_size_t i = 0; i < REMAINING; i++) { char name[256]; sprintf(name, "dir%03x", i); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t i = 0; i < REMAINING; i++) { char name[256]; sprintf(name, "dir%03x", i); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' [cases.test_dirs_rm_many_2layers] defines.N = [1, 2, 4, 8, 16] defines.REMAINING = [2, 1, 0] defines.REMOUNT = [false, true] if = [ 'N > REMAINING', # limit powerloss testing due to time '!TEST_PLS || N <= 4', # TODO fix this case, it's failing because a mkdir is lining up with an # mdir split, and the chosen split name makes it so our did should have # ended up in the previous mdir '!(TEST_PLS && N == 4)', ] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // make this many directories for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); err = lfs3_mkdir(&lfs3, name); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); // containing this many directories for (lfs3_size_t j = 0; j < N; j++) { sprintf(name, "dir%03x/child%03x", i, j); err = lfs3_mkdir(&lfs3, name); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); } } // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check that our mkdirs worked for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t j = 0; j < N; j++) { char name[256]; sprintf(name, "dir%03x/child%03x", i, j); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; sprintf(name, "child%03x", j); assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } } lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; struct lfs3_info info; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); lfs3_dir_open(&lfs3, &dir, name) => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t j = 0; j < N; j++) { char name[256]; sprintf(name, "child%03x", j); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } // now remove some number of directories for (lfs3_size_t i = 0; i < N; i++) { for (lfs3_size_t j = 0; j < N; j++) { if (i < N-REMAINING || j < N-REMAINING) { char name[256]; sprintf(name, "dir%03x/child%03x", i, j); lfs3_remove(&lfs3, name) => 0; } // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } } if (i < N-REMAINING) { char name[256]; sprintf(name, "dir%03x", i); lfs3_remove(&lfs3, name) => 0; } // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } } for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that our removes worked for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); struct lfs3_info info; if (i < N-REMAINING) { lfs3_stat(&lfs3, name, &info) => LFS3_ERR_NOENT; } else { lfs3_stat(&lfs3, name, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t j = 0; j < N; j++) { char name[256]; sprintf(name, "dir%03x/child%03x", i, j); struct lfs3_info info; if (j < N-REMAINING) { lfs3_stat(&lfs3, name, &info) => LFS3_ERR_NOENT; } else { lfs3_stat(&lfs3, name, &info) => 0; sprintf(name, "child%03x", j); assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } } } } lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t i = 0; i < REMAINING; i++) { char name[256]; sprintf(name, "dir%03x", (int)(N-REMAINING + i)); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; for (lfs3_size_t i = 0; i < REMAINING; i++) { char name[256]; sprintf(name, "dir%03x", (int)(N-REMAINING + i)); lfs3_dir_open(&lfs3, &dir, name) => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t j = 0; j < REMAINING; j++) { char name[256]; sprintf(name, "child%03x", (int)(N-REMAINING + j)); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } } lfs3_unmount(&lfs3) => 0; ''' [cases.test_dirs_rm_many_3layers] defines.N = [1, 2, 4] defines.REMAINING = [2, 1, 0] defines.REMOUNT = [false, true] if = [ 'N > REMAINING', # limit powerloss testing due to time '!TEST_PLS || N <= 2', ] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // make this many directories for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); err = lfs3_mkdir(&lfs3, name); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); // containing this many directories for (lfs3_size_t j = 0; j < N; j++) { sprintf(name, "dir%03x/child%03x", i, j); err = lfs3_mkdir(&lfs3, name); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); // containing this many directories for (lfs3_size_t k = 0; k < N; k++) { sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k); err = lfs3_mkdir(&lfs3, name); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); } } } // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check that our mkdirs worked for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t j = 0; j < N; j++) { char name[256]; sprintf(name, "dir%03x/child%03x", i, j); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; sprintf(name, "child%03x", j); assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t k = 0; k < N; k++) { char name[256]; sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; sprintf(name, "grandchild%03x", k); assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } } } lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; struct lfs3_info info; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); lfs3_dir_open(&lfs3, &dir, name) => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t j = 0; j < N; j++) { char name[256]; sprintf(name, "child%03x", j); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; for (lfs3_size_t j = 0; j < N; j++) { char name[256]; sprintf(name, "dir%03x/child%03x", i, j); lfs3_dir_open(&lfs3, &dir, name) => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t k = 0; k < N; k++) { char name[256]; sprintf(name, "grandchild%03x", k); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } } // now remove some number of directories for (lfs3_size_t i = 0; i < N; i++) { for (lfs3_size_t j = 0; j < N; j++) { for (lfs3_size_t k = 0; k < N; k++) { if (i < N-REMAINING || j < N-REMAINING || k < N-REMAINING) { char name[256]; sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k); lfs3_remove(&lfs3, name) => 0; } // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } } if (i < N-REMAINING || j < N-REMAINING) { char name[256]; sprintf(name, "dir%03x/child%03x", i, j); lfs3_remove(&lfs3, name) => 0; } // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } } if (i < N-REMAINING) { char name[256]; sprintf(name, "dir%03x", i); lfs3_remove(&lfs3, name) => 0; } // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } } for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that our removes worked for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); struct lfs3_info info; if (i < N-REMAINING) { lfs3_stat(&lfs3, name, &info) => LFS3_ERR_NOENT; } else { lfs3_stat(&lfs3, name, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t j = 0; j < N; j++) { char name[256]; sprintf(name, "dir%03x/child%03x", i, j); struct lfs3_info info; if (j < N-REMAINING) { lfs3_stat(&lfs3, name, &info) => LFS3_ERR_NOENT; } else { lfs3_stat(&lfs3, name, &info) => 0; sprintf(name, "child%03x", j); assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t k = 0; k < N; k++) { char name[256]; sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k); struct lfs3_info info; if (k < N-REMAINING) { lfs3_stat(&lfs3, name, &info) => LFS3_ERR_NOENT; } else { lfs3_stat(&lfs3, name, &info) => 0; sprintf(name, "grandchild%03x", k); assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } } } } } } lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t i = 0; i < REMAINING; i++) { char name[256]; sprintf(name, "dir%03x", (int)(N-REMAINING + i)); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; for (lfs3_size_t i = 0; i < REMAINING; i++) { char name[256]; sprintf(name, "dir%03x", (int)(N-REMAINING + i)); lfs3_dir_open(&lfs3, &dir, name) => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t j = 0; j < REMAINING; j++) { char name[256]; sprintf(name, "child%03x", (int)(N-REMAINING + j)); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } for (lfs3_size_t i = 0; i < REMAINING; i++) { for (lfs3_size_t j = 0; j < REMAINING; j++) { char name[256]; sprintf(name, "dir%03x/child%03x", (int)(N-REMAINING + i), (int)(N-REMAINING + j)); lfs3_dir_open(&lfs3, &dir, name) => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t k = 0; k < REMAINING; k++) { char name[256]; sprintf(name, "grandchild%03x", (int)(N-REMAINING + k)); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } } } lfs3_unmount(&lfs3) => 0; ''' [cases.test_dirs_rm_many_linkedlist] defines.N = [1, 2, 4, 8, 16, 32, 64] defines.REMAINING = [16, 2, 1, 0] defines.REMOUNT = [false, true] if = [ 'N > REMAINING', # limit powerloss testing due to time '!TEST_PLS || N <= 16', ] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // create this many directory in a sort of linked-list by nesting char name[4096]; memset(name, 0, sizeof(name)); for (lfs3_size_t i = 0; i < N; i++) { sprintf(&name[strlen(name)], "/dir%03x", i); err = lfs3_mkdir(&lfs3, name); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); } // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check that our mkdir worked memset(name, 0, sizeof(name)); for (lfs3_size_t i = 0; i < N; i++) { sprintf(&name[strlen(name)], "/dir%03x", i); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; char name2[256]; sprintf(name2, "dir%03x", i); assert(strcmp(info.name, name2) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } memset(name, 0, sizeof(name)); for (lfs3_size_t i = 0; i < N; i++) { sprintf(&name[strlen(name)], "/dir%03x", i); lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, name) => 0; struct lfs3_info info; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); if (i < N-1) { char name2[256]; sprintf(name2, "dir%03x", i+1); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name2) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } // now remove some number of directories for (lfs3_size_t i = 0; i < N-REMAINING; i++) { lfs3_remove(&lfs3, name) => 0; name[strlen(name) - strlen("/dir...")] = '\0'; // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } } for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that our remove worked memset(name, 0, sizeof(name)); for (lfs3_size_t i = 0; i < REMAINING; i++) { sprintf(&name[strlen(name)], "/dir%03x", i); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; char name2[256]; sprintf(name2, "dir%03x", i); assert(strcmp(info.name, name2) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } memset(name, 0, sizeof(name)); for (lfs3_size_t i = 0; i < REMAINING; i++) { sprintf(&name[strlen(name)], "/dir%03x", i); lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, name) => 0; struct lfs3_info info; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); if (i < REMAINING-1) { char name2[256]; sprintf(name2, "dir%03x", i+1); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name2) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } } lfs3_unmount(&lfs3) => 0; ''' [cases.test_dirs_rm_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256] # do more ops than dirs to encourage rename collisions defines.OPS = '2*N' defines.PARENT = [false, true] defines.SEED = 'range(20)' fuzz = 'SEED' # limit powerloss testing due to time if = '!TEST_PLS || N <= 8' reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } if (PARENT) { err = lfs3_mkdir(&lfs3, "pricklypear"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); } // set up a simulation to compare against lfs3_size_t *sim = malloc(N*sizeof(lfs3_size_t)); lfs3_size_t sim_size = 0; uint32_t prng = SEED; for (lfs3_size_t i = 0; i < OPS; i++) { // choose a pseudo-random op, either mkdir or rmdir uint8_t op = TEST_PRNG(&prng) % 2; if (op == 0 || sim_size == 0) { // choose a pseudo-random number lfs3_size_t x = TEST_PRNG(&prng) % N; // insert into our sim for (lfs3_size_t j = 0;; j++) { if (j >= sim_size || sim[j] >= x) { // already seen? if (j < sim_size && sim[j] == x) { // do nothing } else { // insert memmove(&sim[j+1], &sim[j], (sim_size-j)*sizeof(lfs3_size_t)); sim_size += 1; sim[j] = x; } break; } } // create a directory here char name[256]; sprintf(name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), x); int err = lfs3_mkdir(&lfs3, name); assert(!err || err == LFS3_ERR_EXIST); } else { // choose a pseudo-random entry to delete lfs3_size_t j = TEST_PRNG(&prng) % sim_size; lfs3_size_t x = sim[j]; // delete from our sim memmove(&sim[j], &sim[j+1], (sim_size-(j+1))*sizeof(lfs3_size_t)); sim_size -= 1; // remove this directory char name[256]; sprintf(name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), x); lfs3_remove(&lfs3, name) => 0; } } for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // test that our directories match our simulation for (lfs3_size_t j = 0; j < sim_size; j++) { char name[256]; sprintf(name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), sim[j]); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; char name2[256]; sprintf(name2, "dir%03x", sim[j]); assert(strcmp(info.name, name2) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, ((PARENT) ? "pricklypear" : "/")) => 0; struct lfs3_info info; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t j = 0; j < sim_size; j++) { char name[256]; sprintf(name, "dir%03x", sim[j]); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } // clean up sim/lfs3 free(sim); lfs3_unmount(&lfs3) => 0; ''' ## dir rename tests [cases.test_dirs_mv] defines.REMOUNT = [false, true] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // make a directory err = lfs3_mkdir(&lfs3, "ardvark"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); // clean up interrupted renames if (TEST_PLS) { err = lfs3_remove(&lfs3, "banana"); assert(!err || err == LFS3_ERR_NOENT); } // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check that our mkdir worked with stat struct lfs3_info info; lfs3_stat(&lfs3, "ardvark", &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); // and with dir_read lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; // now rename the directory lfs3_rename(&lfs3, "ardvark", "banana") => 0; for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that rename worked with stat lfs3_stat(&lfs3, "ardvark", &info) => LFS3_ERR_NOENT; lfs3_stat(&lfs3, "banana", &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); // and with dir_read lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' # test that we can rename, and replace, other directories [cases.test_dirs_mv_replace] defines.REMOUNT = [false, true] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // make directories err = lfs3_mkdir(&lfs3, "ardvark"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); err = lfs3_mkdir(&lfs3, "banana"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check that our mkdir worked with stat struct lfs3_info info; lfs3_stat(&lfs3, "ardvark", &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); // and with dir_read lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; // now rename the directory lfs3_rename(&lfs3, "ardvark", "banana") => 0; for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that rename worked with stat lfs3_stat(&lfs3, "ardvark", &info) => LFS3_ERR_NOENT; lfs3_stat(&lfs3, "banana", &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); // and with dir_read lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' # test that we can rename to ourselves [cases.test_dirs_mv_noop] defines.REMOUNT = [false, true] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // make directories err = lfs3_mkdir(&lfs3, "ardvark"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check that our mkdir worked with stat struct lfs3_info info; lfs3_stat(&lfs3, "ardvark", &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); // and with dir_read lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; // now rename the directory to itself lfs3_rename(&lfs3, "ardvark", "ardvark") => 0; for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that rename worked with stat lfs3_stat(&lfs3, "ardvark", &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); // and with dir_read lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' # test that we catch replacing an invalid path [cases.test_dirs_mv_noent] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // make directories err = lfs3_mkdir(&lfs3, "ardvark"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); // try to rename a nonsense directory lfs3_rename(&lfs3, "no", "ardvark") => LFS3_ERR_NOENT; // try to rename a directory in a nonsense directory lfs3_rename(&lfs3, "no/ardvark", "ardvark") => LFS3_ERR_NOENT; // try to rename a nonsense child directory lfs3_rename(&lfs3, "ardvark/no", "banana") => LFS3_ERR_NOENT; // try to rename to a nonense directory lfs3_rename(&lfs3, "ardvark", "no/ardvark") => LFS3_ERR_NOENT; for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // and check that this didn't interfere with our original directory struct lfs3_info info; lfs3_stat(&lfs3, "ardvark", &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' # test that we catch replacing a non-empty directory [cases.test_dirs_mv_notempty] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // make directories err = lfs3_mkdir(&lfs3, "ardvark"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); err = lfs3_mkdir(&lfs3, "banana"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); // fill dest with stuff err = lfs3_mkdir(&lfs3, "banana/cat"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); // try to rename lfs3_rename(&lfs3, "ardvark", "banana") => LFS3_ERR_NOTEMPTY; for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // and check that this didn't interfere with our original directory struct lfs3_info info; lfs3_stat(&lfs3, "ardvark", &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "banana", &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "banana/cat", &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; lfs3_dir_open(&lfs3, &dir, "banana") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' # test that dir existance is the same before/after mkconsistent [cases.test_dirs_mv_consistent] defines.REMOUNT = [false, true] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check if dirs exist before mkconsistent struct lfs3_info info; err = lfs3_stat(&lfs3, "ardvark", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool a_exists = !err; err = lfs3_stat(&lfs3, "banana", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool b_exists = !err; // and with dir_read lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); if (a_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } if (b_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; // make a directory err = lfs3_mkdir(&lfs3, "ardvark"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == a_exists); // clean up interrupted renames if (TEST_PLS) { err = lfs3_remove(&lfs3, "banana"); assert(!err || err == LFS3_ERR_NOENT); assert(!err == b_exists); } // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check that our mkdir worked with stat lfs3_stat(&lfs3, "ardvark", &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); // and with dir_read lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; // now rename the directory lfs3_rename(&lfs3, "ardvark", "banana") => 0; for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that rename worked with stat lfs3_stat(&lfs3, "ardvark", &info) => LFS3_ERR_NOENT; lfs3_stat(&lfs3, "banana", &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); // and with dir_read lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' # test what happens if we try to rename root [cases.test_dirs_mv_root] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // try to rename root, which doesn't really make sense lfs3_rename(&lfs3, "/", "notroot") => LFS3_ERR_BUSY; // make a directory err = lfs3_mkdir(&lfs3, "ardvark"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); // try to rename root, which doesn't really make sense lfs3_rename(&lfs3, "/", "notroot") => LFS3_ERR_BUSY; for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // and check that this didn't interfere with our original directory struct lfs3_info info; lfs3_stat(&lfs3, "ardvark", &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' [cases.test_dirs_mv_siblings] defines.REMOUNT = [false, true] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check if dirs exist before mkconsistent struct lfs3_info info; err = lfs3_stat(&lfs3, "ardvark", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool a_exists = !err; err = lfs3_stat(&lfs3, "banana", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool b_exists = !err; err = lfs3_stat(&lfs3, "cat", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool c_exists = !err; err = lfs3_stat(&lfs3, "disco", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool d_exists = !err; err = lfs3_stat(&lfs3, "eggplant", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool e_exists = !err; err = lfs3_stat(&lfs3, "fish", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool f_exists = !err; lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); if (a_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } if (b_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } if (c_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } if (d_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "disco") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } if (e_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "eggplant") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } if (f_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "fish") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; // make some directories err = lfs3_mkdir(&lfs3, "ardvark"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == a_exists); err = lfs3_mkdir(&lfs3, "banana"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == b_exists); err = lfs3_mkdir(&lfs3, "cat"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == c_exists); // clean up interrupted renames if (TEST_PLS) { err = lfs3_remove(&lfs3, "disco"); assert(!err || err == LFS3_ERR_NOENT); assert(!err == d_exists); err = lfs3_remove(&lfs3, "eggplant"); assert(!err || err == LFS3_ERR_NOENT); assert(!err == e_exists); err = lfs3_remove(&lfs3, "fish"); assert(!err || err == LFS3_ERR_NOENT); assert(!err == f_exists); } // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check that our mkdir worked lfs3_stat(&lfs3, "ardvark", &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "banana", &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "cat", &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; // now rename each directory lfs3_rename(&lfs3, "ardvark", "disco") => 0; // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check that our rename worked lfs3_stat(&lfs3, "banana", &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "cat", &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "disco", &info) => 0; assert(strcmp(info.name, "disco") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "disco") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; // rename another lfs3_rename(&lfs3, "banana", "eggplant") => 0; // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check that our rename worked lfs3_stat(&lfs3, "cat", &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "disco", &info) => 0; assert(strcmp(info.name, "disco") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "eggplant", &info) => 0; assert(strcmp(info.name, "eggplant") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "disco") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "eggplant") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; // rename another lfs3_rename(&lfs3, "cat", "fish") => 0; for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that our rename worked lfs3_stat(&lfs3, "disco", &info) => 0; assert(strcmp(info.name, "disco") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "eggplant", &info) => 0; assert(strcmp(info.name, "eggplant") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "fish", &info) => 0; assert(strcmp(info.name, "fish") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "disco") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "eggplant") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "fish") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' [cases.test_dirs_mv_children] defines.REMOUNT = [false, true] reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check if dirs exist before mkconsistent struct lfs3_info info; err = lfs3_stat(&lfs3, "ardvark", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool a_exists = !err; err = lfs3_stat(&lfs3, "ardvark/banana", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool b_exists = !err; err = lfs3_stat(&lfs3, "ardvark/banana/cat", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool c_exists = !err; err = lfs3_stat(&lfs3, "disco", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool d_exists = !err; err = lfs3_stat(&lfs3, "disco/eggplant", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool e_exists = !err; err = lfs3_stat(&lfs3, "disco/eggplant/fish", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool f_exists = !err; err = lfs3_stat(&lfs3, "disco/banana", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool db_exists = !err; err = lfs3_stat(&lfs3, "disco/banana/cat", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool dbc_exists = !err; err = lfs3_stat(&lfs3, "disco/eggplant/cat", &info); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); bool dec_exists = !err; lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); if (a_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } if (d_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "disco") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; err = lfs3_dir_open(&lfs3, &dir, "/ardvark"); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); assert(!err == a_exists); if (a_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); if (b_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } err = lfs3_dir_open(&lfs3, &dir, "/ardvark/banana"); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); assert(!err == b_exists); if (b_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); if (c_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } err = lfs3_dir_open(&lfs3, &dir, "/disco"); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); assert(!err == d_exists); if (d_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); if (db_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } if (e_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "eggplant") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } err = lfs3_dir_open(&lfs3, &dir, "/disco/eggplant"); assert(err == LFS3_ERR_NOENT || (TEST_PLS && !err)); assert(!err == e_exists); if (e_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); if (dec_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } if (f_exists) { lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "fish") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } // make some directories err = lfs3_mkdir(&lfs3, "ardvark"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == a_exists); err = lfs3_mkdir(&lfs3, "ardvark/banana"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == b_exists); err = lfs3_mkdir(&lfs3, "ardvark/banana/cat"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); assert((err == LFS3_ERR_EXIST) == c_exists); // clean up interrupted renames if (TEST_PLS) { err = lfs3_remove(&lfs3, "disco/eggplant/fish"); assert(!err || err == LFS3_ERR_NOENT); assert(!err == f_exists); err = lfs3_remove(&lfs3, "disco/eggplant/cat"); assert(!err || err == LFS3_ERR_NOENT); assert(!err == dec_exists); err = lfs3_remove(&lfs3, "disco/eggplant"); assert(!err || err == LFS3_ERR_NOENT); assert(!err == e_exists); err = lfs3_remove(&lfs3, "disco/banana/cat"); assert(!err || err == LFS3_ERR_NOENT); assert(!err == dbc_exists); err = lfs3_remove(&lfs3, "disco/banana"); assert(!err || err == LFS3_ERR_NOENT); assert(!err == db_exists); err = lfs3_remove(&lfs3, "disco"); assert(!err || err == LFS3_ERR_NOENT); assert(!err == d_exists); } // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check that our mkdirs worked lfs3_stat(&lfs3, "ardvark", &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "ardvark/banana", &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "ardvark/banana/cat", &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "ardvark") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; lfs3_dir_open(&lfs3, &dir, "/ardvark") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; lfs3_dir_open(&lfs3, &dir, "/ardvark/banana") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; // now rename each directory lfs3_rename(&lfs3, "ardvark", "disco") => 0; // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check that our rename worked lfs3_stat(&lfs3, "disco", &info) => 0; assert(strcmp(info.name, "disco") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "disco/banana", &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "disco/banana/cat", &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "disco") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; lfs3_dir_open(&lfs3, &dir, "/disco") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "banana") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; lfs3_dir_open(&lfs3, &dir, "/disco/banana") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; // rename another lfs3_rename(&lfs3, "disco/banana", "disco/eggplant") => 0; // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check that our rename worked lfs3_stat(&lfs3, "disco", &info) => 0; assert(strcmp(info.name, "disco") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "disco/eggplant", &info) => 0; assert(strcmp(info.name, "eggplant") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "disco/eggplant/cat", &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "disco") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; lfs3_dir_open(&lfs3, &dir, "/disco") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "eggplant") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; lfs3_dir_open(&lfs3, &dir, "/disco/eggplant") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "cat") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; // rename another lfs3_rename(&lfs3, "disco/eggplant/cat", "disco/eggplant/fish") => 0; for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that our rename worked lfs3_stat(&lfs3, "disco", &info) => 0; assert(strcmp(info.name, "disco") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "disco/eggplant", &info) => 0; assert(strcmp(info.name, "eggplant") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_stat(&lfs3, "disco/eggplant/fish", &info) => 0; assert(strcmp(info.name, "fish") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "disco") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; lfs3_dir_open(&lfs3, &dir, "/disco") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "eggplant") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; lfs3_dir_open(&lfs3, &dir, "/disco/eggplant") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "fish") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' [cases.test_dirs_mv_many] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] defines.BEFORE = [false, true] defines.REMOUNT = [false, true] # limit powerloss testing due to time if = '!TEST_PLS || N <= 16' reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check if we have already started renaming, in case of powerloss struct lfs3_info info; err = lfs3_stat(&lfs3, ((BEFORE) ? "/0mved000" : "/mved000"), &info); if (err == LFS3_ERR_NOENT) { // make this many directories for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); err = lfs3_mkdir(&lfs3, name); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); } // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check that our mkdir worked for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; struct lfs3_info info; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } // now rename the directories for (lfs3_size_t i = 0; i < N; i++) { char old_name[256]; sprintf(old_name, "dir%03x", i); char new_name[256]; sprintf(new_name, "%smved%03x", ((BEFORE) ? "0" : ""), i); int err = lfs3_rename(&lfs3, old_name, new_name); assert(!err || (TEST_PLS && err == LFS3_ERR_NOENT)); // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } } for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that our renames worked for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' [cases.test_dirs_mv_many_backwards] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] defines.BEFORE = [false, true] defines.REMOUNT = [false, true] # limit powerloss testing due to time if = '!TEST_PLS || N <= 16' reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check if we have already started renaming, in case of powerloss struct lfs3_info info; err = lfs3_stat(&lfs3, ((BEFORE) ? "/0mved000" : "/mved000"), &info); if (err == LFS3_ERR_NOENT) { // make this many directories for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", (int)(N-1-i)); err = lfs3_mkdir(&lfs3, name); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); } // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check that our mkdir worked for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; struct lfs3_info info; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } // now rename the directories for (lfs3_size_t i = 0; i < N; i++) { char old_name[256]; sprintf(old_name, "dir%03x", i); char new_name[256]; sprintf(new_name, "%smved%03x", ((BEFORE) ? "0" : ""), i); int err = lfs3_rename(&lfs3, old_name, new_name); assert(!err || (TEST_PLS && err == LFS3_ERR_NOENT)); // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } } for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that our renames worked for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } lfs3_unmount(&lfs3) => 0; ''' [cases.test_dirs_mv_many_2layers] defines.N = [1, 2, 4, 8, 16] defines.BEFORE = [false, true] defines.REMOUNT = [false, true] # limit powerloss testing due to time if = '!TEST_PLS || N <= 4' reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check if we have already started renaming, in case of powerloss struct lfs3_info info; err = lfs3_stat(&lfs3, ((BEFORE) ? "/0mved000" : "/mved000"), &info); if (err == LFS3_ERR_NOENT) { // make this many directories for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); err = lfs3_mkdir(&lfs3, name); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); // containing this many directories for (lfs3_size_t j = 0; j < N; j++) { sprintf(name, "dir%03x/child%03x", i, j); err = lfs3_mkdir(&lfs3, name); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); } } // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check that our mkdirs worked for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t j = 0; j < N; j++) { char name[256]; sprintf(name, "dir%03x/child%03x", i, j); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; sprintf(name, "child%03x", j); assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } } lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; struct lfs3_info info; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); lfs3_dir_open(&lfs3, &dir, name) => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t j = 0; j < N; j++) { char name[256]; sprintf(name, "child%03x", j); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } } // now rename our directories for (lfs3_size_t i = 0; i < N; i++) { char old_name[256]; sprintf(old_name, "dir%03x", i); char new_name[256]; sprintf(new_name, "%smved%03x", ((BEFORE) ? "0" : ""), i); int err = lfs3_rename(&lfs3, old_name, new_name); assert(!err || (TEST_PLS && err == LFS3_ERR_NOENT)); // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } for (lfs3_size_t j = 0; j < N; j++) { char old_name[256]; sprintf(old_name, "%smved%03x/child%03x", ((BEFORE) ? "0" : ""), i, j); char new_name[256]; sprintf(new_name, "%smved%03x/%schmved%03x", ((BEFORE) ? "0" : ""), i, ((BEFORE) ? "0" : ""), j); int err = lfs3_rename(&lfs3, old_name, new_name); assert(!err || (TEST_PLS && err == LFS3_ERR_NOENT)); // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } } } for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that our renames worked for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t j = 0; j < N; j++) { char name[256]; sprintf(name, "%smved%03x/%schmved%03x", ((BEFORE) ? "0" : ""), i, ((BEFORE) ? "0" : ""), j); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; sprintf(name, "%schmved%03x", ((BEFORE) ? "0" : ""), j); assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } } lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i); lfs3_dir_open(&lfs3, &dir, name) => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t j = 0; j < N; j++) { char name[256]; sprintf(name, "%schmved%03x", ((BEFORE) ? "0" : ""), j); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } } lfs3_unmount(&lfs3) => 0; ''' [cases.test_dirs_mv_many_3layers] defines.N = [1, 2, 4] defines.BEFORE = [false, true] defines.REMOUNT = [false, true] # limit powerloss testing due to time if = '!TEST_PLS || N <= 2' reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check if we have already started renaming, in case of powerloss struct lfs3_info info; err = lfs3_stat(&lfs3, ((BEFORE) ? "/0mved000" : "/mved000"), &info); if (err == LFS3_ERR_NOENT) { // make this many directories for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); err = lfs3_mkdir(&lfs3, name); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); // containing this many directories for (lfs3_size_t j = 0; j < N; j++) { sprintf(name, "dir%03x/child%03x", i, j); err = lfs3_mkdir(&lfs3, name); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); // containing this many directories for (lfs3_size_t k = 0; k < N; k++) { sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k); err = lfs3_mkdir(&lfs3, name); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); } } } // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check that our mkdirs worked for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t j = 0; j < N; j++) { char name[256]; sprintf(name, "dir%03x/child%03x", i, j); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; sprintf(name, "child%03x", j); assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t k = 0; k < N; k++) { char name[256]; sprintf(name, "dir%03x/child%03x/grandchild%03x", i, j, k); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; sprintf(name, "grandchild%03x", k); assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } } } lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; struct lfs3_info info; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "dir%03x", i); lfs3_dir_open(&lfs3, &dir, name) => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t j = 0; j < N; j++) { char name[256]; sprintf(name, "child%03x", j); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; for (lfs3_size_t j = 0; j < N; j++) { char name[256]; sprintf(name, "dir%03x/child%03x", i, j); lfs3_dir_open(&lfs3, &dir, name) => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t k = 0; k < N; k++) { char name[256]; sprintf(name, "grandchild%03x", k); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } } } // now rename our directories for (lfs3_size_t i = 0; i < N; i++) { char old_name[256]; sprintf(old_name, "dir%03x", i); char new_name[256]; sprintf(new_name, "%smved%03x", ((BEFORE) ? "0" : ""), i); int err = lfs3_rename(&lfs3, old_name, new_name); assert(!err || (TEST_PLS && err == LFS3_ERR_NOENT)); // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } for (lfs3_size_t j = 0; j < N; j++) { char old_name[256]; sprintf(old_name, "%smved%03x/child%03x", ((BEFORE) ? "0" : ""), i, j); char new_name[256]; sprintf(new_name, "%smved%03x/%schmved%03x", ((BEFORE) ? "0" : ""), i, ((BEFORE) ? "0" : ""), j); int err = lfs3_rename(&lfs3, old_name, new_name); assert(!err || (TEST_PLS && err == LFS3_ERR_NOENT)); // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } for (lfs3_size_t k = 0; k < N; k++) { char old_name[256]; sprintf(old_name, "%smved%03x/%schmved%03x/grandchild%03x", ((BEFORE) ? "0" : ""), i, ((BEFORE) ? "0" : ""), j, k); char new_name[256]; sprintf(new_name, "%smved%03x/%schmved%03x/%sgrmved%03x", ((BEFORE) ? "0" : ""), i, ((BEFORE) ? "0" : ""), j, ((BEFORE) ? "0" : ""), k); int err = lfs3_rename(&lfs3, old_name, new_name); assert(!err || (TEST_PLS && err == LFS3_ERR_NOENT)); // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } } } } for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that our removes worked for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t j = 0; j < N; j++) { char name[256]; sprintf(name, "%smved%03x/%schmved%03x", ((BEFORE) ? "0" : ""), i, ((BEFORE) ? "0" : ""), j); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; sprintf(name, "%schmved%03x", ((BEFORE) ? "0" : ""), j); assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t k = 0; k < N; k++) { char name[256]; sprintf(name, "%smved%03x/%schmved%03x/%sgrmved%03x", ((BEFORE) ? "0" : ""), i, ((BEFORE) ? "0" : ""), j, ((BEFORE) ? "0" : ""), k); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; sprintf(name, "%sgrmved%03x", ((BEFORE) ? "0" : ""), k); assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } } } lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, "/") => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; for (lfs3_size_t i = 0; i < N; i++) { char name[256]; sprintf(name, "%smved%03x", ((BEFORE) ? "0" : ""), i); lfs3_dir_open(&lfs3, &dir, name) => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t j = 0; j < N; j++) { char name[256]; sprintf(name, "%schmved%03x", ((BEFORE) ? "0" : ""), j); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; for (lfs3_size_t j = 0; j < N; j++) { char name[256]; sprintf(name, "%smved%03x/%schmved%03x", ((BEFORE) ? "0" : ""), i, ((BEFORE) ? "0" : ""), j); lfs3_dir_open(&lfs3, &dir, name) => 0; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t k = 0; k < N; k++) { char name[256]; sprintf(name, "%sgrmved%03x", ((BEFORE) ? "0" : ""), k); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } } } lfs3_unmount(&lfs3) => 0; ''' [cases.test_dirs_mv_many_linkedlist] defines.N = [1, 2, 4, 8, 16, 32, 64] defines.BEFORE = [false, true] defines.REMOUNT = [false, true] # limit powerloss testing due to time if = '!TEST_PLS || N <= 16' reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check if we have already started renaming, in case of powerloss struct lfs3_info info; err = lfs3_stat(&lfs3, ((BEFORE) ? "/0mved000" : "/mved000"), &info); if (err == LFS3_ERR_NOENT) { // create this many directory in a sort of linked-list by nesting char name[4096]; memset(name, 0, sizeof(name)); for (lfs3_size_t i = 0; i < N; i++) { sprintf(&name[strlen(name)], "/dir%03x", i); err = lfs3_mkdir(&lfs3, name); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); } // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // check that our mkdir worked memset(name, 0, sizeof(name)); for (lfs3_size_t i = 0; i < N; i++) { sprintf(&name[strlen(name)], "/dir%03x", i); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; char name2[256]; sprintf(name2, "dir%03x", i); assert(strcmp(info.name, name2) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } memset(name, 0, sizeof(name)); for (lfs3_size_t i = 0; i < N; i++) { sprintf(&name[strlen(name)], "/dir%03x", i); lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, name) => 0; struct lfs3_info info; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); if (i < N-1) { char name2[256]; sprintf(name2, "dir%03x", i+1); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name2) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } } // now rename our directories char old_name[4096]; memset(old_name, 0, sizeof(old_name)); char new_name[4096]; memset(new_name, 0, sizeof(new_name)); for (lfs3_size_t i = 0; i < N; i++) { sprintf(&old_name[strlen(old_name)], "/dir%03x", i); sprintf(&new_name[strlen(new_name)], "/%smved%03x", ((BEFORE) ? "0" : ""), i); err = lfs3_rename(&lfs3, old_name, new_name); assert(!err || (TEST_PLS && err == LFS3_ERR_NOENT)); // remount? if (REMOUNT) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // update old_name's path memcpy(old_name, new_name, sizeof(old_name)); } for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // check that our renames worked char name[4096]; memset(name, 0, sizeof(name)); for (lfs3_size_t i = 0; i < N; i++) { sprintf(&name[strlen(name)], "/%smved%03x", ((BEFORE) ? "0" : ""), i); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; char name2[256]; sprintf(name2, "%smved%03x", ((BEFORE) ? "0" : ""), i); assert(strcmp(info.name, name2) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } memset(name, 0, sizeof(name)); for (lfs3_size_t i = 0; i < N; i++) { sprintf(&name[strlen(name)], "/%smved%03x", ((BEFORE) ? "0" : ""), i); lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, name) => 0; struct lfs3_info info; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); if (i < N-1) { char name2[256]; sprintf(name2, "%smved%03x", ((BEFORE) ? "0" : ""), i+1); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name2) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } } lfs3_unmount(&lfs3) => 0; ''' [cases.test_dirs_mv_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256] # do more ops than dirs to encourage rename collisions defines.OPS = '2*N' defines.PARENT = [false, true] defines.SEED = 'range(20)' fuzz = 'SEED' # limit powerloss testing due to time if = '!TEST_PLS || N <= 8' reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } if (PARENT) { err = lfs3_mkdir(&lfs3, "pricklypear"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); } // set up a simulation to compare against lfs3_size_t *sim = malloc(N*sizeof(lfs3_size_t)); lfs3_size_t sim_size = 0; uint32_t prng = SEED; for (lfs3_size_t i = 0; i < OPS; i++) { // choose a pseudo-random op, either mkdir or rename uint8_t op = TEST_PRNG(&prng) % 2; if (op == 0 || sim_size == 0) { // choose a pseudo-random number lfs3_size_t x = TEST_PRNG(&prng) % N; // insert into our sim for (lfs3_size_t j = 0;; j++) { if (j >= sim_size || sim[j] >= x) { // already seen? if (j < sim_size && sim[j] == x) { // do nothing } else { // insert memmove(&sim[j+1], &sim[j], (sim_size-j)*sizeof(lfs3_size_t)); sim_size += 1; sim[j] = x; } break; } } // create a directory here char name[256]; sprintf(name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), x); int err = lfs3_mkdir(&lfs3, name); assert(!err || err == LFS3_ERR_EXIST); } else { // choose a pseudo-random entry to rename, and a pseudo-random // number to rename to lfs3_size_t j = TEST_PRNG(&prng) % sim_size; lfs3_size_t x = sim[j]; lfs3_size_t y = TEST_PRNG(&prng) % N; for (lfs3_size_t k = 0;; k++) { if (k >= sim_size || sim[k] >= y) { // already seen and not a noop? if (k < sim_size && sim[k] == y && x != y) { // just delete the original entry memmove(&sim[j], &sim[j+1], (sim_size-(j+1))*sizeof(lfs3_size_t)); sim_size -= 1; } else { // first delete memmove(&sim[j], &sim[j+1], (sim_size-(j+1))*sizeof(lfs3_size_t)); if (k > j) { k -= 1; } // then insert memmove(&sim[k+1], &sim[k], (sim_size-k)*sizeof(lfs3_size_t)); sim[k] = y; } break; } } // rename this directory char old_name[256]; sprintf(old_name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), x); char new_name[256]; sprintf(new_name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), y); lfs3_rename(&lfs3, old_name, new_name) => 0; } } for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // test that our directories match our simulation for (lfs3_size_t j = 0; j < sim_size; j++) { char name[256]; sprintf(name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), sim[j]); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; char name2[256]; sprintf(name2, "dir%03x", sim[j]); assert(strcmp(info.name, name2) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, ((PARENT) ? "pricklypear" : "/")) => 0; struct lfs3_info info; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t j = 0; j < sim_size; j++) { char name[256]; sprintf(name, "dir%03x", sim[j]); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } // clean up sim/lfs3 free(sim); lfs3_unmount(&lfs3) => 0; ''' # test all of the operations together [cases.test_dirs_mvrm_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256] # do more ops than dirs to encourage rename collisions defines.OPS = '2*N' defines.PARENT = [false, true] defines.SEED = 'range(20)' fuzz = 'SEED' # limit powerloss testing due to time if = '!TEST_PLS || N <= 8' reentrant = true code = ''' // format once per test lfs3_t lfs3; int err = lfs3_mount(&lfs3, LFS3_M_RDWR, CFG); if (err) { lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } if (PARENT) { err = lfs3_mkdir(&lfs3, "pricklypear"); assert(!err || (TEST_PLS && err == LFS3_ERR_EXIST)); } // set up a simulation to compare against lfs3_size_t *sim = malloc(N*sizeof(lfs3_size_t)); lfs3_size_t sim_size = 0; uint32_t prng = SEED; for (lfs3_size_t i = 0; i < OPS; i++) { // choose a pseudo-random op, either mkdir, remove, or rename uint8_t op = TEST_PRNG(&prng) % 3; if (op == 0 || sim_size == 0) { // choose a pseudo-random number lfs3_size_t x = TEST_PRNG(&prng) % N; // insert into our sim for (lfs3_size_t j = 0;; j++) { if (j >= sim_size || sim[j] >= x) { // already seen? if (j < sim_size && sim[j] == x) { // do nothing } else { // insert memmove(&sim[j+1], &sim[j], (sim_size-j)*sizeof(lfs3_size_t)); sim_size += 1; sim[j] = x; } break; } } // create a directory here char name[256]; sprintf(name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), x); int err = lfs3_mkdir(&lfs3, name); assert(!err || err == LFS3_ERR_EXIST); } else if (op == 1) { // choose a pseudo-random entry to delete lfs3_size_t j = TEST_PRNG(&prng) % sim_size; lfs3_size_t x = sim[j]; // delete from our sim memmove(&sim[j], &sim[j+1], (sim_size-(j+1))*sizeof(lfs3_size_t)); sim_size -= 1; // remove this directory char name[256]; sprintf(name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), x); lfs3_remove(&lfs3, name) => 0; } else { // choose a pseudo-random entry to rename, and a pseudo-random // number to rename to lfs3_size_t j = TEST_PRNG(&prng) % sim_size; lfs3_size_t x = sim[j]; lfs3_size_t y = TEST_PRNG(&prng) % N; for (lfs3_size_t k = 0;; k++) { if (k >= sim_size || sim[k] >= y) { // already seen and not a noop? if (k < sim_size && sim[k] == y && x != y) { // just delete the original entry memmove(&sim[j], &sim[j+1], (sim_size-(j+1))*sizeof(lfs3_size_t)); sim_size -= 1; } else { // first delete memmove(&sim[j], &sim[j+1], (sim_size-(j+1))*sizeof(lfs3_size_t)); if (k > j) { k -= 1; } // then insert memmove(&sim[k+1], &sim[k], (sim_size-k)*sizeof(lfs3_size_t)); sim[k] = y; } break; } } // rename this directory char old_name[256]; sprintf(old_name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), x); char new_name[256]; sprintf(new_name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), y); lfs3_rename(&lfs3, old_name, new_name) => 0; } } for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; } // grm should be zero here assert(lfs3.grm_p[0] == 0); // test that our directories match our simulation for (lfs3_size_t j = 0; j < sim_size; j++) { char name[256]; sprintf(name, "%s/dir%03x", ((PARENT) ? "pricklypear" : ""), sim[j]); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; char name2[256]; sprintf(name2, "dir%03x", sim[j]); assert(strcmp(info.name, name2) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_t dir; lfs3_dir_open(&lfs3, &dir, ((PARENT) ? "pricklypear" : "/")) => 0; struct lfs3_info info; lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); for (lfs3_size_t j = 0; j < sim_size; j++) { char name[256]; sprintf(name, "dir%03x", sim[j]); lfs3_dir_read(&lfs3, &dir, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_DIR); assert(info.size == 0); } lfs3_dir_read(&lfs3, &dir, &info) => LFS3_ERR_NOENT; lfs3_dir_close(&lfs3, &dir) => 0; } // clean up sim/lfs3 free(sim); lfs3_unmount(&lfs3) => 0; '''