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)
|
return ((self.suite, self.lineno, self.name)
|
||||||
< (other.suite, other.lineno, other.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:
|
class BenchSuite:
|
||||||
# create a BenchSuite object from a toml file
|
# create a BenchSuite object from a toml file
|
||||||
@@ -200,6 +205,7 @@ class BenchSuite:
|
|||||||
(l for l in code_linenos
|
(l for l in code_linenos
|
||||||
if not case_linenos or l < case_linenos[0][0]),
|
if not case_linenos or l < case_linenos[0][0]),
|
||||||
default=None)
|
default=None)
|
||||||
|
self.in_ = config.pop('in', None)
|
||||||
|
|
||||||
self.after = config.pop('after', [])
|
self.after = config.pop('after', [])
|
||||||
if not isinstance(self.after, list):
|
if not isinstance(self.after, list):
|
||||||
@@ -207,7 +213,6 @@ class BenchSuite:
|
|||||||
|
|
||||||
# a couple of these we just forward to all cases
|
# a couple of these we just forward to all cases
|
||||||
defines = config.pop('defines', {})
|
defines = config.pop('defines', {})
|
||||||
in_ = config.pop('in', None)
|
|
||||||
|
|
||||||
self.cases = []
|
self.cases = []
|
||||||
for name, case in cases.items():
|
for name, case in cases.items():
|
||||||
@@ -217,7 +222,7 @@ class BenchSuite:
|
|||||||
if 'lineno' in case else ''),
|
if 'lineno' in case else ''),
|
||||||
'suite': self.name,
|
'suite': self.name,
|
||||||
'suite_defines': defines,
|
'suite_defines': defines,
|
||||||
'suite_in': in_,
|
'suite_in': self.in_,
|
||||||
**case},
|
**case},
|
||||||
args=args))
|
args=args))
|
||||||
|
|
||||||
@@ -248,6 +253,11 @@ class BenchSuite:
|
|||||||
# note we override this with a topological sort during compilation
|
# note we override this with a topological sort during compilation
|
||||||
return self.name < other.name
|
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):
|
def compile(bench_paths, **args):
|
||||||
# find .toml files
|
# find .toml files
|
||||||
@@ -419,16 +429,7 @@ def compile(bench_paths, **args):
|
|||||||
f.writeln()
|
f.writeln()
|
||||||
|
|
||||||
if not args.get('source'):
|
if not args.get('source'):
|
||||||
if suite.code is not None:
|
# write any suite defines
|
||||||
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()
|
|
||||||
|
|
||||||
if suite.defines:
|
if suite.defines:
|
||||||
for i, define in enumerate(sorted(suite.defines)):
|
for i, define in enumerate(sorted(suite.defines)):
|
||||||
f.writeln('#ifndef %s' % define)
|
f.writeln('#ifndef %s' % define)
|
||||||
@@ -439,6 +440,17 @@ def compile(bench_paths, **args):
|
|||||||
f.writeln('#endif')
|
f.writeln('#endif')
|
||||||
f.writeln()
|
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
|
# create case functions
|
||||||
for case in suite.cases:
|
for case in suite.cases:
|
||||||
if case.in_ is None:
|
if case.in_ is None:
|
||||||
@@ -529,40 +541,54 @@ def compile(bench_paths, **args):
|
|||||||
|
|
||||||
# write any internal benches
|
# write any internal benches
|
||||||
for suite in suites:
|
for suite in suites:
|
||||||
for case in suite.cases:
|
if (suite.isin(args['source'])
|
||||||
if (case.in_ is not None
|
or any(case.isin(args['source'])
|
||||||
and os.path.normpath(case.in_)
|
for case in suite.cases)):
|
||||||
== os.path.normpath(args['source'])):
|
# write defines, but note we need to undef any
|
||||||
# write defines, but note we need to undef any
|
# new defines since we're in someone else's file
|
||||||
# new defines since we're in someone else's file
|
if suite.defines:
|
||||||
if suite.defines:
|
for i, define in enumerate(
|
||||||
for i, define in enumerate(
|
sorted(suite.defines)):
|
||||||
sorted(suite.defines)):
|
f.writeln('#ifndef %s' % define)
|
||||||
f.writeln('#ifndef %s' % define)
|
f.writeln('#define %-24s '
|
||||||
f.writeln('#define %-24s '
|
'BENCH_IMPLICIT_DEFINE_COUNT+%d' % (
|
||||||
'BENCH_IMPLICIT_DEFINE_COUNT+%d' % (
|
define+'_i', i))
|
||||||
define+'_i', i))
|
f.writeln('#define %-24s '
|
||||||
f.writeln('#define %-24s '
|
'BENCH_DEFINE(%s)' % (
|
||||||
'BENCH_DEFINE(%s)' % (
|
define, define+'_i'))
|
||||||
define, define+'_i'))
|
f.writeln('#define '
|
||||||
f.writeln('#define '
|
'__BENCH__%s__NEEDS_UNDEF' % (
|
||||||
'__BENCH__%s__NEEDS_UNDEF' % (
|
define))
|
||||||
define))
|
f.writeln('#endif')
|
||||||
f.writeln('#endif')
|
f.writeln()
|
||||||
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)
|
write_case_functions(f, suite, case)
|
||||||
|
|
||||||
if suite.defines:
|
if (suite.isin(args['source'])
|
||||||
for define in sorted(suite.defines):
|
or any(case.isin(args['source'])
|
||||||
f.writeln('#ifdef __BENCH__%s__NEEDS_UNDEF'
|
for case in suite.cases)):
|
||||||
% define)
|
for define in sorted(suite.defines):
|
||||||
f.writeln('#undef __BENCH__%s__NEEDS_UNDEF'
|
f.writeln('#ifdef __BENCH__%s__NEEDS_UNDEF'
|
||||||
% define)
|
% define)
|
||||||
f.writeln('#undef %s' % define)
|
f.writeln('#undef __BENCH__%s__NEEDS_UNDEF'
|
||||||
f.writeln('#undef %s' % (define+'_i'))
|
% define)
|
||||||
f.writeln('#endif')
|
f.writeln('#undef %s' % define)
|
||||||
f.writeln()
|
f.writeln('#undef %s' % (define+'_i'))
|
||||||
|
f.writeln('#endif')
|
||||||
|
f.writeln()
|
||||||
|
|
||||||
# declare our bench suites
|
# declare our bench suites
|
||||||
#
|
#
|
||||||
|
|||||||
+69
-43
@@ -152,6 +152,11 @@ class TestCase:
|
|||||||
return ((self.suite, self.lineno, self.name)
|
return ((self.suite, self.lineno, self.name)
|
||||||
< (other.suite, other.lineno, other.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 TestSuite:
|
class TestSuite:
|
||||||
# create a TestSuite object from a toml file
|
# create a TestSuite object from a toml file
|
||||||
@@ -202,6 +207,7 @@ class TestSuite:
|
|||||||
(l for l in code_linenos
|
(l for l in code_linenos
|
||||||
if not case_linenos or l < case_linenos[0][0]),
|
if not case_linenos or l < case_linenos[0][0]),
|
||||||
default=None)
|
default=None)
|
||||||
|
self.in_ = config.pop('in', None)
|
||||||
|
|
||||||
self.after = config.pop('after', [])
|
self.after = config.pop('after', [])
|
||||||
if not isinstance(self.after, list):
|
if not isinstance(self.after, list):
|
||||||
@@ -209,7 +215,6 @@ class TestSuite:
|
|||||||
|
|
||||||
# a couple of these we just forward to all cases
|
# a couple of these we just forward to all cases
|
||||||
defines = config.pop('defines', {})
|
defines = config.pop('defines', {})
|
||||||
in_ = config.pop('in', None)
|
|
||||||
reentrant = config.pop('reentrant', False)
|
reentrant = config.pop('reentrant', False)
|
||||||
|
|
||||||
self.cases = []
|
self.cases = []
|
||||||
@@ -220,7 +225,7 @@ class TestSuite:
|
|||||||
if 'lineno' in case else ''),
|
if 'lineno' in case else ''),
|
||||||
'suite': self.name,
|
'suite': self.name,
|
||||||
'suite_defines': defines,
|
'suite_defines': defines,
|
||||||
'suite_in': in_,
|
'suite_in': self.in_,
|
||||||
'suite_reentrant': reentrant,
|
'suite_reentrant': reentrant,
|
||||||
**case},
|
**case},
|
||||||
args=args))
|
args=args))
|
||||||
@@ -253,6 +258,11 @@ class TestSuite:
|
|||||||
# note we override this with a topological sort during compilation
|
# note we override this with a topological sort during compilation
|
||||||
return self.name < other.name
|
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(test_paths, **args):
|
def compile(test_paths, **args):
|
||||||
# find .toml files
|
# find .toml files
|
||||||
@@ -424,16 +434,7 @@ def compile(test_paths, **args):
|
|||||||
f.writeln()
|
f.writeln()
|
||||||
|
|
||||||
if not args.get('source'):
|
if not args.get('source'):
|
||||||
if suite.code is not None:
|
# write any suite defines
|
||||||
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()
|
|
||||||
|
|
||||||
if suite.defines:
|
if suite.defines:
|
||||||
for i, define in enumerate(sorted(suite.defines)):
|
for i, define in enumerate(sorted(suite.defines)):
|
||||||
f.writeln('#ifndef %s' % define)
|
f.writeln('#ifndef %s' % define)
|
||||||
@@ -444,6 +445,17 @@ def compile(test_paths, **args):
|
|||||||
f.writeln('#endif')
|
f.writeln('#endif')
|
||||||
f.writeln()
|
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
|
# create case functions
|
||||||
for case in suite.cases:
|
for case in suite.cases:
|
||||||
if case.in_ is None:
|
if case.in_ is None:
|
||||||
@@ -536,40 +548,54 @@ def compile(test_paths, **args):
|
|||||||
|
|
||||||
# write any internal tests
|
# write any internal tests
|
||||||
for suite in suites:
|
for suite in suites:
|
||||||
for case in suite.cases:
|
if (suite.isin(args['source'])
|
||||||
if (case.in_ is not None
|
or any(case.isin(args['source'])
|
||||||
and os.path.normpath(case.in_)
|
for case in suite.cases)):
|
||||||
== os.path.normpath(args['source'])):
|
# write defines, but note we need to undef any
|
||||||
# write defines, but note we need to undef any
|
# new defines since we're in someone else's file
|
||||||
# new defines since we're in someone else's file
|
if suite.defines:
|
||||||
if suite.defines:
|
for i, define in enumerate(
|
||||||
for i, define in enumerate(
|
sorted(suite.defines)):
|
||||||
sorted(suite.defines)):
|
f.writeln('#ifndef %s' % define)
|
||||||
f.writeln('#ifndef %s' % define)
|
f.writeln('#define %-24s '
|
||||||
f.writeln('#define %-24s '
|
'TEST_IMPLICIT_DEFINE_COUNT+%d' % (
|
||||||
'TEST_IMPLICIT_DEFINE_COUNT+%d' % (
|
define+'_i', i))
|
||||||
define+'_i', i))
|
f.writeln('#define %-24s '
|
||||||
f.writeln('#define %-24s '
|
'TEST_DEFINE(%s)' % (
|
||||||
'TEST_DEFINE(%s)' % (
|
define, define+'_i'))
|
||||||
define, define+'_i'))
|
f.writeln('#define '
|
||||||
f.writeln('#define '
|
'__TEST__%s__NEEDS_UNDEF' % (
|
||||||
'__TEST__%s__NEEDS_UNDEF' % (
|
define))
|
||||||
define))
|
f.writeln('#endif')
|
||||||
f.writeln('#endif')
|
f.writeln()
|
||||||
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)
|
write_case_functions(f, suite, case)
|
||||||
|
|
||||||
if suite.defines:
|
if (suite.isin(args['source'])
|
||||||
for define in sorted(suite.defines):
|
or any(case.isin(args['source'])
|
||||||
f.writeln('#ifdef __TEST__%s__NEEDS_UNDEF'
|
for case in suite.cases)):
|
||||||
% define)
|
for define in sorted(suite.defines):
|
||||||
f.writeln('#undef __TEST__%s__NEEDS_UNDEF'
|
f.writeln('#ifdef __TEST__%s__NEEDS_UNDEF'
|
||||||
% define)
|
% define)
|
||||||
f.writeln('#undef %s' % define)
|
f.writeln('#undef __TEST__%s__NEEDS_UNDEF'
|
||||||
f.writeln('#undef %s' % (define+'_i'))
|
% define)
|
||||||
f.writeln('#endif')
|
f.writeln('#undef %s' % define)
|
||||||
f.writeln()
|
f.writeln('#undef %s' % (define+'_i'))
|
||||||
|
f.writeln('#endif')
|
||||||
|
f.writeln()
|
||||||
|
|
||||||
# declare our test suites
|
# declare our test suites
|
||||||
#
|
#
|
||||||
|
|||||||
Reference in New Issue
Block a user