forked from Imagelibrary/littlefs
Carved out ckreads, disabled at compile-time by default
This moves all ckread-related logic behind the new opt-in compile-time
LFS_CKREADS flag. So in order to use ckreads you need to 1. define
LFS_CKREADS at compile time, and 2. pass LFS_M_CKREADS during
lfsr_mount.
This was always the plan since, even if ckreads worked perfectly, it
adds a significant amount of baggage (stack mostly) to track the
ck context of all reads.
---
This is the first non-trivial opt-in define in littlefs, so more test
framework features!
test.py and build.py now support the optional ifdef attribute, which
makes it easy to indicate a test suite/case should not be compiled when
a feature is missing.
Also interesting to note is the addition of LFS_IFDEF_CKREADS, which
solves several issues (and general ugliness) related to #ifdefs in
expression. For example:
// does not compile :( (can't embed ifdefs in macros)
LFS_ASSERT(flags == (
LFS_M_CKPROGS
#ifdef LFS_CKREADS
| LFS_M_CKREADS
#endif
))
// does compile :)
LFS_ASSERT(flags == (
LFS_M_CKPROGS
| LFS_IFDEF_CKREADS(LFS_M_CKREADS, 0)));
---
This brings us way back down to our pre-ckread levels of code/stack:
code stack
before-ckreads: 36352 2672
ckreads: 38060 (+4.7%) 3056 (+14.4%)
after-ckreads: 36428 (+0.2%) 2680 (+0.3%)
Unfortunately, we do end up with a bit more code cost than where we
started. Mainly due to code moving around to support the ckread
infrastructure:
code stack
lfsr_bd_readtag: +52 (+23.2%) +8 (+10.0%)
lfsr_rbyd_fetch: +36 (+5.0%) +8 (+6.2%, cold)
lfs_toleb128: -12 (-25.0%) -4 (-20.0%, cold)
total: +76 (+0.2%) +8 (+0.3%)
But oh well. Note that some of these changes are good even without
ckreads, such as only parsing the last ecksum tag.
This commit is contained in:
@@ -55,6 +55,9 @@ class TestCase:
|
||||
self.if_ = config.pop('if', [])
|
||||
if not isinstance(self.if_, list):
|
||||
self.if_ = [self.if_]
|
||||
self.ifdef = config.pop('ifdef', [])
|
||||
if not isinstance(self.ifdef, list):
|
||||
self.ifdef = [self.ifdef]
|
||||
self.code = config.pop('code')
|
||||
self.code_lineno = config.pop('code_lineno', None)
|
||||
self.in_ = config.pop('in',
|
||||
@@ -204,6 +207,10 @@ class TestSuite:
|
||||
if not isinstance(self.if_, list):
|
||||
self.if_ = [self.if_]
|
||||
|
||||
self.ifdef = config.pop('ifdef', [])
|
||||
if not isinstance(self.ifdef, list):
|
||||
self.ifdef = [self.ifdef]
|
||||
|
||||
self.code = config.pop('code', None)
|
||||
self.code_lineno = min(
|
||||
(l for l in code_linenos
|
||||
@@ -368,6 +375,12 @@ def compile(test_paths, **args):
|
||||
# note it's up to the specific generated file to declare
|
||||
# the test defines
|
||||
def write_case_functions(f, suite, case):
|
||||
# write any ifdef prologues
|
||||
if case.ifdef:
|
||||
for ifdef in case.ifdef:
|
||||
f.writeln('#ifdef %s' % ifdef)
|
||||
f.writeln()
|
||||
|
||||
# create case define functions
|
||||
for i, permutation in enumerate(case.permutations):
|
||||
for k, vs in sorted(permutation.items()):
|
||||
@@ -424,7 +437,19 @@ def compile(test_paths, **args):
|
||||
f.writeln('}')
|
||||
f.writeln()
|
||||
|
||||
# write any ifdef epilogues
|
||||
if case.ifdef:
|
||||
for ifdef in case.ifdef:
|
||||
f.writeln('#endif')
|
||||
f.writeln()
|
||||
|
||||
if not args.get('source'):
|
||||
# write any ifdef prologues
|
||||
if suite.ifdef:
|
||||
for ifdef in suite.ifdef:
|
||||
f.writeln('#ifdef %s' % ifdef)
|
||||
f.writeln()
|
||||
|
||||
# write any suite defines
|
||||
if suite.defines:
|
||||
for define in sorted(suite.defines):
|
||||
@@ -462,6 +487,12 @@ def compile(test_paths, **args):
|
||||
% (case.name))
|
||||
f.writeln()
|
||||
|
||||
# write any ifdef epilogues
|
||||
if suite.ifdef:
|
||||
for ifdef in suite.ifdef:
|
||||
f.writeln('#endif')
|
||||
f.writeln()
|
||||
|
||||
# create suite struct
|
||||
f.writeln('const struct test_suite __test__%s__suite = {'
|
||||
% suite.name)
|
||||
@@ -473,6 +504,8 @@ def compile(test_paths, **args):
|
||||
'TEST_REENTRANT' if suite.reentrant else None,
|
||||
'TEST_FUZZ' if suite.fuzz else None]))
|
||||
or 0))
|
||||
for ifdef in suite.ifdef:
|
||||
f.writeln(4*' '+'#ifdef %s' % ifdef)
|
||||
# create suite defines
|
||||
if suite.defines:
|
||||
f.writeln(4*' '+'.defines = (const test_define_t[]){')
|
||||
@@ -481,6 +514,8 @@ def compile(test_paths, **args):
|
||||
% (k, k))
|
||||
f.writeln(4*' '+'},')
|
||||
f.writeln(4*' '+'.define_count = %d,' % len(suite.defines))
|
||||
for ifdef in suite.ifdef:
|
||||
f.writeln(4*' '+'#endif')
|
||||
if suite.cases:
|
||||
f.writeln(4*' '+'.cases = (const struct test_case[]){')
|
||||
for case in suite.cases:
|
||||
@@ -494,6 +529,8 @@ def compile(test_paths, **args):
|
||||
'TEST_REENTRANT' if case.reentrant else None,
|
||||
'TEST_FUZZ' if case.fuzz else None]))
|
||||
or 0))
|
||||
for ifdef in it.chain(suite.ifdef, case.ifdef):
|
||||
f.writeln(12*' '+'#ifdef %s' % ifdef)
|
||||
# create case defines
|
||||
if case.defines:
|
||||
f.writeln(12*' '+'.defines'
|
||||
@@ -521,6 +558,8 @@ def compile(test_paths, **args):
|
||||
% (case.name))
|
||||
f.writeln(12*' '+'.run = __test__%s__run,'
|
||||
% (case.name))
|
||||
for ifdef in it.chain(suite.ifdef, case.ifdef):
|
||||
f.writeln(12*' '+'#endif')
|
||||
f.writeln(8*' '+'},')
|
||||
f.writeln(4*' '+'},')
|
||||
f.writeln(4*' '+'.case_count = %d,' % len(suite.cases))
|
||||
@@ -553,6 +592,13 @@ def compile(test_paths, **args):
|
||||
|
||||
# write any internal tests
|
||||
for suite in suites:
|
||||
# any ifdef prologues
|
||||
if suite.ifdef:
|
||||
for ifdef in suite.ifdef:
|
||||
f.writeln('#ifdef %s' % ifdef)
|
||||
f.writeln()
|
||||
|
||||
# any suite code
|
||||
if suite.isin(args['source']):
|
||||
if suite.code_lineno is not None:
|
||||
f.writeln('#line %d "%s"'
|
||||
@@ -563,10 +609,17 @@ def compile(test_paths, **args):
|
||||
% (f.lineno+1, args['output']))
|
||||
f.writeln()
|
||||
|
||||
# any case functions
|
||||
for case in suite.cases:
|
||||
if case.isin(args['source']):
|
||||
write_case_functions(f, suite, case)
|
||||
|
||||
# any ifdef epilogues
|
||||
if suite.ifdef:
|
||||
for ifdef in suite.ifdef:
|
||||
f.writeln('#endif')
|
||||
f.writeln()
|
||||
|
||||
# declare our test suites
|
||||
#
|
||||
# by declaring these as weak we can write these to every
|
||||
|
||||
Reference in New Issue
Block a user