ab46cb0bbd
Changed:
- lfsr_mkdir(&lfs, "/") => LFS_ERR_EXIST
- lfsr_file_open(&lfs, &file, "/", *) => LFS_ERR_ISDIR
Unchanged:
- lfsr_remove(&lfs, "/") => LFS_ERR_INVAL
- lfsr_rename(&lfs, "/", *) => LFS_ERR_INVAL
- lfsr_rename(&lfs, *, "/") => LFS_ERR_INVAL
This better matches what Linux, etc, does: prefering a normal
dir-related error unless the only issue is that the dir in question is
the root.
Though Linux, etc, usually return EBUSY, which seems to also be used for
special device files. We could add LFS_ERR_BUSY, but I'm not sure it's
really worth it for such a rare error. It's not like the name would help
anything...
Internally, lfsr_mtree_pathlookup always returns LFS_ERR_INVAL for root,
so this unfortunately requires a bit more code to map to the correct
errors:
code stack
before: 33598 2592
after 33634 (+0.1%) 2592 (+0.0%)
327 lines
10 KiB
TOML
327 lines
10 KiB
TOML
# Test various path-related corner cases
|
|
after = 'test_dirs'
|
|
|
|
# simple path test
|
|
[cases.test_paths_normal]
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, CFG) => 0;
|
|
lfsr_mount(&lfs, CFG) => 0;
|
|
lfsr_mkdir(&lfs, "tea") => 0;
|
|
lfsr_mkdir(&lfs, "tea/green") => 0;
|
|
lfsr_mkdir(&lfs, "tea/oolong") => 0;
|
|
lfsr_mkdir(&lfs, "tea/black") => 0;
|
|
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "tea/green", &info) => 0;
|
|
assert(strcmp(info.name, "green") == 0);
|
|
lfsr_stat(&lfs, "/tea/green", &info) => 0;
|
|
assert(strcmp(info.name, "green") == 0);
|
|
|
|
lfsr_mkdir(&lfs, "/milk") => 0;
|
|
lfsr_stat(&lfs, "/milk", &info) => 0;
|
|
assert(strcmp(info.name, "milk") == 0);
|
|
lfsr_stat(&lfs, "milk", &info) => 0;
|
|
assert(strcmp(info.name, "milk") == 0);
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# redundant slashes
|
|
[cases.test_paths_redundant_slashes]
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, CFG) => 0;
|
|
lfsr_mount(&lfs, CFG) => 0;
|
|
lfsr_mkdir(&lfs, "tea") => 0;
|
|
lfsr_mkdir(&lfs, "tea/green") => 0;
|
|
lfsr_mkdir(&lfs, "tea/oolong") => 0;
|
|
lfsr_mkdir(&lfs, "tea/black") => 0;
|
|
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "/tea/green", &info) => 0;
|
|
assert(strcmp(info.name, "green") == 0);
|
|
lfsr_stat(&lfs, "//tea//green", &info) => 0;
|
|
assert(strcmp(info.name, "green") == 0);
|
|
lfsr_stat(&lfs, "///tea///green", &info) => 0;
|
|
assert(strcmp(info.name, "green") == 0);
|
|
|
|
lfsr_mkdir(&lfs, "////milk") => 0;
|
|
lfsr_stat(&lfs, "////milk", &info) => 0;
|
|
assert(strcmp(info.name, "milk") == 0);
|
|
lfsr_stat(&lfs, "milk", &info) => 0;
|
|
assert(strcmp(info.name, "milk") == 0);
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# dot path test
|
|
[cases.test_paths_dot]
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, CFG) => 0;
|
|
lfsr_mount(&lfs, CFG) => 0;
|
|
lfsr_mkdir(&lfs, "tea") => 0;
|
|
lfsr_mkdir(&lfs, "tea/green") => 0;
|
|
lfsr_mkdir(&lfs, "tea/oolong") => 0;
|
|
lfsr_mkdir(&lfs, "tea/black") => 0;
|
|
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "./tea/green", &info) => 0;
|
|
assert(strcmp(info.name, "green") == 0);
|
|
lfsr_stat(&lfs, "/./tea/green", &info) => 0;
|
|
assert(strcmp(info.name, "green") == 0);
|
|
lfsr_stat(&lfs, "/././tea/green", &info) => 0;
|
|
assert(strcmp(info.name, "green") == 0);
|
|
lfsr_stat(&lfs, "/./tea/./green", &info) => 0;
|
|
assert(strcmp(info.name, "green") == 0);
|
|
|
|
lfsr_mkdir(&lfs, "/./milk") => 0;
|
|
lfsr_stat(&lfs, "/./milk", &info) => 0;
|
|
assert(strcmp(info.name, "milk") == 0);
|
|
lfsr_stat(&lfs, "milk", &info) => 0;
|
|
assert(strcmp(info.name, "milk") == 0);
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# dot dot path test
|
|
[cases.test_paths_dot_dot]
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, CFG) => 0;
|
|
lfsr_mount(&lfs, CFG) => 0;
|
|
lfsr_mkdir(&lfs, "tea") => 0;
|
|
lfsr_mkdir(&lfs, "tea/green") => 0;
|
|
lfsr_mkdir(&lfs, "tea/oolong") => 0;
|
|
lfsr_mkdir(&lfs, "tea/black") => 0;
|
|
lfsr_mkdir(&lfs, "coffee") => 0;
|
|
lfsr_mkdir(&lfs, "coffee/drip") => 0;
|
|
lfsr_mkdir(&lfs, "coffee/espresso") => 0;
|
|
lfsr_mkdir(&lfs, "coffee/coldbrew") => 0;
|
|
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "coffee/../tea/green", &info) => 0;
|
|
assert(strcmp(info.name, "green") == 0);
|
|
lfsr_stat(&lfs, "tea/black/../green", &info) => 0;
|
|
assert(strcmp(info.name, "green") == 0);
|
|
lfsr_stat(&lfs, "coffee/coldbrew/../../tea/green", &info) => 0;
|
|
assert(strcmp(info.name, "green") == 0);
|
|
lfsr_stat(&lfs, "coffee/../coffee/../tea/green", &info) => 0;
|
|
assert(strcmp(info.name, "green") == 0);
|
|
|
|
lfsr_mkdir(&lfs, "coffee/../milk") => 0;
|
|
lfsr_stat(&lfs, "coffee/../milk", &info) => 0;
|
|
strcmp(info.name, "milk") => 0;
|
|
lfsr_stat(&lfs, "milk", &info) => 0;
|
|
strcmp(info.name, "milk") => 0;
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# trailing dot path test
|
|
[cases.test_paths_trailing_dot]
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, CFG) => 0;
|
|
lfsr_mount(&lfs, CFG) => 0;
|
|
lfsr_mkdir(&lfs, "tea") => 0;
|
|
lfsr_mkdir(&lfs, "tea/green") => 0;
|
|
lfsr_mkdir(&lfs, "tea/oolong") => 0;
|
|
lfsr_mkdir(&lfs, "tea/black") => 0;
|
|
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "tea/green/", &info) => 0;
|
|
assert(strcmp(info.name, "green") == 0);
|
|
lfsr_stat(&lfs, "tea/green/.", &info) => 0;
|
|
assert(strcmp(info.name, "green") == 0);
|
|
lfsr_stat(&lfs, "tea/green/./.", &info) => 0;
|
|
assert(strcmp(info.name, "green") == 0);
|
|
lfsr_stat(&lfs, "tea/green/..", &info) => 0;
|
|
assert(strcmp(info.name, "tea") == 0);
|
|
lfsr_stat(&lfs, "tea/green/../.", &info) => 0;
|
|
assert(strcmp(info.name, "tea") == 0);
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# leading dot path test
|
|
[cases.test_paths_leading_dot]
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, CFG) => 0;
|
|
lfsr_mount(&lfs, CFG) => 0;
|
|
lfsr_mkdir(&lfs, ".milk") => 0;
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, ".milk", &info) => 0;
|
|
strcmp(info.name, ".milk") => 0;
|
|
lfsr_stat(&lfs, "tea/.././.milk", &info) => 0;
|
|
strcmp(info.name, ".milk") => 0;
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# root dot dot path test
|
|
[cases.test_paths_root_dot_dot]
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, CFG) => 0;
|
|
lfsr_mount(&lfs, CFG) => 0;
|
|
lfsr_mkdir(&lfs, "tea") => 0;
|
|
lfsr_mkdir(&lfs, "tea/green") => 0;
|
|
lfsr_mkdir(&lfs, "tea/oolong") => 0;
|
|
lfsr_mkdir(&lfs, "tea/black") => 0;
|
|
lfsr_mkdir(&lfs, "coffee") => 0;
|
|
lfsr_mkdir(&lfs, "coffee/drip") => 0;
|
|
lfsr_mkdir(&lfs, "coffee/espresso") => 0;
|
|
lfsr_mkdir(&lfs, "coffee/coldbrew") => 0;
|
|
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "coffee/../../../../../../tea/green", &info) => 0;
|
|
strcmp(info.name, "green") => 0;
|
|
|
|
lfsr_mkdir(&lfs, "coffee/../../../../../../milk") => 0;
|
|
lfsr_stat(&lfs, "coffee/../../../../../../milk", &info) => 0;
|
|
strcmp(info.name, "milk") => 0;
|
|
lfsr_stat(&lfs, "milk", &info) => 0;
|
|
strcmp(info.name, "milk") => 0;
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# invalid path tests
|
|
[cases.test_paths_invalid]
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, CFG);
|
|
lfsr_mount(&lfs, CFG) => 0;
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "milk", &info) => LFS_ERR_NOENT;
|
|
lfsr_stat(&lfs, "milk/cream", &info) => LFS_ERR_NOENT;
|
|
lfsr_stat(&lfs, "milk/cream/foam", &info) => LFS_ERR_NOENT;
|
|
|
|
lfsr_remove(&lfs, "milk") => LFS_ERR_NOENT;
|
|
lfsr_remove(&lfs, "milk/cream") => LFS_ERR_NOENT;
|
|
lfsr_remove(&lfs, "milk/cream/foam") => LFS_ERR_NOENT;
|
|
|
|
lfsr_mkdir(&lfs, "milk/cream") => LFS_ERR_NOENT;
|
|
lfsr_file_t file;
|
|
lfsr_file_open(&lfs, &file, "milk/cream",
|
|
LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOENT;
|
|
lfsr_mkdir(&lfs, "milk/cream/foam") => LFS_ERR_NOENT;
|
|
lfsr_file_open(&lfs, &file, "milk/cream/foam",
|
|
LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOENT;
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# root operations
|
|
[cases.test_paths_root]
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, CFG) => 0;
|
|
lfsr_mount(&lfs, CFG) => 0;
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "/", &info) => 0;
|
|
assert(strcmp(info.name, "/") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
assert(info.size == 0);
|
|
|
|
lfsr_mkdir(&lfs, "/") => LFS_ERR_EXIST;
|
|
lfsr_file_t file;
|
|
lfsr_file_open(&lfs, &file, "/",
|
|
LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR;
|
|
|
|
lfsr_remove(&lfs, "/") => LFS_ERR_INVAL;
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# root representations
|
|
[cases.test_paths_root_reprs]
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, CFG) => 0;
|
|
lfsr_mount(&lfs, CFG) => 0;
|
|
struct lfs_info info;
|
|
lfsr_stat(&lfs, "/", &info) => 0;
|
|
assert(strcmp(info.name, "/") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
assert(info.size == 0);
|
|
lfsr_stat(&lfs, "", &info) => 0;
|
|
assert(strcmp(info.name, "/") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
assert(info.size == 0);
|
|
lfsr_stat(&lfs, ".", &info) => 0;
|
|
assert(strcmp(info.name, "/") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
assert(info.size == 0);
|
|
lfsr_stat(&lfs, "..", &info) => 0;
|
|
assert(strcmp(info.name, "/") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
assert(info.size == 0);
|
|
lfsr_stat(&lfs, "//", &info) => 0;
|
|
assert(strcmp(info.name, "/") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
assert(info.size == 0);
|
|
lfsr_stat(&lfs, "./", &info) => 0;
|
|
assert(strcmp(info.name, "/") == 0);
|
|
assert(info.type == LFS_TYPE_DIR);
|
|
assert(info.size == 0);
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# max path test
|
|
[cases.test_paths_max]
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, CFG) => 0;
|
|
lfsr_mount(&lfs, CFG) => 0;
|
|
lfsr_mkdir(&lfs, "coffee") => 0;
|
|
lfsr_mkdir(&lfs, "coffee/drip") => 0;
|
|
lfsr_mkdir(&lfs, "coffee/espresso") => 0;
|
|
lfsr_mkdir(&lfs, "coffee/coldbrew") => 0;
|
|
|
|
char path[2*LFS_NAME_MAX+2];
|
|
memset(path, 'w', LFS_NAME_MAX+1);
|
|
path[LFS_NAME_MAX+1] = '\0';
|
|
lfsr_mkdir(&lfs, path) => LFS_ERR_NAMETOOLONG;
|
|
lfsr_file_t file;
|
|
lfsr_file_open(&lfs, &file, path,
|
|
LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NAMETOOLONG;
|
|
|
|
memcpy(path, "coffee/", strlen("coffee/"));
|
|
memset(path+strlen("coffee/"), 'w', LFS_NAME_MAX+1);
|
|
path[strlen("coffee/")+LFS_NAME_MAX+1] = '\0';
|
|
lfsr_mkdir(&lfs, path) => LFS_ERR_NAMETOOLONG;
|
|
lfsr_file_open(&lfs, &file, path,
|
|
LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NAMETOOLONG;
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# really big path test
|
|
[cases.test_paths_really_big]
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, CFG) => 0;
|
|
lfsr_mount(&lfs, CFG) => 0;
|
|
lfsr_mkdir(&lfs, "coffee") => 0;
|
|
lfsr_mkdir(&lfs, "coffee/drip") => 0;
|
|
lfsr_mkdir(&lfs, "coffee/espresso") => 0;
|
|
lfsr_mkdir(&lfs, "coffee/coldbrew") => 0;
|
|
|
|
char path[2*LFS_NAME_MAX+2];
|
|
memset(path, 'w', LFS_NAME_MAX);
|
|
path[LFS_NAME_MAX] = '\0';
|
|
lfsr_mkdir(&lfs, path) => 0;
|
|
lfsr_remove(&lfs, path) => 0;
|
|
lfsr_file_t file;
|
|
lfsr_file_open(&lfs, &file, path,
|
|
LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
|
lfsr_file_close(&lfs, &file) => 0;
|
|
lfsr_remove(&lfs, path) => 0;
|
|
|
|
memcpy(path, "coffee/", strlen("coffee/"));
|
|
memset(path+strlen("coffee/"), 'w', LFS_NAME_MAX);
|
|
path[strlen("coffee/")+LFS_NAME_MAX] = '\0';
|
|
lfsr_mkdir(&lfs, path) => 0;
|
|
lfsr_remove(&lfs, path) => 0;
|
|
lfsr_file_open(&lfs, &file, path,
|
|
LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
|
lfsr_file_close(&lfs, &file) => 0;
|
|
lfsr_remove(&lfs, path) => 0;
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|