tinytest-codegen.py 3.5 KB

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