f539d3341c
These functions provide simple access to littlefs's custom attributes,
which are small pieces of user-specified metadata that can be attached
to files, dirs, root, etc:
- lfsr_getattr - Reads an attribute
- lfsr_sizeattr - Gets the size of an attribute
- lfsr_setattr - Writes an attribute
- lfsr_removeattr - Removes an attribute
You may notice these functions look quite a bit different from their
previous incarnations. This is because the custom attribute API is
getting an overhaul based on feedback provided by users
The previous API had some real design flaws that interfered with
usability, but now that things have had some time to settle (6 years!),
hopefully most of the pain points are clear.
Notable changes:
- lfsr_getattr's return value is now limited by buffer size.
The intention of the previous API, where lfsr_getattr always returns
the attr size, even if it's larger than the buffer, was to allow users
to find the attr size without an infinitely large buffer.
In defense of this design, Linux's getxattr does something somewhat
similar, returning the attr size when the buffer size equals zero.
Though getxattr does truncate when buffer size is non-zero, which is
probably safer.
But, let's be honest, this multipurpose abuse of lfsr_getattr's return
value is inconsistent with other read functions and potentially
dangerous for users.
I think one of the reasons for this API in Linux-land is the limited
syscall numbers discouraging new functions, but we have no such
limitation here! We might as well add a dedicated function for
this: lfsr_sizeattr.
- No more padding with zeros!
This was a cludge to get around the lack of returned size in custom
attributes attached to files, but is inconsistent with other read
functions, so needs to go.
In general, inconsistencies violate user assumptions, and are usually
a sign of a bad API.
- lfsr_setattr now takes flags.
This gives lfsr_setattr more flexiblity in how it operates, and may
make future extensions easier.
lfsr_setattr currently supports two flags, which may look a bit
familiar:
LFS_A_CREAT 0x04 // Create an attr if it does not exist
LFS_A_EXCL 0x08 // Fail if an attr already exists
One long-term idea is to eventually add a simple lfsr_set function to
make it easier to create small files, so this sort of design overlap
between lfsr_setattr and lfsr_file_open is hopefully a good thing.
---
Code-wise, these function are really not that bad. Adding functions adds
code, but these are just small wrappers over our internal lookup/commit
functions:
code stack
before: 36556 2608
after: 37116 (+1.5%) 2608 (+0.0%)
Of course the real cost of custom attributes is how they interact with
open files, a detail which is conveniently missing for now...
1861 lines
59 KiB
TOML
1861 lines
59 KiB
TOML
# Custom attribute tests
|
|
after = ['test_files', 'test_fsync', 'test_forphans']
|
|
|
|
|
|
# test some simple attr operations
|
|
[cases.test_attrs_setattr]
|
|
# type of file to attach attrs to
|
|
# FILETYPE=0 => regular file
|
|
# FILETYPE=1 => directory
|
|
# FILETYPE=2 => root
|
|
defines.FILETYPE = [0, 1, 2]
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
|
|
|
const char *path;
|
|
// create a file?
|
|
if (FILETYPE == 0) {
|
|
path = "cat";
|
|
lfsr_file_t file;
|
|
lfsr_file_open(&lfs, &file, path, LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
|
lfsr_file_write(&lfs, &file, "meow", strlen("meow")) => strlen("meow");
|
|
lfsr_file_close(&lfs, &file) => 0;
|
|
|
|
// create a dir?
|
|
} else if (FILETYPE == 1) {
|
|
path = "armadillo";
|
|
lfsr_mkdir(&lfs, path) => 0;
|
|
|
|
// do nothing for root
|
|
} else {
|
|
path = "/";
|
|
}
|
|
|
|
// create some attrs
|
|
const char *a = "One 18.25 ounce package chocolate cake mix.";
|
|
lfsr_setattr(&lfs, path, 'a', a, strlen(a),
|
|
LFS_A_CREAT | LFS_A_EXCL) => 0;
|
|
const char *b = "One can prepared coconut pecan frosting.";
|
|
lfsr_setattr(&lfs, path, 'b', b, strlen(b),
|
|
LFS_A_CREAT | LFS_A_EXCL) => 0;
|
|
const char *c = "Three slash four cup vegetable oil.";
|
|
lfsr_setattr(&lfs, path, 'c', c, strlen(c),
|
|
LFS_A_CREAT | LFS_A_EXCL) => 0;
|
|
|
|
for (int remount = 0; remount < 2; remount++) {
|
|
// remount?
|
|
if (remount) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
|
}
|
|
|
|
// try getting the attr sizes
|
|
lfsr_sizeattr(&lfs, path, 'a') => strlen(a);
|
|
lfsr_sizeattr(&lfs, path, 'b') => strlen(b);
|
|
lfsr_sizeattr(&lfs, path, 'c') => strlen(c);
|
|
// try reading the attrs
|
|
uint8_t rbuf[256];
|
|
lfsr_getattr(&lfs, path, 'a', rbuf, sizeof(rbuf)) => strlen(a);
|
|
assert(memcmp(rbuf, a, strlen(a)) == 0);
|
|
lfsr_getattr(&lfs, path, 'b', rbuf, sizeof(rbuf)) => strlen(b);
|
|
assert(memcmp(rbuf, b, strlen(b)) == 0);
|
|
lfsr_getattr(&lfs, path, 'c', rbuf, sizeof(rbuf)) => strlen(c);
|
|
assert(memcmp(rbuf, c, strlen(c)) == 0);
|
|
}
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# test some simple attr operations
|
|
[cases.test_attrs_setattr_trunc]
|
|
# type of file to attach attrs to
|
|
# FILETYPE=0 => regular file
|
|
# FILETYPE=1 => directory
|
|
# FILETYPE=2 => root
|
|
defines.FILETYPE = [0, 1, 2]
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
|
|
|
const char *path;
|
|
// create a file?
|
|
if (FILETYPE == 0) {
|
|
path = "cat";
|
|
lfsr_file_t file;
|
|
lfsr_file_open(&lfs, &file, path, LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
|
lfsr_file_write(&lfs, &file, "meow", strlen("meow")) => strlen("meow");
|
|
lfsr_file_close(&lfs, &file) => 0;
|
|
|
|
// create a dir?
|
|
} else if (FILETYPE == 1) {
|
|
path = "armadillo";
|
|
lfsr_mkdir(&lfs, path) => 0;
|
|
|
|
// do nothing for root
|
|
} else {
|
|
path = "/";
|
|
}
|
|
|
|
// create some attrs
|
|
const char *a = "One 18.25 ounce package chocolate cake mix.";
|
|
lfsr_setattr(&lfs, path, 'a', a, strlen(a),
|
|
LFS_A_CREAT | LFS_A_EXCL) => 0;
|
|
const char *b = "One can prepared coconut pecan frosting.";
|
|
lfsr_setattr(&lfs, path, 'b', b, strlen(b),
|
|
LFS_A_CREAT | LFS_A_EXCL) => 0;
|
|
const char *c = "Three slash four cup vegetable oil.";
|
|
lfsr_setattr(&lfs, path, 'c', c, strlen(c),
|
|
LFS_A_CREAT | LFS_A_EXCL) => 0;
|
|
|
|
for (int remount = 0; remount < 2; remount++) {
|
|
// remount?
|
|
if (remount) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
|
}
|
|
|
|
// try getting the attr sizes
|
|
lfsr_sizeattr(&lfs, path, 'a') => strlen(a);
|
|
lfsr_sizeattr(&lfs, path, 'b') => strlen(b);
|
|
lfsr_sizeattr(&lfs, path, 'c') => strlen(c);
|
|
|
|
// mark rbuf so we can detect overflow
|
|
uint8_t rbuf[256];
|
|
rbuf[1] = '!';
|
|
// try reading truncated attrs
|
|
lfsr_getattr(&lfs, path, 'a', rbuf, 1) => 1;
|
|
assert(memcmp(rbuf, a, 1) == 0);
|
|
assert(rbuf[1] == '!');
|
|
lfsr_getattr(&lfs, path, 'b', rbuf, 1) => 1;
|
|
assert(memcmp(rbuf, b, 1) == 0);
|
|
assert(rbuf[1] == '!');
|
|
lfsr_getattr(&lfs, path, 'c', rbuf, 1) => 1;
|
|
assert(memcmp(rbuf, c, 1) == 0);
|
|
assert(rbuf[1] == '!');
|
|
|
|
// mark rbuf so we can detect overflow
|
|
rbuf[4] = '!';
|
|
// try reading truncated attrs
|
|
lfsr_getattr(&lfs, path, 'a', rbuf, 4) => 4;
|
|
assert(memcmp(rbuf, a, 4) == 0);
|
|
assert(rbuf[4] == '!');
|
|
lfsr_getattr(&lfs, path, 'b', rbuf, 4) => 4;
|
|
assert(memcmp(rbuf, b, 4) == 0);
|
|
assert(rbuf[4] == '!');
|
|
lfsr_getattr(&lfs, path, 'c', rbuf, 4) => 4;
|
|
assert(memcmp(rbuf, c, 4) == 0);
|
|
assert(rbuf[4] == '!');
|
|
|
|
// try reading the full attrs
|
|
lfsr_getattr(&lfs, path, 'a', rbuf, sizeof(rbuf)) => strlen(a);
|
|
assert(memcmp(rbuf, a, strlen(a)) == 0);
|
|
lfsr_getattr(&lfs, path, 'b', rbuf, sizeof(rbuf)) => strlen(b);
|
|
assert(memcmp(rbuf, b, strlen(b)) == 0);
|
|
lfsr_getattr(&lfs, path, 'c', rbuf, sizeof(rbuf)) => strlen(c);
|
|
assert(memcmp(rbuf, c, strlen(c)) == 0);
|
|
}
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# test ENOATTR works
|
|
[cases.test_attrs_setattr_noattr]
|
|
# type of file to attach attrs to
|
|
# FILETYPE=0 => regular file
|
|
# FILETYPE=1 => directory
|
|
# FILETYPE=2 => root
|
|
defines.FILETYPE = [0, 1, 2]
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
|
|
|
const char *path;
|
|
// create a file?
|
|
if (FILETYPE == 0) {
|
|
path = "cat";
|
|
lfsr_file_t file;
|
|
lfsr_file_open(&lfs, &file, path, LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
|
lfsr_file_write(&lfs, &file, "meow", strlen("meow")) => strlen("meow");
|
|
lfsr_file_close(&lfs, &file) => 0;
|
|
|
|
// create a dir?
|
|
} else if (FILETYPE == 1) {
|
|
path = "armadillo";
|
|
lfsr_mkdir(&lfs, path) => 0;
|
|
|
|
// do nothing for root
|
|
} else {
|
|
path = "/";
|
|
}
|
|
// try getting the attr sizes
|
|
lfsr_sizeattr(&lfs, path, 'a') => LFS_ERR_NOATTR;
|
|
lfsr_sizeattr(&lfs, path, 'b') => LFS_ERR_NOATTR;
|
|
lfsr_sizeattr(&lfs, path, 'c') => LFS_ERR_NOATTR;
|
|
|
|
// try reading attrs
|
|
uint8_t rbuf[256];
|
|
lfsr_getattr(&lfs, path, 'a', rbuf, sizeof(rbuf)) => LFS_ERR_NOATTR;
|
|
lfsr_getattr(&lfs, path, 'b', rbuf, sizeof(rbuf)) => LFS_ERR_NOATTR;
|
|
lfsr_getattr(&lfs, path, 'c', rbuf, sizeof(rbuf)) => LFS_ERR_NOATTR;
|
|
|
|
// try setting attrs but without CREAT
|
|
const char *a = "One 18.25 ounce package chocolate cake mix.";
|
|
lfsr_setattr(&lfs, path, 'a', a, strlen(a), 0) => LFS_ERR_NOATTR;
|
|
const char *b = "One can prepared coconut pecan frosting.";
|
|
lfsr_setattr(&lfs, path, 'b', b, strlen(b), 0) => LFS_ERR_NOATTR;
|
|
const char *c = "Three slash four cup vegetable oil.";
|
|
lfsr_setattr(&lfs, path, 'c', c, strlen(c), 0) => LFS_ERR_NOATTR;
|
|
|
|
for (int remount = 0; remount < 2; remount++) {
|
|
// remount?
|
|
if (remount) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
|
}
|
|
|
|
// make sure setattr didn't quietly create attrs
|
|
|
|
// try getting the attr sizes
|
|
lfsr_sizeattr(&lfs, path, 'a') => LFS_ERR_NOATTR;
|
|
lfsr_sizeattr(&lfs, path, 'b') => LFS_ERR_NOATTR;
|
|
lfsr_sizeattr(&lfs, path, 'c') => LFS_ERR_NOATTR;
|
|
// try reading attrs
|
|
uint8_t rbuf[256];
|
|
lfsr_getattr(&lfs, path, 'a', rbuf, sizeof(rbuf)) => LFS_ERR_NOATTR;
|
|
lfsr_getattr(&lfs, path, 'b', rbuf, sizeof(rbuf)) => LFS_ERR_NOATTR;
|
|
lfsr_getattr(&lfs, path, 'c', rbuf, sizeof(rbuf)) => LFS_ERR_NOATTR;
|
|
}
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# test EEXIST works
|
|
[cases.test_attrs_setattr_excl]
|
|
# type of file to attach attrs to
|
|
# FILETYPE=0 => regular file
|
|
# FILETYPE=1 => directory
|
|
# FILETYPE=2 => root
|
|
defines.FILETYPE = [0, 1, 2]
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
|
|
|
const char *path;
|
|
// create a file?
|
|
if (FILETYPE == 0) {
|
|
path = "cat";
|
|
lfsr_file_t file;
|
|
lfsr_file_open(&lfs, &file, path, LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
|
lfsr_file_write(&lfs, &file, "meow", strlen("meow")) => strlen("meow");
|
|
lfsr_file_close(&lfs, &file) => 0;
|
|
|
|
// create a dir?
|
|
} else if (FILETYPE == 1) {
|
|
path = "armadillo";
|
|
lfsr_mkdir(&lfs, path) => 0;
|
|
|
|
// do nothing for root
|
|
} else {
|
|
path = "/";
|
|
}
|
|
|
|
// create some attrs
|
|
const char *a = "One 18.25 ounce package chocolate cake mix.";
|
|
lfsr_setattr(&lfs, path, 'a', a, strlen(a),
|
|
LFS_A_CREAT | LFS_A_EXCL) => 0;
|
|
const char *b = "One can prepared coconut pecan frosting.";
|
|
lfsr_setattr(&lfs, path, 'b', b, strlen(b),
|
|
LFS_A_CREAT | LFS_A_EXCL) => 0;
|
|
const char *c = "Three slash four cup vegetable oil.";
|
|
lfsr_setattr(&lfs, path, 'c', c, strlen(c),
|
|
LFS_A_CREAT | LFS_A_EXCL) => 0;
|
|
|
|
// try to create again with excl, this should fail
|
|
const char *a_ = "Four large eggs. One cup semi-sweet chocolate chips.";
|
|
lfsr_setattr(&lfs, path, 'a', a_, strlen(a_),
|
|
LFS_A_CREAT | LFS_A_EXCL) => LFS_ERR_EXIST;
|
|
const char *b_ = "Three slash four cup butter or margarine.";
|
|
lfsr_setattr(&lfs, path, 'b', b_, strlen(b_),
|
|
LFS_A_CREAT | LFS_A_EXCL) => LFS_ERR_EXIST;
|
|
const char *c_ = "One and two third cups granulated sugar.";
|
|
lfsr_setattr(&lfs, path, 'c', c_, strlen(b_),
|
|
LFS_A_CREAT | LFS_A_EXCL) => LFS_ERR_EXIST;
|
|
|
|
for (int remount = 0; remount < 2; remount++) {
|
|
// remount?
|
|
if (remount) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
|
}
|
|
|
|
// try getting the attr sizes
|
|
lfsr_sizeattr(&lfs, path, 'a') => strlen(a);
|
|
lfsr_sizeattr(&lfs, path, 'b') => strlen(b);
|
|
lfsr_sizeattr(&lfs, path, 'c') => strlen(c);
|
|
// try reading the attrs
|
|
uint8_t rbuf[256];
|
|
lfsr_getattr(&lfs, path, 'a', rbuf, sizeof(rbuf)) => strlen(a);
|
|
assert(memcmp(rbuf, a, strlen(a)) == 0);
|
|
lfsr_getattr(&lfs, path, 'b', rbuf, sizeof(rbuf)) => strlen(b);
|
|
assert(memcmp(rbuf, b, strlen(b)) == 0);
|
|
lfsr_getattr(&lfs, path, 'c', rbuf, sizeof(rbuf)) => strlen(c);
|
|
assert(memcmp(rbuf, c, strlen(c)) == 0);
|
|
}
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# test that updating attrs works
|
|
[cases.test_attrs_setattr_update]
|
|
# type of file to attach attrs to
|
|
# FILETYPE=0 => regular file
|
|
# FILETYPE=1 => directory
|
|
# FILETYPE=2 => root
|
|
defines.FILETYPE = [0, 1, 2]
|
|
# update based on this mask
|
|
defines.MASK = 'range(0x8)'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
|
|
|
const char *path;
|
|
// create a file?
|
|
if (FILETYPE == 0) {
|
|
path = "cat";
|
|
lfsr_file_t file;
|
|
lfsr_file_open(&lfs, &file, path, LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
|
lfsr_file_write(&lfs, &file, "meow", strlen("meow")) => strlen("meow");
|
|
lfsr_file_close(&lfs, &file) => 0;
|
|
|
|
// create a dir?
|
|
} else if (FILETYPE == 1) {
|
|
path = "armadillo";
|
|
lfsr_mkdir(&lfs, path) => 0;
|
|
|
|
// do nothing for root
|
|
} else {
|
|
path = "/";
|
|
}
|
|
|
|
// create some attrs
|
|
const char *a = "One 18.25 ounce package chocolate cake mix.";
|
|
lfsr_setattr(&lfs, path, 'a', a, strlen(a),
|
|
LFS_A_CREAT | LFS_A_EXCL) => 0;
|
|
const char *b = "One can prepared coconut pecan frosting.";
|
|
lfsr_setattr(&lfs, path, 'b', b, strlen(b),
|
|
LFS_A_CREAT | LFS_A_EXCL) => 0;
|
|
const char *c = "Three slash four cup vegetable oil.";
|
|
lfsr_setattr(&lfs, path, 'c', c, strlen(c),
|
|
LFS_A_CREAT | LFS_A_EXCL) => 0;
|
|
|
|
// rewrite some attrs
|
|
const char *a_ = "Four large eggs. One cup semi-sweet chocolate chips.";
|
|
if (MASK & 0x1) {
|
|
lfsr_setattr(&lfs, path, 'a', a_, strlen(a_), 0) => 0;
|
|
}
|
|
const char *b_ = "Three slash four cup butter or margarine.";
|
|
if (MASK & 0x2) {
|
|
lfsr_setattr(&lfs, path, 'b', b_, strlen(b_), 0) => 0;
|
|
}
|
|
const char *c_ = "One and two third cups granulated sugar.";
|
|
if (MASK & 0x4) {
|
|
lfsr_setattr(&lfs, path, 'c', c_, strlen(c_), 0) => 0;
|
|
}
|
|
|
|
for (int remount = 0; remount < 2; remount++) {
|
|
// remount?
|
|
if (remount) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
|
}
|
|
|
|
// try getting the attr sizes
|
|
if (MASK & 0x1) {
|
|
lfsr_sizeattr(&lfs, path, 'a') => strlen(a_);
|
|
} else {
|
|
lfsr_sizeattr(&lfs, path, 'a') => strlen(a);
|
|
}
|
|
if (MASK & 0x2) {
|
|
lfsr_sizeattr(&lfs, path, 'b') => strlen(b_);
|
|
} else {
|
|
lfsr_sizeattr(&lfs, path, 'b') => strlen(b);
|
|
}
|
|
if (MASK & 0x4) {
|
|
lfsr_sizeattr(&lfs, path, 'c') => strlen(c_);
|
|
} else {
|
|
lfsr_sizeattr(&lfs, path, 'c') => strlen(c);
|
|
}
|
|
|
|
// try reading attrs
|
|
uint8_t rbuf[256];
|
|
if (MASK & 0x1) {
|
|
lfsr_getattr(&lfs, path, 'a', rbuf, sizeof(rbuf)) => strlen(a_);
|
|
assert(memcmp(rbuf, a_, strlen(a_)) == 0);
|
|
} else {
|
|
lfsr_getattr(&lfs, path, 'a', rbuf, sizeof(rbuf)) => strlen(a);
|
|
assert(memcmp(rbuf, a, strlen(a)) == 0);
|
|
}
|
|
if (MASK & 0x2) {
|
|
lfsr_getattr(&lfs, path, 'b', rbuf, sizeof(rbuf)) => strlen(b_);
|
|
assert(memcmp(rbuf, b_, strlen(b_)) == 0);
|
|
} else {
|
|
lfsr_getattr(&lfs, path, 'b', rbuf, sizeof(rbuf)) => strlen(b);
|
|
assert(memcmp(rbuf, b, strlen(b)) == 0);
|
|
}
|
|
if (MASK & 0x4) {
|
|
lfsr_getattr(&lfs, path, 'c', rbuf, sizeof(rbuf)) => strlen(c_);
|
|
assert(memcmp(rbuf, c_, strlen(c_)) == 0);
|
|
} else {
|
|
lfsr_getattr(&lfs, path, 'c', rbuf, sizeof(rbuf)) => strlen(c);
|
|
assert(memcmp(rbuf, c, strlen(c)) == 0);
|
|
}
|
|
}
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# test removing attrs
|
|
[cases.test_attrs_removeattr]
|
|
# type of file to attach attrs to
|
|
# FILETYPE=0 => regular file
|
|
# FILETYPE=1 => directory
|
|
# FILETYPE=2 => root
|
|
defines.FILETYPE = [0, 1, 2]
|
|
# remove based on this mask
|
|
defines.MASK = 'range(0x8)'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
|
|
|
const char *path;
|
|
// create a file?
|
|
if (FILETYPE == 0) {
|
|
path = "cat";
|
|
lfsr_file_t file;
|
|
lfsr_file_open(&lfs, &file, path, LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
|
lfsr_file_write(&lfs, &file, "meow", strlen("meow")) => strlen("meow");
|
|
lfsr_file_close(&lfs, &file) => 0;
|
|
|
|
// create a dir?
|
|
} else if (FILETYPE == 1) {
|
|
path = "armadillo";
|
|
lfsr_mkdir(&lfs, path) => 0;
|
|
|
|
// do nothing for root
|
|
} else {
|
|
path = "/";
|
|
}
|
|
|
|
// create some attrs
|
|
const char *a = "One 18.25 ounce package chocolate cake mix.";
|
|
lfsr_setattr(&lfs, path, 'a', a, strlen(a),
|
|
LFS_A_CREAT | LFS_A_EXCL) => 0;
|
|
const char *b = "One can prepared coconut pecan frosting.";
|
|
lfsr_setattr(&lfs, path, 'b', b, strlen(b),
|
|
LFS_A_CREAT | LFS_A_EXCL) => 0;
|
|
const char *c = "Three slash four cup vegetable oil.";
|
|
lfsr_setattr(&lfs, path, 'c', c, strlen(c),
|
|
LFS_A_CREAT | LFS_A_EXCL) => 0;
|
|
|
|
// remove some attrs
|
|
if (MASK & 0x1) {
|
|
lfsr_removeattr(&lfs, path, 'a') => 0;
|
|
}
|
|
if (MASK & 0x2) {
|
|
lfsr_removeattr(&lfs, path, 'b') => 0;
|
|
}
|
|
if (MASK & 0x4) {
|
|
lfsr_removeattr(&lfs, path, 'c') => 0;
|
|
}
|
|
|
|
for (int remount = 0; remount < 2; remount++) {
|
|
// remount?
|
|
if (remount) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
|
}
|
|
|
|
// try getting the attr sizes
|
|
if (MASK & 0x1) {
|
|
lfsr_sizeattr(&lfs, path, 'a') => LFS_ERR_NOATTR;
|
|
} else {
|
|
lfsr_sizeattr(&lfs, path, 'a') => strlen(a);
|
|
}
|
|
if (MASK & 0x2) {
|
|
lfsr_sizeattr(&lfs, path, 'b') => LFS_ERR_NOATTR;
|
|
} else {
|
|
lfsr_sizeattr(&lfs, path, 'b') => strlen(b);
|
|
}
|
|
if (MASK & 0x4) {
|
|
lfsr_sizeattr(&lfs, path, 'c') => LFS_ERR_NOATTR;
|
|
} else {
|
|
lfsr_sizeattr(&lfs, path, 'c') => strlen(c);
|
|
}
|
|
|
|
// try reading the full attrs
|
|
uint8_t rbuf[256];
|
|
if (MASK & 0x1) {
|
|
lfsr_getattr(&lfs, path, 'a', rbuf, sizeof(rbuf))
|
|
=> LFS_ERR_NOATTR;
|
|
} else {
|
|
lfsr_getattr(&lfs, path, 'a', rbuf, sizeof(rbuf))
|
|
=> strlen(a);
|
|
assert(memcmp(rbuf, a, strlen(a)) == 0);
|
|
}
|
|
if (MASK & 0x2) {
|
|
lfsr_getattr(&lfs, path, 'b', rbuf, sizeof(rbuf))
|
|
=> LFS_ERR_NOATTR;
|
|
} else {
|
|
lfsr_getattr(&lfs, path, 'b', rbuf, sizeof(rbuf))
|
|
=> strlen(b);
|
|
assert(memcmp(rbuf, b, strlen(b)) == 0);
|
|
}
|
|
if (MASK & 0x4) {
|
|
lfsr_getattr(&lfs, path, 'c', rbuf, sizeof(rbuf))
|
|
=> LFS_ERR_NOATTR;
|
|
} else {
|
|
lfsr_getattr(&lfs, path, 'c', rbuf, sizeof(rbuf))
|
|
=> strlen(c);
|
|
assert(memcmp(rbuf, c, strlen(c)) == 0);
|
|
}
|
|
}
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
|
|
# test the full range of attrs
|
|
[cases.test_attrs_all]
|
|
# type of file to attach attrs to
|
|
# FILETYPE=0 => regular file
|
|
# FILETYPE=1 => directory
|
|
# FILETYPE=2 => root
|
|
defines.FILETYPE = [0, 1, 2]
|
|
defines.SIZE = 4
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
|
|
|
const char *path;
|
|
// create a file?
|
|
if (FILETYPE == 0) {
|
|
path = "cat";
|
|
lfsr_file_t file;
|
|
lfsr_file_open(&lfs, &file, path, LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
|
lfsr_file_write(&lfs, &file, "meow", strlen("meow")) => strlen("meow");
|
|
lfsr_file_close(&lfs, &file) => 0;
|
|
|
|
// create a dir?
|
|
} else if (FILETYPE == 1) {
|
|
path = "armadillo";
|
|
lfsr_mkdir(&lfs, path) => 0;
|
|
|
|
// do nothing for root
|
|
} else {
|
|
path = "/";
|
|
}
|
|
|
|
// try creating every attr, this tests encoding quirks
|
|
uint32_t prng = 42;
|
|
for (uint16_t a = 0; a < 0x100; a++) {
|
|
// create the attr
|
|
uint8_t wbuf[SIZE];
|
|
for (lfs_size_t i = 0; i < SIZE; i++) {
|
|
wbuf[i] = 'a' + (TEST_PRNG(&prng) % 26);
|
|
}
|
|
lfsr_setattr(&lfs, path, a, wbuf, SIZE,
|
|
LFS_A_CREAT | LFS_A_EXCL) => 0;
|
|
|
|
// try getting the attr size
|
|
lfsr_sizeattr(&lfs, path, a) => SIZE;
|
|
// try reading the attr
|
|
uint8_t rbuf[256];
|
|
lfsr_getattr(&lfs, path, a, rbuf, sizeof(rbuf)) => SIZE;
|
|
assert(memcmp(rbuf, wbuf, SIZE) == 0);
|
|
|
|
// remove the attr
|
|
lfsr_removeattr(&lfs, path, a) => 0;
|
|
}
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# test creating a bunch of attrs
|
|
[cases.test_attrs_many]
|
|
# type of file to attach attrs to
|
|
# FILETYPE=0 => regular file
|
|
# FILETYPE=1 => directory
|
|
# FILETYPE=2 => root
|
|
defines.FILETYPE = [0, 1, 2]
|
|
defines.M = 40
|
|
defines.SIZE = 4
|
|
defines.COMPACT = [false, true]
|
|
defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
|
|
|
const char *path;
|
|
// create a file?
|
|
if (FILETYPE == 0) {
|
|
path = "cat";
|
|
lfsr_file_t file;
|
|
lfsr_file_open(&lfs, &file, path, LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
|
lfsr_file_write(&lfs, &file, "meow", strlen("meow")) => strlen("meow");
|
|
lfsr_file_close(&lfs, &file) => 0;
|
|
|
|
// create a dir?
|
|
} else if (FILETYPE == 1) {
|
|
path = "armadillo";
|
|
lfsr_mkdir(&lfs, path) => 0;
|
|
|
|
// do nothing for root
|
|
} else {
|
|
path = "/";
|
|
}
|
|
|
|
// create M attrs
|
|
uint32_t prng = 42;
|
|
for (uint16_t a = 0; a < M; a++) {
|
|
uint8_t wbuf[SIZE];
|
|
for (lfs_size_t i = 0; i < SIZE; i++) {
|
|
wbuf[i] = 'a' + (TEST_PRNG(&prng) % 26);
|
|
}
|
|
lfsr_setattr(&lfs, path, a, wbuf, SIZE,
|
|
LFS_A_CREAT | LFS_A_EXCL) => 0;
|
|
}
|
|
|
|
// try compacting?
|
|
if (COMPACT) {
|
|
lfsr_fs_gc(&lfs, -1, LFS_GC_COMPACT) => 0;
|
|
}
|
|
|
|
for (int remount = 0; remount < 2; remount++) {
|
|
// remount?
|
|
if (remount) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
|
}
|
|
|
|
// try getting the attr sizes
|
|
for (uint16_t a = 0; a < M; a++) {
|
|
lfsr_sizeattr(&lfs, path, a) => SIZE;
|
|
}
|
|
// try reading the attrs
|
|
prng = 42;
|
|
for (uint16_t a = 0; a < M; a++) {
|
|
uint8_t wbuf[SIZE];
|
|
for (lfs_size_t i = 0; i < SIZE; i++) {
|
|
wbuf[i] = 'a' + (TEST_PRNG(&prng) % 26);
|
|
}
|
|
uint8_t rbuf[256];
|
|
lfsr_getattr(&lfs, path, a, rbuf, sizeof(rbuf)) => SIZE;
|
|
assert(memcmp(rbuf, wbuf, SIZE) == 0);
|
|
}
|
|
}
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# test creating a bunch of attrs on a bunch of files
|
|
[cases.test_attrs_many_many]
|
|
# type of file to attach attrs to
|
|
# FILETYPE=0 => regular file
|
|
# FILETYPE=1 => directory
|
|
defines.FILETYPE = [0, 1]
|
|
defines.N = 64
|
|
defines.M = 4
|
|
defines.SIZE = 4
|
|
defines.COMPACT = [false, true]
|
|
defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
|
|
|
// create N files
|
|
uint32_t prng = 42;
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char path[256];
|
|
// create a file?
|
|
if (FILETYPE == 0) {
|
|
sprintf(path, "cat%03x", i);
|
|
lfsr_file_t file;
|
|
lfsr_file_open(&lfs, &file, path,
|
|
LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
|
lfsr_file_write(&lfs, &file, "meow", strlen("meow"))
|
|
=> strlen("meow");
|
|
lfsr_file_close(&lfs, &file) => 0;
|
|
|
|
// create a dir?
|
|
} else {
|
|
sprintf(path, "armadillo%03x", i);
|
|
lfsr_mkdir(&lfs, path) => 0;
|
|
}
|
|
|
|
// create M attrs
|
|
for (uint16_t a = 0; a < M; a++) {
|
|
uint8_t wbuf[SIZE];
|
|
for (lfs_size_t j = 0; j < SIZE; j++) {
|
|
wbuf[j] = 'a' + (TEST_PRNG(&prng) % 26);
|
|
}
|
|
lfsr_setattr(&lfs, path, a, wbuf, SIZE,
|
|
LFS_A_CREAT | LFS_A_EXCL) => 0;
|
|
}
|
|
}
|
|
|
|
// try compacting?
|
|
if (COMPACT) {
|
|
lfsr_fs_gc(&lfs, -1, LFS_GC_COMPACT) => 0;
|
|
}
|
|
|
|
for (int remount = 0; remount < 2; remount++) {
|
|
// remount?
|
|
if (remount) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
|
}
|
|
|
|
prng = 42;
|
|
for (lfs_size_t x = 0; x < N; x++) {
|
|
char path[256];
|
|
// file?
|
|
if (FILETYPE == 0) {
|
|
sprintf(path, "cat%03x", x);
|
|
// dir?
|
|
} else {
|
|
sprintf(path, "armadillo%03x", x);
|
|
}
|
|
|
|
// try getting the attr sizes
|
|
for (uint16_t a = 0; a < M; a++) {
|
|
lfsr_sizeattr(&lfs, path, a) => SIZE;
|
|
}
|
|
// try reading the attrs
|
|
for (uint16_t a = 0; a < M; a++) {
|
|
uint8_t wbuf[SIZE];
|
|
for (lfs_size_t j = 0; j < SIZE; j++) {
|
|
wbuf[j] = 'a' + (TEST_PRNG(&prng) % 26);
|
|
}
|
|
uint8_t rbuf[256];
|
|
lfsr_getattr(&lfs, path, a, rbuf, sizeof(rbuf)) => SIZE;
|
|
assert(memcmp(rbuf, wbuf, SIZE) == 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# fuzz attrs
|
|
[cases.test_attrs_fuzz]
|
|
# type of file to attach attrs to
|
|
# FILETYPE=0 => regular file
|
|
# FILETYPE=1 => directory
|
|
# FILETYPE=2 => root
|
|
defines.FILETYPE = [0, 1, 2]
|
|
defines.M = 10
|
|
defines.SIZE = 4
|
|
defines.OPS = '4*M'
|
|
defines.SEED = 'range(20)'
|
|
fuzz = 'SEED'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
|
|
|
const char *path;
|
|
// create a file?
|
|
if (FILETYPE == 0) {
|
|
path = "cat";
|
|
lfsr_file_t file;
|
|
lfsr_file_open(&lfs, &file, path, LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
|
lfsr_file_write(&lfs, &file, "meow", strlen("meow")) => strlen("meow");
|
|
lfsr_file_close(&lfs, &file) => 0;
|
|
|
|
// create a dir?
|
|
} else if (FILETYPE == 1) {
|
|
path = "armadillo";
|
|
lfsr_mkdir(&lfs, path) => 0;
|
|
|
|
// do nothing for root
|
|
} else {
|
|
path = "/";
|
|
}
|
|
|
|
// set up a simulation to compare against
|
|
uint32_t *sim_prngs = malloc(M*sizeof(uint32_t));
|
|
memset(sim_prngs, 0, M*sizeof(uint32_t));
|
|
|
|
uint32_t prng = SEED;
|
|
for (lfs_size_t i = 0; i < OPS; i++) {
|
|
// choose which operation to do
|
|
uint8_t op = TEST_PRNG(&prng) % 2;
|
|
|
|
// create an attr?
|
|
if (op == 0) {
|
|
// choose an attr
|
|
uint8_t a = TEST_PRNG(&prng) % M;
|
|
// choose a prng
|
|
uint32_t wprng = TEST_PRNG(&prng);
|
|
|
|
// create the attr
|
|
uint32_t wprng_ = wprng;
|
|
uint8_t wbuf[SIZE];
|
|
for (lfs_size_t j = 0; j < SIZE; j++) {
|
|
wbuf[j] = 'a' + (TEST_PRNG(&wprng_) % 26);
|
|
}
|
|
if (sim_prngs[a]) {
|
|
lfsr_setattr(&lfs, path, a, wbuf, SIZE, 0) => 0;
|
|
} else {
|
|
lfsr_setattr(&lfs, path, a, wbuf, SIZE,
|
|
LFS_A_CREAT | LFS_A_EXCL) => 0;
|
|
}
|
|
|
|
// update our sim
|
|
sim_prngs[a] = wprng;
|
|
|
|
// remove an attr?
|
|
} else if (op == 1) {
|
|
// choose an attr
|
|
uint8_t a = TEST_PRNG(&prng) % M;
|
|
|
|
// remove the attr
|
|
if (sim_prngs[a]) {
|
|
lfsr_removeattr(&lfs, path, a) => 0;
|
|
} else {
|
|
lfsr_removeattr(&lfs, path, a) => LFS_ERR_NOATTR;
|
|
}
|
|
|
|
// update our sim
|
|
sim_prngs[a] = 0;
|
|
}
|
|
}
|
|
|
|
for (int remount = 0; remount < 2; remount++) {
|
|
// remount?
|
|
if (remount) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
|
}
|
|
|
|
// try getting each attr size
|
|
for (uint16_t a = 0; a < M; a++) {
|
|
if (sim_prngs[a]) {
|
|
lfsr_sizeattr(&lfs, path, a) => SIZE;
|
|
} else {
|
|
lfsr_sizeattr(&lfs, path, a) => LFS_ERR_NOATTR;
|
|
}
|
|
}
|
|
// try reading each attr
|
|
for (uint16_t a = 0; a < M; a++) {
|
|
if (sim_prngs[a]) {
|
|
uint32_t wprng_ = sim_prngs[a];
|
|
uint8_t wbuf[SIZE];
|
|
for (lfs_size_t i = 0; i < SIZE; i++) {
|
|
wbuf[i] = 'a' + (TEST_PRNG(&wprng_) % 26);
|
|
}
|
|
uint8_t rbuf[256];
|
|
lfsr_getattr(&lfs, path, a, rbuf, sizeof(rbuf)) => SIZE;
|
|
assert(memcmp(rbuf, wbuf, SIZE) == 0);
|
|
} else {
|
|
uint8_t rbuf[256];
|
|
lfsr_getattr(&lfs, path, a, rbuf, sizeof(rbuf))
|
|
=> LFS_ERR_NOATTR;
|
|
}
|
|
}
|
|
}
|
|
|
|
// clean up sim/lfs
|
|
free(sim_prngs);
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# fuzz attrs on multiple files
|
|
[cases.test_attrs_fuzz_fuzz]
|
|
# type of file to attach attrs to
|
|
# FILETYPE=0 => regular file
|
|
# FILETYPE=1 => directory
|
|
defines.FILETYPE = [0, 1]
|
|
defines.N = 64
|
|
defines.M = 4
|
|
defines.SIZE = 4
|
|
defines.OPS = '4*N*M'
|
|
defines.SEED = 'range(20)'
|
|
fuzz = 'SEED'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
|
|
|
// create N files
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char path[256];
|
|
// create a file?
|
|
if (FILETYPE == 0) {
|
|
sprintf(path, "cat%03x", i);
|
|
lfsr_file_t file;
|
|
lfsr_file_open(&lfs, &file, path,
|
|
LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
|
lfsr_file_write(&lfs, &file, "meow", strlen("meow"))
|
|
=> strlen("meow");
|
|
lfsr_file_close(&lfs, &file) => 0;
|
|
|
|
// create a dir?
|
|
} else {
|
|
sprintf(path, "armadillo%03x", i);
|
|
lfsr_mkdir(&lfs, path) => 0;
|
|
}
|
|
}
|
|
|
|
// set up a simulation to compare against
|
|
uint32_t *sim_prngs = malloc(N*M*sizeof(uint32_t));
|
|
memset(sim_prngs, 0, N*M*sizeof(uint32_t));
|
|
|
|
uint32_t prng = SEED;
|
|
for (lfs_size_t i = 0; i < OPS; i++) {
|
|
// choose which operation to do
|
|
uint8_t op = TEST_PRNG(&prng) % 2;
|
|
|
|
// create an attr?
|
|
if (op == 0) {
|
|
// choose a file
|
|
lfs_size_t x = TEST_PRNG(&prng) % N;
|
|
char path[256];
|
|
// file?
|
|
if (FILETYPE == 0) {
|
|
sprintf(path, "cat%03x", x);
|
|
// dir?
|
|
} else {
|
|
sprintf(path, "armadillo%03x", x);
|
|
}
|
|
// choose an attr
|
|
uint8_t a = TEST_PRNG(&prng) % M;
|
|
// choose a prng
|
|
uint32_t wprng = TEST_PRNG(&prng);
|
|
|
|
// create the attr
|
|
uint32_t wprng_ = wprng;
|
|
uint8_t wbuf[SIZE];
|
|
for (lfs_size_t j = 0; j < SIZE; j++) {
|
|
wbuf[j] = 'a' + (TEST_PRNG(&wprng_) % 26);
|
|
}
|
|
if (sim_prngs[x*M+a]) {
|
|
lfsr_setattr(&lfs, path, a, wbuf, SIZE, 0) => 0;
|
|
} else {
|
|
lfsr_setattr(&lfs, path, a, wbuf, SIZE,
|
|
LFS_A_CREAT | LFS_A_EXCL) => 0;
|
|
}
|
|
|
|
// update our sim
|
|
sim_prngs[x*M+a] = wprng;
|
|
|
|
// remove an attr?
|
|
} else if (op == 1) {
|
|
// choose a file
|
|
lfs_size_t x = TEST_PRNG(&prng) % N;
|
|
char path[256];
|
|
// file?
|
|
if (FILETYPE == 0) {
|
|
sprintf(path, "cat%03x", x);
|
|
// dir?
|
|
} else {
|
|
sprintf(path, "armadillo%03x", x);
|
|
}
|
|
// choose an attr
|
|
uint8_t a = TEST_PRNG(&prng) % M;
|
|
|
|
// remove the attr
|
|
if (sim_prngs[x*M+a]) {
|
|
lfsr_removeattr(&lfs, path, a) => 0;
|
|
} else {
|
|
lfsr_removeattr(&lfs, path, a) => LFS_ERR_NOATTR;
|
|
}
|
|
|
|
// update our sim
|
|
sim_prngs[x*M+a] = 0;
|
|
}
|
|
}
|
|
|
|
for (int remount = 0; remount < 2; remount++) {
|
|
// remount?
|
|
if (remount) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
|
}
|
|
|
|
for (lfs_size_t x = 0; x < N; x++) {
|
|
char path[256];
|
|
// file?
|
|
if (FILETYPE == 0) {
|
|
sprintf(path, "cat%03x", x);
|
|
// dir?
|
|
} else {
|
|
sprintf(path, "armadillo%03x", x);
|
|
}
|
|
|
|
// try getting each attr size
|
|
for (uint16_t a = 0; a < M; a++) {
|
|
if (sim_prngs[x*M+a]) {
|
|
lfsr_sizeattr(&lfs, path, a) => SIZE;
|
|
} else {
|
|
lfsr_sizeattr(&lfs, path, a) => LFS_ERR_NOATTR;
|
|
}
|
|
}
|
|
// try reading each attr
|
|
for (uint16_t a = 0; a < M; a++) {
|
|
if (sim_prngs[x*M+a]) {
|
|
uint32_t wprng_ = sim_prngs[x*M+a];
|
|
uint8_t wbuf[SIZE];
|
|
for (lfs_size_t i = 0; i < SIZE; i++) {
|
|
wbuf[i] = 'a' + (TEST_PRNG(&wprng_) % 26);
|
|
}
|
|
uint8_t rbuf[256];
|
|
lfsr_getattr(&lfs, path, a, rbuf, sizeof(rbuf)) => SIZE;
|
|
assert(memcmp(rbuf, wbuf, SIZE) == 0);
|
|
} else {
|
|
uint8_t rbuf[256];
|
|
lfsr_getattr(&lfs, path, a, rbuf, sizeof(rbuf))
|
|
=> LFS_ERR_NOATTR;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// clean up sim/lfs
|
|
free(sim_prngs);
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
|
|
# test that removing a file removes all attrs
|
|
[cases.test_attrs_rm]
|
|
# type of file to attach attrs to
|
|
# FILETYPE=0 => regular file
|
|
# FILETYPE=1 => directory
|
|
defines.FILETYPE = [0, 1]
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
|
|
|
const char *path;
|
|
// create a file?
|
|
if (FILETYPE == 0) {
|
|
path = "cat";
|
|
lfsr_file_t file;
|
|
lfsr_file_open(&lfs, &file, path, LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
|
lfsr_file_write(&lfs, &file, "meow", strlen("meow")) => strlen("meow");
|
|
lfsr_file_close(&lfs, &file) => 0;
|
|
|
|
// create a dir?
|
|
} else {
|
|
path = "armadillo";
|
|
lfsr_mkdir(&lfs, path) => 0;
|
|
}
|
|
|
|
// create some attrs
|
|
const char *a = "One 18.25 ounce package chocolate cake mix.";
|
|
lfsr_setattr(&lfs, path, 'a', a, strlen(a),
|
|
LFS_A_CREAT | LFS_A_EXCL) => 0;
|
|
const char *b = "One can prepared coconut pecan frosting.";
|
|
lfsr_setattr(&lfs, path, 'b', b, strlen(b),
|
|
LFS_A_CREAT | LFS_A_EXCL) => 0;
|
|
const char *c = "Three slash four cup vegetable oil.";
|
|
lfsr_setattr(&lfs, path, 'c', c, strlen(c),
|
|
LFS_A_CREAT | LFS_A_EXCL) => 0;
|
|
|
|
// remove the file
|
|
lfsr_remove(&lfs, path) => 0;
|
|
|
|
// create the file again
|
|
|
|
// file?
|
|
if (FILETYPE == 0) {
|
|
lfsr_file_t file;
|
|
lfsr_file_open(&lfs, &file, path, LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
|
lfsr_file_write(&lfs, &file, "miao", strlen("miao")) => strlen("miao");
|
|
lfsr_file_close(&lfs, &file) => 0;
|
|
|
|
// dir?
|
|
} else {
|
|
lfsr_mkdir(&lfs, path) => 0;
|
|
}
|
|
|
|
for (int remount = 0; remount < 2; remount++) {
|
|
// remount?
|
|
if (remount) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
|
}
|
|
|
|
// try getting the attr sizes
|
|
lfsr_sizeattr(&lfs, path, 'a') => LFS_ERR_NOATTR;
|
|
lfsr_sizeattr(&lfs, path, 'b') => LFS_ERR_NOATTR;
|
|
lfsr_sizeattr(&lfs, path, 'c') => LFS_ERR_NOATTR;
|
|
// try reading the attrs
|
|
uint8_t rbuf[256];
|
|
lfsr_getattr(&lfs, path, 'a', rbuf, sizeof(rbuf)) => LFS_ERR_NOATTR;
|
|
lfsr_getattr(&lfs, path, 'b', rbuf, sizeof(rbuf)) => LFS_ERR_NOATTR;
|
|
lfsr_getattr(&lfs, path, 'c', rbuf, sizeof(rbuf)) => LFS_ERR_NOATTR;
|
|
}
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# test that moving onto a file removes all attrs
|
|
[cases.test_attrs_mv_dst]
|
|
# type of file to attach attrs to
|
|
# FILETYPE=0 => regular file
|
|
# FILETYPE=1 => directory
|
|
defines.FILETYPE = [0, 1]
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
|
|
|
const char *path;
|
|
// create a file?
|
|
if (FILETYPE == 0) {
|
|
path = "cat";
|
|
lfsr_file_t file;
|
|
lfsr_file_open(&lfs, &file, path, LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
|
lfsr_file_write(&lfs, &file, "meow", strlen("meow")) => strlen("meow");
|
|
lfsr_file_close(&lfs, &file) => 0;
|
|
|
|
// create a dir?
|
|
} else {
|
|
path = "armadillo";
|
|
lfsr_mkdir(&lfs, path) => 0;
|
|
}
|
|
|
|
// create some attrs
|
|
const char *a = "One 18.25 ounce package chocolate cake mix.";
|
|
lfsr_setattr(&lfs, path, 'a', a, strlen(a),
|
|
LFS_A_CREAT | LFS_A_EXCL) => 0;
|
|
const char *b = "One can prepared coconut pecan frosting.";
|
|
lfsr_setattr(&lfs, path, 'b', b, strlen(b),
|
|
LFS_A_CREAT | LFS_A_EXCL) => 0;
|
|
const char *c = "Three slash four cup vegetable oil.";
|
|
lfsr_setattr(&lfs, path, 'c', c, strlen(c),
|
|
LFS_A_CREAT | LFS_A_EXCL) => 0;
|
|
|
|
// create another file and move it onto our file
|
|
|
|
// file?
|
|
if (FILETYPE == 0) {
|
|
lfsr_file_t file;
|
|
lfsr_file_open(&lfs, &file, "beaver", LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
|
lfsr_file_write(&lfs, &file, "miao", strlen("miao")) => strlen("miao");
|
|
lfsr_file_close(&lfs, &file) => 0;
|
|
|
|
// dir?
|
|
} else {
|
|
lfsr_mkdir(&lfs, "beaver") => 0;
|
|
}
|
|
|
|
lfsr_rename(&lfs, "beaver", path) => 0;
|
|
|
|
for (int remount = 0; remount < 2; remount++) {
|
|
// remount?
|
|
if (remount) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
|
}
|
|
|
|
// try getting the attr sizes
|
|
lfsr_sizeattr(&lfs, path, 'a') => LFS_ERR_NOATTR;
|
|
lfsr_sizeattr(&lfs, path, 'b') => LFS_ERR_NOATTR;
|
|
lfsr_sizeattr(&lfs, path, 'c') => LFS_ERR_NOATTR;
|
|
// try reading the attrs
|
|
uint8_t rbuf[256];
|
|
lfsr_getattr(&lfs, path, 'a', rbuf, sizeof(rbuf)) => LFS_ERR_NOATTR;
|
|
lfsr_getattr(&lfs, path, 'b', rbuf, sizeof(rbuf)) => LFS_ERR_NOATTR;
|
|
lfsr_getattr(&lfs, path, 'c', rbuf, sizeof(rbuf)) => LFS_ERR_NOATTR;
|
|
}
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# test that moves bring over all attrs
|
|
[cases.test_attrs_mv_src]
|
|
# type of file to attach attrs to
|
|
# FILETYPE=0 => regular file
|
|
# FILETYPE=1 => directory
|
|
defines.FILETYPE = [0, 1]
|
|
defines.REPLACE = [false, true]
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
|
|
|
const char *path;
|
|
// file?
|
|
if (FILETYPE == 0) {
|
|
path = "cat";
|
|
// dir?
|
|
} else {
|
|
path = "armadillo";
|
|
}
|
|
|
|
// if replacing create a file to replace
|
|
if (REPLACE) {
|
|
// create a file?
|
|
if (FILETYPE == 0) {
|
|
lfsr_file_t file;
|
|
lfsr_file_open(&lfs, &file, path, LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
|
lfsr_file_write(&lfs, &file, "meow", strlen("meow"))
|
|
=> strlen("meow");
|
|
lfsr_file_close(&lfs, &file) => 0;
|
|
|
|
// create a dir?
|
|
} else {
|
|
lfsr_mkdir(&lfs, path) => 0;
|
|
}
|
|
}
|
|
|
|
// create a file?
|
|
if (FILETYPE == 0) {
|
|
lfsr_file_t file;
|
|
lfsr_file_open(&lfs, &file, "beaver",
|
|
LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
|
lfsr_file_write(&lfs, &file, "miao", strlen("miao"))
|
|
=> strlen("miao");
|
|
lfsr_file_close(&lfs, &file) => 0;
|
|
|
|
// create a dir?
|
|
} else {
|
|
lfsr_mkdir(&lfs, "beaver") => 0;
|
|
}
|
|
|
|
// create some attrs
|
|
const char *a = "One 18.25 ounce package chocolate cake mix.";
|
|
lfsr_setattr(&lfs, "beaver", 'a', a, strlen(a),
|
|
LFS_A_CREAT | LFS_A_EXCL) => 0;
|
|
const char *b = "One can prepared coconut pecan frosting.";
|
|
lfsr_setattr(&lfs, "beaver", 'b', b, strlen(b),
|
|
LFS_A_CREAT | LFS_A_EXCL) => 0;
|
|
const char *c = "Three slash four cup vegetable oil.";
|
|
lfsr_setattr(&lfs, "beaver", 'c', c, strlen(c),
|
|
LFS_A_CREAT | LFS_A_EXCL) => 0;
|
|
|
|
// move file
|
|
lfsr_rename(&lfs, "beaver", path) => 0;
|
|
|
|
for (int remount = 0; remount < 2; remount++) {
|
|
// remount?
|
|
if (remount) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
|
}
|
|
|
|
// try getting the attr sizes
|
|
lfsr_sizeattr(&lfs, path, 'a') => strlen(a);
|
|
lfsr_sizeattr(&lfs, path, 'b') => strlen(b);
|
|
lfsr_sizeattr(&lfs, path, 'c') => strlen(c);
|
|
// try reading the attrs
|
|
uint8_t rbuf[256];
|
|
lfsr_getattr(&lfs, path, 'a', rbuf, sizeof(rbuf)) => strlen(a);
|
|
assert(memcmp(rbuf, a, strlen(a)) == 0);
|
|
lfsr_getattr(&lfs, path, 'b', rbuf, sizeof(rbuf)) => strlen(b);
|
|
assert(memcmp(rbuf, b, strlen(b)) == 0);
|
|
lfsr_getattr(&lfs, path, 'c', rbuf, sizeof(rbuf)) => strlen(c);
|
|
assert(memcmp(rbuf, c, strlen(c)) == 0);
|
|
}
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
# fuzz attrs mixed with file moves and removes
|
|
[cases.test_attrs_mvrm_fuzz_fuzz]
|
|
# type of file to attach attrs to
|
|
# FILETYPE=0 => regular file
|
|
# FILETYPE=1 => directory
|
|
defines.FILETYPE = [0, 1]
|
|
defines.N = 64
|
|
defines.M = 4
|
|
defines.SIZE = 4
|
|
defines.OPS = '4*N*M'
|
|
defines.SEED = 'range(20)'
|
|
fuzz = 'SEED'
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
|
|
|
// create N files
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
char path[256];
|
|
// create a file?
|
|
if (FILETYPE == 0) {
|
|
sprintf(path, "cat%03x", i);
|
|
lfsr_file_t file;
|
|
lfsr_file_open(&lfs, &file, path,
|
|
LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
|
lfsr_file_write(&lfs, &file, "meow", strlen("meow"))
|
|
=> strlen("meow");
|
|
lfsr_file_close(&lfs, &file) => 0;
|
|
|
|
// create a dir?
|
|
} else {
|
|
sprintf(path, "armadillo%03x", i);
|
|
lfsr_mkdir(&lfs, path) => 0;
|
|
}
|
|
}
|
|
|
|
// set up a simulation to compare against
|
|
uint32_t *sim_prngs = malloc(N*M*sizeof(uint32_t));
|
|
memset(sim_prngs, 0, N*M*sizeof(uint32_t));
|
|
|
|
uint32_t prng = SEED;
|
|
for (lfs_size_t i = 0; i < OPS; i++) {
|
|
// choose which operation to do
|
|
uint8_t op = TEST_PRNG(&prng) % 4;
|
|
|
|
// create an attr?
|
|
if (op == 0) {
|
|
// choose a file
|
|
lfs_size_t x = TEST_PRNG(&prng) % N;
|
|
char path[256];
|
|
// file?
|
|
if (FILETYPE == 0) {
|
|
sprintf(path, "cat%03x", x);
|
|
// dir?
|
|
} else {
|
|
sprintf(path, "armadillo%03x", x);
|
|
}
|
|
// choose an attr
|
|
uint8_t a = TEST_PRNG(&prng) % M;
|
|
// choose a prng
|
|
uint32_t wprng = TEST_PRNG(&prng);
|
|
|
|
// create the attr
|
|
uint32_t wprng_ = wprng;
|
|
uint8_t wbuf[SIZE];
|
|
for (lfs_size_t j = 0; j < SIZE; j++) {
|
|
wbuf[j] = 'a' + (TEST_PRNG(&wprng_) % 26);
|
|
}
|
|
if (sim_prngs[x*M+a]) {
|
|
lfsr_setattr(&lfs, path, a, wbuf, SIZE, 0) => 0;
|
|
} else {
|
|
lfsr_setattr(&lfs, path, a, wbuf, SIZE,
|
|
LFS_A_CREAT | LFS_A_EXCL) => 0;
|
|
}
|
|
|
|
// update our sim
|
|
sim_prngs[x*M+a] = wprng;
|
|
|
|
// remove an attr?
|
|
} else if (op == 1) {
|
|
// choose a file
|
|
lfs_size_t x = TEST_PRNG(&prng) % N;
|
|
char path[256];
|
|
// file?
|
|
if (FILETYPE == 0) {
|
|
sprintf(path, "cat%03x", x);
|
|
// dir?
|
|
} else {
|
|
sprintf(path, "armadillo%03x", x);
|
|
}
|
|
// choose an attr
|
|
uint8_t a = TEST_PRNG(&prng) % M;
|
|
|
|
// remove the attr
|
|
if (sim_prngs[x*M+a]) {
|
|
lfsr_removeattr(&lfs, path, a) => 0;
|
|
} else {
|
|
lfsr_removeattr(&lfs, path, a) => LFS_ERR_NOATTR;
|
|
}
|
|
|
|
// update our sim
|
|
sim_prngs[x*M+a] = 0;
|
|
|
|
// remove a file?
|
|
} else if (op == 2) {
|
|
// choose a file
|
|
lfs_size_t x = TEST_PRNG(&prng) % N;
|
|
char path[256];
|
|
// file?
|
|
if (FILETYPE == 0) {
|
|
sprintf(path, "cat%03x", x);
|
|
// dir?
|
|
} else {
|
|
sprintf(path, "armadillo%03x", x);
|
|
}
|
|
|
|
// remove the file
|
|
lfsr_remove(&lfs, path) => 0;
|
|
|
|
// but recreate the file so we always have something to
|
|
// attach attrs to
|
|
|
|
// create a file?
|
|
if (FILETYPE == 0) {
|
|
sprintf(path, "cat%03x", x);
|
|
lfsr_file_t file;
|
|
lfsr_file_open(&lfs, &file, path,
|
|
LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
|
lfsr_file_write(&lfs, &file, "miao", strlen("miao"))
|
|
=> strlen("miao");
|
|
lfsr_file_close(&lfs, &file) => 0;
|
|
|
|
// create a dir?
|
|
} else {
|
|
sprintf(path, "armadillo%03x", x);
|
|
lfsr_mkdir(&lfs, path) => 0;
|
|
}
|
|
|
|
// update our sim
|
|
memset(&sim_prngs[x*M], 0, M*sizeof(uint32_t));
|
|
|
|
// rename a file?
|
|
} else if (op == 3) {
|
|
// choose two files
|
|
lfs_size_t x = TEST_PRNG(&prng) % N;
|
|
lfs_size_t y = TEST_PRNG(&prng) % N;
|
|
char path[256];
|
|
char path_[256];
|
|
// file?
|
|
if (FILETYPE == 0) {
|
|
sprintf(path, "cat%03x", x);
|
|
sprintf(path_, "cat%03x", y);
|
|
// dir?
|
|
} else {
|
|
sprintf(path, "armadillo%03x", x);
|
|
sprintf(path_, "armadillo%03x", y);
|
|
}
|
|
|
|
// rename the file
|
|
lfsr_rename(&lfs, path, path_) => 0;
|
|
|
|
if (x != y) {
|
|
// but recreate the file so we always have something to
|
|
// attach attrs to
|
|
|
|
// create a file?
|
|
if (FILETYPE == 0) {
|
|
sprintf(path, "cat%03x", x);
|
|
lfsr_file_t file;
|
|
lfsr_file_open(&lfs, &file, path,
|
|
LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
|
lfsr_file_write(&lfs, &file, "nyan", strlen("nyan"))
|
|
=> strlen("nyan");
|
|
lfsr_file_close(&lfs, &file) => 0;
|
|
|
|
// create a dir?
|
|
} else {
|
|
sprintf(path, "armadillo%03x", x);
|
|
lfsr_mkdir(&lfs, path) => 0;
|
|
}
|
|
|
|
// update our sim
|
|
memcpy(&sim_prngs[y*M], &sim_prngs[x*M], M*sizeof(uint32_t));
|
|
memset(&sim_prngs[x*M], 0, M*sizeof(uint32_t));
|
|
}
|
|
}
|
|
}
|
|
|
|
for (int remount = 0; remount < 2; remount++) {
|
|
// remount?
|
|
if (remount) {
|
|
lfsr_unmount(&lfs) => 0;
|
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
|
}
|
|
|
|
for (lfs_size_t x = 0; x < N; x++) {
|
|
char path[256];
|
|
// file?
|
|
if (FILETYPE == 0) {
|
|
sprintf(path, "cat%03x", x);
|
|
// dir?
|
|
} else {
|
|
sprintf(path, "armadillo%03x", x);
|
|
}
|
|
|
|
// try getting each attr size
|
|
for (uint16_t a = 0; a < M; a++) {
|
|
if (sim_prngs[x*M+a]) {
|
|
lfsr_sizeattr(&lfs, path, a) => SIZE;
|
|
} else {
|
|
lfsr_sizeattr(&lfs, path, a) => LFS_ERR_NOATTR;
|
|
}
|
|
}
|
|
// try reading each attr
|
|
for (uint16_t a = 0; a < M; a++) {
|
|
if (sim_prngs[x*M+a]) {
|
|
uint32_t wprng_ = sim_prngs[x*M+a];
|
|
uint8_t wbuf[SIZE];
|
|
for (lfs_size_t i = 0; i < SIZE; i++) {
|
|
wbuf[i] = 'a' + (TEST_PRNG(&wprng_) % 26);
|
|
}
|
|
uint8_t rbuf[256];
|
|
lfsr_getattr(&lfs, path, a, rbuf, sizeof(rbuf)) => SIZE;
|
|
assert(memcmp(rbuf, wbuf, SIZE) == 0);
|
|
} else {
|
|
uint8_t rbuf[256];
|
|
lfsr_getattr(&lfs, path, a, rbuf, sizeof(rbuf))
|
|
=> LFS_ERR_NOATTR;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// clean up sim/lfs
|
|
free(sim_prngs);
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[cases.test_attrs_get_set]
|
|
#code = '''
|
|
# lfs_t lfs;
|
|
# lfs_format(&lfs, cfg) => 0;
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_mkdir(&lfs, "hello") => 0;
|
|
# lfs_file_t file;
|
|
# lfs_file_open(&lfs, &file, "hello/hello", LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
|
# lfs_file_write(&lfs, &file, "hello", strlen("hello")) => strlen("hello");
|
|
# lfs_file_close(&lfs, &file);
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# uint8_t buffer[1024];
|
|
# memset(buffer, 0, sizeof(buffer));
|
|
# lfs_setattr(&lfs, "hello", 'A', "aaaa", 4) => 0;
|
|
# lfs_setattr(&lfs, "hello", 'B', "bbbbbb", 6) => 0;
|
|
# lfs_setattr(&lfs, "hello", 'C', "ccccc", 5) => 0;
|
|
# lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4;
|
|
# lfs_getattr(&lfs, "hello", 'B', buffer+4, 6) => 6;
|
|
# lfs_getattr(&lfs, "hello", 'C', buffer+10, 5) => 5;
|
|
# memcmp(buffer, "aaaa", 4) => 0;
|
|
# memcmp(buffer+4, "bbbbbb", 6) => 0;
|
|
# memcmp(buffer+10, "ccccc", 5) => 0;
|
|
#
|
|
# lfs_setattr(&lfs, "hello", 'B', "", 0) => 0;
|
|
# lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4;
|
|
# lfs_getattr(&lfs, "hello", 'B', buffer+4, 6) => 0;
|
|
# lfs_getattr(&lfs, "hello", 'C', buffer+10, 5) => 5;
|
|
# memcmp(buffer, "aaaa", 4) => 0;
|
|
# memcmp(buffer+4, "\0\0\0\0\0\0", 6) => 0;
|
|
# memcmp(buffer+10, "ccccc", 5) => 0;
|
|
#
|
|
# lfs_removeattr(&lfs, "hello", 'B') => 0;
|
|
# lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4;
|
|
# lfs_getattr(&lfs, "hello", 'B', buffer+4, 6) => LFS_ERR_NOATTR;
|
|
# lfs_getattr(&lfs, "hello", 'C', buffer+10, 5) => 5;
|
|
# memcmp(buffer, "aaaa", 4) => 0;
|
|
# memcmp(buffer+4, "\0\0\0\0\0\0", 6) => 0;
|
|
# memcmp(buffer+10, "ccccc", 5) => 0;
|
|
#
|
|
# lfs_setattr(&lfs, "hello", 'B', "dddddd", 6) => 0;
|
|
# lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4;
|
|
# lfs_getattr(&lfs, "hello", 'B', buffer+4, 6) => 6;
|
|
# lfs_getattr(&lfs, "hello", 'C', buffer+10, 5) => 5;
|
|
# memcmp(buffer, "aaaa", 4) => 0;
|
|
# memcmp(buffer+4, "dddddd", 6) => 0;
|
|
# memcmp(buffer+10, "ccccc", 5) => 0;
|
|
#
|
|
# lfs_setattr(&lfs, "hello", 'B', "eee", 3) => 0;
|
|
# lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4;
|
|
# lfs_getattr(&lfs, "hello", 'B', buffer+4, 6) => 3;
|
|
# lfs_getattr(&lfs, "hello", 'C', buffer+10, 5) => 5;
|
|
# memcmp(buffer, "aaaa", 4) => 0;
|
|
# memcmp(buffer+4, "eee\0\0\0", 6) => 0;
|
|
# memcmp(buffer+10, "ccccc", 5) => 0;
|
|
#
|
|
# lfs_setattr(&lfs, "hello", 'A', buffer, LFS_ATTR_MAX+1) => LFS_ERR_NOSPC;
|
|
# lfs_setattr(&lfs, "hello", 'B', "fffffffff", 9) => 0;
|
|
# lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4;
|
|
# lfs_getattr(&lfs, "hello", 'B', buffer+4, 6) => 9;
|
|
# lfs_getattr(&lfs, "hello", 'C', buffer+10, 5) => 5;
|
|
#
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# memset(buffer, 0, sizeof(buffer));
|
|
# lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4;
|
|
# lfs_getattr(&lfs, "hello", 'B', buffer+4, 9) => 9;
|
|
# lfs_getattr(&lfs, "hello", 'C', buffer+13, 5) => 5;
|
|
# memcmp(buffer, "aaaa", 4) => 0;
|
|
# memcmp(buffer+4, "fffffffff", 9) => 0;
|
|
# memcmp(buffer+13, "ccccc", 5) => 0;
|
|
#
|
|
# lfs_file_open(&lfs, &file, "hello/hello", LFS_O_RDONLY) => 0;
|
|
# lfs_file_read(&lfs, &file, buffer, sizeof(buffer)) => strlen("hello");
|
|
# memcmp(buffer, "hello", strlen("hello")) => 0;
|
|
# lfs_file_close(&lfs, &file);
|
|
# lfs_unmount(&lfs) => 0;
|
|
#'''
|
|
#
|
|
#[cases.test_attrs_get_set_root]
|
|
#code = '''
|
|
# lfs_t lfs;
|
|
# lfs_format(&lfs, cfg) => 0;
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_mkdir(&lfs, "hello") => 0;
|
|
# lfs_file_t file;
|
|
# lfs_file_open(&lfs, &file, "hello/hello", LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
|
# lfs_file_write(&lfs, &file, "hello", strlen("hello")) => strlen("hello");
|
|
# lfs_file_close(&lfs, &file);
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# uint8_t buffer[1024];
|
|
# memset(buffer, 0, sizeof(buffer));
|
|
# lfs_setattr(&lfs, "/", 'A', "aaaa", 4) => 0;
|
|
# lfs_setattr(&lfs, "/", 'B', "bbbbbb", 6) => 0;
|
|
# lfs_setattr(&lfs, "/", 'C', "ccccc", 5) => 0;
|
|
# lfs_getattr(&lfs, "/", 'A', buffer, 4) => 4;
|
|
# lfs_getattr(&lfs, "/", 'B', buffer+4, 6) => 6;
|
|
# lfs_getattr(&lfs, "/", 'C', buffer+10, 5) => 5;
|
|
# memcmp(buffer, "aaaa", 4) => 0;
|
|
# memcmp(buffer+4, "bbbbbb", 6) => 0;
|
|
# memcmp(buffer+10, "ccccc", 5) => 0;
|
|
#
|
|
# lfs_setattr(&lfs, "/", 'B', "", 0) => 0;
|
|
# lfs_getattr(&lfs, "/", 'A', buffer, 4) => 4;
|
|
# lfs_getattr(&lfs, "/", 'B', buffer+4, 6) => 0;
|
|
# lfs_getattr(&lfs, "/", 'C', buffer+10, 5) => 5;
|
|
# memcmp(buffer, "aaaa", 4) => 0;
|
|
# memcmp(buffer+4, "\0\0\0\0\0\0", 6) => 0;
|
|
# memcmp(buffer+10, "ccccc", 5) => 0;
|
|
#
|
|
# lfs_removeattr(&lfs, "/", 'B') => 0;
|
|
# lfs_getattr(&lfs, "/", 'A', buffer, 4) => 4;
|
|
# lfs_getattr(&lfs, "/", 'B', buffer+4, 6) => LFS_ERR_NOATTR;
|
|
# lfs_getattr(&lfs, "/", 'C', buffer+10, 5) => 5;
|
|
# memcmp(buffer, "aaaa", 4) => 0;
|
|
# memcmp(buffer+4, "\0\0\0\0\0\0", 6) => 0;
|
|
# memcmp(buffer+10, "ccccc", 5) => 0;
|
|
#
|
|
# lfs_setattr(&lfs, "/", 'B', "dddddd", 6) => 0;
|
|
# lfs_getattr(&lfs, "/", 'A', buffer, 4) => 4;
|
|
# lfs_getattr(&lfs, "/", 'B', buffer+4, 6) => 6;
|
|
# lfs_getattr(&lfs, "/", 'C', buffer+10, 5) => 5;
|
|
# memcmp(buffer, "aaaa", 4) => 0;
|
|
# memcmp(buffer+4, "dddddd", 6) => 0;
|
|
# memcmp(buffer+10, "ccccc", 5) => 0;
|
|
#
|
|
# lfs_setattr(&lfs, "/", 'B', "eee", 3) => 0;
|
|
# lfs_getattr(&lfs, "/", 'A', buffer, 4) => 4;
|
|
# lfs_getattr(&lfs, "/", 'B', buffer+4, 6) => 3;
|
|
# lfs_getattr(&lfs, "/", 'C', buffer+10, 5) => 5;
|
|
# memcmp(buffer, "aaaa", 4) => 0;
|
|
# memcmp(buffer+4, "eee\0\0\0", 6) => 0;
|
|
# memcmp(buffer+10, "ccccc", 5) => 0;
|
|
#
|
|
# lfs_setattr(&lfs, "/", 'A', buffer, LFS_ATTR_MAX+1) => LFS_ERR_NOSPC;
|
|
# lfs_setattr(&lfs, "/", 'B', "fffffffff", 9) => 0;
|
|
# lfs_getattr(&lfs, "/", 'A', buffer, 4) => 4;
|
|
# lfs_getattr(&lfs, "/", 'B', buffer+4, 6) => 9;
|
|
# lfs_getattr(&lfs, "/", 'C', buffer+10, 5) => 5;
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# memset(buffer, 0, sizeof(buffer));
|
|
# lfs_getattr(&lfs, "/", 'A', buffer, 4) => 4;
|
|
# lfs_getattr(&lfs, "/", 'B', buffer+4, 9) => 9;
|
|
# lfs_getattr(&lfs, "/", 'C', buffer+13, 5) => 5;
|
|
# memcmp(buffer, "aaaa", 4) => 0;
|
|
# memcmp(buffer+4, "fffffffff", 9) => 0;
|
|
# memcmp(buffer+13, "ccccc", 5) => 0;
|
|
#
|
|
# lfs_file_open(&lfs, &file, "hello/hello", LFS_O_RDONLY) => 0;
|
|
# lfs_file_read(&lfs, &file, buffer, sizeof(buffer)) => strlen("hello");
|
|
# memcmp(buffer, "hello", strlen("hello")) => 0;
|
|
# lfs_file_close(&lfs, &file);
|
|
# lfs_unmount(&lfs) => 0;
|
|
#'''
|
|
#
|
|
#[cases.test_attrs_get_set_file]
|
|
#code = '''
|
|
# lfs_t lfs;
|
|
# lfs_format(&lfs, cfg) => 0;
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_mkdir(&lfs, "hello") => 0;
|
|
# lfs_file_t file;
|
|
# lfs_file_open(&lfs, &file, "hello/hello", LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
|
# lfs_file_write(&lfs, &file, "hello", strlen("hello")) => strlen("hello");
|
|
# lfs_file_close(&lfs, &file);
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# uint8_t buffer[1024];
|
|
# memset(buffer, 0, sizeof(buffer));
|
|
# struct lfs_attr attrs1[] = {
|
|
# {'A', buffer, 4},
|
|
# {'B', buffer+4, 6},
|
|
# {'C', buffer+10, 5},
|
|
# };
|
|
# struct lfs_file_config cfg1 = {.attrs=attrs1, .attr_count=3};
|
|
#
|
|
# lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_WRONLY, &cfg1) => 0;
|
|
# memcpy(buffer, "aaaa", 4);
|
|
# memcpy(buffer+4, "bbbbbb", 6);
|
|
# memcpy(buffer+10, "ccccc", 5);
|
|
# lfs_file_close(&lfs, &file) => 0;
|
|
# memset(buffer, 0, 15);
|
|
# lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDONLY, &cfg1) => 0;
|
|
# lfs_file_close(&lfs, &file) => 0;
|
|
# memcmp(buffer, "aaaa", 4) => 0;
|
|
# memcmp(buffer+4, "bbbbbb", 6) => 0;
|
|
# memcmp(buffer+10, "ccccc", 5) => 0;
|
|
#
|
|
# attrs1[1].size = 0;
|
|
# lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_WRONLY, &cfg1) => 0;
|
|
# lfs_file_close(&lfs, &file) => 0;
|
|
# memset(buffer, 0, 15);
|
|
# attrs1[1].size = 6;
|
|
# lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDONLY, &cfg1) => 0;
|
|
# lfs_file_close(&lfs, &file) => 0;
|
|
# memcmp(buffer, "aaaa", 4) => 0;
|
|
# memcmp(buffer+4, "\0\0\0\0\0\0", 6) => 0;
|
|
# memcmp(buffer+10, "ccccc", 5) => 0;
|
|
#
|
|
# attrs1[1].size = 6;
|
|
# lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_WRONLY, &cfg1) => 0;
|
|
# memcpy(buffer+4, "dddddd", 6);
|
|
# lfs_file_close(&lfs, &file) => 0;
|
|
# memset(buffer, 0, 15);
|
|
# attrs1[1].size = 6;
|
|
# lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDONLY, &cfg1) => 0;
|
|
# lfs_file_close(&lfs, &file) => 0;
|
|
# memcmp(buffer, "aaaa", 4) => 0;
|
|
# memcmp(buffer+4, "dddddd", 6) => 0;
|
|
# memcmp(buffer+10, "ccccc", 5) => 0;
|
|
#
|
|
# attrs1[1].size = 3;
|
|
# lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_WRONLY, &cfg1) => 0;
|
|
# memcpy(buffer+4, "eee", 3);
|
|
# lfs_file_close(&lfs, &file) => 0;
|
|
# memset(buffer, 0, 15);
|
|
# attrs1[1].size = 6;
|
|
# lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDONLY, &cfg1) => 0;
|
|
# lfs_file_close(&lfs, &file) => 0;
|
|
# memcmp(buffer, "aaaa", 4) => 0;
|
|
# memcmp(buffer+4, "eee\0\0\0", 6) => 0;
|
|
# memcmp(buffer+10, "ccccc", 5) => 0;
|
|
#
|
|
# attrs1[0].size = LFS_ATTR_MAX+1;
|
|
# lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_WRONLY, &cfg1)
|
|
# => LFS_ERR_NOSPC;
|
|
#
|
|
# struct lfs_attr attrs2[] = {
|
|
# {'A', buffer, 4},
|
|
# {'B', buffer+4, 9},
|
|
# {'C', buffer+13, 5},
|
|
# };
|
|
# struct lfs_file_config cfg2 = {.attrs=attrs2, .attr_count=3};
|
|
# lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDWR, &cfg2) => 0;
|
|
# memcpy(buffer+4, "fffffffff", 9);
|
|
# lfs_file_close(&lfs, &file) => 0;
|
|
# attrs1[0].size = 4;
|
|
# lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDONLY, &cfg1) => 0;
|
|
# lfs_file_close(&lfs, &file) => 0;
|
|
#
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# memset(buffer, 0, sizeof(buffer));
|
|
# struct lfs_attr attrs3[] = {
|
|
# {'A', buffer, 4},
|
|
# {'B', buffer+4, 9},
|
|
# {'C', buffer+13, 5},
|
|
# };
|
|
# struct lfs_file_config cfg3 = {.attrs=attrs3, .attr_count=3};
|
|
#
|
|
# lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDONLY, &cfg3) => 0;
|
|
# lfs_file_close(&lfs, &file) => 0;
|
|
# memcmp(buffer, "aaaa", 4) => 0;
|
|
# memcmp(buffer+4, "fffffffff", 9) => 0;
|
|
# memcmp(buffer+13, "ccccc", 5) => 0;
|
|
#
|
|
# lfs_file_open(&lfs, &file, "hello/hello", LFS_O_RDONLY) => 0;
|
|
# lfs_file_read(&lfs, &file, buffer, sizeof(buffer)) => strlen("hello");
|
|
# memcmp(buffer, "hello", strlen("hello")) => 0;
|
|
# lfs_file_close(&lfs, &file);
|
|
# lfs_unmount(&lfs) => 0;
|
|
#'''
|
|
#
|
|
#[cases.test_attrs_deferred_file]
|
|
#code = '''
|
|
# lfs_t lfs;
|
|
# lfs_format(&lfs, cfg) => 0;
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_mkdir(&lfs, "hello") => 0;
|
|
# lfs_file_t file;
|
|
# lfs_file_open(&lfs, &file, "hello/hello", LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
|
# lfs_file_write(&lfs, &file, "hello", strlen("hello")) => strlen("hello");
|
|
# lfs_file_close(&lfs, &file);
|
|
# lfs_unmount(&lfs) => 0;
|
|
#
|
|
# lfs_mount(&lfs, cfg) => 0;
|
|
# lfs_setattr(&lfs, "hello/hello", 'B', "fffffffff", 9) => 0;
|
|
# lfs_setattr(&lfs, "hello/hello", 'C', "ccccc", 5) => 0;
|
|
#
|
|
# uint8_t buffer[1024];
|
|
# memset(buffer, 0, sizeof(buffer));
|
|
# struct lfs_attr attrs1[] = {
|
|
# {'B', "gggg", 4},
|
|
# {'C', "", 0},
|
|
# {'D', "hhhh", 4},
|
|
# };
|
|
# struct lfs_file_config cfg1 = {.attrs=attrs1, .attr_count=3};
|
|
#
|
|
# lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_WRONLY, &cfg1) => 0;
|
|
#
|
|
# lfs_getattr(&lfs, "hello/hello", 'B', buffer, 9) => 9;
|
|
# lfs_getattr(&lfs, "hello/hello", 'C', buffer+9, 9) => 5;
|
|
# lfs_getattr(&lfs, "hello/hello", 'D', buffer+18, 9) => LFS_ERR_NOATTR;
|
|
# memcmp(buffer, "fffffffff", 9) => 0;
|
|
# memcmp(buffer+9, "ccccc\0\0\0\0", 9) => 0;
|
|
# memcmp(buffer+18, "\0\0\0\0\0\0\0\0\0", 9) => 0;
|
|
#
|
|
# lfs_file_sync(&lfs, &file) => 0;
|
|
# lfs_getattr(&lfs, "hello/hello", 'B', buffer, 9) => 4;
|
|
# lfs_getattr(&lfs, "hello/hello", 'C', buffer+9, 9) => 0;
|
|
# lfs_getattr(&lfs, "hello/hello", 'D', buffer+18, 9) => 4;
|
|
# memcmp(buffer, "gggg\0\0\0\0\0", 9) => 0;
|
|
# memcmp(buffer+9, "\0\0\0\0\0\0\0\0\0", 9) => 0;
|
|
# memcmp(buffer+18, "hhhh\0\0\0\0\0", 9) => 0;
|
|
#
|
|
# lfs_file_close(&lfs, &file) => 0;
|
|
# lfs_unmount(&lfs) => 0;
|
|
#'''
|