Generated v2 prefixes
This commit is contained in:
@@ -374,6 +374,29 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
CFLAGS="$CFLAGS -DLFS2_NO_INTRINSICS" make test
|
CFLAGS="$CFLAGS -DLFS2_NO_INTRINSICS" make test
|
||||||
|
|
||||||
|
# run with all trace options enabled to at least make sure these
|
||||||
|
# all compile
|
||||||
|
test-yes-trace:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: install
|
||||||
|
run: |
|
||||||
|
# need a few things
|
||||||
|
sudo apt-get update -qq
|
||||||
|
sudo apt-get install -qq gcc python3 python3-pip
|
||||||
|
pip3 install toml
|
||||||
|
gcc --version
|
||||||
|
python3 --version
|
||||||
|
- name: test-yes-trace
|
||||||
|
run: |
|
||||||
|
CFLAGS="$CFLAGS \
|
||||||
|
-DLFS2_YES_TRACE \
|
||||||
|
-DLFS2_RAMBD_YES_TRACE \
|
||||||
|
-DLFS2_FILEBD_YES_TRACE \
|
||||||
|
-DLFS2_RAMBD_YES_TRACE" \
|
||||||
|
make test
|
||||||
|
|
||||||
# run LFS2_MULTIVERSION tests
|
# run LFS2_MULTIVERSION tests
|
||||||
test-multiversion:
|
test-multiversion:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
@@ -199,6 +199,47 @@ The tests assume a Linux environment and can be started with make:
|
|||||||
make test
|
make test
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Tests are implemented in C in the .toml files found in the `tests` directory.
|
||||||
|
When developing a feature or fixing a bug, it is frequently useful to run a
|
||||||
|
single test case or suite of tests:
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
./scripts/test.py -l runners/test_runner # list available test suites
|
||||||
|
./scripts/test.py -L runners/test_runner test_dirs # list available test cases
|
||||||
|
./scripts/test.py runners/test_runner test_dirs # run a specific test suite
|
||||||
|
```
|
||||||
|
|
||||||
|
If an assert fails in a test, test.py will try to print information about the
|
||||||
|
failure:
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
tests/test_dirs.toml:1:failure: test_dirs_root:1g12gg2 (PROG_SIZE=16, ERASE_SIZE=512) failed
|
||||||
|
tests/test_dirs.toml:5:assert: assert failed with 0, expected eq 42
|
||||||
|
lfs2_mount(&lfs2, cfg) => 42;
|
||||||
|
```
|
||||||
|
|
||||||
|
This includes the test id, which can be passed to test.py to run only that
|
||||||
|
specific test permutation:
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
./scripts/test.py runners/test_runner test_dirs_root:1g12gg2 # run a specific test permutation
|
||||||
|
./scripts/test.py runners/test_runner test_dirs_root:1g12gg2 --gdb # drop into gdb on failure
|
||||||
|
```
|
||||||
|
|
||||||
|
Some other flags that may be useful:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/test.py runners/test_runner -b -j # run tests in parallel
|
||||||
|
./scripts/test.py runners/test_runner -v -O- # redirect stdout to stdout
|
||||||
|
./scripts/test.py runners/test_runner -ddisk # capture resulting disk image
|
||||||
|
```
|
||||||
|
|
||||||
|
See `-h/--help` for a full list of available flags:
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
./scripts/test.py --help
|
||||||
|
```
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
The littlefs is provided under the [BSD-3-Clause] license. See
|
The littlefs is provided under the [BSD-3-Clause] license. See
|
||||||
|
|||||||
+1
-1
@@ -133,7 +133,7 @@ int lfs2_filebd_prog(const struct lfs2_config *cfg, lfs2_block_t block,
|
|||||||
|
|
||||||
int lfs2_filebd_erase(const struct lfs2_config *cfg, lfs2_block_t block) {
|
int lfs2_filebd_erase(const struct lfs2_config *cfg, lfs2_block_t block) {
|
||||||
LFS2_FILEBD_TRACE("lfs2_filebd_erase(%p, 0x%"PRIx32" (%"PRIu32"))",
|
LFS2_FILEBD_TRACE("lfs2_filebd_erase(%p, 0x%"PRIx32" (%"PRIu32"))",
|
||||||
(void*)cfg, block, ((lfs2_file_t*)cfg->context)->cfg->erase_size);
|
(void*)cfg, block, ((lfs2_filebd_t*)cfg->context)->cfg->erase_size);
|
||||||
lfs2_filebd_t *bd = cfg->context;
|
lfs2_filebd_t *bd = cfg->context;
|
||||||
|
|
||||||
// check if erase is valid
|
// check if erase is valid
|
||||||
|
|||||||
@@ -404,18 +404,15 @@ struct lfs2_diskoff {
|
|||||||
|
|
||||||
// operations on global state
|
// operations on global state
|
||||||
static inline void lfs2_gstate_xor(lfs2_gstate_t *a, const lfs2_gstate_t *b) {
|
static inline void lfs2_gstate_xor(lfs2_gstate_t *a, const lfs2_gstate_t *b) {
|
||||||
for (int i = 0; i < 3; i++) {
|
a->tag ^= b->tag;
|
||||||
((uint32_t*)a)[i] ^= ((const uint32_t*)b)[i];
|
a->pair[0] ^= b->pair[0];
|
||||||
}
|
a->pair[1] ^= b->pair[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool lfs2_gstate_iszero(const lfs2_gstate_t *a) {
|
static inline bool lfs2_gstate_iszero(const lfs2_gstate_t *a) {
|
||||||
for (int i = 0; i < 3; i++) {
|
return a->tag == 0
|
||||||
if (((uint32_t*)a)[i] != 0) {
|
&& a->pair[0] == 0
|
||||||
return false;
|
&& a->pair[1] == 0;
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef LFS2_READONLY
|
#ifndef LFS2_READONLY
|
||||||
@@ -2369,7 +2366,8 @@ fixmlist:;
|
|||||||
if (d->m.pair != pair) {
|
if (d->m.pair != pair) {
|
||||||
for (int i = 0; i < attrcount; i++) {
|
for (int i = 0; i < attrcount; i++) {
|
||||||
if (lfs2_tag_type3(attrs[i].tag) == LFS2_TYPE_DELETE &&
|
if (lfs2_tag_type3(attrs[i].tag) == LFS2_TYPE_DELETE &&
|
||||||
d->id == lfs2_tag_id(attrs[i].tag)) {
|
d->id == lfs2_tag_id(attrs[i].tag) &&
|
||||||
|
d->type != LFS2_TYPE_DIR) {
|
||||||
d->m.pair[0] = LFS2_BLOCK_NULL;
|
d->m.pair[0] = LFS2_BLOCK_NULL;
|
||||||
d->m.pair[1] = LFS2_BLOCK_NULL;
|
d->m.pair[1] = LFS2_BLOCK_NULL;
|
||||||
} else if (lfs2_tag_type3(attrs[i].tag) == LFS2_TYPE_DELETE &&
|
} else if (lfs2_tag_type3(attrs[i].tag) == LFS2_TYPE_DELETE &&
|
||||||
@@ -2558,7 +2556,7 @@ static int lfs2_dir_orphaningcommit(lfs2_t *lfs2, lfs2_mdir_t *dir,
|
|||||||
if (err != LFS2_ERR_NOENT) {
|
if (err != LFS2_ERR_NOENT) {
|
||||||
if (lfs2_gstate_hasorphans(&lfs2->gstate)) {
|
if (lfs2_gstate_hasorphans(&lfs2->gstate)) {
|
||||||
// next step, clean up orphans
|
// next step, clean up orphans
|
||||||
err = lfs2_fs_preporphans(lfs2, -hasparent);
|
err = lfs2_fs_preporphans(lfs2, -(int8_t)hasparent);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -6288,7 +6286,7 @@ lfs2_soff_t lfs2_file_size(lfs2_t *lfs2, lfs2_file_t *file) {
|
|||||||
|
|
||||||
lfs2_soff_t res = lfs2_file_size_(lfs2, file);
|
lfs2_soff_t res = lfs2_file_size_(lfs2, file);
|
||||||
|
|
||||||
LFS2_TRACE("lfs2_file_size -> %"PRId32, res);
|
LFS2_TRACE("lfs2_file_size -> %"PRIu32, res);
|
||||||
LFS2_UNLOCK(lfs2->cfg);
|
LFS2_UNLOCK(lfs2->cfg);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,10 +35,10 @@ LEXEMES = {
|
|||||||
'assert': ['assert'],
|
'assert': ['assert'],
|
||||||
'arrow': ['=>'],
|
'arrow': ['=>'],
|
||||||
'string': [r'"(?:\\.|[^"])*"', r"'(?:\\.|[^'])\'"],
|
'string': [r'"(?:\\.|[^"])*"', r"'(?:\\.|[^'])\'"],
|
||||||
'paren': ['\(', '\)'],
|
'paren': [r'\(', r'\)'],
|
||||||
'cmp': CMP.keys(),
|
'cmp': CMP.keys(),
|
||||||
'logic': ['\&\&', '\|\|'],
|
'logic': [r'\&\&', r'\|\|'],
|
||||||
'sep': [':', ';', '\{', '\}', ','],
|
'sep': [':', ';', r'\{', r'\}', ','],
|
||||||
'op': ['->'], # specifically ops that conflict with cmp
|
'op': ['->'], # specifically ops that conflict with cmp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+19
-19
@@ -102,9 +102,9 @@ class TestCase:
|
|||||||
# the runner itself.
|
# the runner itself.
|
||||||
for v_ in csplit(v):
|
for v_ in csplit(v):
|
||||||
m = re.search(r'\brange\b\s*\('
|
m = re.search(r'\brange\b\s*\('
|
||||||
'(?P<start>[^,\s]*)'
|
r'(?P<start>[^,\s]*)'
|
||||||
'\s*(?:,\s*(?P<stop>[^,\s]*)'
|
r'\s*(?:,\s*(?P<stop>[^,\s]*)'
|
||||||
'\s*(?:,\s*(?P<step>[^,\s]*)\s*)?)?\)',
|
r'\s*(?:,\s*(?P<step>[^,\s]*)\s*)?)?\)',
|
||||||
v_)
|
v_)
|
||||||
if m:
|
if m:
|
||||||
start = (int(m.group('start'), 0)
|
start = (int(m.group('start'), 0)
|
||||||
@@ -163,8 +163,8 @@ class TestSuite:
|
|||||||
code_linenos = []
|
code_linenos = []
|
||||||
for i, line in enumerate(f):
|
for i, line in enumerate(f):
|
||||||
match = re.match(
|
match = re.match(
|
||||||
'(?P<case>\[\s*cases\s*\.\s*(?P<name>\w+)\s*\])'
|
r'(?P<case>\[\s*cases\s*\.\s*(?P<name>\w+)\s*\])'
|
||||||
'|' '(?P<code>code\s*=)',
|
r'|' r'(?P<code>code\s*=)',
|
||||||
line)
|
line)
|
||||||
if match and match.group('case'):
|
if match and match.group('case'):
|
||||||
case_linenos.append((i+1, match.group('name')))
|
case_linenos.append((i+1, match.group('name')))
|
||||||
@@ -602,9 +602,9 @@ def find_perms(runner_, ids=[], **args):
|
|||||||
errors='replace',
|
errors='replace',
|
||||||
close_fds=False)
|
close_fds=False)
|
||||||
pattern = re.compile(
|
pattern = re.compile(
|
||||||
'^(?P<case>[^\s]+)'
|
r'^(?P<case>[^\s]+)'
|
||||||
'\s+(?P<flags>[^\s]+)'
|
r'\s+(?P<flags>[^\s]+)'
|
||||||
'\s+(?P<filtered>\d+)/(?P<perms>\d+)')
|
r'\s+(?P<filtered>\d+)/(?P<perms>\d+)')
|
||||||
# skip the first line
|
# skip the first line
|
||||||
for line in it.islice(proc.stdout, 1, None):
|
for line in it.islice(proc.stdout, 1, None):
|
||||||
m = pattern.match(line)
|
m = pattern.match(line)
|
||||||
@@ -632,8 +632,8 @@ def find_perms(runner_, ids=[], **args):
|
|||||||
errors='replace',
|
errors='replace',
|
||||||
close_fds=False)
|
close_fds=False)
|
||||||
pattern = re.compile(
|
pattern = re.compile(
|
||||||
'^(?P<case>[^\s]+)'
|
r'^(?P<case>[^\s]+)'
|
||||||
'\s+(?P<path>[^:]+):(?P<lineno>\d+)')
|
r'\s+(?P<path>[^:]+):(?P<lineno>\d+)')
|
||||||
# skip the first line
|
# skip the first line
|
||||||
for line in it.islice(proc.stdout, 1, None):
|
for line in it.islice(proc.stdout, 1, None):
|
||||||
m = pattern.match(line)
|
m = pattern.match(line)
|
||||||
@@ -676,8 +676,8 @@ def find_path(runner_, id, **args):
|
|||||||
errors='replace',
|
errors='replace',
|
||||||
close_fds=False)
|
close_fds=False)
|
||||||
pattern = re.compile(
|
pattern = re.compile(
|
||||||
'^(?P<case>[^\s]+)'
|
r'^(?P<case>[^\s]+)'
|
||||||
'\s+(?P<path>[^:]+):(?P<lineno>\d+)')
|
r'\s+(?P<path>[^:]+):(?P<lineno>\d+)')
|
||||||
# skip the first line
|
# skip the first line
|
||||||
for line in it.islice(proc.stdout, 1, None):
|
for line in it.islice(proc.stdout, 1, None):
|
||||||
m = pattern.match(line)
|
m = pattern.match(line)
|
||||||
@@ -706,7 +706,7 @@ def find_defines(runner_, id, **args):
|
|||||||
errors='replace',
|
errors='replace',
|
||||||
close_fds=False)
|
close_fds=False)
|
||||||
defines = co.OrderedDict()
|
defines = co.OrderedDict()
|
||||||
pattern = re.compile('^(?P<define>\w+)=(?P<value>.+)')
|
pattern = re.compile(r'^(?P<define>\w+)=(?P<value>.+)')
|
||||||
for line in proc.stdout:
|
for line in proc.stdout:
|
||||||
m = pattern.match(line)
|
m = pattern.match(line)
|
||||||
if m:
|
if m:
|
||||||
@@ -781,12 +781,12 @@ def run_stage(name, runner_, ids, stdout_, trace_, output_, **args):
|
|||||||
failures = []
|
failures = []
|
||||||
killed = False
|
killed = False
|
||||||
|
|
||||||
pattern = re.compile('^(?:'
|
pattern = re.compile(r'^(?:'
|
||||||
'(?P<op>running|finished|skipped|powerloss) '
|
r'(?P<op>running|finished|skipped|powerloss) '
|
||||||
'(?P<id>(?P<case>[^:]+)[^\s]*)'
|
r'(?P<id>(?P<case>[^:]+)[^\s]*)'
|
||||||
'|' '(?P<path>[^:]+):(?P<lineno>\d+):(?P<op_>assert):'
|
r'|' r'(?P<path>[^:]+):(?P<lineno>\d+):(?P<op_>assert):'
|
||||||
' *(?P<message>.*)'
|
r' *(?P<message>.*)'
|
||||||
')$')
|
r')$')
|
||||||
locals = th.local()
|
locals = th.local()
|
||||||
children = set()
|
children = set()
|
||||||
|
|
||||||
|
|||||||
@@ -725,6 +725,82 @@ code = '''
|
|||||||
lfs2_unmount(&lfs2) => 0;
|
lfs2_unmount(&lfs2) => 0;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
[cases.test_dirs_remove_read]
|
||||||
|
defines.N = 10
|
||||||
|
if = 'N < BLOCK_COUNT/2'
|
||||||
|
code = '''
|
||||||
|
lfs2_t lfs2;
|
||||||
|
lfs2_format(&lfs2, cfg) => 0;
|
||||||
|
lfs2_mount(&lfs2, cfg) => 0;
|
||||||
|
lfs2_mkdir(&lfs2, "prickly-pear") => 0;
|
||||||
|
for (int i = 0; i < N; i++) {
|
||||||
|
char path[1024];
|
||||||
|
sprintf(path, "prickly-pear/cactus%03d", i);
|
||||||
|
lfs2_mkdir(&lfs2, path) => 0;
|
||||||
|
}
|
||||||
|
lfs2_dir_t dir;
|
||||||
|
lfs2_dir_open(&lfs2, &dir, "prickly-pear") => 0;
|
||||||
|
struct lfs2_info info;
|
||||||
|
lfs2_dir_read(&lfs2, &dir, &info) => 1;
|
||||||
|
assert(info.type == LFS2_TYPE_DIR);
|
||||||
|
assert(strcmp(info.name, ".") == 0);
|
||||||
|
lfs2_dir_read(&lfs2, &dir, &info) => 1;
|
||||||
|
assert(info.type == LFS2_TYPE_DIR);
|
||||||
|
assert(strcmp(info.name, "..") == 0);
|
||||||
|
for (int i = 0; i < N; i++) {
|
||||||
|
char path[1024];
|
||||||
|
sprintf(path, "cactus%03d", i);
|
||||||
|
lfs2_dir_read(&lfs2, &dir, &info) => 1;
|
||||||
|
assert(info.type == LFS2_TYPE_DIR);
|
||||||
|
assert(strcmp(info.name, path) == 0);
|
||||||
|
}
|
||||||
|
lfs2_dir_read(&lfs2, &dir, &info) => 0;
|
||||||
|
lfs2_dir_close(&lfs2, &dir) => 0;
|
||||||
|
lfs2_unmount(&lfs2);
|
||||||
|
|
||||||
|
for (lfs2_size_t k = 0; k < N; k++) {
|
||||||
|
for (lfs2_size_t j = 0; j < N; j++) {
|
||||||
|
lfs2_mount(&lfs2, cfg) => 0;
|
||||||
|
lfs2_dir_open(&lfs2, &dir, "prickly-pear") => 0;
|
||||||
|
lfs2_dir_read(&lfs2, &dir, &info) => 1;
|
||||||
|
assert(info.type == LFS2_TYPE_DIR);
|
||||||
|
assert(strcmp(info.name, ".") == 0);
|
||||||
|
lfs2_dir_read(&lfs2, &dir, &info) => 1;
|
||||||
|
assert(info.type == LFS2_TYPE_DIR);
|
||||||
|
assert(strcmp(info.name, "..") == 0);
|
||||||
|
// iterate over dirs < j
|
||||||
|
for (unsigned i = 0; i < j; i++) {
|
||||||
|
char path[1024];
|
||||||
|
sprintf(path, "cactus%03d", i);
|
||||||
|
lfs2_dir_read(&lfs2, &dir, &info) => 1;
|
||||||
|
assert(info.type == LFS2_TYPE_DIR);
|
||||||
|
assert(strcmp(info.name, path) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove k while iterating
|
||||||
|
char path[1024];
|
||||||
|
sprintf(path, "prickly-pear/cactus%03d", k);
|
||||||
|
lfs2_remove(&lfs2, path) => 0;
|
||||||
|
|
||||||
|
// iterate over dirs >= j
|
||||||
|
for (unsigned i = j; i < ((k >= j) ? N-1 : N); i++) {
|
||||||
|
char path[1024];
|
||||||
|
sprintf(path, "cactus%03d", (k >= j && i >= k) ? i+1 : i);
|
||||||
|
lfs2_dir_read(&lfs2, &dir, &info) => 1;
|
||||||
|
assert(info.type == LFS2_TYPE_DIR);
|
||||||
|
assert(strcmp(info.name, path) == 0);
|
||||||
|
}
|
||||||
|
lfs2_dir_read(&lfs2, &dir, &info) => 0;
|
||||||
|
lfs2_dir_close(&lfs2, &dir) => 0;
|
||||||
|
|
||||||
|
// recreate k
|
||||||
|
sprintf(path, "prickly-pear/cactus%03d", k);
|
||||||
|
lfs2_mkdir(&lfs2, path) => 0;
|
||||||
|
lfs2_unmount(&lfs2) => 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
|
||||||
[cases.test_dirs_other_errors]
|
[cases.test_dirs_other_errors]
|
||||||
code = '''
|
code = '''
|
||||||
lfs2_t lfs2;
|
lfs2_t lfs2;
|
||||||
|
|||||||
Reference in New Issue
Block a user