Changed all dir tests to be reentrant
To help with this, added TEST_PL, which is set to true when powerloss testing. This way tests can check for stronger conditions (no EEXIST) when not powerloss testing. With TEST_PL, there's really no reason every test in t5_dirs shouldn't be reentrant, and this gives us a huge improvement of test coverage very cheaply. --- The increased test coverage caught a bug, which is that gstate wasn't being consumed properly when mtree uninlining. Humorously, this went unnoticed because the most common form of mtree uninlining, mdir splitting, ended up incorrectly consuming the gstate twice, which canceled itself out since the consume operation is basically just xor. Also added support for printing dstarts to dbglfs.py, to help debugging.
This commit is contained in:
@@ -5386,18 +5386,9 @@ static int lfsr_mdir_compact_(lfs_t *lfs, lfsr_mdir_t *mdir,
|
|||||||
// - mid = wl => only alloc if mdir is tired (wear-leveling)
|
// - mid = wl => only alloc if mdir is tired (wear-leveling)
|
||||||
// - otherwise => always alloc, use this mid (new mdir)
|
// - otherwise => always alloc, use this mid (new mdir)
|
||||||
|
|
||||||
// consume gstate on original rbyd, we need this even if we drop
|
|
||||||
// our mdir to avoid losing info
|
|
||||||
//
|
|
||||||
// if succesful, this should get immediately appended to our new commit
|
|
||||||
int err = lfsr_fs_consumegdelta(lfs, msource);
|
|
||||||
if (err) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
// first thing we need to do is read our current revision count
|
// first thing we need to do is read our current revision count
|
||||||
uint32_t rev;
|
uint32_t rev;
|
||||||
err = lfsr_bd_read(lfs, msource->rbyd.block, 0, sizeof(uint32_t),
|
int err = lfsr_bd_read(lfs, msource->rbyd.block, 0, sizeof(uint32_t),
|
||||||
&rev, sizeof(uint32_t));
|
&rev, sizeof(uint32_t));
|
||||||
if (err && err != LFS_ERR_CORRUPT) {
|
if (err && err != LFS_ERR_CORRUPT) {
|
||||||
return err;
|
return err;
|
||||||
@@ -5430,6 +5421,19 @@ static int lfsr_mdir_compact_(lfs_t *lfs, lfsr_mdir_t *mdir,
|
|||||||
rev = (err != LFS_ERR_CORRUPT ? lfs_fromle32_(&rev) : 0);
|
rev = (err != LFS_ERR_CORRUPT ? lfs_fromle32_(&rev) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// only consume gstate here during normal compacts
|
||||||
|
// TODO avoid duplicate conditions somehow?
|
||||||
|
if (mid == LFSR_MID_WL) {
|
||||||
|
// consume gstate on original rbyd, we need this even if we drop
|
||||||
|
// our mdir to avoid losing info
|
||||||
|
//
|
||||||
|
// if succesful, this should get immediately appended to our new commit
|
||||||
|
int err = lfsr_fs_consumegdelta(lfs, msource);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// swap our rbyds
|
// swap our rbyds
|
||||||
lfs_swap32(&mdir->rbyd.block, &mdir->redund_block);
|
lfs_swap32(&mdir->rbyd.block, &mdir->redund_block);
|
||||||
// update our revision count
|
// update our revision count
|
||||||
@@ -7509,6 +7513,11 @@ static int lfsr_fs_preparemutation(lfs_t *lfs) {
|
|||||||
LFS_DEBUG("Fixing grm (%"PRId32".%"PRId32")",
|
LFS_DEBUG("Fixing grm (%"PRId32".%"PRId32")",
|
||||||
lfs->grm_.mid,
|
lfs->grm_.mid,
|
||||||
lfs->grm_.rid);
|
lfs->grm_.rid);
|
||||||
|
|
||||||
|
// checkpoint the allocator in case fixing the grm causes mtree
|
||||||
|
// manipulation
|
||||||
|
lfs_alloc_ack(lfs);
|
||||||
|
|
||||||
int err = lfsr_fs_fixgrm(lfs);
|
int err = lfsr_fs_fixgrm(lfs);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
|
|||||||
@@ -478,6 +478,7 @@ extern size_t test_geometry_count;
|
|||||||
|
|
||||||
extern const test_powerloss_t *test_powerlosses;
|
extern const test_powerloss_t *test_powerlosses;
|
||||||
extern size_t test_powerloss_count;
|
extern size_t test_powerloss_count;
|
||||||
|
bool test_pl = false;
|
||||||
|
|
||||||
const test_id_t *test_ids = (const test_id_t[]) {
|
const test_id_t *test_ids = (const test_id_t[]) {
|
||||||
{NULL, NULL, 0, NULL, 0},
|
{NULL, NULL, 0, NULL, 0},
|
||||||
@@ -606,7 +607,6 @@ void test_trace(const char *fmt, ...) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// test prng
|
// test prng
|
||||||
uint32_t test_prng(uint32_t *state) {
|
uint32_t test_prng(uint32_t *state) {
|
||||||
// A simple xorshift32 generator, easily reproducible. Keep in mind
|
// A simple xorshift32 generator, easily reproducible. Keep in mind
|
||||||
@@ -771,6 +771,7 @@ static void case_forperm(
|
|||||||
|
|
||||||
// explicit powerloss cycles?
|
// explicit powerloss cycles?
|
||||||
if (cycles) {
|
if (cycles) {
|
||||||
|
test_pl = true;
|
||||||
cb(data, suite, case_, &(test_powerloss_t){
|
cb(data, suite, case_, &(test_powerloss_t){
|
||||||
.run=run_powerloss_cycles,
|
.run=run_powerloss_cycles,
|
||||||
.cycles=cycles,
|
.cycles=cycles,
|
||||||
@@ -778,8 +779,8 @@ static void case_forperm(
|
|||||||
} else {
|
} else {
|
||||||
for (size_t p = 0; p < test_powerloss_count; p++) {
|
for (size_t p = 0; p < test_powerloss_count; p++) {
|
||||||
// skip non-reentrant tests when powerloss testing
|
// skip non-reentrant tests when powerloss testing
|
||||||
if (test_powerlosses[p].run != run_powerloss_none
|
test_pl = test_powerlosses[p].run != run_powerloss_none;
|
||||||
&& !(case_->flags & TEST_REENTRANT)) {
|
if (test_pl && !(case_->flags & TEST_REENTRANT)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -820,6 +821,7 @@ static void case_forperm(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (cycles) {
|
if (cycles) {
|
||||||
|
test_pl = true;
|
||||||
cb(data, suite, case_, &(test_powerloss_t){
|
cb(data, suite, case_, &(test_powerloss_t){
|
||||||
.run=run_powerloss_cycles,
|
.run=run_powerloss_cycles,
|
||||||
.cycles=cycles,
|
.cycles=cycles,
|
||||||
@@ -827,8 +829,8 @@ static void case_forperm(
|
|||||||
} else {
|
} else {
|
||||||
for (size_t p = 0; p < test_powerloss_count; p++) {
|
for (size_t p = 0; p < test_powerloss_count; p++) {
|
||||||
// skip non-reentrant tests when powerloss testing
|
// skip non-reentrant tests when powerloss testing
|
||||||
if (test_powerlosses[p].run != run_powerloss_none
|
test_pl = test_powerlosses[p].run != run_powerloss_none;
|
||||||
&& !(case_->flags & TEST_REENTRANT)) {
|
if (test_pl && !(case_->flags & TEST_REENTRANT)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -69,6 +69,11 @@ struct test_suite {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// this is defined as true when powerloss-testing
|
||||||
|
extern bool test_pl;
|
||||||
|
|
||||||
|
#define TEST_PL test_pl
|
||||||
|
|
||||||
// deterministic prng for pseudo-randomness in testes
|
// deterministic prng for pseudo-randomness in testes
|
||||||
uint32_t test_prng(uint32_t *state);
|
uint32_t test_prng(uint32_t *state);
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -511,7 +511,8 @@ def main(disk, roots=None, *,
|
|||||||
btree.addr(), btree.rev, btree.weight))
|
btree.addr(), btree.rev, btree.weight))
|
||||||
|
|
||||||
# look up an id, while keeping track of the search path
|
# look up an id, while keeping track of the search path
|
||||||
def btree_lookup(bid, depth=None):
|
def btree_lookup(bid, *,
|
||||||
|
depth=None):
|
||||||
rbyd = btree
|
rbyd = btree
|
||||||
rid = bid
|
rid = bid
|
||||||
depth_ = 1
|
depth_ = 1
|
||||||
|
|||||||
+49
-25
@@ -396,7 +396,8 @@ class Rbyd:
|
|||||||
yield id, tag, w, j, d, data
|
yield id, tag, w, j, d, data
|
||||||
|
|
||||||
# btree lookup with this rbyd as the root
|
# btree lookup with this rbyd as the root
|
||||||
def btree_lookup(self, f, block_size, bid, depth=None):
|
def btree_lookup(self, f, block_size, bid, *,
|
||||||
|
depth=None):
|
||||||
rbyd = self
|
rbyd = self
|
||||||
rid = bid
|
rid = bid
|
||||||
depth_ = 1
|
depth_ = 1
|
||||||
@@ -558,13 +559,13 @@ class Rbyd:
|
|||||||
mtree = Rbyd.fetch(f, block_size, block, trunk)
|
mtree = Rbyd.fetch(f, block_size, block, trunk)
|
||||||
# corrupted?
|
# corrupted?
|
||||||
if not mtree:
|
if not mtree:
|
||||||
return False, 0, b'', -1, None, -1, 0, 0
|
return False, -1, None, -1, 0, 0
|
||||||
|
|
||||||
# lookup our name in the mtree
|
# lookup our name in the mtree
|
||||||
mid, tag_, w, data = mtree.btree_namelookup(
|
mid, tag_, w, data = mtree.btree_namelookup(
|
||||||
f, block_size, did, name)
|
f, block_size, did, name)
|
||||||
if tag_ != TAG_MDIR:
|
if tag_ != TAG_MDIR:
|
||||||
return False, 0, b'', -1, None, -1, 0, 0
|
return False, -1, None, -1, 0, 0
|
||||||
|
|
||||||
# fetch the mdir
|
# fetch the mdir
|
||||||
blocks = frommdir(data)
|
blocks = frommdir(data)
|
||||||
@@ -588,12 +589,32 @@ class Rbyd:
|
|||||||
return found, mid, mdir, rid, tag, w
|
return found, mid, mdir, rid, tag, w
|
||||||
|
|
||||||
# iterate through a directory assuming this is the mtree root
|
# iterate through a directory assuming this is the mtree root
|
||||||
def mtree_dir(self, f, block_size, did):
|
def mtree_dir(self, f, block_size, did, *,
|
||||||
|
all=False):
|
||||||
|
all_, all = all, __builtins__.all
|
||||||
|
|
||||||
# lookup the dstart
|
# lookup the dstart
|
||||||
found, mid, mdir, rid, tag, w = self.mtree_namelookup(
|
found, mid, mdir, rid, tag, w = self.mtree_namelookup(
|
||||||
f, block_size, did, b'')
|
f, block_size, did, b'')
|
||||||
# iterate through all files until the next dstart
|
# iterate through all files until the next dstart
|
||||||
while found:
|
while found:
|
||||||
|
# lookup each rid
|
||||||
|
done, rid, tag, w, j, d, data, _ = mdir.lookup(rid, TAG_NAME)
|
||||||
|
if done:
|
||||||
|
break
|
||||||
|
|
||||||
|
# parse out each name
|
||||||
|
did_, d_ = fromleb128(data)
|
||||||
|
name_ = data[d_:]
|
||||||
|
|
||||||
|
# end if we see another did
|
||||||
|
if did_ != did:
|
||||||
|
break
|
||||||
|
|
||||||
|
# skip dstarts unless all entries are requested
|
||||||
|
if tag != TAG_DSTART or all_:
|
||||||
|
yield name_, mid, mdir, rid, tag, w
|
||||||
|
|
||||||
rid += w
|
rid += w
|
||||||
if rid >= mdir.weight:
|
if rid >= mdir.weight:
|
||||||
rid -= mdir.weight
|
rid -= mdir.weight
|
||||||
@@ -603,17 +624,6 @@ class Rbyd:
|
|||||||
if not mdir:
|
if not mdir:
|
||||||
break
|
break
|
||||||
|
|
||||||
# lookup each rid
|
|
||||||
done, rid, tag, w, j, d, data, _ = mdir.lookup(rid, TAG_NAME)
|
|
||||||
if done or tag == TAG_DSTART:
|
|
||||||
break
|
|
||||||
|
|
||||||
# parse out each name
|
|
||||||
did_, d_ = fromleb128(data)
|
|
||||||
name_ = data[d_:]
|
|
||||||
|
|
||||||
yield did_, name_, mid, mdir, rid, tag, w
|
|
||||||
|
|
||||||
|
|
||||||
# read the superconfig
|
# read the superconfig
|
||||||
def superconfig(mroot):
|
def superconfig(mroot):
|
||||||
@@ -679,7 +689,15 @@ def grepr(tag, data):
|
|||||||
return 'gstate 0x%02x %d' % (tag, len(data))
|
return 'gstate 0x%02x %d' % (tag, len(data))
|
||||||
|
|
||||||
def frepr(mdir, rid, tag):
|
def frepr(mdir, rid, tag):
|
||||||
if tag == TAG_DIR:
|
if tag == TAG_DSTART:
|
||||||
|
# read the did
|
||||||
|
did = '?'
|
||||||
|
done, rid_, tag_, w_, j, d, data, _ = mdir.lookup(rid, TAG_DSTART)
|
||||||
|
if not done and rid_ == rid and tag_ == TAG_DSTART:
|
||||||
|
did, _ = fromleb128(data)
|
||||||
|
did = '0x%x' % did
|
||||||
|
return 'dstart %s' % did
|
||||||
|
elif tag == TAG_DIR:
|
||||||
# read the did
|
# read the did
|
||||||
did = '?'
|
did = '?'
|
||||||
done, rid_, tag_, w_, j, d, data, _ = mdir.lookup(rid, TAG_DID)
|
done, rid_, tag_, w_, j, d, data, _ = mdir.lookup(rid, TAG_DID)
|
||||||
@@ -815,8 +833,9 @@ def main(disk, mroots=None, *,
|
|||||||
def rec_f_width(did, depth):
|
def rec_f_width(did, depth):
|
||||||
depth_ = 0
|
depth_ = 0
|
||||||
width_ = 0
|
width_ = 0
|
||||||
for did, name, mid, mdir, rid, tag, w in mroot.mtree_dir(
|
for name, mid, mdir, rid, tag, w in mroot.mtree_dir(
|
||||||
f, block_size, did):
|
f, block_size, did,
|
||||||
|
all=args.get('all')):
|
||||||
width_ = max(width_, len(name))
|
width_ = max(width_, len(name))
|
||||||
# recurse?
|
# recurse?
|
||||||
if tag == TAG_DIR and depth > 1:
|
if tag == TAG_DIR and depth > 1:
|
||||||
@@ -928,14 +947,16 @@ def main(disk, mroots=None, *,
|
|||||||
# print gdeltas?
|
# print gdeltas?
|
||||||
if args.get('gdelta'):
|
if args.get('gdelta'):
|
||||||
for mid, mdir, j, d, data in gstate.gdelta[tag]:
|
for mid, mdir, j, d, data in gstate.gdelta[tag]:
|
||||||
print('{%s}: %*s %-22s %s' % (
|
print('%s{%s}: %*s %-22s %s%s' % (
|
||||||
|
'\x1b[90m' if color else '',
|
||||||
','.join('%04x' % block
|
','.join('%04x' % block
|
||||||
for block in it.chain([mdir.block],
|
for block in it.chain([mdir.block],
|
||||||
mdir.redund_blocks)),
|
mdir.redund_blocks)),
|
||||||
w_width, mid,
|
w_width, mid,
|
||||||
tagrepr(tag, 0, len(data)),
|
tagrepr(tag, 0, len(data)),
|
||||||
next(xxd(data, 8), '')
|
next(xxd(data, 8), '')
|
||||||
if not args.get('no_truncate') else ''))
|
if not args.get('no_truncate') else '',
|
||||||
|
'\x1b[m' if color else ''))
|
||||||
|
|
||||||
# show in-device representation
|
# show in-device representation
|
||||||
if args.get('device'):
|
if args.get('device'):
|
||||||
@@ -976,9 +997,11 @@ def main(disk, mroots=None, *,
|
|||||||
def rec_dir(did, depth, prefixes=('', '', '', '')):
|
def rec_dir(did, depth, prefixes=('', '', '', '')):
|
||||||
nonlocal pmid
|
nonlocal pmid
|
||||||
# collect all entries first so we know when the dir ends
|
# collect all entries first so we know when the dir ends
|
||||||
dir = list(mroot.mtree_dir(f, block_size, did))
|
dir = list(mroot.mtree_dir(f, block_size, did,
|
||||||
for i, (did, name, mid, mdir, rid, tag, w) in enumerate(dir):
|
all=args.get('all')))
|
||||||
print('%12s %*s %-*s %s' % (
|
for i, (name, mid, mdir, rid, tag, w) in enumerate(dir):
|
||||||
|
print('%s%12s %*s %-*s %s%s' % (
|
||||||
|
'\x1b[90m' if color and tag == TAG_DSTART else '',
|
||||||
'{%s}:' % ','.join('%04x' % block
|
'{%s}:' % ','.join('%04x' % block
|
||||||
for block in it.chain([mdir.block],
|
for block in it.chain([mdir.block],
|
||||||
mdir.redund_blocks))
|
mdir.redund_blocks))
|
||||||
@@ -989,7 +1012,8 @@ def main(disk, mroots=None, *,
|
|||||||
f_width, '%s%s' % (
|
f_width, '%s%s' % (
|
||||||
prefixes[0+(i==len(dir)-1)],
|
prefixes[0+(i==len(dir)-1)],
|
||||||
name.decode('utf8')),
|
name.decode('utf8')),
|
||||||
frepr(mdir, rid, tag)))
|
frepr(mdir, rid, tag),
|
||||||
|
'\x1b[m' if color and tag == TAG_DSTART else ''))
|
||||||
pmid = mid
|
pmid = mid
|
||||||
|
|
||||||
# print attrs associated with this file?
|
# print attrs associated with this file?
|
||||||
@@ -1107,7 +1131,7 @@ if __name__ == "__main__":
|
|||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-a', '--all',
|
'-a', '--all',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help="Show all files including grmed files.")
|
help="Show all files including dstarts and grmed files.")
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-r', '--raw',
|
'-r', '--raw',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
|
|||||||
+6
-3
@@ -488,7 +488,8 @@ class Rbyd:
|
|||||||
return tree, t_depth
|
return tree, t_depth
|
||||||
|
|
||||||
# btree lookup with this rbyd as the root
|
# btree lookup with this rbyd as the root
|
||||||
def btree_lookup(self, f, block_size, bid, depth=None):
|
def btree_lookup(self, f, block_size, bid, *,
|
||||||
|
depth=None):
|
||||||
rbyd = self
|
rbyd = self
|
||||||
rid = bid
|
rid = bid
|
||||||
depth_ = 1
|
depth_ = 1
|
||||||
@@ -543,7 +544,8 @@ class Rbyd:
|
|||||||
return not tags, bid + (rid_-rid), w, rbyd, rid_, tags, path
|
return not tags, bid + (rid_-rid), w, rbyd, rid_, tags, path
|
||||||
|
|
||||||
# btree rbyd-tree generation for debugging
|
# btree rbyd-tree generation for debugging
|
||||||
def btree_tree(self, f, block_size, depth=None, *,
|
def btree_tree(self, f, block_size, *,
|
||||||
|
depth=None,
|
||||||
inner=False):
|
inner=False):
|
||||||
# find the max depth of each layer to nicely align trees
|
# find the max depth of each layer to nicely align trees
|
||||||
bdepths = {}
|
bdepths = {}
|
||||||
@@ -671,7 +673,8 @@ class Rbyd:
|
|||||||
return tree, max((branch.d+1 for branch in tree), default=0)
|
return tree, max((branch.d+1 for branch in tree), default=0)
|
||||||
|
|
||||||
# btree B-tree generation for debugging
|
# btree B-tree generation for debugging
|
||||||
def btree_btree(self, f, block_size, depth=None, *,
|
def btree_btree(self, f, block_size, *,
|
||||||
|
depth=None,
|
||||||
inner=False):
|
inner=False):
|
||||||
# find all branches
|
# find all branches
|
||||||
tree = set()
|
tree = set()
|
||||||
|
|||||||
+182
-131
@@ -2,13 +2,19 @@
|
|||||||
|
|
||||||
[cases.t5_dirs_mkdir]
|
[cases.t5_dirs_mkdir]
|
||||||
defines.REMOUNT = [false, true]
|
defines.REMOUNT = [false, true]
|
||||||
|
reentrant = true
|
||||||
code = '''
|
code = '''
|
||||||
|
// format once per test
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, cfg) => 0;
|
int err = lfsr_mount(&lfs, cfg);
|
||||||
lfsr_mount(&lfs, cfg) => 0;
|
if (err) {
|
||||||
|
lfsr_format(&lfs, cfg) => 0;
|
||||||
|
lfsr_mount(&lfs, cfg) => 0;
|
||||||
|
}
|
||||||
|
|
||||||
// make a directory
|
// make a directory
|
||||||
lfsr_mkdir(&lfs, "ardvark") => 0;
|
err = lfsr_mkdir(&lfs, "ardvark");
|
||||||
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
|
||||||
// remount?
|
// remount?
|
||||||
if (REMOUNT) {
|
if (REMOUNT) {
|
||||||
@@ -44,13 +50,19 @@ code = '''
|
|||||||
# test that noent errors work
|
# test that noent errors work
|
||||||
[cases.t5_dirs_noent]
|
[cases.t5_dirs_noent]
|
||||||
defines.REMOUNT = [false, true]
|
defines.REMOUNT = [false, true]
|
||||||
|
reentrant = true
|
||||||
code = '''
|
code = '''
|
||||||
|
// format once per test
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, cfg) => 0;
|
int err = lfsr_mount(&lfs, cfg);
|
||||||
lfsr_mount(&lfs, cfg) => 0;
|
if (err) {
|
||||||
|
lfsr_format(&lfs, cfg) => 0;
|
||||||
|
lfsr_mount(&lfs, cfg) => 0;
|
||||||
|
}
|
||||||
|
|
||||||
// make a directory
|
// make a directory
|
||||||
lfsr_mkdir(&lfs, "ardvark") => 0;
|
err = lfsr_mkdir(&lfs, "ardvark");
|
||||||
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
|
||||||
// try to read a nonsense path
|
// try to read a nonsense path
|
||||||
struct lfs_info info;
|
struct lfs_info info;
|
||||||
@@ -90,13 +102,19 @@ code = '''
|
|||||||
# test that creating the same directory twice errors
|
# test that creating the same directory twice errors
|
||||||
[cases.t5_dirs_mkdir_exists]
|
[cases.t5_dirs_mkdir_exists]
|
||||||
defines.REMOUNT = [false, true]
|
defines.REMOUNT = [false, true]
|
||||||
|
reentrant = true
|
||||||
code = '''
|
code = '''
|
||||||
|
// format once per test
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, cfg) => 0;
|
int err = lfsr_mount(&lfs, cfg);
|
||||||
lfsr_mount(&lfs, cfg) => 0;
|
if (err) {
|
||||||
|
lfsr_format(&lfs, cfg) => 0;
|
||||||
|
lfsr_mount(&lfs, cfg) => 0;
|
||||||
|
}
|
||||||
|
|
||||||
// make a directory
|
// make a directory
|
||||||
lfsr_mkdir(&lfs, "ardvark") => 0;
|
err = lfsr_mkdir(&lfs, "ardvark");
|
||||||
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
|
||||||
// make the same directory, should error
|
// make the same directory, should error
|
||||||
lfsr_mkdir(&lfs, "ardvark") => LFS_ERR_EXIST;
|
lfsr_mkdir(&lfs, "ardvark") => LFS_ERR_EXIST;
|
||||||
@@ -134,13 +152,19 @@ code = '''
|
|||||||
# test that creating a directory with an invalid path errors
|
# test that creating a directory with an invalid path errors
|
||||||
[cases.t5_dirs_mkdir_noent]
|
[cases.t5_dirs_mkdir_noent]
|
||||||
defines.REMOUNT = [false, true]
|
defines.REMOUNT = [false, true]
|
||||||
|
reentrant = true
|
||||||
code = '''
|
code = '''
|
||||||
|
// format once per test
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, cfg) => 0;
|
int err = lfsr_mount(&lfs, cfg);
|
||||||
lfsr_mount(&lfs, cfg) => 0;
|
if (err) {
|
||||||
|
lfsr_format(&lfs, cfg) => 0;
|
||||||
|
lfsr_mount(&lfs, cfg) => 0;
|
||||||
|
}
|
||||||
|
|
||||||
// make a directory
|
// make a directory
|
||||||
lfsr_mkdir(&lfs, "ardvark") => 0;
|
err = lfsr_mkdir(&lfs, "ardvark");
|
||||||
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
|
||||||
// make a nonsense directory, should error
|
// make a nonsense directory, should error
|
||||||
lfsr_mkdir(&lfs, "no/hmm") => LFS_ERR_NOENT;
|
lfsr_mkdir(&lfs, "no/hmm") => LFS_ERR_NOENT;
|
||||||
@@ -180,15 +204,23 @@ code = '''
|
|||||||
|
|
||||||
[cases.t5_dirs_mkdir_siblings]
|
[cases.t5_dirs_mkdir_siblings]
|
||||||
defines.REMOUNT = [false, true]
|
defines.REMOUNT = [false, true]
|
||||||
|
reentrant = true
|
||||||
code = '''
|
code = '''
|
||||||
|
// format once per test
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, cfg) => 0;
|
int err = lfsr_mount(&lfs, cfg);
|
||||||
lfsr_mount(&lfs, cfg) => 0;
|
if (err) {
|
||||||
|
lfsr_format(&lfs, cfg) => 0;
|
||||||
|
lfsr_mount(&lfs, cfg) => 0;
|
||||||
|
}
|
||||||
|
|
||||||
// make some directories
|
// make some directories
|
||||||
lfsr_mkdir(&lfs, "ardvark") => 0;
|
err = lfsr_mkdir(&lfs, "ardvark");
|
||||||
lfsr_mkdir(&lfs, "batman") => 0;
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
lfsr_mkdir(&lfs, "cantaloupe") => 0;
|
err = lfsr_mkdir(&lfs, "batman");
|
||||||
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
err = lfsr_mkdir(&lfs, "cantaloupe");
|
||||||
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
|
||||||
// remount?
|
// remount?
|
||||||
if (REMOUNT) {
|
if (REMOUNT) {
|
||||||
@@ -234,15 +266,23 @@ code = '''
|
|||||||
|
|
||||||
[cases.t5_dirs_mkdir_children]
|
[cases.t5_dirs_mkdir_children]
|
||||||
defines.REMOUNT = [false, true]
|
defines.REMOUNT = [false, true]
|
||||||
|
reentrant = true
|
||||||
code = '''
|
code = '''
|
||||||
|
// format once per test
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, cfg) => 0;
|
int err = lfsr_mount(&lfs, cfg);
|
||||||
lfsr_mount(&lfs, cfg) => 0;
|
if (err) {
|
||||||
|
lfsr_format(&lfs, cfg) => 0;
|
||||||
|
lfsr_mount(&lfs, cfg) => 0;
|
||||||
|
}
|
||||||
|
|
||||||
// make some directories
|
// make some directories
|
||||||
lfsr_mkdir(&lfs, "ardvark") => 0;
|
err = lfsr_mkdir(&lfs, "ardvark");
|
||||||
lfsr_mkdir(&lfs, "ardvark/batman") => 0;
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
lfsr_mkdir(&lfs, "ardvark/batman/cantaloupe") => 0;
|
err = lfsr_mkdir(&lfs, "ardvark/batman");
|
||||||
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
err = lfsr_mkdir(&lfs, "ardvark/batman/cantaloupe");
|
||||||
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
|
||||||
// remount?
|
// remount?
|
||||||
if (REMOUNT) {
|
if (REMOUNT) {
|
||||||
@@ -307,16 +347,22 @@ code = '''
|
|||||||
[cases.t5_dirs_mkdir_many]
|
[cases.t5_dirs_mkdir_many]
|
||||||
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
|
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
|
||||||
defines.REMOUNT = [false, true]
|
defines.REMOUNT = [false, true]
|
||||||
|
reentrant = true
|
||||||
code = '''
|
code = '''
|
||||||
|
// format once per test
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, cfg) => 0;
|
int err = lfsr_mount(&lfs, cfg);
|
||||||
lfsr_mount(&lfs, cfg) => 0;
|
if (err) {
|
||||||
|
lfsr_format(&lfs, cfg) => 0;
|
||||||
|
lfsr_mount(&lfs, cfg) => 0;
|
||||||
|
}
|
||||||
|
|
||||||
// make this many directories
|
// make this many directories
|
||||||
for (lfs_size_t i = 0; i < N; i++) {
|
for (lfs_size_t i = 0; i < N; i++) {
|
||||||
char name[256];
|
char name[256];
|
||||||
sprintf(name, "dir%04d", i);
|
sprintf(name, "dir%04d", i);
|
||||||
lfsr_mkdir(&lfs, name) => 0;
|
err = lfsr_mkdir(&lfs, name);
|
||||||
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
|
||||||
// remount?
|
// remount?
|
||||||
if (REMOUNT) {
|
if (REMOUNT) {
|
||||||
@@ -359,23 +405,30 @@ code = '''
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
[cases.t5_dirs_mkdir_many_2layers]
|
[cases.t5_dirs_mkdir_many_2layers]
|
||||||
defines.N = [1, 2, 4, 8, 16, 32]
|
defines.N = [1, 2, 4, 8, 16]
|
||||||
defines.REMOUNT = [false, true]
|
defines.REMOUNT = [false, true]
|
||||||
|
reentrant = true
|
||||||
code = '''
|
code = '''
|
||||||
|
// format once per test
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, cfg) => 0;
|
int err = lfsr_mount(&lfs, cfg);
|
||||||
lfsr_mount(&lfs, cfg) => 0;
|
if (err) {
|
||||||
|
lfsr_format(&lfs, cfg) => 0;
|
||||||
|
lfsr_mount(&lfs, cfg) => 0;
|
||||||
|
}
|
||||||
|
|
||||||
// make this many directories
|
// make this many directories
|
||||||
for (lfs_size_t i = 0; i < N; i++) {
|
for (lfs_size_t i = 0; i < N; i++) {
|
||||||
char name[256];
|
char name[256];
|
||||||
sprintf(name, "dir%04d", i);
|
sprintf(name, "dir%04d", i);
|
||||||
lfsr_mkdir(&lfs, name) => 0;
|
err = lfsr_mkdir(&lfs, name);
|
||||||
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
|
||||||
// containing this many directories
|
// containing this many directories
|
||||||
for (lfs_size_t j = 0; j < N; j++) {
|
for (lfs_size_t j = 0; j < N; j++) {
|
||||||
sprintf(name, "dir%04d/child%04d", i, j);
|
sprintf(name, "dir%04d/child%04d", i, j);
|
||||||
lfsr_mkdir(&lfs, name) => 0;
|
err = lfsr_mkdir(&lfs, name);
|
||||||
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
|
||||||
// remount?
|
// remount?
|
||||||
if (REMOUNT) {
|
if (REMOUNT) {
|
||||||
@@ -449,28 +502,36 @@ code = '''
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
[cases.t5_dirs_mkdir_many_3layers]
|
[cases.t5_dirs_mkdir_many_3layers]
|
||||||
defines.N = [1, 2, 4, 8]
|
defines.N = [1, 2, 4]
|
||||||
defines.REMOUNT = [false, true]
|
defines.REMOUNT = [false, true]
|
||||||
|
reentrant = true
|
||||||
code = '''
|
code = '''
|
||||||
|
// format once per test
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, cfg) => 0;
|
int err = lfsr_mount(&lfs, cfg);
|
||||||
lfsr_mount(&lfs, cfg) => 0;
|
if (err) {
|
||||||
|
lfsr_format(&lfs, cfg) => 0;
|
||||||
|
lfsr_mount(&lfs, cfg) => 0;
|
||||||
|
}
|
||||||
|
|
||||||
// make this many directories
|
// make this many directories
|
||||||
for (lfs_size_t i = 0; i < N; i++) {
|
for (lfs_size_t i = 0; i < N; i++) {
|
||||||
char name[256];
|
char name[256];
|
||||||
sprintf(name, "dir%04d", i);
|
sprintf(name, "dir%04d", i);
|
||||||
lfsr_mkdir(&lfs, name) => 0;
|
err = lfsr_mkdir(&lfs, name);
|
||||||
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
|
||||||
// containing this many directories
|
// containing this many directories
|
||||||
for (lfs_size_t j = 0; j < N; j++) {
|
for (lfs_size_t j = 0; j < N; j++) {
|
||||||
sprintf(name, "dir%04d/child%04d", i, j);
|
sprintf(name, "dir%04d/child%04d", i, j);
|
||||||
lfsr_mkdir(&lfs, name) => 0;
|
err = lfsr_mkdir(&lfs, name);
|
||||||
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
|
||||||
// containing this many directories
|
// containing this many directories
|
||||||
for (lfs_size_t k = 0; k < N; k++) {
|
for (lfs_size_t k = 0; k < N; k++) {
|
||||||
sprintf(name, "dir%04d/child%04d/grandchild%04d", i, j, k);
|
sprintf(name, "dir%04d/child%04d/grandchild%04d", i, j, k);
|
||||||
lfsr_mkdir(&lfs, name) => 0;
|
err = lfsr_mkdir(&lfs, name);
|
||||||
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
|
||||||
// remount?
|
// remount?
|
||||||
if (REMOUNT) {
|
if (REMOUNT) {
|
||||||
@@ -577,17 +638,23 @@ code = '''
|
|||||||
[cases.t5_dirs_mkdir_many_linkedlist]
|
[cases.t5_dirs_mkdir_many_linkedlist]
|
||||||
defines.N = [1, 2, 4, 8, 16, 32, 64]
|
defines.N = [1, 2, 4, 8, 16, 32, 64]
|
||||||
defines.REMOUNT = [false, true]
|
defines.REMOUNT = [false, true]
|
||||||
|
reentrant = true
|
||||||
code = '''
|
code = '''
|
||||||
|
// format once per test
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, cfg) => 0;
|
int err = lfsr_mount(&lfs, cfg);
|
||||||
lfsr_mount(&lfs, cfg) => 0;
|
if (err) {
|
||||||
|
lfsr_format(&lfs, cfg) => 0;
|
||||||
|
lfsr_mount(&lfs, cfg) => 0;
|
||||||
|
}
|
||||||
|
|
||||||
// create this many directory in a sort of linked-list by nesting
|
// create this many directory in a sort of linked-list by nesting
|
||||||
char name[4096];
|
char name[4096];
|
||||||
memset(name, 0, sizeof(name));
|
memset(name, 0, sizeof(name));
|
||||||
for (lfs_size_t i = 0; i < N; i++) {
|
for (lfs_size_t i = 0; i < N; i++) {
|
||||||
sprintf(&name[strlen(name)], "/dir%04d", i);
|
sprintf(&name[strlen(name)], "/dir%04d", i);
|
||||||
lfsr_mkdir(&lfs, name) => 0;
|
err = lfsr_mkdir(&lfs, name);
|
||||||
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
|
||||||
// remount?
|
// remount?
|
||||||
if (REMOUNT) {
|
if (REMOUNT) {
|
||||||
@@ -738,10 +805,15 @@ code = '''
|
|||||||
# test that did collisions don't cause issues
|
# test that did collisions don't cause issues
|
||||||
[cases.t5_dirs_did_collisions]
|
[cases.t5_dirs_did_collisions]
|
||||||
defines.REMOUNT = [false, true]
|
defines.REMOUNT = [false, true]
|
||||||
|
reentrant = true
|
||||||
code = '''
|
code = '''
|
||||||
|
// format once per test
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, cfg) => 0;
|
int err = lfsr_mount(&lfs, cfg);
|
||||||
lfsr_mount(&lfs, cfg) => 0;
|
if (err) {
|
||||||
|
lfsr_format(&lfs, cfg) => 0;
|
||||||
|
lfsr_mount(&lfs, cfg) => 0;
|
||||||
|
}
|
||||||
|
|
||||||
assert(lfs_crc32c(0, "a_SNmwMTHH", 10) == 0x12345678);
|
assert(lfs_crc32c(0, "a_SNmwMTHH", 10) == 0x12345678);
|
||||||
assert(lfs_crc32c(0, "b_skvjpWJH", 10) == 0x12345678);
|
assert(lfs_crc32c(0, "b_skvjpWJH", 10) == 0x12345678);
|
||||||
@@ -751,12 +823,18 @@ code = '''
|
|||||||
assert(lfs_crc32c(0, "f_lUoVuhJH", 10) == 0x12345678);
|
assert(lfs_crc32c(0, "f_lUoVuhJH", 10) == 0x12345678);
|
||||||
|
|
||||||
// make directories
|
// make directories
|
||||||
lfsr_mkdir(&lfs, "a_SNmwMTHH") => 0;
|
err = lfsr_mkdir(&lfs, "a_SNmwMTHH");
|
||||||
lfsr_mkdir(&lfs, "b_skvjpWJH") => 0;
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
lfsr_mkdir(&lfs, "c_OnOQhVPH") => 0;
|
err = lfsr_mkdir(&lfs, "b_skvjpWJH");
|
||||||
lfsr_mkdir(&lfs, "d_puMpPjRH") => 0;
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
lfsr_mkdir(&lfs, "e_LptKHkHH") => 0;
|
err = lfsr_mkdir(&lfs, "c_OnOQhVPH");
|
||||||
lfsr_mkdir(&lfs, "f_lUoVuhJH") => 0;
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
err = lfsr_mkdir(&lfs, "d_puMpPjRH");
|
||||||
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
err = lfsr_mkdir(&lfs, "e_LptKHkHH");
|
||||||
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
err = lfsr_mkdir(&lfs, "f_lUoVuhJH");
|
||||||
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
|
||||||
// remount?
|
// remount?
|
||||||
if (REMOUNT) {
|
if (REMOUNT) {
|
||||||
@@ -821,10 +899,15 @@ code = '''
|
|||||||
# these will also collide with the root
|
# these will also collide with the root
|
||||||
[cases.t5_dirs_did_zero]
|
[cases.t5_dirs_did_zero]
|
||||||
defines.REMOUNT = [false, true]
|
defines.REMOUNT = [false, true]
|
||||||
|
reentrant = true
|
||||||
code = '''
|
code = '''
|
||||||
|
// format once per test
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, cfg) => 0;
|
int err = lfsr_mount(&lfs, cfg);
|
||||||
lfsr_mount(&lfs, cfg) => 0;
|
if (err) {
|
||||||
|
lfsr_format(&lfs, cfg) => 0;
|
||||||
|
lfsr_mount(&lfs, cfg) => 0;
|
||||||
|
}
|
||||||
|
|
||||||
assert(lfs_crc32c(0, "a_IplRNrPH", 10) == 0x00000000);
|
assert(lfs_crc32c(0, "a_IplRNrPH", 10) == 0x00000000);
|
||||||
assert(lfs_crc32c(0, "b_iUwOsqRH", 10) == 0x00000000);
|
assert(lfs_crc32c(0, "b_iUwOsqRH", 10) == 0x00000000);
|
||||||
@@ -833,21 +916,19 @@ code = '''
|
|||||||
assert(lfs_crc32c(0, "e_VNunKMPH", 10) == 0x00000000);
|
assert(lfs_crc32c(0, "e_VNunKMPH", 10) == 0x00000000);
|
||||||
assert(lfs_crc32c(0, "f_vknsvNRH", 10) == 0x00000000);
|
assert(lfs_crc32c(0, "f_vknsvNRH", 10) == 0x00000000);
|
||||||
|
|
||||||
// remount?
|
|
||||||
if (REMOUNT) {
|
|
||||||
lfsr_unmount(&lfs) => 0;
|
|
||||||
lfsr_mount(&lfs, cfg) => 0;
|
|
||||||
// grm should be zero here
|
|
||||||
assert(lfs.grm[0] == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// make directories
|
// make directories
|
||||||
lfsr_mkdir(&lfs, "a_IplRNrPH") => 0;
|
err = lfsr_mkdir(&lfs, "a_IplRNrPH");
|
||||||
lfsr_mkdir(&lfs, "b_iUwOsqRH") => 0;
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
lfsr_mkdir(&lfs, "c_UPNtkpHH") => 0;
|
err = lfsr_mkdir(&lfs, "b_iUwOsqRH");
|
||||||
lfsr_mkdir(&lfs, "d_jKLUSLJH") => 0;
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
lfsr_mkdir(&lfs, "e_VNunKMPH") => 0;
|
err = lfsr_mkdir(&lfs, "c_UPNtkpHH");
|
||||||
lfsr_mkdir(&lfs, "f_vknsvNRH") => 0;
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
err = lfsr_mkdir(&lfs, "d_jKLUSLJH");
|
||||||
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
err = lfsr_mkdir(&lfs, "e_VNunKMPH");
|
||||||
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
err = lfsr_mkdir(&lfs, "f_vknsvNRH");
|
||||||
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
|
||||||
// remount?
|
// remount?
|
||||||
if (REMOUNT) {
|
if (REMOUNT) {
|
||||||
@@ -914,10 +995,15 @@ code = '''
|
|||||||
# note this is true even if you truncate
|
# note this is true even if you truncate
|
||||||
[cases.t5_dirs_did_ones]
|
[cases.t5_dirs_did_ones]
|
||||||
defines.REMOUNT = [false, true]
|
defines.REMOUNT = [false, true]
|
||||||
|
reentrant = true
|
||||||
code = '''
|
code = '''
|
||||||
|
// format once per test
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, cfg) => 0;
|
int err = lfsr_mount(&lfs, cfg);
|
||||||
lfsr_mount(&lfs, cfg) => 0;
|
if (err) {
|
||||||
|
lfsr_format(&lfs, cfg) => 0;
|
||||||
|
lfsr_mount(&lfs, cfg) => 0;
|
||||||
|
}
|
||||||
|
|
||||||
assert(lfs_crc32c(0, "a_iomlVKPH", 10) == 0xffffffff);
|
assert(lfs_crc32c(0, "a_iomlVKPH", 10) == 0xffffffff);
|
||||||
assert(lfs_crc32c(0, "b_IJvqkHRH", 10) == 0xffffffff);
|
assert(lfs_crc32c(0, "b_IJvqkHRH", 10) == 0xffffffff);
|
||||||
@@ -927,12 +1013,18 @@ code = '''
|
|||||||
assert(lfs_crc32c(0, "f_VtoMnwRH", 10) == 0xffffffff);
|
assert(lfs_crc32c(0, "f_VtoMnwRH", 10) == 0xffffffff);
|
||||||
|
|
||||||
// make directories
|
// make directories
|
||||||
lfsr_mkdir(&lfs, "a_iomlVKPH") => 0;
|
err = lfsr_mkdir(&lfs, "a_iomlVKPH");
|
||||||
lfsr_mkdir(&lfs, "b_IJvqkHRH") => 0;
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
lfsr_mkdir(&lfs, "c_uOOJsIHH") => 0;
|
err = lfsr_mkdir(&lfs, "b_IJvqkHRH");
|
||||||
lfsr_mkdir(&lfs, "d_JTMkKuJH") => 0;
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
lfsr_mkdir(&lfs, "e_vQtPStPH") => 0;
|
err = lfsr_mkdir(&lfs, "c_uOOJsIHH");
|
||||||
lfsr_mkdir(&lfs, "f_VtoMnwRH") => 0;
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
err = lfsr_mkdir(&lfs, "d_JTMkKuJH");
|
||||||
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
err = lfsr_mkdir(&lfs, "e_vQtPStPH");
|
||||||
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
err = lfsr_mkdir(&lfs, "f_VtoMnwRH");
|
||||||
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
|
||||||
// remount?
|
// remount?
|
||||||
if (REMOUNT) {
|
if (REMOUNT) {
|
||||||
@@ -999,10 +1091,15 @@ code = '''
|
|||||||
# issues
|
# issues
|
||||||
[cases.t5_dirs_did_leb128_boundaries]
|
[cases.t5_dirs_did_leb128_boundaries]
|
||||||
defines.REMOUNT = [false, true]
|
defines.REMOUNT = [false, true]
|
||||||
|
reentrant = true
|
||||||
code = '''
|
code = '''
|
||||||
|
// format once per test
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, cfg) => 0;
|
int err = lfsr_mount(&lfs, cfg);
|
||||||
lfsr_mount(&lfs, cfg) => 0;
|
if (err) {
|
||||||
|
lfsr_format(&lfs, cfg) => 0;
|
||||||
|
lfsr_mount(&lfs, cfg) => 0;
|
||||||
|
}
|
||||||
|
|
||||||
assert(lfs_crc32c(0, "a_IOtUptRH", 10) == 0x0000007f);
|
assert(lfs_crc32c(0, "a_IOtUptRH", 10) == 0x0000007f);
|
||||||
assert(lfs_crc32c(0, "b_nquQsKHH", 10) == 0x00000080);
|
assert(lfs_crc32c(0, "b_nquQsKHH", 10) == 0x00000080);
|
||||||
@@ -1012,12 +1109,18 @@ code = '''
|
|||||||
assert(lfs_crc32c(0, "f_pNtQTPJH", 10) == 0x00004001);
|
assert(lfs_crc32c(0, "f_pNtQTPJH", 10) == 0x00004001);
|
||||||
|
|
||||||
// make directories
|
// make directories
|
||||||
lfsr_mkdir(&lfs, "a_IOtUptRH") => 0;
|
err = lfsr_mkdir(&lfs, "a_IOtUptRH");
|
||||||
lfsr_mkdir(&lfs, "b_nquQsKHH") => 0;
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
lfsr_mkdir(&lfs, "c_vwQtKjHH") => 0;
|
err = lfsr_mkdir(&lfs, "b_nquQsKHH");
|
||||||
lfsr_mkdir(&lfs, "d_sVrvrWHH") => 0;
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
lfsr_mkdir(&lfs, "e_thrRIsRH") => 0;
|
err = lfsr_mkdir(&lfs, "c_vwQtKjHH");
|
||||||
lfsr_mkdir(&lfs, "f_pNtQTPJH") => 0;
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
err = lfsr_mkdir(&lfs, "d_sVrvrWHH");
|
||||||
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
err = lfsr_mkdir(&lfs, "e_thrRIsRH");
|
||||||
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
err = lfsr_mkdir(&lfs, "f_pNtQTPJH");
|
||||||
|
assert(!err || (TEST_PL && err == LFS_ERR_EXIST));
|
||||||
|
|
||||||
// remount?
|
// remount?
|
||||||
if (REMOUNT) {
|
if (REMOUNT) {
|
||||||
@@ -1079,58 +1182,6 @@ code = '''
|
|||||||
lfsr_unmount(&lfs) => 0;
|
lfsr_unmount(&lfs) => 0;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
[cases.t5_dirs_mkdir_many_pl]
|
|
||||||
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
|
|
||||||
reentrant = true
|
|
||||||
code = '''
|
|
||||||
// format once per test
|
|
||||||
lfs_t lfs;
|
|
||||||
int err = lfsr_mount(&lfs, cfg);
|
|
||||||
if (err) {
|
|
||||||
lfsr_format(&lfs, cfg) => 0;
|
|
||||||
lfsr_mount(&lfs, cfg) => 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// make this many directories
|
|
||||||
for (lfs_size_t i = 0; i < N; i++) {
|
|
||||||
char name[256];
|
|
||||||
sprintf(name, "dir%04d", i);
|
|
||||||
int err = lfsr_mkdir(&lfs, name);
|
|
||||||
assert(!err || err == LFS_ERR_EXIST);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check that our mkdir worked
|
|
||||||
for (lfs_size_t i = 0; i < N; i++) {
|
|
||||||
char name[256];
|
|
||||||
sprintf(name, "dir%04d", i);
|
|
||||||
struct lfs_info info;
|
|
||||||
lfsr_stat(&lfs, name, &info) => 0;
|
|
||||||
assert(strcmp(info.name, name) == 0);
|
|
||||||
assert(info.type == LFS_TYPE_DIR);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
||||||
assert(strcmp(info.name, "..") == 0);
|
|
||||||
assert(info.type == LFS_TYPE_DIR);
|
|
||||||
for (lfs_size_t i = 0; i < N; i++) {
|
|
||||||
char name[256];
|
|
||||||
sprintf(name, "dir%04d", i);
|
|
||||||
lfsr_dir_read(&lfs, &dir, &info) => 0;
|
|
||||||
assert(strcmp(info.name, name) == 0);
|
|
||||||
assert(info.type == LFS_TYPE_DIR);
|
|
||||||
}
|
|
||||||
lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
|
|
||||||
|
|
||||||
lfsr_unmount(&lfs) => 0;
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[cases.test_dirs_root]
|
#[cases.test_dirs_root]
|
||||||
|
|||||||
Reference in New Issue
Block a user