Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/littlefs-project/littlefs.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Haster <chaster@utexas.edu>2020-01-13 07:21:09 +0300
committerChristopher Haster <chaster@utexas.edu>2020-01-13 07:21:09 +0300
commitb06ce542791d0d3d0ff56fdb762404e9ce5bedea (patch)
tree912e1fa11b3bab8dba5af1d07217a42953b0c27b /scripts
parent1d2688a7714d2d0d560dc47acc87b19ed03dba9f (diff)
Migrated the bulk of the feature-specific tests
This involved some minor tweaks for the various types of tests, added predicates to the test framework (necessary for test_entries and test_alloc), and cleaned up some of the testing semantics such as reporting how many tests are filtered, showing permutation config on the result screen, and properly inheriting suite config in cases.
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/test_.py126
1 files changed, 88 insertions, 38 deletions
diff --git a/scripts/test_.py b/scripts/test_.py
index 2f016e4..ab674c9 100755
--- a/scripts/test_.py
+++ b/scripts/test_.py
@@ -4,6 +4,20 @@
# .toml files stored in the tests directory.
#
+# TODO
+# - nargs > 1?
+# x show perm config on failure
+# x filtering
+# n show perm config on verbose?
+# - better lineno tracking for cases?
+# n non-int perms?
+# - different path format?
+# - suite.prologue, suite.epilogue
+# - in
+# x change BLOCK_CYCLES to -1 by default
+# x change persist behaviour
+# x config chaining correct
+
import toml
import glob
import re
@@ -20,7 +34,7 @@ import shlex
TESTDIR = 'tests_'
RULES = """
define FLATTEN
-%$(subst /,.,$(target:.c=.t.c)): $(target)
+%$(subst /,.,$(target:.c=.tc)): $(target)
cat <(echo '#line 1 "$$<"') $$< > $$@
endef
$(foreach target,$(SRC),$(eval $(FLATTEN)))
@@ -28,12 +42,12 @@ $(foreach target,$(SRC),$(eval $(FLATTEN)))
-include tests_/*.d
.SECONDARY:
-%.c: %.t.c
+%.c: %.tc
./scripts/explode_asserts.py $< -o $@
%.test: override CFLAGS += -fdiagnostics-color=always
%.test: override CFLAGS += -ggdb
-%.test: %.test.o $(foreach f,$(subst /,.,$(SRC:.c=.o)),%.test.$f)
+%.test: %.test.o $(foreach f,$(subst /,.,$(SRC:.c=.o)),%.$f)
$(CC) $(CFLAGS) $^ $(LFLAGS) -o $@
"""
GLOBALS = """
@@ -49,7 +63,7 @@ DEFINES = {
"LFS_PROG_SIZE": "LFS_READ_SIZE",
"LFS_BLOCK_SIZE": 512,
"LFS_BLOCK_COUNT": 1024,
- "LFS_BLOCK_CYCLES": 1024,
+ "LFS_BLOCK_CYCLES": -1,
"LFS_CACHE_SIZE": "(64 % LFS_PROG_SIZE == 0 ? 64 : LFS_PROG_SIZE)",
"LFS_LOOKAHEAD_SIZE": 16,
"LFS_ERASE_VALUE": 0xff,
@@ -122,12 +136,19 @@ class TestCase:
self.code = config['code']
self.defines = config.get('define', {})
+ self.if_ = config.get('if', None)
self.leaky = config.get('leaky', False)
def __str__(self):
if hasattr(self, 'permno'):
- return '%s[%d,%d]' % (
- self.suite.name, self.caseno, self.permno)
+ if any(k not in self.case.defines for k in self.defines):
+ return '%s[%d,%d] (%s)' % (
+ self.suite.name, self.caseno, self.permno, ', '.join(
+ '%s=%s' % (k, v) for k, v in self.defines.items()
+ if k not in self.case.defines))
+ else:
+ return '%s[%d,%d]' % (
+ self.suite.name, self.caseno, self.permno)
else:
return '%s[%d]' % (
self.suite.name, self.caseno)
@@ -176,12 +197,26 @@ class TestCase:
f.write('}\n')
+ def shouldtest(self, **args):
+ if self.if_ is not None:
+ return eval(self.if_, None, self.defines.copy())
+ else:
+ return True
+
def test(self, exec=[], persist=False, gdb=False, failure=None, **args):
# build command
cmd = exec + ['./%s.test' % self.suite.path,
repr(self.caseno), repr(self.permno)]
+
+ # persist disk or keep in RAM for speed?
if persist:
- cmd.append(self.suite.path + '.test.disk')
+ if persist != 'noerase':
+ try:
+ os.remove(self.suite.path + '.disk')
+ except FileNotFoundError:
+ pass
+
+ cmd.append(self.suite.path + '.disk')
# failed? drop into debugger?
if gdb and failure:
@@ -244,10 +279,10 @@ class ValgrindTestCase(TestCase):
self.leaky = config.get('leaky', False)
super().__init__(config, **args)
- def test(self, exec=[], **args):
- if self.leaky:
- return
+ def shouldtest(self, **args):
+ return not self.leaky and super().shouldtest(**args)
+ def test(self, exec=[], **args):
exec = exec + [
'valgrind',
'--leak-check=full',
@@ -260,14 +295,14 @@ class ReentrantTestCase(TestCase):
self.reentrant = config.get('reentrant', False)
super().__init__(config, **args)
- def test(self, exec=[], persist=False, gdb=False, failure=None, **args):
- if not self.reentrant:
- return
+ def shouldtest(self, **args):
+ return self.reentrant and super().shouldtest(**args)
+ def test(self, exec=[], persist=False, gdb=False, failure=None, **args):
# clear disk first?
- if not persist:
+ if persist != 'noerase':
try:
- os.remove(self.suite.path + '.test.disk')
+ os.remove(self.suite.path + '.disk')
except FileNotFoundError:
pass
@@ -293,7 +328,7 @@ class ReentrantTestCase(TestCase):
'33',
'--args']
try:
- return super().test(exec=nexec, persist=True, **args)
+ return super().test(exec=nexec, persist='noerase', **args)
except TestFailure as nfailure:
if nfailure.returncode == 33:
continue
@@ -326,6 +361,11 @@ class TestSuite:
# create initial test cases
self.cases = []
for i, (case, lineno) in enumerate(zip(config['case'], linenos)):
+ # give our case's config a copy of our "global" config
+ for k, v in config.items():
+ if k not in case:
+ case[k] = v
+ # initialize test case
self.cases.append(self.TestCase(case,
suite=self, caseno=i, lineno=lineno, **args))
@@ -430,7 +470,7 @@ class TestSuite:
# add test-related rules
rules = RULES.replace(4*' ', '\t')
- with open(self.path + '.test.mk', 'w') as mk:
+ with open(self.path + '.mk', 'w') as mk:
mk.write(rules)
mk.write('\n')
@@ -440,13 +480,13 @@ class TestSuite:
self.path+'.test', k, v))
# write test.c in base64 so make can decide when to rebuild
- mk.write('%s: %s\n' % (self.path+'.test.t.c', self.path))
+ mk.write('%s: %s\n' % (self.path+'.test.tc', self.path))
mk.write('\t@base64 -d <<< ')
mk.write(base64.b64encode(
f.getvalue().encode('utf8')).decode('utf8'))
mk.write(' > $@\n')
- self.makefile = self.path + '.test.mk'
+ self.makefile = self.path + '.mk'
self.target = self.path + '.test'
return self.makefile, self.target
@@ -460,6 +500,8 @@ class TestSuite:
continue
if permno is not None and perm.permno != permno:
continue
+ if not perm.shouldtest(**args):
+ continue
try:
result = perm.test(**args)
@@ -473,11 +515,10 @@ class TestSuite:
sys.stdout.write('\n')
raise
else:
- if result == PASS:
- perm.result = PASS
- if not args.get('verbose', True):
- sys.stdout.write(PASS)
- sys.stdout.flush()
+ perm.result = PASS
+ if not args.get('verbose', True):
+ sys.stdout.write(PASS)
+ sys.stdout.flush()
if not args.get('verbose', True):
sys.stdout.write('\n')
@@ -581,6 +622,13 @@ def main(**args):
sum(len(suite.cases) for suite in suites),
sum(len(suite.perms) for suite in suites)))
+ filtered = 0
+ for suite in suites:
+ for perm in suite.perms:
+ filtered += perm.shouldtest(**args)
+ if filtered != sum(len(suite.perms) for suite in suites):
+ print('filtered down to %d permutations' % filtered)
+
print('====== testing ======')
try:
for suite in suites:
@@ -588,18 +636,6 @@ def main(**args):
except TestFailure:
pass
- if args.get('gdb', False):
- failure = None
- for suite in suites:
- for perm in suite.perms:
- if getattr(perm, 'result', PASS) != PASS:
- failure = perm.result
- if failure is not None:
- print('======= gdb ======')
- # drop into gdb
- failure.case.test(failure=failure, **args)
- sys.exit(0)
-
print('====== results ======')
passed = 0
failed = 0
@@ -633,6 +669,19 @@ def main(**args):
sys.stdout.write('\n')
failed += 1
+ if args.get('gdb', False):
+ failure = None
+ for suite in suites:
+ for perm in suite.perms:
+ if getattr(perm, 'result', PASS) != PASS:
+ failure = perm.result
+ if failure is not None:
+ print('======= gdb ======')
+ # drop into gdb
+ failure.case.test(failure=failure, **args)
+ sys.exit(0)
+
+
print('tests passed: %d' % passed)
print('tests failed: %d' % failed)
@@ -652,8 +701,9 @@ if __name__ == "__main__":
help="Output everything that is happening.")
parser.add_argument('-k', '--keep-going', action='store_true',
help="Run all tests instead of stopping on first error. Useful for CI.")
- parser.add_argument('-p', '--persist', action='store_true',
- help="Don't reset the tests disk before each test.")
+ parser.add_argument('-p', '--persist', choices=['erase', 'noerase'],
+ nargs='?', const='erase',
+ help="Store disk image in a file.")
parser.add_argument('-g', '--gdb', choices=['init', 'start', 'assert'],
nargs='?', const='assert',
help="Drop into gdb on test failure.")