summaryrefslogtreecommitdiff
path: root/tools/tinytest-codegen.py
blob: 0f9e62847656991e73bf9969e0850d6b6a8fd6e6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#! /usr/bin/env python3

import os, sys
from glob import glob
from re import sub

def escape(s):
  lookup = {
    '\0': '\\0',
    '\t': '\\t',
    '\n': '\\n\"\n\"',
    '\r': '\\r',
    '\\': '\\\\',
    '\"': '\\\"',
  }
  return "\"\"\n\"{}\"".format(''.join([lookup[x] if x in lookup else x for x in s]))

def chew_filename(t):
  return { 'func': "test_{}_fn".format(sub(r'/|\.|-', '_', t)), 'desc': t.split('/')[1] }

def script_to_map(t):
  r = { 'name': chew_filename(t)['func'] }
  with open(t) as test:
    script = test.readlines()

    # Test for import skip_if and inject it into the test as needed.
    if "import skip_if\n" in script:
      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(''.join(script))
  return r

test_function = (
    "void {name}(void* data) {{\n"
    "  const char * pystr = {script};\n"
    "  do_str(pystr);\n"
    "}}"
)

testcase_struct = (
    "struct testcase_t {name}_tests[] = {{\n{body}\n  END_OF_TESTCASES\n}};"
)
testcase_member = (
    "  {{ \"{desc}\", {func}, TT_ENABLED_, 0, 0 }},"
)

testgroup_struct = (
    "struct testgroup_t groups[] = {{\n{body}\n  END_OF_GROUPS\n}};"
)
testgroup_member = (
    "  {{ \"{name}/\", {name}_tests }},"
)

## XXX: may be we could have `--without <groups>` argument...
# currently these tests are selected because they pass on qemu-arm
test_dirs = ('basics', 'micropython', 'float', 'extmod', 'inlineasm') # 'import', 'io', 'misc')
exclude_tests = (
    'float/float2int_doubleprec_intbig.py', # requires double precision floating point to work
    'inlineasm/asmfpaddsub.py', 'inlineasm/asmfpcmp.py', 'inlineasm/asmfpldrstr.py', 'inlineasm/asmfpmuldiv.py', 'inlineasm/asmfpsqrt.py',
    'extmod/ticks_diff.py', 'extmod/time_ms_us.py', 'extmod/uheapq_timeq.py',
    'extmod/vfs_fat_ramdisk.py', 'extmod/vfs_fat_fileio.py', 'extmod/vfs_fat_fsusermount.py', 'extmod/vfs_fat_oldproto.py',
)

output = []

for group in test_dirs:
  tests = [test for test in glob('{}/*.py'.format(group)) if test not in exclude_tests]
  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]
  output.append(testcase_struct.format(name=group, body='\n'.join(testcase_members)))

testgroup_members = [testgroup_member.format(name=group) for group in test_dirs]

output.append(testgroup_struct.format(body='\n'.join(testgroup_members)))

## XXX: may be we could have `--output <filename>` argument...
print('\n\n'.join(output))