Files
littlefs/tests/test_compat.toml
T
Christopher Haster acad3a3143 Added format flags to lfsr_format
This is mainly to solve the weird check-hole where passing CKPROGS/
CKREADS as mount flags has no effect on lfsr_format (I mean, it'd be a
bit silly if it did somehow):

  LFS_F_RDWR              0  // Format the filesystem as read and write
  LFS_F_CKPROGS  0x00000010  // Check progs by reading back progged data
  LFS_F_CKREADS  0x00000020  // Check reads via parity bits/checksums

This makes lfsr_format a more cumbersome interface, but I don't know if
this is necessarily a bad thing. There's always risk of data loss when
calling lfsr_format, so maybe it should be a pain to call.

At the very least, format flags may be useful in the future for
enabling/disabling format-time things such as the planned block-map,
parity-tree, etc. Though it's unclear if such significant settings
should be format flags or somehow encoded as fields in our config
struct.

---

The LFS_F_* format flags of course ended up conflicting with our
internal LFS_F_* flags, so I renamed most of the internal flags to match
the closest flag set they participate in:

- LFS_F_TYPE        -> LFS_O_TYPE
- LFS_F_UNFLUSH     -> LFS_O_UNFLUSH
- LFS_F_UNSYNC      -> LFS_O_UNSYNC
- LFS_F_ORPHAN      -> LFS_O_ORPHAN
- LFS_F_ZOMBIE      -> LFS_O_ZOMBIE

- LFS_F_ORPHANS     -> LFS_I_ORPHANS
- LFS_F_UNCOMPACTED -> LFS_I_UNCOMPACTED

- LFS_F_TSTATE      -> LFS_T_TSTATE
- LFS_F_BTYPE       -> LFS_T_BTYPE
- LFS_F_DIRTY       -> LFS_T_DIRTY
- LFS_F_MUTATED     -> LFS_T_MUTATED

This may make it a bit less clear which flags are a part of the public
API, vs intended only for internal use, but at the very least our asserts
in format/mount/open/etc should catch most of these mistakes.

---

Code cost ended up being pretty minimal. Actually negative. This is the
second time we're _adding_ a feature that somehow saves code, though the
reality for this one is we're really just pushing constants up into the
user's stack frame. Still, it's a good indication the cost of format
flags is small:

           code          stack
  before: 36452           2680
  after:  36448 (-0.0%)   2680 (+0.0%)
2024-08-16 01:04:13 -05:00

1341 lines
40 KiB
TOML

