1#!/usr/bin/env python3 2 3import os, sys 4from glob import glob 5from re import sub 6import argparse 7 8 9def escape(s): 10 s = s.decode() 11 lookup = { 12 "\0": "\\0", 13 "\t": "\\t", 14 "\n": '\\n"\n"', 15 "\r": "\\r", 16 "\\": "\\\\", 17 '"': '\\"', 18 } 19 return '""\n"{}"'.format("".join([lookup[x] if x in lookup else x for x in s])) 20 21 22def chew_filename(t): 23 return {"func": "test_{}_fn".format(sub(r"/|\.|-", "_", t)), "desc": t} 24 25 26def script_to_map(test_file): 27 r = {"name": chew_filename(test_file)["func"]} 28 with open(test_file, "rb") as f: 29 r["script"] = escape(f.read()) 30 with open(test_file + ".exp", "rb") as f: 31 r["output"] = escape(f.read()) 32 return r 33 34 35test_function = ( 36 "void {name}(void* data) {{\n" 37 " static const char pystr[] = {script};\n" 38 " static const char exp[] = {output};\n" 39 ' printf("\\n");\n' 40 " upytest_set_expected_output(exp, sizeof(exp) - 1);\n" 41 " upytest_execute_test(pystr);\n" 42 ' printf("result: ");\n' 43 "}}" 44) 45 46testcase_struct = "struct testcase_t {name}_tests[] = {{\n{body}\n END_OF_TESTCASES\n}};" 47testcase_member = ' {{ "{desc}", {func}, TT_ENABLED_, 0, 0 }},' 48 49testgroup_struct = "struct testgroup_t groups[] = {{\n{body}\n END_OF_GROUPS\n}};" 50testgroup_member = ' {{ "{name}", {name}_tests }},' 51 52## XXX: may be we could have `--without <groups>` argument... 53# currently these tests are selected because they pass on qemu-arm 54test_dirs = ( 55 "basics", 56 "micropython", 57 "misc", 58 "extmod", 59 "float", 60 "inlineasm", 61 "qemu-arm", 62) # 'import', 'io',) 63exclude_tests = ( 64 # pattern matching in .exp 65 "basics/bytes_compare3.py", 66 "extmod/ticks_diff.py", 67 "extmod/time_ms_us.py", 68 "extmod/uheapq_timeq.py", 69 # unicode char issue 70 "extmod/ujson_loads.py", 71 # doesn't output to python stdout 72 "extmod/ure_debug.py", 73 "extmod/vfs_basic.py", 74 "extmod/vfs_fat_ramdisk.py", 75 "extmod/vfs_fat_fileio.py", 76 "extmod/vfs_fat_fsusermount.py", 77 "extmod/vfs_fat_oldproto.py", 78 # rounding issues 79 "float/float_divmod.py", 80 # requires double precision floating point to work 81 "float/float2int_doubleprec_intbig.py", 82 "float/float_parse_doubleprec.py", 83 # inline asm FP tests (require Cortex-M4) 84 "inlineasm/asmfpaddsub.py", 85 "inlineasm/asmfpcmp.py", 86 "inlineasm/asmfpldrstr.py", 87 "inlineasm/asmfpmuldiv.py", 88 "inlineasm/asmfpsqrt.py", 89 # different filename in output 90 "micropython/emg_exc.py", 91 "micropython/heapalloc_traceback.py", 92 # don't have emergency exception buffer 93 "micropython/heapalloc_exc_compressed_emg_exc.py", 94 # pattern matching in .exp 95 "micropython/meminfo.py", 96 # needs sys stdfiles 97 "misc/print_exception.py", 98 # settrace .exp files are too large 99 "misc/sys_settrace_loop.py", 100 "misc/sys_settrace_generator.py", 101 "misc/sys_settrace_features.py", 102 # don't have f-string 103 "basics/string_fstring.py", 104 "basics/string_fstring_debug.py", 105) 106 107output = [] 108tests = [] 109 110argparser = argparse.ArgumentParser( 111 description="Convert native MicroPython tests to tinytest/upytesthelper C code" 112) 113argparser.add_argument("--stdin", action="store_true", help="read list of tests from stdin") 114argparser.add_argument("--exclude", action="append", help="exclude test by name") 115args = argparser.parse_args() 116 117if not args.stdin: 118 if args.exclude: 119 exclude_tests += tuple(args.exclude) 120 for group in test_dirs: 121 tests += [test for test in glob("{}/*.py".format(group)) if test not in exclude_tests] 122else: 123 for l in sys.stdin: 124 tests.append(l.rstrip()) 125 126output.extend([test_function.format(**script_to_map(test)) for test in tests]) 127testcase_members = [testcase_member.format(**chew_filename(test)) for test in tests] 128output.append(testcase_struct.format(name="", body="\n".join(testcase_members))) 129 130testgroup_members = [testgroup_member.format(name=group) for group in [""]] 131 132output.append(testgroup_struct.format(body="\n".join(testgroup_members))) 133 134## XXX: may be we could have `--output <filename>` argument... 135# Don't depend on what system locale is set, use utf8 encoding. 136sys.stdout.buffer.write("\n\n".join(output).encode("utf8")) 137