Enabled internal test code at the suite-level
Test suites already had the ability to provide suite-level code via the "code" attribute, but this was placed in the suite's generated source file, making it inaccessbile to internal tests. This change allows suite code to be placed in the same place as internal tests, via the "in" attribute, though this has some caveats: 1. Suite-level code generally declares helper functions in global scope. We don't parse this code or anything, so name collisions between helper functions across different test suites is up to the developer to resolve. 2. Internal suite-level code has access to internal functions/variables/ etc, this means we can't place a copy in our suite's generate source and expect it to compile. For this reason, internal suite-level code is unavailable for non-internal tests in the suite. This also means you only get to place internal suite-level code in a single source file. Though this is not really an issue since littlefs is basically a single file...
This commit is contained in:
+69
-43
@@ -150,6 +150,11 @@ class BenchCase:
|
||||
return ((self.suite, self.lineno, self.name)
|
||||
< (other.suite, other.lineno, other.name))
|
||||
|
||||
def isin(self, path):
|
||||
return (self.in_ is not None
|
||||
and os.path.normpath(self.in_)
|
||||
== os.path.normpath(path))
|
||||
|
||||
|
||||
class BenchSuite:
|
||||
# create a BenchSuite object from a toml file
|
||||
@@ -200,6 +205,7 @@ class BenchSuite:
|
||||
(l for l in code_linenos
|
||||
if not case_linenos or l < case_linenos[0][0]),
|
||||
default=None)
|
||||
self.in_ = config.pop('in', None)
|
||||
|
||||
self.after = config.pop('after', [])
|
||||
if not isinstance(self.after, list):
|
||||
@@ -207,7 +213,6 @@ class BenchSuite:
|
||||
|
||||
# a couple of these we just forward to all cases
|
||||
defines = config.pop('defines', {})
|
||||
in_ = config.pop('in', None)
|
||||
|
||||
self.cases = []
|
||||
for name, case in cases.items():
|
||||
@@ -217,7 +222,7 @@ class BenchSuite:
|
||||
if 'lineno' in case else ''),
|
||||
'suite': self.name,
|
||||
'suite_defines': defines,
|
||||
'suite_in': in_,
|
||||
'suite_in': self.in_,
|
||||
**case},
|
||||
args=args))
|
||||
|
||||
@@ -248,6 +253,11 @@ class BenchSuite:
|
||||
# note we override this with a topological sort during compilation
|
||||
return self.name < other.name
|
||||
|
||||
def isin(self, path):
|
||||
return (self.in_ is not None
|
||||
and os.path.normpath(self.in_)
|
||||
== os.path.normpath(path))
|
||||
|
||||
|
||||
def compile(bench_paths, **args):
|
||||
# find .toml files
|
||||
@@ -419,16 +429,7 @@ def compile(bench_paths, **args):
|
||||
f.writeln()
|
||||
|
||||
if not args.get('source'):
|
||||
if suite.code is not None:
|
||||
if suite.code_lineno is not None:
|
||||
f.writeln('#line %d "%s"'
|
||||
% (suite.code_lineno, suite.path))
|
||||
f.write(suite.code)
|
||||
if suite.code_lineno is not None:
|
||||
f.writeln('#line %d "%s"'
|
||||
% (f.lineno+1, args['output']))
|
||||
f.writeln()
|
||||
|
||||
# write any suite defines
|
||||
if suite.defines:
|
||||
for i, define in enumerate(sorted(suite.defines)):
|
||||
f.writeln('#ifndef %s' % define)
|
||||
@@ -439,6 +440,17 @@ def compile(bench_paths, **args):
|
||||
f.writeln('#endif')
|
||||
f.writeln()
|
||||
|
||||
# write any suite code
|
||||
if suite.code is not None and suite.in_ is None:
|
||||
if suite.code_lineno is not None:
|
||||
f.writeln('#line %d "%s"'
|
||||
% (suite.code_lineno, suite.path))
|
||||
f.write(suite.code)
|
||||
if suite.code_lineno is not None:
|
||||
f.writeln('#line %d "%s"'
|
||||
% (f.lineno+1, args['output']))
|
||||
f.writeln()
|
||||
|
||||
# create case functions
|
||||
for case in suite.cases:
|
||||
if case.in_ is None:
|
||||
@@ -529,40 +541,54 @@ def compile(bench_paths, **args):
|
||||
|
||||
# write any internal benches
|
||||
for suite in suites:
|
||||
for case in suite.cases:
|
||||
if (case.in_ is not None
|
||||
and os.path.normpath(case.in_)
|
||||
== os.path.normpath(args['source'])):
|
||||
# write defines, but note we need to undef any
|
||||
# new defines since we're in someone else's file
|
||||
if suite.defines:
|
||||
for i, define in enumerate(
|
||||
sorted(suite.defines)):
|
||||
f.writeln('#ifndef %s' % define)
|
||||
f.writeln('#define %-24s '
|
||||
'BENCH_IMPLICIT_DEFINE_COUNT+%d' % (
|
||||
define+'_i', i))
|
||||
f.writeln('#define %-24s '
|
||||
'BENCH_DEFINE(%s)' % (
|
||||
define, define+'_i'))
|
||||
f.writeln('#define '
|
||||
'__BENCH__%s__NEEDS_UNDEF' % (
|
||||
define))
|
||||
f.writeln('#endif')
|
||||
f.writeln()
|
||||
if (suite.isin(args['source'])
|
||||
or any(case.isin(args['source'])
|
||||
for case in suite.cases)):
|
||||
# write defines, but note we need to undef any
|
||||
# new defines since we're in someone else's file
|
||||
if suite.defines:
|
||||
for i, define in enumerate(
|
||||
sorted(suite.defines)):
|
||||
f.writeln('#ifndef %s' % define)
|
||||
f.writeln('#define %-24s '
|
||||
'BENCH_IMPLICIT_DEFINE_COUNT+%d' % (
|
||||
define+'_i', i))
|
||||
f.writeln('#define %-24s '
|
||||
'BENCH_DEFINE(%s)' % (
|
||||
define, define+'_i'))
|
||||
f.writeln('#define '
|
||||
'__BENCH__%s__NEEDS_UNDEF' % (
|
||||
define))
|
||||
f.writeln('#endif')
|
||||
f.writeln()
|
||||
|
||||
# write any internal suite code
|
||||
if suite.isin(args['source']):
|
||||
if suite.code_lineno is not None:
|
||||
f.writeln('#line %d "%s"'
|
||||
% (suite.code_lineno, suite.path))
|
||||
f.write(suite.code)
|
||||
if suite.code_lineno is not None:
|
||||
f.writeln('#line %d "%s"'
|
||||
% (f.lineno+1, args['output']))
|
||||
f.writeln()
|
||||
|
||||
for case in suite.cases:
|
||||
if case.isin(args['source']):
|
||||
write_case_functions(f, suite, case)
|
||||
|
||||
if suite.defines:
|
||||
for define in sorted(suite.defines):
|
||||
f.writeln('#ifdef __BENCH__%s__NEEDS_UNDEF'
|
||||
% define)
|
||||
f.writeln('#undef __BENCH__%s__NEEDS_UNDEF'
|
||||
% define)
|
||||
f.writeln('#undef %s' % define)
|
||||
f.writeln('#undef %s' % (define+'_i'))
|
||||
f.writeln('#endif')
|
||||
f.writeln()
|
||||
if (suite.isin(args['source'])
|
||||
or any(case.isin(args['source'])
|
||||
for case in suite.cases)):
|
||||
for define in sorted(suite.defines):
|
||||
f.writeln('#ifdef __BENCH__%s__NEEDS_UNDEF'
|
||||
% define)
|
||||
f.writeln('#undef __BENCH__%s__NEEDS_UNDEF'
|
||||
% define)
|
||||
f.writeln('#undef %s' % define)
|
||||
f.writeln('#undef %s' % (define+'_i'))
|
||||
f.writeln('#endif')
|
||||
f.writeln()
|
||||
|
||||
# declare our bench suites
|
||||
#
|
||||
|
||||
Reference in New Issue
Block a user