# Test compatibility between different littlefs versions
after = [
'test_dirs',
'test_files',
'test_fwrite',
'test_forphans',
'test_mount',
]
# Note, these tests are a bit special. They can run as-is to test various
# compatbility corner-cases, but if you link a previous version of littlefs
# as "lfsp" and define LFSP, they will also test migrating from lfsp -> lfs.
#
# If LFSP is not defined, these tests will alias lfsp = lfs so things will
# still compile and run, but the value of many of these tests is to test
# against a previous version linked in with the help of
# scripts/changeprefix.py
#
# Though we are also limited by API changes... so by default these tests
# won't run if LFS_VERSION changes. This can be bypassed with the test
# runner's -a/--all flag.
#
# alias littlefs symbols as needed
#
# there may be a better way to do this but oh well, explicit aliases works
code = '''
#ifdef LFSP
#define STRINGIZE(x) STRINGIZE_(x)
#define STRINGIZE_(x) #x
#include STRINGIZE(LFSP)
#else
#define LFSP_VERSION LFS_VERSION
#define LFSP_VERSION_MAJOR LFS_VERSION_MAJOR
#define LFSP_VERSION_MINOR LFS_VERSION_MINOR
#define LFSP_DISK_VERSION LFS_DISK_VERSION
#define LFSP_DISK_VERSION_MAJOR LFS_DISK_VERSION_MAJOR
#define LFSP_DISK_VERSION_MINOR LFS_DISK_VERSION_MINOR
#define lfsp_t lfs_t
#define lfsp_config lfs_config
#define LFSP_ERR_NOENT LFS_ERR_NOENT
#define lfsp_format lfsr_format
#define LFSP_M_RDWR LFS_M_RDWR
#define lfsp_mount lfsr_mount
#define lfsp_unmount lfsr_unmount
#define lfsp_fsinfo lfs_fsinfo
#define lfsp_fs_stat lfsr_fs_stat
#define lfsp_dir_t lfsr_dir_t
#define lfsp_info lfs_info
#define LFSP_TYPE_REG LFS_TYPE_REG
#define LFSP_TYPE_DIR LFS_TYPE_DIR
#define lfsp_mkdir lfsr_mkdir
#define lfsp_dir_open lfsr_dir_open
#define lfsp_dir_read lfsr_dir_read
#define lfsp_dir_close lfsr_dir_close
#define lfsp_file_t lfsr_file_t
#define LFSP_O_RDONLY LFS_O_RDONLY
#define LFSP_O_WRONLY LFS_O_WRONLY
#define LFSP_O_CREAT LFS_O_CREAT
#define LFSP_O_EXCL LFS_O_EXCL
#define LFSP_SEEK_SET LFS_SEEK_SET
#define lfsp_file_open lfsr_file_open
#define lfsp_file_write lfsr_file_write
#define lfsp_file_read lfsr_file_read
#define lfsp_file_seek lfsr_file_seek
#define lfsp_file_close lfsr_file_close
#endif
'''
## forward-compatibility tests ##
# test we can mount in a new version
[cases.test_compat_forward_mount]
if = [
'LFS_VERSION == LFSP_VERSION',
'LFS_DISK_VERSION_MAJOR == LFSP_DISK_VERSION_MAJOR',
]
code = '''
// create the previous version
struct lfsp_config cfgp;
assert(sizeof(struct lfsp_config) == sizeof(struct lfs_config));
memcpy(&cfgp, CFG, sizeof(cfgp));
lfsp_t lfsp;
lfsr_format(&lfsp, LFS_F_RDWR, &cfgp) => 0;
// confirm the previous mount works
lfsp_mount(&lfsp, LFSP_M_RDWR, &cfgp) => 0;
lfsp_unmount(&lfsp) => 0;
//////
// now mount with new version
lfs_t lfs;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
lfsr_unmount(&lfs) => 0;
'''
# test we can read dirs in a new version
[cases.test_compat_forward_read_dirs]
defines.COUNT = 5
if = [
'LFS_VERSION == LFSP_VERSION',
'LFS_DISK_VERSION_MAJOR == LFSP_DISK_VERSION_MAJOR',
]
code = '''
// create the previous version
struct lfsp_config cfgp;
assert(sizeof(struct lfsp_config) == sizeof(struct lfs_config));
memcpy(&cfgp, CFG, sizeof(cfgp));
lfsp_t lfsp;
lfsr_format(&lfsp, LFS_F_RDWR, &cfgp) => 0;
// write COUNT dirs
lfsp_mount(&lfsp, LFSP_M_RDWR, &cfgp) => 0;
for (lfs_size_t i = 0; i < COUNT; i++) {
char name[8];
sprintf(name, "dir%03d", i);
lfsp_mkdir(&lfsp, name) => 0;
}
lfsp_unmount(&lfsp) => 0;
//////
// now mount with new version
lfs_t lfs;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
// can we list the directories?
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
struct lfs_info info;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < COUNT; i++) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
char name[8];
sprintf(name, "dir%03d", i);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
# test we can read files in a new version
[cases.test_compat_forward_read_files]
defines.COUNT = 5
defines.SIZE = [4, 32, 512, 8192]
defines.CHUNK = 4
if = [
'LFS_VERSION == LFSP_VERSION',
'LFS_DISK_VERSION_MAJOR == LFSP_DISK_VERSION_MAJOR',
]
code = '''
// create the previous version
struct lfsp_config cfgp;
assert(sizeof(struct lfsp_config) == sizeof(struct lfs_config));
memcpy(&cfgp, CFG, sizeof(cfgp));
lfsp_t lfsp;
lfsr_format(&lfsp, LFS_F_RDWR, &cfgp) => 0;
// write COUNT files
lfsp_mount(&lfsp, LFSP_M_RDWR, &cfgp) => 0;
uint32_t prng = 42;
for (lfs_size_t i = 0; i < COUNT; i++) {
lfsp_file_t file;
char name[8];
sprintf(name, "file%03d", i);
lfsp_file_open(&lfsp, &file, name,
LFSP_O_WRONLY | LFSP_O_CREAT | LFSP_O_EXCL) => 0;
for (lfs_size_t j = 0; j < SIZE; j += CHUNK) {
uint8_t chunk[CHUNK];
for (lfs_size_t k = 0; k < CHUNK; k++) {
chunk[k] = TEST_PRNG(&prng) & 0xff;
}
lfsp_file_write(&lfsp, &file, chunk, CHUNK) => CHUNK;
}
lfsp_file_close(&lfsp, &file) => 0;
}
lfsp_unmount(&lfsp) => 0;
//////
// now mount with new version
lfs_t lfs;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
// can we list the files?
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
struct lfs_info info;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < COUNT; i++) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
char name[8];
sprintf(name, "file%03d", i);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_REG);
assert(info.size == SIZE);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// now can we read the files?
prng = 42;
for (lfs_size_t i = 0; i < COUNT; i++) {
lfsr_file_t file;
char name[8];
sprintf(name, "file%03d", i);
lfsr_file_open(&lfs, &file, name, LFS_O_RDONLY) => 0;
for (lfs_size_t j = 0; j < SIZE; j += CHUNK) {
uint8_t chunk[CHUNK];
lfsr_file_read(&lfs, &file, chunk, CHUNK) => CHUNK;
for (lfs_size_t k = 0; k < CHUNK; k++) {
assert(chunk[k] == (TEST_PRNG(&prng) & 0xff));
}
}
lfsr_file_close(&lfs, &file) => 0;
}
lfsr_unmount(&lfs) => 0;
'''
# test we can read files in dirs in a new version
[cases.test_compat_forward_read_files_in_dirs]
defines.COUNT = 5
defines.SIZE = [4, 32, 512, 8192]
defines.CHUNK = 4
if = [
'LFS_VERSION == LFSP_VERSION',
'LFS_DISK_VERSION_MAJOR == LFSP_DISK_VERSION_MAJOR',
]
code = '''
// create the previous version
struct lfsp_config cfgp;
assert(sizeof(struct lfsp_config) == sizeof(struct lfs_config));
memcpy(&cfgp, CFG, sizeof(cfgp));
lfsp_t lfsp;
lfsr_format(&lfsp, LFS_F_RDWR, &cfgp) => 0;
// write COUNT files+dirs
lfsp_mount(&lfsp, LFSP_M_RDWR, &cfgp) => 0;
uint32_t prng = 42;
for (lfs_size_t i = 0; i < COUNT; i++) {
char name[16];
sprintf(name, "dir%03d", i);
lfsp_mkdir(&lfsp, name) => 0;
lfsp_file_t file;
sprintf(name, "dir%03d/file%03d", i, i);
lfsp_file_open(&lfsp, &file, name,
LFSP_O_WRONLY | LFSP_O_CREAT | LFSP_O_EXCL) => 0;
for (lfs_size_t j = 0; j < SIZE; j += CHUNK) {
uint8_t chunk[CHUNK];
for (lfs_size_t k = 0; k < CHUNK; k++) {
chunk[k] = TEST_PRNG(&prng) & 0xff;
}
lfsp_file_write(&lfsp, &file, chunk, CHUNK) => CHUNK;
}
lfsp_file_close(&lfsp, &file) => 0;
}
lfsp_unmount(&lfsp) => 0;
//////
// now mount with new version
lfs_t lfs;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
// can we list the directories?
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
struct lfs_info info;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < COUNT; i++) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
char name[8];
sprintf(name, "dir%03d", i);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// can we list the files?
for (lfs_size_t i = 0; i < COUNT; i++) {
char name[8];
sprintf(name, "dir%03d", i);
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, name) => 0;
struct lfs_info info;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
sprintf(name, "file%03d", i);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_REG);
assert(info.size == SIZE);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
// now can we read the files?
prng = 42;
for (lfs_size_t i = 0; i < COUNT; i++) {
lfsr_file_t file;
char name[16];
sprintf(name, "dir%03d/file%03d", i, i);
lfsr_file_open(&lfs, &file, name, LFS_O_RDONLY) => 0;
for (lfs_size_t j = 0; j < SIZE; j += CHUNK) {
uint8_t chunk[CHUNK];
lfsr_file_read(&lfs, &file, chunk, CHUNK) => CHUNK;
for (lfs_size_t k = 0; k < CHUNK; k++) {
assert(chunk[k] == (TEST_PRNG(&prng) & 0xff));
}
}
lfsr_file_close(&lfs, &file) => 0;
}
lfsr_unmount(&lfs) => 0;
'''
# test we can write dirs in a new version
[cases.test_compat_forward_write_dirs]
defines.COUNT = 10
if = [
'LFS_VERSION == LFSP_VERSION',
'LFS_DISK_VERSION_MAJOR == LFSP_DISK_VERSION_MAJOR',
]
code = '''
// create the previous version
struct lfsp_config cfgp;
assert(sizeof(struct lfsp_config) == sizeof(struct lfs_config));
memcpy(&cfgp, CFG, sizeof(cfgp));
lfsp_t lfsp;
lfsr_format(&lfsp, LFS_F_RDWR, &cfgp) => 0;
// write COUNT/2 dirs
lfsp_mount(&lfsp, LFSP_M_RDWR, &cfgp) => 0;
for (lfs_size_t i = 0; i < COUNT/2; i++) {
char name[8];
sprintf(name, "dir%03d", i);
lfsp_mkdir(&lfsp, name) => 0;
}
lfsp_unmount(&lfsp) => 0;
//////
// now mount with new version
lfs_t lfs;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
// write another COUNT/2 dirs
for (lfs_size_t i = COUNT/2; i < COUNT; i++) {
char name[8];
sprintf(name, "dir%03d", i);
lfsr_mkdir(&lfs, name) => 0;
}
// can we list the directories?
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
struct lfs_info info;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < COUNT; i++) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
char name[8];
sprintf(name, "dir%03d", i);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
lfsr_unmount(&lfs) => 0;
'''
# test we can write files in a new version
[cases.test_compat_forward_write_files]
defines.COUNT = 5
defines.SIZE = [4, 32, 512, 8192]
defines.CHUNK = 2
if = [
'LFS_VERSION == LFSP_VERSION',
'LFS_DISK_VERSION_MAJOR == LFSP_DISK_VERSION_MAJOR',
]
code = '''
// create the previous version
struct lfsp_config cfgp;
assert(sizeof(struct lfsp_config) == sizeof(struct lfs_config));
memcpy(&cfgp, CFG, sizeof(cfgp));
lfsp_t lfsp;
lfsr_format(&lfsp, LFS_F_RDWR, &cfgp) => 0;
// write half COUNT files
lfsp_mount(&lfsp, LFSP_M_RDWR, &cfgp) => 0;
uint32_t prng = 42;
for (lfs_size_t i = 0; i < COUNT; i++) {
// write half
lfsp_file_t file;
char name[8];
sprintf(name, "file%03d", i);
lfsp_file_open(&lfsp, &file, name,
LFSP_O_WRONLY | LFSP_O_CREAT | LFSP_O_EXCL) => 0;
for (lfs_size_t j = 0; j < SIZE/2; j += CHUNK) {
uint8_t chunk[CHUNK];
for (lfs_size_t k = 0; k < CHUNK; k++) {
chunk[k] = TEST_PRNG(&prng) & 0xff;
}
lfsp_file_write(&lfsp, &file, chunk, CHUNK) => CHUNK;
}
lfsp_file_close(&lfsp, &file) => 0;
// skip the other half but keep our prng reproducible
for (lfs_size_t j = SIZE/2; j < SIZE; j++) {
TEST_PRNG(&prng);
}
}
lfsp_unmount(&lfsp) => 0;
//////
// now mount with new version
lfs_t lfs;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
// write half COUNT files
prng = 42;
for (lfs_size_t i = 0; i < COUNT; i++) {
// skip half but keep our prng reproducible
for (lfs_size_t j = 0; j < SIZE/2; j++) {
TEST_PRNG(&prng);
}
// write the other half
lfsr_file_t file;
char name[8];
sprintf(name, "file%03d", i);
lfsr_file_open(&lfs, &file, name, LFS_O_WRONLY) => 0;
lfsr_file_seek(&lfs, &file, SIZE/2, LFS_SEEK_SET) => SIZE/2;
for (lfs_size_t j = SIZE/2; j < SIZE; j += CHUNK) {
uint8_t chunk[CHUNK];
for (lfs_size_t k = 0; k < CHUNK; k++) {
chunk[k] = TEST_PRNG(&prng) & 0xff;
}
lfsr_file_write(&lfs, &file, chunk, CHUNK) => CHUNK;
}
lfsr_file_close(&lfs, &file) => 0;
}
// can we list the files?
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
struct lfs_info info;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < COUNT; i++) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
char name[8];
sprintf(name, "file%03d", i);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_REG);
assert(info.size == SIZE);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// now can we read the files?
prng = 42;
for (lfs_size_t i = 0; i < COUNT; i++) {
lfsr_file_t file;
char name[8];
sprintf(name, "file%03d", i);
lfsr_file_open(&lfs, &file, name, LFS_O_RDONLY) => 0;
for (lfs_size_t j = 0; j < SIZE; j += CHUNK) {
uint8_t chunk[CHUNK];
lfsr_file_read(&lfs, &file, chunk, CHUNK) => CHUNK;
for (lfs_size_t k = 0; k < CHUNK; k++) {
assert(chunk[k] == (TEST_PRNG(&prng) & 0xff));
}
}
lfsr_file_close(&lfs, &file) => 0;
}
lfsr_unmount(&lfs) => 0;
'''
# test we can write files in dirs in a new version
[cases.test_compat_forward_write_files_in_dirs]
defines.COUNT = 5
defines.SIZE = [4, 32, 512, 8192]
defines.CHUNK = 2
if = [
'LFS_VERSION == LFSP_VERSION',
'LFS_DISK_VERSION_MAJOR == LFSP_DISK_VERSION_MAJOR',
]
code = '''
// create the previous version
struct lfsp_config cfgp;
assert(sizeof(struct lfsp_config) == sizeof(struct lfs_config));
memcpy(&cfgp, CFG, sizeof(cfgp));
lfsp_t lfsp;
lfsr_format(&lfsp, LFS_F_RDWR, &cfgp) => 0;
//////
// now mount with new version
lfsp_mount(&lfsp, LFSP_M_RDWR, &cfgp) => 0;
uint32_t prng = 42;
for (lfs_size_t i = 0; i < COUNT; i++) {
char name[16];
sprintf(name, "dir%03d", i);
lfsp_mkdir(&lfsp, name) => 0;
// write half
lfsp_file_t file;
sprintf(name, "dir%03d/file%03d", i, i);
lfsp_file_open(&lfsp, &file, name,
LFSP_O_WRONLY | LFSP_O_CREAT | LFSP_O_EXCL) => 0;
for (lfs_size_t j = 0; j < SIZE/2; j += CHUNK) {
uint8_t chunk[CHUNK];
for (lfs_size_t k = 0; k < CHUNK; k++) {
chunk[k] = TEST_PRNG(&prng) & 0xff;
}
lfsp_file_write(&lfsp, &file, chunk, CHUNK) => CHUNK;
}
lfsp_file_close(&lfsp, &file) => 0;
// skip the other half but keep our prng reproducible
for (lfs_size_t j = SIZE/2; j < SIZE; j++) {
TEST_PRNG(&prng);
}
}
lfsp_unmount(&lfsp) => 0;
// mount the new version
lfs_t lfs;
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
// write half COUNT files
prng = 42;
for (lfs_size_t i = 0; i < COUNT; i++) {
// skip half but keep our prng reproducible
for (lfs_size_t j = 0; j < SIZE/2; j++) {
TEST_PRNG(&prng);
}
// write the other half
lfsr_file_t file;
char name[16];
sprintf(name, "dir%03d/file%03d", i, i);
lfsr_file_open(&lfs, &file, name, LFS_O_WRONLY) => 0;
lfsr_file_seek(&lfs, &file, SIZE/2, LFS_SEEK_SET) => SIZE/2;
for (lfs_size_t j = SIZE/2; j < SIZE; j += CHUNK) {
uint8_t chunk[CHUNK];
for (lfs_size_t k = 0; k < CHUNK; k++) {
chunk[k] = TEST_PRNG(&prng) & 0xff;
}
lfsr_file_write(&lfs, &file, chunk, CHUNK) => CHUNK;
}
lfsr_file_close(&lfs, &file) => 0;
}
// can we list the directories?
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, "/") => 0;
struct lfs_info info;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < COUNT; i++) {
lfsr_dir_read(&lfs, &dir, &info) => 0;
char name[8];
sprintf(name, "dir%03d", i);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
}
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
// can we list the files?
for (lfs_size_t i = 0; i < COUNT; i++) {
char name[8];
sprintf(name, "dir%03d", i);
lfsr_dir_t dir;
lfsr_dir_open(&lfs, &dir, name) => 0;
struct lfs_info info;
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFS_TYPE_DIR);
assert(info.size == 0);
lfsr_dir_read(&lfs, &dir, &info) => 0;
sprintf(name, "file%03d", i);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS_TYPE_REG);
assert(info.size == SIZE);
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
lfsr_dir_close(&lfs, &dir) => 0;
}
// now can we read the files?
prng = 42;
for (lfs_size_t i = 0; i < COUNT; i++) {
lfsr_file_t file;
char name[16];
sprintf(name, "dir%03d/file%03d", i, i);
lfsr_file_open(&lfs, &file, name, LFS_O_RDONLY) => 0;
for (lfs_size_t j = 0; j < SIZE; j += CHUNK) {
uint8_t chunk[CHUNK];
lfsr_file_read(&lfs, &file, chunk, CHUNK) => CHUNK;
for (lfs_size_t k = 0; k < CHUNK; k++) {
assert(chunk[k] == (TEST_PRNG(&prng) & 0xff));
}
}
lfsr_file_close(&lfs, &file) => 0;
}
lfsr_unmount(&lfs) => 0;
'''
## backwards-compatibility tests ##
# test we can mount in an old version
[cases.test_compat_backward_mount]
if = [
'LFS_VERSION == LFSP_VERSION',
'LFS_DISK_VERSION == LFSP_DISK_VERSION',
]
code = '''
// create the new version
lfs_t lfs;
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
// confirm the new mount works
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
lfsr_unmount(&lfs) => 0;
//////
// now mount with previous version
struct lfsp_config cfgp;
assert(sizeof(struct lfsp_config) == sizeof(struct lfs_config));
memcpy(&cfgp, CFG, sizeof(cfgp));
lfsp_t lfsp;
lfsp_mount(&lfsp, LFSP_M_RDWR, &cfgp) => 0;
lfsp_unmount(&lfsp) => 0;
'''
# test we can read dirs in an old version
[cases.test_compat_backward_read_dirs]
defines.COUNT = 5
if = [
'LFS_VERSION == LFSP_VERSION',
'LFS_DISK_VERSION == LFSP_DISK_VERSION',
]
code = '''
// create the new version
lfs_t lfs;
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
// write COUNT dirs
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
for (lfs_size_t i = 0; i < COUNT; i++) {
char name[8];
sprintf(name, "dir%03d", i);
lfsr_mkdir(&lfs, name) => 0;
}
lfsr_unmount(&lfs) => 0;
//////
// now mount with previous version
struct lfsp_config cfgp;
assert(sizeof(struct lfsp_config) == sizeof(struct lfs_config));
memcpy(&cfgp, CFG, sizeof(cfgp));
lfsp_t lfsp;
lfsp_mount(&lfsp, LFSP_M_RDWR, &cfgp) => 0;
// can we list the directories?
lfsp_dir_t dir;
lfsp_dir_open(&lfsp, &dir, "/") => 0;
struct lfsp_info info;
lfsp_dir_read(&lfsp, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFSP_TYPE_DIR);
assert(info.size == 0);
lfsp_dir_read(&lfsp, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFSP_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < COUNT; i++) {
lfsp_dir_read(&lfsp, &dir, &info) => 0;
char name[8];
sprintf(name, "dir%03d", i);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFSP_TYPE_DIR);
assert(info.size == 0);
}
lfsp_dir_read(&lfsp, &dir, &info) => LFSP_ERR_NOENT;
lfsp_dir_close(&lfsp, &dir) => 0;
lfsp_unmount(&lfsp) => 0;
'''
# test we can read files in an old version
[cases.test_compat_backward_read_files]
defines.COUNT = 5
defines.SIZE = [4, 32, 512, 8192]
defines.CHUNK = 4
if = [
'LFS_VERSION == LFSP_VERSION',
'LFS_DISK_VERSION == LFSP_DISK_VERSION',
]
code = '''
// create the new version
lfs_t lfs;
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
// write COUNT files
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
uint32_t prng = 42;
for (lfs_size_t i = 0; i < COUNT; i++) {
lfsr_file_t file;
char name[8];
sprintf(name, "file%03d", i);
lfsr_file_open(&lfs, &file, name,
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
for (lfs_size_t j = 0; j < SIZE; j += CHUNK) {
uint8_t chunk[CHUNK];
for (lfs_size_t k = 0; k < CHUNK; k++) {
chunk[k] = TEST_PRNG(&prng) & 0xff;
}
lfsr_file_write(&lfs, &file, chunk, CHUNK) => CHUNK;
}
lfsr_file_close(&lfs, &file) => 0;
}
lfsr_unmount(&lfs) => 0;
//////
// now mount with previous version
struct lfsp_config cfgp;
assert(sizeof(struct lfsp_config) == sizeof(struct lfs_config));
memcpy(&cfgp, CFG, sizeof(cfgp));
lfsp_t lfsp;
lfsp_mount(&lfsp, LFSP_M_RDWR, &cfgp) => 0;
// can we list the files?
lfsp_dir_t dir;
lfsp_dir_open(&lfsp, &dir, "/") => 0;
struct lfsp_info info;
lfsp_dir_read(&lfsp, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFSP_TYPE_DIR);
assert(info.size == 0);
lfsp_dir_read(&lfsp, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFSP_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < COUNT; i++) {
lfsp_dir_read(&lfsp, &dir, &info) => 0;
char name[8];
sprintf(name, "file%03d", i);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFSP_TYPE_REG);
assert(info.size == SIZE);
}
lfsp_dir_read(&lfsp, &dir, &info) => LFSP_ERR_NOENT;
lfsp_dir_close(&lfsp, &dir) => 0;
// now can we read the files?
prng = 42;
for (lfs_size_t i = 0; i < COUNT; i++) {
lfsp_file_t file;
char name[8];
sprintf(name, "file%03d", i);
lfsp_file_open(&lfsp, &file, name, LFSP_O_RDONLY) => 0;
for (lfs_size_t j = 0; j < SIZE; j += CHUNK) {
uint8_t chunk[CHUNK];
lfsp_file_read(&lfsp, &file, chunk, CHUNK) => CHUNK;
for (lfs_size_t k = 0; k < CHUNK; k++) {
assert(chunk[k] == (TEST_PRNG(&prng) & 0xff));
}
}
lfsp_file_close(&lfsp, &file) => 0;
}
lfsp_unmount(&lfsp) => 0;
'''
# test we can read files in dirs in an old version
[cases.test_compat_backward_read_files_in_dirs]
defines.COUNT = 5
defines.SIZE = [4, 32, 512, 8192]
defines.CHUNK = 4
if = [
'LFS_VERSION == LFSP_VERSION',
'LFS_DISK_VERSION == LFSP_DISK_VERSION',
]
code = '''
// create the new version
lfs_t lfs;
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
// write COUNT files+dirs
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
uint32_t prng = 42;
for (lfs_size_t i = 0; i < COUNT; i++) {
char name[16];
sprintf(name, "dir%03d", i);
lfsr_mkdir(&lfs, name) => 0;
lfsr_file_t file;
sprintf(name, "dir%03d/file%03d", i, i);
lfsr_file_open(&lfs, &file, name,
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
for (lfs_size_t j = 0; j < SIZE; j += CHUNK) {
uint8_t chunk[CHUNK];
for (lfs_size_t k = 0; k < CHUNK; k++) {
chunk[k] = TEST_PRNG(&prng) & 0xff;
}
lfsr_file_write(&lfs, &file, chunk, CHUNK) => CHUNK;
}
lfsr_file_close(&lfs, &file) => 0;
}
lfsr_unmount(&lfs) => 0;
//////
// now mount with previous version
struct lfsp_config cfgp;
assert(sizeof(struct lfsp_config) == sizeof(struct lfs_config));
memcpy(&cfgp, CFG, sizeof(cfgp));
lfsp_t lfsp;
lfsp_mount(&lfsp, LFSP_M_RDWR, &cfgp) => 0;
// can we list the directories?
lfsp_dir_t dir;
lfsp_dir_open(&lfsp, &dir, "/") => 0;
struct lfsp_info info;
lfsp_dir_read(&lfsp, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFSP_TYPE_DIR);
assert(info.size == 0);
lfsp_dir_read(&lfsp, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFSP_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < COUNT; i++) {
lfsp_dir_read(&lfsp, &dir, &info) => 0;
char name[8];
sprintf(name, "dir%03d", i);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFSP_TYPE_DIR);
assert(info.size == 0);
}
lfsp_dir_read(&lfsp, &dir, &info) => LFSP_ERR_NOENT;
lfsp_dir_close(&lfsp, &dir) => 0;
// can we list the files?
for (lfs_size_t i = 0; i < COUNT; i++) {
char name[8];
sprintf(name, "dir%03d", i);
lfsp_dir_t dir;
lfsp_dir_open(&lfsp, &dir, name) => 0;
struct lfsp_info info;
lfsp_dir_read(&lfsp, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFSP_TYPE_DIR);
assert(info.size == 0);
lfsp_dir_read(&lfsp, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFSP_TYPE_DIR);
assert(info.size == 0);
lfsp_dir_read(&lfsp, &dir, &info) => 0;
sprintf(name, "file%03d", i);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFSP_TYPE_REG);
assert(info.size == SIZE);
lfsp_dir_read(&lfsp, &dir, &info) => LFSP_ERR_NOENT;
lfsp_dir_close(&lfsp, &dir) => 0;
}
// now can we read the files?
prng = 42;
for (lfs_size_t i = 0; i < COUNT; i++) {
lfsp_file_t file;
char name[16];
sprintf(name, "dir%03d/file%03d", i, i);
lfsp_file_open(&lfsp, &file, name, LFSP_O_RDONLY) => 0;
for (lfs_size_t j = 0; j < SIZE; j += CHUNK) {
uint8_t chunk[CHUNK];
lfsp_file_read(&lfsp, &file, chunk, CHUNK) => CHUNK;
for (lfs_size_t k = 0; k < CHUNK; k++) {
assert(chunk[k] == (TEST_PRNG(&prng) & 0xff));
}
}
lfsp_file_close(&lfsp, &file) => 0;
}
lfsp_unmount(&lfsp) => 0;
'''
# test we can write dirs in an old version
[cases.test_compat_backward_write_dirs]
defines.COUNT = 10
if = [
'LFS_VERSION == LFSP_VERSION',
'LFS_DISK_VERSION == LFSP_DISK_VERSION',
]
code = '''
// create the new version
lfs_t lfs;
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
// write COUNT/2 dirs
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
for (lfs_size_t i = 0; i < COUNT/2; i++) {
char name[8];
sprintf(name, "dir%03d", i);
lfsr_mkdir(&lfs, name) => 0;
}
lfsr_unmount(&lfs) => 0;
//////
// now mount with previous version
struct lfsp_config cfgp;
assert(sizeof(struct lfsp_config) == sizeof(struct lfs_config));
memcpy(&cfgp, CFG, sizeof(cfgp));
lfsp_t lfsp;
lfsp_mount(&lfsp, LFSP_M_RDWR, &cfgp) => 0;
// write another COUNT/2 dirs
for (lfs_size_t i = COUNT/2; i < COUNT; i++) {
char name[8];
sprintf(name, "dir%03d", i);
lfsp_mkdir(&lfsp, name) => 0;
}
// can we list the directories?
lfsp_dir_t dir;
lfsp_dir_open(&lfsp, &dir, "/") => 0;
struct lfsp_info info;
lfsp_dir_read(&lfsp, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFSP_TYPE_DIR);
assert(info.size == 0);
lfsp_dir_read(&lfsp, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFSP_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < COUNT; i++) {
lfsp_dir_read(&lfsp, &dir, &info) => 0;
char name[8];
sprintf(name, "dir%03d", i);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFSP_TYPE_DIR);
assert(info.size == 0);
}
lfsp_dir_read(&lfsp, &dir, &info) => LFSP_ERR_NOENT;
lfsp_dir_close(&lfsp, &dir) => 0;
lfsp_unmount(&lfsp) => 0;
'''
# test we can write files in an old version
[cases.test_compat_backward_write_files]
defines.COUNT = 5
defines.SIZE = [4, 32, 512, 8192]
defines.CHUNK = 2
if = [
'LFS_VERSION == LFSP_VERSION',
'LFS_DISK_VERSION == LFSP_DISK_VERSION',
]
code = '''
// create the previous version
lfs_t lfs;
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
// write half COUNT files
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
uint32_t prng = 42;
for (lfs_size_t i = 0; i < COUNT; i++) {
// write half
lfsr_file_t file;
char name[8];
sprintf(name, "file%03d", i);
lfsr_file_open(&lfs, &file, name,
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
for (lfs_size_t j = 0; j < SIZE/2; j += CHUNK) {
uint8_t chunk[CHUNK];
for (lfs_size_t k = 0; k < CHUNK; k++) {
chunk[k] = TEST_PRNG(&prng) & 0xff;
}
lfsr_file_write(&lfs, &file, chunk, CHUNK) => CHUNK;
}
lfsr_file_close(&lfs, &file) => 0;
// skip the other half but keep our prng reproducible
for (lfs_size_t j = SIZE/2; j < SIZE; j++) {
TEST_PRNG(&prng);
}
}
lfsr_unmount(&lfs) => 0;
//////
// now mount with previous version
struct lfsp_config cfgp;
assert(sizeof(struct lfsp_config) == sizeof(struct lfs_config));
memcpy(&cfgp, CFG, sizeof(cfgp));
lfsp_t lfsp;
lfsp_mount(&lfsp, LFSP_M_RDWR, &cfgp) => 0;
// write half COUNT files
prng = 42;
for (lfs_size_t i = 0; i < COUNT; i++) {
// skip half but keep our prng reproducible
for (lfs_size_t j = 0; j < SIZE/2; j++) {
TEST_PRNG(&prng);
}
// write the other half
lfsp_file_t file;
char name[8];
sprintf(name, "file%03d", i);
lfsp_file_open(&lfsp, &file, name, LFSP_O_WRONLY) => 0;
lfsp_file_seek(&lfsp, &file, SIZE/2, LFSP_SEEK_SET) => SIZE/2;
for (lfs_size_t j = SIZE/2; j < SIZE; j += CHUNK) {
uint8_t chunk[CHUNK];
for (lfs_size_t k = 0; k < CHUNK; k++) {
chunk[k] = TEST_PRNG(&prng) & 0xff;
}
lfsp_file_write(&lfsp, &file, chunk, CHUNK) => CHUNK;
}
lfsp_file_close(&lfsp, &file) => 0;
}
// can we list the files?
lfsp_dir_t dir;
lfsp_dir_open(&lfsp, &dir, "/") => 0;
struct lfsp_info info;
lfsp_dir_read(&lfsp, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFSP_TYPE_DIR);
assert(info.size == 0);
lfsp_dir_read(&lfsp, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFSP_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < COUNT; i++) {
lfsp_dir_read(&lfsp, &dir, &info) => 0;
char name[8];
sprintf(name, "file%03d", i);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFSP_TYPE_REG);
assert(info.size == SIZE);
}
lfsp_dir_read(&lfsp, &dir, &info) => LFSP_ERR_NOENT;
lfsp_dir_close(&lfsp, &dir) => 0;
// now can we read the files?
prng = 42;
for (lfs_size_t i = 0; i < COUNT; i++) {
lfsp_file_t file;
char name[8];
sprintf(name, "file%03d", i);
lfsp_file_open(&lfsp, &file, name, LFSP_O_RDONLY) => 0;
for (lfs_size_t j = 0; j < SIZE; j += CHUNK) {
uint8_t chunk[CHUNK];
lfsp_file_read(&lfsp, &file, chunk, CHUNK) => CHUNK;
for (lfs_size_t k = 0; k < CHUNK; k++) {
assert(chunk[k] == (TEST_PRNG(&prng) & 0xff));
}
}
lfsp_file_close(&lfsp, &file) => 0;
}
lfsp_unmount(&lfsp) => 0;
'''
# test we can write files in dirs in an old version
[cases.test_compat_backward_write_files_in_dirs]
defines.COUNT = 5
defines.SIZE = [4, 32, 512, 8192]
defines.CHUNK = 2
if = [
'LFS_VERSION == LFSP_VERSION',
'LFS_DISK_VERSION == LFSP_DISK_VERSION',
]
code = '''
// create the previous version
lfs_t lfs;
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
// write half COUNT files
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
uint32_t prng = 42;
for (lfs_size_t i = 0; i < COUNT; i++) {
char name[16];
sprintf(name, "dir%03d", i);
lfsr_mkdir(&lfs, name) => 0;
// write half
lfsr_file_t file;
sprintf(name, "dir%03d/file%03d", i, i);
lfsr_file_open(&lfs, &file, name,
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
for (lfs_size_t j = 0; j < SIZE/2; j += CHUNK) {
uint8_t chunk[CHUNK];
for (lfs_size_t k = 0; k < CHUNK; k++) {
chunk[k] = TEST_PRNG(&prng) & 0xff;
}
lfsr_file_write(&lfs, &file, chunk, CHUNK) => CHUNK;
}
lfsr_file_close(&lfs, &file) => 0;
// skip the other half but keep our prng reproducible
for (lfs_size_t j = SIZE/2; j < SIZE; j++) {
TEST_PRNG(&prng);
}
}
lfsr_unmount(&lfs) => 0;
//////
// now mount with previous version
struct lfsp_config cfgp;
assert(sizeof(struct lfsp_config) == sizeof(struct lfs_config));
memcpy(&cfgp, CFG, sizeof(cfgp));
lfsp_t lfsp;
lfsp_mount(&lfsp, LFSP_M_RDWR, &cfgp) => 0;
// write half COUNT files
prng = 42;
for (lfs_size_t i = 0; i < COUNT; i++) {
// skip half but keep our prng reproducible
for (lfs_size_t j = 0; j < SIZE/2; j++) {
TEST_PRNG(&prng);
}
// write the other half
lfsp_file_t file;
char name[16];
sprintf(name, "dir%03d/file%03d", i, i);
lfsp_file_open(&lfsp, &file, name, LFSP_O_WRONLY) => 0;
lfsp_file_seek(&lfsp, &file, SIZE/2, LFSP_SEEK_SET) => SIZE/2;
for (lfs_size_t j = SIZE/2; j < SIZE; j += CHUNK) {
uint8_t chunk[CHUNK];
for (lfs_size_t k = 0; k < CHUNK; k++) {
chunk[k] = TEST_PRNG(&prng) & 0xff;
}
lfsp_file_write(&lfsp, &file, chunk, CHUNK) => CHUNK;
}
lfsp_file_close(&lfsp, &file) => 0;
}
// can we list the directories?
lfsp_dir_t dir;
lfsp_dir_open(&lfsp, &dir, "/") => 0;
struct lfsp_info info;
lfsp_dir_read(&lfsp, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFSP_TYPE_DIR);
assert(info.size == 0);
lfsp_dir_read(&lfsp, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFSP_TYPE_DIR);
assert(info.size == 0);
for (lfs_size_t i = 0; i < COUNT; i++) {
lfsp_dir_read(&lfsp, &dir, &info) => 0;
char name[8];
sprintf(name, "dir%03d", i);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFSP_TYPE_DIR);
assert(info.size == 0);
}
lfsp_dir_read(&lfsp, &dir, &info) => LFSP_ERR_NOENT;
lfsp_dir_close(&lfsp, &dir) => 0;
// can we list the files?
for (lfs_size_t i = 0; i < COUNT; i++) {
char name[8];
sprintf(name, "dir%03d", i);
lfsp_dir_t dir;
lfsp_dir_open(&lfsp, &dir, name) => 0;
struct lfsp_info info;
lfsp_dir_read(&lfsp, &dir, &info) => 0;
assert(strcmp(info.name, ".") == 0);
assert(info.type == LFSP_TYPE_DIR);
assert(info.size == 0);
lfsp_dir_read(&lfsp, &dir, &info) => 0;
assert(strcmp(info.name, "..") == 0);
assert(info.type == LFSP_TYPE_DIR);
assert(info.size == 0);
lfsp_dir_read(&lfsp, &dir, &info) => 0;
sprintf(name, "file%03d", i);
assert(strcmp(info.name, name) == 0);
assert(info.type == LFSP_TYPE_REG);
assert(info.size == SIZE);
lfsp_dir_read(&lfsp, &dir, &info) => LFSP_ERR_NOENT;
lfsp_dir_close(&lfsp, &dir) => 0;
}
// now can we read the files?
prng = 42;
for (lfs_size_t i = 0; i < COUNT; i++) {
lfsp_file_t file;
char name[16];
sprintf(name, "dir%03d/file%03d", i, i);
lfsp_file_open(&lfsp, &file, name, LFSP_O_RDONLY) => 0;
for (lfs_size_t j = 0; j < SIZE; j += CHUNK) {
uint8_t chunk[CHUNK];
lfsp_file_read(&lfsp, &file, chunk, CHUNK) => CHUNK;
for (lfs_size_t k = 0; k < CHUNK; k++) {
assert(chunk[k] == (TEST_PRNG(&prng) & 0xff));
}
}
lfsp_file_close(&lfsp, &file) => 0;
}
lfsp_unmount(&lfsp) => 0;
'''