circuitpython/tools/tinytest-codegen.py

158 lines
4.9 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
2014-05-05 11:49:52 -04:00
2020-06-03 18:40:05 -04:00
# SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
#
# SPDX-License-Identifier: MIT
2014-05-05 11:49:52 -04:00
import os, sys
from glob import glob
from re import sub
import argparse
2014-05-05 11:49:52 -04:00
def escape(s):
s = s.decode()
lookup = {
2021-04-20 01:22:44 -04:00
"\0": "\\0",
"\t": "\\t",
"\n": '\\n"\n"',
"\r": "\\r",
"\\": "\\\\",
'"': '\\"',
}
2021-03-15 09:57:36 -04:00
return '""\n"{}"'.format("".join([lookup[x] if x in lookup else x for x in s]))
2014-05-05 11:49:52 -04:00
def chew_filename(t):
2021-03-15 09:57:36 -04:00
return {"func": "test_{}_fn".format(sub(r"/|\.|-", "_", t)), "desc": t}
2014-05-05 11:49:52 -04:00
def script_to_map(test_file):
r = {"name": chew_filename(test_file)["func"]}
2018-12-20 19:44:39 -05:00
with open(test_file, "rb") as test:
2018-07-11 16:45:30 -04:00
script = test.readlines()
# Test for import skip_if and inject it into the test as needed.
if "import skip_if\n" in script:
2021-03-15 09:57:36 -04:00
index = script.index("import skip_if\n")
script.pop(index)
script.insert(index, "class skip_if:\n")
with open("../tests/skip_if.py") as skip_if:
total_lines = 1
for line in skip_if:
stripped = line.strip()
if not stripped or stripped.startswith(("#", '"""')):
continue
script.insert(index + total_lines, "\t" + line)
total_lines += 1
r["script"] = escape(b"".join(script))
2018-12-20 19:44:39 -05:00
with open(test_file + ".exp", "rb") as f:
r["output"] = escape(f.read())
return r
2014-05-05 11:49:52 -04:00
2021-03-15 09:57:36 -04:00
2014-05-05 11:49:52 -04:00
test_function = (
"void {name}(void* data) {{\n"
" static const char pystr[] = {script};\n"
" static const char exp[] = {output};\n"
' printf("\\n");\n'
" upytest_set_expected_output(exp, sizeof(exp) - 1);\n"
" upytest_execute_test(pystr);\n"
' printf("result: ");\n'
2014-05-05 11:49:52 -04:00
"}}"
)
2021-03-15 09:57:36 -04:00
testcase_struct = "struct testcase_t {name}_tests[] = {{\n{body}\n END_OF_TESTCASES\n}};"
testcase_member = ' {{ "{desc}", {func}, TT_ENABLED_, 0, 0 }},'
2014-05-05 11:49:52 -04:00
2021-03-15 09:57:36 -04:00
testgroup_struct = "struct testgroup_t groups[] = {{\n{body}\n END_OF_GROUPS\n}};"
testgroup_member = ' {{ "{name}", {name}_tests }},'
2014-05-05 11:49:52 -04:00
## XXX: may be we could have `--without <groups>` argument...
# currently these tests are selected because they pass on qemu-arm
test_dirs = (
"basics",
"micropython",
"misc",
"extmod",
"float",
"inlineasm",
"qemu-arm",
) # 'import', 'io',)
exclude_tests = (
# pattern matching in .exp
2021-03-15 09:57:36 -04:00
"basics/bytes_compare3.py",
"extmod/ticks_diff.py",
"extmod/time_ms_us.py",
"extmod/uheapq_timeq.py",
# unicode char issue
2021-03-15 09:57:36 -04:00
"extmod/ujson_loads.py",
# doesn't output to python stdout
2021-03-15 09:57:36 -04:00
"extmod/ure_debug.py",
"extmod/vfs_basic.py",
"extmod/vfs_fat_ramdisk.py",
"extmod/vfs_fat_fileio.py",
"extmod/vfs_fat_fsusermount.py",
"extmod/vfs_fat_oldproto.py",
# rounding issues
2021-03-15 09:57:36 -04:00
"float/float_divmod.py",
# requires double precision floating point to work
2021-03-15 09:57:36 -04:00
"float/float2int_doubleprec_intbig.py",
"float/float_parse_doubleprec.py",
# inline asm FP tests (require Cortex-M4)
2021-03-15 09:57:36 -04:00
"inlineasm/asmfpaddsub.py",
"inlineasm/asmfpcmp.py",
"inlineasm/asmfpldrstr.py",
"inlineasm/asmfpmuldiv.py",
"inlineasm/asmfpsqrt.py",
# different filename in output
2021-03-15 09:57:36 -04:00
"micropython/emg_exc.py",
"micropython/heapalloc_traceback.py",
# don't have emergency exception buffer
"micropython/heapalloc_exc_compressed_emg_exc.py",
# pattern matching in .exp
2021-03-15 09:57:36 -04:00
"micropython/meminfo.py",
# needs sys stdfiles
"misc/print_exception.py",
# settrace .exp files are too large
"misc/sys_settrace_loop.py",
"misc/sys_settrace_generator.py",
"misc/sys_settrace_features.py",
# don't have f-string
"basics/string_fstring.py",
"basics/string_fstring_debug.py",
)
2014-05-05 11:49:52 -04:00
output = []
tests = []
2021-03-15 09:57:36 -04:00
argparser = argparse.ArgumentParser(
description="Convert native MicroPython tests to tinytest/upytesthelper C code"
)
argparser.add_argument("--stdin", action="store_true", help="read list of tests from stdin")
argparser.add_argument("--exclude", action="append", help="exclude test by name")
args = argparser.parse_args()
if not args.stdin:
if args.exclude:
exclude_tests += tuple(args.exclude)
for group in test_dirs:
2021-03-15 09:57:36 -04:00
tests += [test for test in glob("{}/*.py".format(group)) if test not in exclude_tests]
else:
for l in sys.stdin:
tests.append(l.rstrip())
2014-05-05 11:49:52 -04:00
output.extend([test_function.format(**script_to_map(test)) for test in tests])
testcase_members = [testcase_member.format(**chew_filename(test)) for test in tests]
2021-03-15 09:57:36 -04:00
output.append(testcase_struct.format(name="", body="\n".join(testcase_members)))
2014-05-05 11:49:52 -04:00
testgroup_members = [testgroup_member.format(name=group) for group in [""]]
2014-05-05 11:49:52 -04:00
2021-03-15 09:57:36 -04:00
output.append(testgroup_struct.format(body="\n".join(testgroup_members)))
2014-05-05 11:49:52 -04:00
## XXX: may be we could have `--output <filename>` argument...
# Don't depend on what system locale is set, use utf8 encoding.
2021-03-15 09:57:36 -04:00
sys.stdout.buffer.write("\n\n".join(output).encode("utf8"))