Added tests over shared scratch files
One downside of scratch files is that there are a lot of corner cases to consider.
This commit is contained in:
@@ -5081,22 +5081,29 @@ static int lfsr_mdir_fetch(lfs_t *lfs, lfsr_mdir_t *mdir,
|
|||||||
static int lfsr_mdir_lookupnext(lfs_t *lfs, const lfsr_mdir_t *mdir,
|
static int lfsr_mdir_lookupnext(lfs_t *lfs, const lfsr_mdir_t *mdir,
|
||||||
lfsr_smid_t mid, lfsr_tag_t tag,
|
lfsr_smid_t mid, lfsr_tag_t tag,
|
||||||
lfsr_tag_t *tag_, lfsr_data_t *data_) {
|
lfsr_tag_t *tag_, lfsr_data_t *data_) {
|
||||||
lfsr_smid_t mid_;
|
lfsr_srid_t rid__;
|
||||||
lfsr_tag_t tag__;
|
lfsr_tag_t tag__;
|
||||||
int err = lfsr_rbyd_lookupnext(lfs, &mdir->rbyd,
|
int err = lfsr_rbyd_lookupnext(lfs, &mdir->rbyd,
|
||||||
lfsr_mid_rid(lfs, mid), tag,
|
lfsr_mid_rid(lfs, mid), tag,
|
||||||
&mid_, &tag__, NULL, data_);
|
&rid__, &tag__, NULL, data_);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is very similar to lfsr_rbyd_lookupnext, but we error if
|
// this is very similar to lfsr_rbyd_lookupnext, but we error if
|
||||||
// lookupnext would change mids
|
// lookupnext would change mids
|
||||||
if (mid_ != lfsr_mid_rid(lfs, mid)) {
|
if (rid__ != lfsr_mid_rid(lfs, mid)) {
|
||||||
return LFS_ERR_NOENT;
|
return LFS_ERR_NOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tag_) {
|
if (tag_) {
|
||||||
|
// intercept pending grms here and pretend they're scratch files
|
||||||
|
//
|
||||||
|
// fortunately pending gmrs/scratch files have roughly the same
|
||||||
|
// semantics, and it's easier to manage the implied mid gap in
|
||||||
|
// higher-levels
|
||||||
|
// TODO
|
||||||
|
|
||||||
*tag_ = tag__;
|
*tag_ = tag__;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -6940,11 +6947,6 @@ static int lfsr_mtree_pathlookup(lfs_t *lfs, const char *path,
|
|||||||
return LFS_ERR_NOENT;
|
return LFS_ERR_NOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// pretend scratch files don't exist
|
|
||||||
if (tag == LFSR_TAG_SCRATCH) {
|
|
||||||
return LFS_ERR_NOENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// go on to next name
|
// go on to next name
|
||||||
name += name_size;
|
name += name_size;
|
||||||
next:;
|
next:;
|
||||||
@@ -8691,6 +8693,11 @@ int lfsr_stat(lfs_t *lfs, const char *path, struct lfs_info *info) {
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pretend scratch files don't exist
|
||||||
|
if (tag == LFSR_TAG_SCRATCH) {
|
||||||
|
return LFS_ERR_NOENT;
|
||||||
|
}
|
||||||
|
|
||||||
// special case for root
|
// special case for root
|
||||||
if (lfsr_mdir_isroot(&mdir)) {
|
if (lfsr_mdir_isroot(&mdir)) {
|
||||||
strcpy(info->name, "/");
|
strcpy(info->name, "/");
|
||||||
@@ -8717,8 +8724,12 @@ int lfsr_dir_open(lfs_t *lfs, lfsr_dir_t *dir, const char *path) {
|
|||||||
|
|
||||||
// are we a directory?
|
// are we a directory?
|
||||||
if (tag != LFSR_TAG_DIR) {
|
if (tag != LFSR_TAG_DIR) {
|
||||||
|
if (tag == LFSR_TAG_SCRATCH) {
|
||||||
|
return LFS_ERR_NOENT;
|
||||||
|
} else {
|
||||||
return LFS_ERR_NOTDIR;
|
return LFS_ERR_NOTDIR;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// setup dir state
|
// setup dir state
|
||||||
dir->type = LFS_TYPE_DIR;
|
dir->type = LFS_TYPE_DIR;
|
||||||
@@ -9052,7 +9063,7 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// creating a new entry?
|
// creating a new entry?
|
||||||
if (err == LFS_ERR_NOENT) {
|
if (err == LFS_ERR_NOENT || tag == LFSR_TAG_SCRATCH) {
|
||||||
if (!lfsr_o_iscreat(flags)) {
|
if (!lfsr_o_iscreat(flags)) {
|
||||||
return LFS_ERR_NOENT;
|
return LFS_ERR_NOENT;
|
||||||
}
|
}
|
||||||
@@ -9063,7 +9074,12 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
return LFS_ERR_NAMETOOLONG;
|
return LFS_ERR_NAMETOOLONG;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a scratch entry, this reserves the mid until first sync
|
// create a scratch entry if we don't have one, this reserves the
|
||||||
|
// mid until first sync
|
||||||
|
//
|
||||||
|
// note because of the preparemutation call above, there can be
|
||||||
|
// no orphaned scratch files at this point
|
||||||
|
if (err == LFS_ERR_NOENT) {
|
||||||
err = lfsr_mdir_commit(lfs, &file->mdir, LFSR_ATTRS(
|
err = lfsr_mdir_commit(lfs, &file->mdir, LFSR_ATTRS(
|
||||||
LFSR_ATTR(file->mdir.mid,
|
LFSR_ATTR(file->mdir.mid,
|
||||||
SCRATCH, +1, CAT(
|
SCRATCH, +1, CAT(
|
||||||
@@ -9072,6 +9088,10 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// mark as unsync and uncreat, we need to convert to reg file
|
||||||
|
// first sync
|
||||||
file->flags |= LFS_F_UNSYNC | LFS_F_UNCREAT;
|
file->flags |= LFS_F_UNSYNC | LFS_F_UNCREAT;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+678
-30
@@ -1,5 +1,5 @@
|
|||||||
# Test scratch files and their various use cases
|
# Test scratch files and their various use cases
|
||||||
after = 'test_fwrite'
|
after = ['test_fwrite', 'test_fsync']
|
||||||
|
|
||||||
|
|
||||||
# Some specific tests
|
# Some specific tests
|
||||||
@@ -24,16 +24,16 @@ code = '''
|
|||||||
struct lfs_info info;
|
struct lfs_info info;
|
||||||
lfsr_stat(&lfs_, "gello", &info) => LFS_ERR_NOENT;
|
lfsr_stat(&lfs_, "gello", &info) => LFS_ERR_NOENT;
|
||||||
// via readdir
|
// via readdir
|
||||||
lfsr_dir_t dir_;
|
lfsr_dir_t dir;
|
||||||
lfsr_dir_open(&lfs_, &dir_, "/") => 0;
|
lfsr_dir_open(&lfs_, &dir, "/") => 0;
|
||||||
lfsr_dir_read(&lfs_, &dir_, &info) => 0;
|
lfsr_dir_read(&lfs_, &dir, &info) => 0;
|
||||||
assert(strcmp(info.name, ".") == 0);
|
assert(strcmp(info.name, ".") == 0);
|
||||||
assert(info.type == LFS_TYPE_DIR);
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
lfsr_dir_read(&lfs_, &dir_, &info) => 0;
|
lfsr_dir_read(&lfs_, &dir, &info) => 0;
|
||||||
assert(strcmp(info.name, "..") == 0);
|
assert(strcmp(info.name, "..") == 0);
|
||||||
assert(info.type == LFS_TYPE_DIR);
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
lfsr_dir_read(&lfs_, &dir_, &info) => LFS_ERR_NOENT;
|
lfsr_dir_read(&lfs_, &dir, &info) => LFS_ERR_NOENT;
|
||||||
lfsr_dir_close(&lfs_, &dir_) => 0;
|
lfsr_dir_close(&lfs_, &dir) => 0;
|
||||||
// via open
|
// via open
|
||||||
lfsr_file_t file_;
|
lfsr_file_t file_;
|
||||||
lfsr_file_open(&lfs_, &file_, "gello", LFS_O_RDONLY) => LFS_ERR_NOENT;
|
lfsr_file_open(&lfs_, &file_, "gello", LFS_O_RDONLY) => LFS_ERR_NOENT;
|
||||||
@@ -53,15 +53,15 @@ code = '''
|
|||||||
// via stat
|
// via stat
|
||||||
lfsr_stat(&lfs_, "gello", &info) => LFS_ERR_NOENT;
|
lfsr_stat(&lfs_, "gello", &info) => LFS_ERR_NOENT;
|
||||||
// via readdir
|
// via readdir
|
||||||
lfsr_dir_open(&lfs_, &dir_, "/") => 0;
|
lfsr_dir_open(&lfs_, &dir, "/") => 0;
|
||||||
lfsr_dir_read(&lfs_, &dir_, &info) => 0;
|
lfsr_dir_read(&lfs_, &dir, &info) => 0;
|
||||||
assert(strcmp(info.name, ".") == 0);
|
assert(strcmp(info.name, ".") == 0);
|
||||||
assert(info.type == LFS_TYPE_DIR);
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
lfsr_dir_read(&lfs_, &dir_, &info) => 0;
|
lfsr_dir_read(&lfs_, &dir, &info) => 0;
|
||||||
assert(strcmp(info.name, "..") == 0);
|
assert(strcmp(info.name, "..") == 0);
|
||||||
assert(info.type == LFS_TYPE_DIR);
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
lfsr_dir_read(&lfs_, &dir_, &info) => LFS_ERR_NOENT;
|
lfsr_dir_read(&lfs_, &dir, &info) => LFS_ERR_NOENT;
|
||||||
lfsr_dir_close(&lfs_, &dir_) => 0;
|
lfsr_dir_close(&lfs_, &dir) => 0;
|
||||||
// via open
|
// via open
|
||||||
lfsr_file_open(&lfs_, &file_, "gello", LFS_O_RDONLY) => LFS_ERR_NOENT;
|
lfsr_file_open(&lfs_, &file_, "gello", LFS_O_RDONLY) => LFS_ERR_NOENT;
|
||||||
lfsr_unmount(&lfs_) => 0;
|
lfsr_unmount(&lfs_) => 0;
|
||||||
@@ -79,19 +79,19 @@ code = '''
|
|||||||
assert(info.type == LFS_TYPE_REG);
|
assert(info.type == LFS_TYPE_REG);
|
||||||
assert(info.size == SIZE);
|
assert(info.size == SIZE);
|
||||||
// via readdir
|
// via readdir
|
||||||
lfsr_dir_open(&lfs_, &dir_, "/") => 0;
|
lfsr_dir_open(&lfs_, &dir, "/") => 0;
|
||||||
lfsr_dir_read(&lfs_, &dir_, &info) => 0;
|
lfsr_dir_read(&lfs_, &dir, &info) => 0;
|
||||||
assert(strcmp(info.name, ".") == 0);
|
assert(strcmp(info.name, ".") == 0);
|
||||||
assert(info.type == LFS_TYPE_DIR);
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
lfsr_dir_read(&lfs_, &dir_, &info) => 0;
|
lfsr_dir_read(&lfs_, &dir, &info) => 0;
|
||||||
assert(strcmp(info.name, "..") == 0);
|
assert(strcmp(info.name, "..") == 0);
|
||||||
assert(info.type == LFS_TYPE_DIR);
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
lfsr_dir_read(&lfs_, &dir_, &info) => 0;
|
lfsr_dir_read(&lfs_, &dir, &info) => 0;
|
||||||
assert(strcmp(info.name, "gello") == 0);
|
assert(strcmp(info.name, "gello") == 0);
|
||||||
assert(info.type == LFS_TYPE_REG);
|
assert(info.type == LFS_TYPE_REG);
|
||||||
assert(info.size == SIZE);
|
assert(info.size == SIZE);
|
||||||
lfsr_dir_read(&lfs_, &dir_, &info) => LFS_ERR_NOENT;
|
lfsr_dir_read(&lfs_, &dir, &info) => LFS_ERR_NOENT;
|
||||||
lfsr_dir_close(&lfs_, &dir_) => 0;
|
lfsr_dir_close(&lfs_, &dir) => 0;
|
||||||
// via open
|
// via open
|
||||||
lfsr_file_open(&lfs_, &file_, "gello", LFS_O_RDONLY) => 0;
|
lfsr_file_open(&lfs_, &file_, "gello", LFS_O_RDONLY) => 0;
|
||||||
uint32_t prng_ = 42;
|
uint32_t prng_ = 42;
|
||||||
@@ -119,19 +119,19 @@ code = '''
|
|||||||
assert(info.type == LFS_TYPE_REG);
|
assert(info.type == LFS_TYPE_REG);
|
||||||
assert(info.size == SIZE);
|
assert(info.size == SIZE);
|
||||||
// via readdir
|
// via readdir
|
||||||
lfsr_dir_open(&lfs_, &dir_, "/") => 0;
|
lfsr_dir_open(&lfs_, &dir, "/") => 0;
|
||||||
lfsr_dir_read(&lfs_, &dir_, &info) => 0;
|
lfsr_dir_read(&lfs_, &dir, &info) => 0;
|
||||||
assert(strcmp(info.name, ".") == 0);
|
assert(strcmp(info.name, ".") == 0);
|
||||||
assert(info.type == LFS_TYPE_DIR);
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
lfsr_dir_read(&lfs_, &dir_, &info) => 0;
|
lfsr_dir_read(&lfs_, &dir, &info) => 0;
|
||||||
assert(strcmp(info.name, "..") == 0);
|
assert(strcmp(info.name, "..") == 0);
|
||||||
assert(info.type == LFS_TYPE_DIR);
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
lfsr_dir_read(&lfs_, &dir_, &info) => 0;
|
lfsr_dir_read(&lfs_, &dir, &info) => 0;
|
||||||
assert(strcmp(info.name, "gello") == 0);
|
assert(strcmp(info.name, "gello") == 0);
|
||||||
assert(info.type == LFS_TYPE_REG);
|
assert(info.type == LFS_TYPE_REG);
|
||||||
assert(info.size == SIZE);
|
assert(info.size == SIZE);
|
||||||
lfsr_dir_read(&lfs_, &dir_, &info) => LFS_ERR_NOENT;
|
lfsr_dir_read(&lfs_, &dir, &info) => LFS_ERR_NOENT;
|
||||||
lfsr_dir_close(&lfs_, &dir_) => 0;
|
lfsr_dir_close(&lfs_, &dir) => 0;
|
||||||
// via open
|
// via open
|
||||||
lfsr_file_open(&lfs_, &file_, "gello", LFS_O_RDONLY) => 0;
|
lfsr_file_open(&lfs_, &file_, "gello", LFS_O_RDONLY) => 0;
|
||||||
uint32_t prng_ = 42;
|
uint32_t prng_ = 42;
|
||||||
@@ -157,19 +157,19 @@ code = '''
|
|||||||
assert(info.type == LFS_TYPE_REG);
|
assert(info.type == LFS_TYPE_REG);
|
||||||
assert(info.size == SIZE);
|
assert(info.size == SIZE);
|
||||||
// via readdir
|
// via readdir
|
||||||
lfsr_dir_open(&lfs_, &dir_, "/") => 0;
|
lfsr_dir_open(&lfs_, &dir, "/") => 0;
|
||||||
lfsr_dir_read(&lfs_, &dir_, &info) => 0;
|
lfsr_dir_read(&lfs_, &dir, &info) => 0;
|
||||||
assert(strcmp(info.name, ".") == 0);
|
assert(strcmp(info.name, ".") == 0);
|
||||||
assert(info.type == LFS_TYPE_DIR);
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
lfsr_dir_read(&lfs_, &dir_, &info) => 0;
|
lfsr_dir_read(&lfs_, &dir, &info) => 0;
|
||||||
assert(strcmp(info.name, "..") == 0);
|
assert(strcmp(info.name, "..") == 0);
|
||||||
assert(info.type == LFS_TYPE_DIR);
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
lfsr_dir_read(&lfs_, &dir_, &info) => 0;
|
lfsr_dir_read(&lfs_, &dir, &info) => 0;
|
||||||
assert(strcmp(info.name, "gello") == 0);
|
assert(strcmp(info.name, "gello") == 0);
|
||||||
assert(info.type == LFS_TYPE_REG);
|
assert(info.type == LFS_TYPE_REG);
|
||||||
assert(info.size == SIZE);
|
assert(info.size == SIZE);
|
||||||
lfsr_dir_read(&lfs_, &dir_, &info) => LFS_ERR_NOENT;
|
lfsr_dir_read(&lfs_, &dir, &info) => LFS_ERR_NOENT;
|
||||||
lfsr_dir_close(&lfs_, &dir_) => 0;
|
lfsr_dir_close(&lfs_, &dir) => 0;
|
||||||
// via open
|
// via open
|
||||||
lfsr_file_open(&lfs_, &file_, "gello", LFS_O_RDONLY) => 0;
|
lfsr_file_open(&lfs_, &file_, "gello", LFS_O_RDONLY) => 0;
|
||||||
prng_ = 42;
|
prng_ = 42;
|
||||||
@@ -339,3 +339,651 @@ code = '''
|
|||||||
|
|
||||||
lfsr_unmount(&lfs) => 0;
|
lfsr_unmount(&lfs) => 0;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
[cases.test_fscratch_create_sync_wr]
|
||||||
|
defines.SIZE = '4*BLOCK_SIZE'
|
||||||
|
defines.CHUNK = 64
|
||||||
|
defines.SYNC = [false, true]
|
||||||
|
code = '''
|
||||||
|
lfs_t lfs;
|
||||||
|
lfsr_format(&lfs, CFG) => 0;
|
||||||
|
lfsr_mount(&lfs, CFG) => 0;
|
||||||
|
|
||||||
|
// create a file
|
||||||
|
lfsr_file_t file;
|
||||||
|
lfsr_file_open(&lfs, &file, "gello",
|
||||||
|
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
||||||
|
|
||||||
|
// as far as the filesystem is concerned, the file does not exist yet
|
||||||
|
// via stat
|
||||||
|
struct lfs_info info;
|
||||||
|
lfsr_stat(&lfs, "gello", &info) => LFS_ERR_NOENT;
|
||||||
|
// via readdir
|
||||||
|
lfsr_dir_t dir;
|
||||||
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, ".") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, "..") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
||||||
|
lfsr_dir_close(&lfs, &dir) => 0;
|
||||||
|
// rdonly rejected
|
||||||
|
lfsr_file_t file_;
|
||||||
|
lfsr_file_open(&lfs, &file_, "gello", LFS_O_RDONLY) => LFS_ERR_NOENT;
|
||||||
|
// non-create rejected
|
||||||
|
lfsr_file_open(&lfs, &file_, "gello", LFS_O_WRONLY) => LFS_ERR_NOENT;
|
||||||
|
lfsr_file_open(&lfs, &file_, "gello", LFS_O_RDWR) => LFS_ERR_NOENT;
|
||||||
|
|
||||||
|
// write to the file
|
||||||
|
uint32_t prng = 42;
|
||||||
|
for (lfs_off_t i = 0; i < SIZE; i += CHUNK) {
|
||||||
|
uint8_t wbuf[CHUNK];
|
||||||
|
for (lfs_size_t j = 0; j < CHUNK; j++) {
|
||||||
|
wbuf[j] = 'a' + (TEST_PRNG(&prng) % 26);
|
||||||
|
}
|
||||||
|
lfsr_file_write(&lfs, &file, wbuf, CHUNK) => CHUNK;
|
||||||
|
|
||||||
|
// as far as the filesystem is concerned, the file does not exist yet
|
||||||
|
// via stat
|
||||||
|
lfsr_stat(&lfs, "gello", &info) => LFS_ERR_NOENT;
|
||||||
|
// via readdir
|
||||||
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, ".") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, "..") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
||||||
|
lfsr_dir_close(&lfs, &dir) => 0;
|
||||||
|
// rdonly rejected
|
||||||
|
lfsr_file_open(&lfs, &file_, "gello", LFS_O_RDONLY) => LFS_ERR_NOENT;
|
||||||
|
// non-create rejected
|
||||||
|
lfsr_file_open(&lfs, &file_, "gello", LFS_O_WRONLY) => LFS_ERR_NOENT;
|
||||||
|
lfsr_file_open(&lfs, &file_, "gello", LFS_O_RDWR) => LFS_ERR_NOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// but we should still recieve sync broadcasts on sync/close
|
||||||
|
lfsr_file_t file__;
|
||||||
|
lfsr_file_open(&lfs, &file__, "gello",
|
||||||
|
LFS_O_RDWR | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
||||||
|
|
||||||
|
if (SYNC) {
|
||||||
|
// sync the file
|
||||||
|
lfsr_file_sync(&lfs, &file) => 0;
|
||||||
|
|
||||||
|
// now it should show up
|
||||||
|
// via stat
|
||||||
|
lfsr_stat(&lfs, "gello", &info) => 0;
|
||||||
|
assert(strcmp(info.name, "gello") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_REG);
|
||||||
|
assert(info.size == SIZE);
|
||||||
|
// via readdir
|
||||||
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, ".") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, "..") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, "gello") == 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;
|
||||||
|
// via open
|
||||||
|
lfsr_file_open(&lfs, &file_, "gello", LFS_O_RDONLY) => 0;
|
||||||
|
uint32_t prng_ = 42;
|
||||||
|
for (lfs_off_t i = 0; i < SIZE; i += CHUNK) {
|
||||||
|
uint8_t wbuf[CHUNK];
|
||||||
|
for (lfs_size_t j = 0; j < CHUNK; j++) {
|
||||||
|
wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26);
|
||||||
|
}
|
||||||
|
uint8_t rbuf[CHUNK];
|
||||||
|
lfsr_file_read(&lfs, &file_, rbuf, CHUNK) => CHUNK;
|
||||||
|
assert(memcmp(wbuf, rbuf, CHUNK) == 0);
|
||||||
|
}
|
||||||
|
lfsr_file_close(&lfs, &file_) => 0;
|
||||||
|
|
||||||
|
// recieved sync broadcast?
|
||||||
|
lfsr_file_rewind(&lfs, &file__) => 0;
|
||||||
|
prng_ = 42;
|
||||||
|
for (lfs_off_t i = 0; i < SIZE; i += CHUNK) {
|
||||||
|
uint8_t wbuf[CHUNK];
|
||||||
|
for (lfs_size_t j = 0; j < CHUNK; j++) {
|
||||||
|
wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26);
|
||||||
|
}
|
||||||
|
uint8_t rbuf[CHUNK];
|
||||||
|
lfsr_file_read(&lfs, &file__, rbuf, CHUNK) => CHUNK;
|
||||||
|
assert(memcmp(wbuf, rbuf, CHUNK) == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// close the file
|
||||||
|
lfsr_file_close(&lfs, &file) => 0;
|
||||||
|
|
||||||
|
// now it should show up
|
||||||
|
// via stat
|
||||||
|
lfsr_stat(&lfs, "gello", &info) => 0;
|
||||||
|
assert(strcmp(info.name, "gello") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_REG);
|
||||||
|
assert(info.size == SIZE);
|
||||||
|
// via readdir
|
||||||
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, ".") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, "..") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, "gello") == 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;
|
||||||
|
// via open
|
||||||
|
lfsr_file_open(&lfs, &file_, "gello", LFS_O_RDONLY) => 0;
|
||||||
|
uint32_t prng_ = 42;
|
||||||
|
for (lfs_off_t i = 0; i < SIZE; i += CHUNK) {
|
||||||
|
uint8_t wbuf[CHUNK];
|
||||||
|
for (lfs_size_t j = 0; j < CHUNK; j++) {
|
||||||
|
wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26);
|
||||||
|
}
|
||||||
|
uint8_t rbuf[CHUNK];
|
||||||
|
lfsr_file_read(&lfs, &file_, rbuf, CHUNK) => CHUNK;
|
||||||
|
assert(memcmp(wbuf, rbuf, CHUNK) == 0);
|
||||||
|
}
|
||||||
|
lfsr_file_close(&lfs, &file_) => 0;
|
||||||
|
|
||||||
|
// recieved sync broadcast?
|
||||||
|
lfsr_file_rewind(&lfs, &file__) => 0;
|
||||||
|
prng_ = 42;
|
||||||
|
for (lfs_off_t i = 0; i < SIZE; i += CHUNK) {
|
||||||
|
uint8_t wbuf[CHUNK];
|
||||||
|
for (lfs_size_t j = 0; j < CHUNK; j++) {
|
||||||
|
wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26);
|
||||||
|
}
|
||||||
|
uint8_t rbuf[CHUNK];
|
||||||
|
lfsr_file_read(&lfs, &file__, rbuf, CHUNK) => CHUNK;
|
||||||
|
assert(memcmp(wbuf, rbuf, CHUNK) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
lfsr_unmount(&lfs) => 0;
|
||||||
|
'''
|
||||||
|
|
||||||
|
[cases.test_fscratch_create_sync_rw]
|
||||||
|
defines.SIZE = '4*BLOCK_SIZE'
|
||||||
|
defines.CHUNK = 64
|
||||||
|
defines.SYNC = [false, true]
|
||||||
|
code = '''
|
||||||
|
lfs_t lfs;
|
||||||
|
lfsr_format(&lfs, CFG) => 0;
|
||||||
|
lfsr_mount(&lfs, CFG) => 0;
|
||||||
|
|
||||||
|
// create a file
|
||||||
|
lfsr_file_t file;
|
||||||
|
lfsr_file_open(&lfs, &file, "gello",
|
||||||
|
LFS_O_RDWR | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
||||||
|
// open a second reference
|
||||||
|
lfsr_file_t file__;
|
||||||
|
lfsr_file_open(&lfs, &file__, "gello",
|
||||||
|
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
||||||
|
|
||||||
|
// as far as the filesystem is concerned, the file does not exist yet
|
||||||
|
// via stat
|
||||||
|
struct lfs_info info;
|
||||||
|
lfsr_stat(&lfs, "gello", &info) => LFS_ERR_NOENT;
|
||||||
|
// via readdir
|
||||||
|
lfsr_dir_t dir;
|
||||||
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, ".") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, "..") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
||||||
|
lfsr_dir_close(&lfs, &dir) => 0;
|
||||||
|
// rdonly rejected
|
||||||
|
lfsr_file_t file_;
|
||||||
|
lfsr_file_open(&lfs, &file_, "gello", LFS_O_RDONLY) => LFS_ERR_NOENT;
|
||||||
|
// non-create rejected
|
||||||
|
lfsr_file_open(&lfs, &file_, "gello", LFS_O_WRONLY) => LFS_ERR_NOENT;
|
||||||
|
lfsr_file_open(&lfs, &file_, "gello", LFS_O_RDWR) => LFS_ERR_NOENT;
|
||||||
|
|
||||||
|
// write to the second file
|
||||||
|
uint32_t prng = 42;
|
||||||
|
for (lfs_off_t i = 0; i < SIZE; i += CHUNK) {
|
||||||
|
uint8_t wbuf[CHUNK];
|
||||||
|
for (lfs_size_t j = 0; j < CHUNK; j++) {
|
||||||
|
wbuf[j] = 'a' + (TEST_PRNG(&prng) % 26);
|
||||||
|
}
|
||||||
|
lfsr_file_write(&lfs, &file__, wbuf, CHUNK) => CHUNK;
|
||||||
|
|
||||||
|
// as far as the filesystem is concerned, the file does not exist yet
|
||||||
|
// via stat
|
||||||
|
lfsr_stat(&lfs, "gello", &info) => LFS_ERR_NOENT;
|
||||||
|
// via readdir
|
||||||
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, ".") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, "..") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
||||||
|
lfsr_dir_close(&lfs, &dir) => 0;
|
||||||
|
// rdonly rejected
|
||||||
|
lfsr_file_open(&lfs, &file_, "gello", LFS_O_RDONLY) => LFS_ERR_NOENT;
|
||||||
|
// non-create rejected
|
||||||
|
lfsr_file_open(&lfs, &file_, "gello", LFS_O_WRONLY) => LFS_ERR_NOENT;
|
||||||
|
lfsr_file_open(&lfs, &file_, "gello", LFS_O_RDWR) => LFS_ERR_NOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SYNC) {
|
||||||
|
// sync the second file
|
||||||
|
lfsr_file_sync(&lfs, &file__) => 0;
|
||||||
|
|
||||||
|
// now it should show up
|
||||||
|
// via stat
|
||||||
|
lfsr_stat(&lfs, "gello", &info) => 0;
|
||||||
|
assert(strcmp(info.name, "gello") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_REG);
|
||||||
|
assert(info.size == SIZE);
|
||||||
|
// via readdir
|
||||||
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, ".") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, "..") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, "gello") == 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;
|
||||||
|
// via open
|
||||||
|
lfsr_file_open(&lfs, &file_, "gello", LFS_O_RDONLY) => 0;
|
||||||
|
uint32_t prng_ = 42;
|
||||||
|
for (lfs_off_t i = 0; i < SIZE; i += CHUNK) {
|
||||||
|
uint8_t wbuf[CHUNK];
|
||||||
|
for (lfs_size_t j = 0; j < CHUNK; j++) {
|
||||||
|
wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26);
|
||||||
|
}
|
||||||
|
uint8_t rbuf[CHUNK];
|
||||||
|
lfsr_file_read(&lfs, &file_, rbuf, CHUNK) => CHUNK;
|
||||||
|
assert(memcmp(wbuf, rbuf, CHUNK) == 0);
|
||||||
|
}
|
||||||
|
lfsr_file_close(&lfs, &file_) => 0;
|
||||||
|
|
||||||
|
// recieved sync broadcast?
|
||||||
|
lfsr_file_rewind(&lfs, &file) => 0;
|
||||||
|
prng_ = 42;
|
||||||
|
for (lfs_off_t i = 0; i < SIZE; i += CHUNK) {
|
||||||
|
uint8_t wbuf[CHUNK];
|
||||||
|
for (lfs_size_t j = 0; j < CHUNK; j++) {
|
||||||
|
wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26);
|
||||||
|
}
|
||||||
|
uint8_t rbuf[CHUNK];
|
||||||
|
lfsr_file_read(&lfs, &file, rbuf, CHUNK) => CHUNK;
|
||||||
|
assert(memcmp(wbuf, rbuf, CHUNK) == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// close the second file
|
||||||
|
lfsr_file_close(&lfs, &file__) => 0;
|
||||||
|
|
||||||
|
// now it should show up
|
||||||
|
// via stat
|
||||||
|
lfsr_stat(&lfs, "gello", &info) => 0;
|
||||||
|
assert(strcmp(info.name, "gello") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_REG);
|
||||||
|
assert(info.size == SIZE);
|
||||||
|
// via readdir
|
||||||
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, ".") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, "..") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, "gello") == 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;
|
||||||
|
// via open
|
||||||
|
lfsr_file_open(&lfs, &file_, "gello", LFS_O_RDONLY) => 0;
|
||||||
|
uint32_t prng_ = 42;
|
||||||
|
for (lfs_off_t i = 0; i < SIZE; i += CHUNK) {
|
||||||
|
uint8_t wbuf[CHUNK];
|
||||||
|
for (lfs_size_t j = 0; j < CHUNK; j++) {
|
||||||
|
wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26);
|
||||||
|
}
|
||||||
|
uint8_t rbuf[CHUNK];
|
||||||
|
lfsr_file_read(&lfs, &file_, rbuf, CHUNK) => CHUNK;
|
||||||
|
assert(memcmp(wbuf, rbuf, CHUNK) == 0);
|
||||||
|
}
|
||||||
|
lfsr_file_close(&lfs, &file_) => 0;
|
||||||
|
|
||||||
|
// recieved sync broadcast?
|
||||||
|
lfsr_file_rewind(&lfs, &file) => 0;
|
||||||
|
prng_ = 42;
|
||||||
|
for (lfs_off_t i = 0; i < SIZE; i += CHUNK) {
|
||||||
|
uint8_t wbuf[CHUNK];
|
||||||
|
for (lfs_size_t j = 0; j < CHUNK; j++) {
|
||||||
|
wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26);
|
||||||
|
}
|
||||||
|
uint8_t rbuf[CHUNK];
|
||||||
|
lfsr_file_read(&lfs, &file, rbuf, CHUNK) => CHUNK;
|
||||||
|
assert(memcmp(wbuf, rbuf, CHUNK) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
lfsr_unmount(&lfs) => 0;
|
||||||
|
'''
|
||||||
|
|
||||||
|
[cases.test_fscratch_create_desync_wdwr]
|
||||||
|
defines.SIZE = '4*BLOCK_SIZE'
|
||||||
|
defines.CHUNK = 64
|
||||||
|
defines.SYNC = [false, true]
|
||||||
|
code = '''
|
||||||
|
lfs_t lfs;
|
||||||
|
lfsr_format(&lfs, CFG) => 0;
|
||||||
|
lfsr_mount(&lfs, CFG) => 0;
|
||||||
|
|
||||||
|
// create a desync file
|
||||||
|
lfsr_file_t file;
|
||||||
|
lfsr_file_open(&lfs, &file, "gello",
|
||||||
|
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL | LFS_O_DESYNC) => 0;
|
||||||
|
// open a second reference
|
||||||
|
lfsr_file_t file__;
|
||||||
|
lfsr_file_open(&lfs, &file__, "gello",
|
||||||
|
LFS_O_RDWR | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
||||||
|
// and a third for checking sync broadcasts
|
||||||
|
lfsr_file_t file___;
|
||||||
|
lfsr_file_open(&lfs, &file___, "gello",
|
||||||
|
LFS_O_RDWR | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
||||||
|
|
||||||
|
// write to the first file
|
||||||
|
uint32_t prng = 42;
|
||||||
|
for (lfs_off_t i = 0; i < SIZE; i += CHUNK) {
|
||||||
|
uint8_t wbuf[CHUNK];
|
||||||
|
for (lfs_size_t j = 0; j < CHUNK; j++) {
|
||||||
|
wbuf[j] = 'a' + (TEST_PRNG(&prng) % 26);
|
||||||
|
}
|
||||||
|
lfsr_file_write(&lfs, &file, wbuf, CHUNK) => CHUNK;
|
||||||
|
|
||||||
|
// as far as the filesystem is concerned, the file does not exist yet
|
||||||
|
// via stat
|
||||||
|
struct lfs_info info;
|
||||||
|
lfsr_stat(&lfs, "gello", &info) => LFS_ERR_NOENT;
|
||||||
|
// via readdir
|
||||||
|
lfsr_dir_t dir;
|
||||||
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, ".") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, "..") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
||||||
|
lfsr_dir_close(&lfs, &dir) => 0;
|
||||||
|
// rdonly rejected
|
||||||
|
lfsr_file_t file_;
|
||||||
|
lfsr_file_open(&lfs, &file_, "gello", LFS_O_RDONLY) => LFS_ERR_NOENT;
|
||||||
|
// non-create rejected
|
||||||
|
lfsr_file_open(&lfs, &file_, "gello", LFS_O_WRONLY) => LFS_ERR_NOENT;
|
||||||
|
lfsr_file_open(&lfs, &file_, "gello", LFS_O_RDWR) => LFS_ERR_NOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// write to the second file
|
||||||
|
prng = 42+1;
|
||||||
|
for (lfs_off_t i = 0; i < SIZE; i += CHUNK) {
|
||||||
|
uint8_t wbuf[CHUNK];
|
||||||
|
for (lfs_size_t j = 0; j < CHUNK; j++) {
|
||||||
|
wbuf[j] = 'a' + (TEST_PRNG(&prng) % 26);
|
||||||
|
}
|
||||||
|
lfsr_file_write(&lfs, &file__, wbuf, CHUNK) => CHUNK;
|
||||||
|
|
||||||
|
// as far as the filesystem is concerned, the file does not exist yet
|
||||||
|
// via stat
|
||||||
|
struct lfs_info info;
|
||||||
|
lfsr_stat(&lfs, "gello", &info) => LFS_ERR_NOENT;
|
||||||
|
// via readdir
|
||||||
|
lfsr_dir_t dir;
|
||||||
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, ".") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, "..") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
||||||
|
lfsr_dir_close(&lfs, &dir) => 0;
|
||||||
|
// rdonly rejected
|
||||||
|
lfsr_file_t file_;
|
||||||
|
lfsr_file_open(&lfs, &file_, "gello", LFS_O_RDONLY) => LFS_ERR_NOENT;
|
||||||
|
// non-create rejected
|
||||||
|
lfsr_file_open(&lfs, &file_, "gello", LFS_O_WRONLY) => LFS_ERR_NOENT;
|
||||||
|
lfsr_file_open(&lfs, &file_, "gello", LFS_O_RDWR) => LFS_ERR_NOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SYNC) {
|
||||||
|
// sync the second file
|
||||||
|
lfsr_file_sync(&lfs, &file__) => 0;
|
||||||
|
|
||||||
|
// now it should show up
|
||||||
|
// via stat
|
||||||
|
struct lfs_info info;
|
||||||
|
lfsr_stat(&lfs, "gello", &info) => 0;
|
||||||
|
assert(strcmp(info.name, "gello") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_REG);
|
||||||
|
assert(info.size == SIZE);
|
||||||
|
// via readdir
|
||||||
|
lfsr_dir_t dir;
|
||||||
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, ".") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, "..") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, "gello") == 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;
|
||||||
|
// via open
|
||||||
|
lfsr_file_t file_;
|
||||||
|
lfsr_file_open(&lfs, &file_, "gello", LFS_O_RDONLY) => 0;
|
||||||
|
uint32_t prng_ = 42+1;
|
||||||
|
for (lfs_off_t i = 0; i < SIZE; i += CHUNK) {
|
||||||
|
uint8_t wbuf[CHUNK];
|
||||||
|
for (lfs_size_t j = 0; j < CHUNK; j++) {
|
||||||
|
wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26);
|
||||||
|
}
|
||||||
|
uint8_t rbuf[CHUNK];
|
||||||
|
lfsr_file_read(&lfs, &file_, rbuf, CHUNK) => CHUNK;
|
||||||
|
assert(memcmp(wbuf, rbuf, CHUNK) == 0);
|
||||||
|
}
|
||||||
|
lfsr_file_close(&lfs, &file_) => 0;
|
||||||
|
|
||||||
|
// recieved sync broadcast?
|
||||||
|
lfsr_file_rewind(&lfs, &file___) => 0;
|
||||||
|
prng_ = 42+1;
|
||||||
|
for (lfs_off_t i = 0; i < SIZE; i += CHUNK) {
|
||||||
|
uint8_t wbuf[CHUNK];
|
||||||
|
for (lfs_size_t j = 0; j < CHUNK; j++) {
|
||||||
|
wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26);
|
||||||
|
}
|
||||||
|
uint8_t rbuf[CHUNK];
|
||||||
|
lfsr_file_read(&lfs, &file___, rbuf, CHUNK) => CHUNK;
|
||||||
|
assert(memcmp(wbuf, rbuf, CHUNK) == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// close the second file
|
||||||
|
lfsr_file_close(&lfs, &file__) => 0;
|
||||||
|
|
||||||
|
// now it should show up
|
||||||
|
// via stat
|
||||||
|
struct lfs_info info;
|
||||||
|
lfsr_stat(&lfs, "gello", &info) => 0;
|
||||||
|
assert(strcmp(info.name, "gello") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_REG);
|
||||||
|
assert(info.size == SIZE);
|
||||||
|
// via readdir
|
||||||
|
lfsr_dir_t dir;
|
||||||
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, ".") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, "..") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, "gello") == 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;
|
||||||
|
// via open
|
||||||
|
lfsr_file_t file_;
|
||||||
|
lfsr_file_open(&lfs, &file_, "gello", LFS_O_RDONLY) => 0;
|
||||||
|
uint32_t prng_ = 42+1;
|
||||||
|
for (lfs_off_t i = 0; i < SIZE; i += CHUNK) {
|
||||||
|
uint8_t wbuf[CHUNK];
|
||||||
|
for (lfs_size_t j = 0; j < CHUNK; j++) {
|
||||||
|
wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26);
|
||||||
|
}
|
||||||
|
uint8_t rbuf[CHUNK];
|
||||||
|
lfsr_file_read(&lfs, &file_, rbuf, CHUNK) => CHUNK;
|
||||||
|
assert(memcmp(wbuf, rbuf, CHUNK) == 0);
|
||||||
|
}
|
||||||
|
lfsr_file_close(&lfs, &file_) => 0;
|
||||||
|
|
||||||
|
// recieved sync broadcast?
|
||||||
|
lfsr_file_rewind(&lfs, &file___) => 0;
|
||||||
|
prng_ = 42+1;
|
||||||
|
for (lfs_off_t i = 0; i < SIZE; i += CHUNK) {
|
||||||
|
uint8_t wbuf[CHUNK];
|
||||||
|
for (lfs_size_t j = 0; j < CHUNK; j++) {
|
||||||
|
wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26);
|
||||||
|
}
|
||||||
|
uint8_t rbuf[CHUNK];
|
||||||
|
lfsr_file_read(&lfs, &file___, rbuf, CHUNK) => CHUNK;
|
||||||
|
assert(memcmp(wbuf, rbuf, CHUNK) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// now sync the first file, this should overwrite what is written
|
||||||
|
lfsr_file_sync(&lfs, &file) => 0;
|
||||||
|
|
||||||
|
// now it should show up
|
||||||
|
// via stat
|
||||||
|
lfsr_stat(&lfs, "gello", &info) => 0;
|
||||||
|
assert(strcmp(info.name, "gello") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_REG);
|
||||||
|
assert(info.size == SIZE);
|
||||||
|
// via readdir
|
||||||
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, ".") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, "..") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, "gello") == 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;
|
||||||
|
// via open
|
||||||
|
lfsr_file_open(&lfs, &file_, "gello", LFS_O_RDONLY) => 0;
|
||||||
|
prng_ = 42;
|
||||||
|
for (lfs_off_t i = 0; i < SIZE; i += CHUNK) {
|
||||||
|
uint8_t wbuf[CHUNK];
|
||||||
|
for (lfs_size_t j = 0; j < CHUNK; j++) {
|
||||||
|
wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26);
|
||||||
|
}
|
||||||
|
uint8_t rbuf[CHUNK];
|
||||||
|
lfsr_file_read(&lfs, &file_, rbuf, CHUNK) => CHUNK;
|
||||||
|
assert(memcmp(wbuf, rbuf, CHUNK) == 0);
|
||||||
|
}
|
||||||
|
lfsr_file_close(&lfs, &file_) => 0;
|
||||||
|
|
||||||
|
// recieved sync broadcast?
|
||||||
|
lfsr_file_rewind(&lfs, &file___) => 0;
|
||||||
|
prng_ = 42;
|
||||||
|
for (lfs_off_t i = 0; i < SIZE; i += CHUNK) {
|
||||||
|
uint8_t wbuf[CHUNK];
|
||||||
|
for (lfs_size_t j = 0; j < CHUNK; j++) {
|
||||||
|
wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26);
|
||||||
|
}
|
||||||
|
uint8_t rbuf[CHUNK];
|
||||||
|
lfsr_file_read(&lfs, &file___, rbuf, CHUNK) => CHUNK;
|
||||||
|
assert(memcmp(wbuf, rbuf, CHUNK) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// and close, this shouldn't change anything
|
||||||
|
//
|
||||||
|
// note we must sync to clear the desync flag
|
||||||
|
lfsr_file_close(&lfs, &file) => 0;
|
||||||
|
|
||||||
|
// via stat
|
||||||
|
lfsr_stat(&lfs, "gello", &info) => 0;
|
||||||
|
assert(strcmp(info.name, "gello") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_REG);
|
||||||
|
assert(info.size == SIZE);
|
||||||
|
// via readdir
|
||||||
|
lfsr_dir_open(&lfs, &dir, "/") => 0;
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, ".") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, "..") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
assert(strcmp(info.name, "gello") == 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;
|
||||||
|
// via open
|
||||||
|
lfsr_file_open(&lfs, &file_, "gello", LFS_O_RDONLY) => 0;
|
||||||
|
prng_ = 42;
|
||||||
|
for (lfs_off_t i = 0; i < SIZE; i += CHUNK) {
|
||||||
|
uint8_t wbuf[CHUNK];
|
||||||
|
for (lfs_size_t j = 0; j < CHUNK; j++) {
|
||||||
|
wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26);
|
||||||
|
}
|
||||||
|
uint8_t rbuf[CHUNK];
|
||||||
|
lfsr_file_read(&lfs, &file_, rbuf, CHUNK) => CHUNK;
|
||||||
|
assert(memcmp(wbuf, rbuf, CHUNK) == 0);
|
||||||
|
}
|
||||||
|
lfsr_file_close(&lfs, &file_) => 0;
|
||||||
|
|
||||||
|
// recieved sync broadcast?
|
||||||
|
lfsr_file_rewind(&lfs, &file___) => 0;
|
||||||
|
prng_ = 42;
|
||||||
|
for (lfs_off_t i = 0; i < SIZE; i += CHUNK) {
|
||||||
|
uint8_t wbuf[CHUNK];
|
||||||
|
for (lfs_size_t j = 0; j < CHUNK; j++) {
|
||||||
|
wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26);
|
||||||
|
}
|
||||||
|
uint8_t rbuf[CHUNK];
|
||||||
|
lfsr_file_read(&lfs, &file___, rbuf, CHUNK) => CHUNK;
|
||||||
|
assert(memcmp(wbuf, rbuf, CHUNK) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
lfsr_file_close(&lfs, &file___) => 0;
|
||||||
|
lfsr_unmount(&lfs) => 0;
|
||||||
|
'''
|
||||||
|
|||||||
Reference in New Issue
Block a user