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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
#! /usr/bin/env python3
import os
import subprocess
import sys
import argparse
import re
from glob import glob
from collections import defaultdict
run_tests_module = __import__("run-tests")
sys.path.append(run_tests_module.base_path("../tools"))
import pyboard
if os.name == "nt":
MICROPYTHON = os.getenv(
"MICROPY_MICROPYTHON", "../ports/windows/build-standard/micropython.exe"
)
else:
MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/unix/build-standard/micropython")
injected_bench_code = b"""
import time
class bench_class:
ITERS = 20000000
@staticmethod
def run(test):
t = time.ticks_us()
test(bench_class.ITERS)
t = time.ticks_diff(time.ticks_us(), t)
s, us = divmod(t, 1_000_000)
print("{}.{:06}".format(s, us))
import sys
sys.modules['bench'] = bench_class
"""
def execbench(pyb, filename, iters):
with open(filename, "rb") as f:
pyfile = f.read()
code = (injected_bench_code + pyfile).replace(b"20000000", str(iters).encode("utf-8"))
return pyb.exec(code).replace(b"\r\n", b"\n")
def run_tests(pyb, test_dict, iters):
test_count = 0
testcase_count = 0
for base_test, tests in sorted(test_dict.items()):
print(base_test + ":")
baseline = None
for test_file in tests:
# run MicroPython
if pyb is None:
# run on PC
try:
output_mupy = subprocess.check_output(
[MICROPYTHON, "-X", "emit=bytecode", test_file[0]]
)
except subprocess.CalledProcessError:
output_mupy = b"CRASH"
else:
# run on pyboard
pyb.enter_raw_repl()
try:
output_mupy = execbench(pyb, test_file[0], iters)
except pyboard.PyboardError:
output_mupy = b"CRASH"
try:
output_mupy = float(output_mupy.strip())
except ValueError:
output_mupy = -1
test_file[1] = output_mupy
testcase_count += 1
if baseline is None:
baseline = test_file[1]
print(
" %.3fs (%+06.2f%%) %s"
% (test_file[1], (test_file[1] * 100 / baseline) - 100, test_file[0])
)
test_count += 1
print("{} tests performed ({} individual testcases)".format(test_count, testcase_count))
# all tests succeeded
return True
def main():
cmd_parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description=f"""Run and manage tests for MicroPython.
{run_tests_module.test_instance_description}
{run_tests_module.test_directory_description}
""",
epilog=run_tests_module.test_instance_epilog,
)
cmd_parser.add_argument(
"-t", "--test-instance", default="unix", help="the MicroPython instance to test"
)
cmd_parser.add_argument(
"-b", "--baudrate", default=115200, help="the baud rate of the serial device"
)
cmd_parser.add_argument("-u", "--user", default="micro", help="the telnet login username")
cmd_parser.add_argument("-p", "--password", default="python", help="the telnet login password")
cmd_parser.add_argument(
"-d", "--test-dirs", nargs="*", help="input test directories (if no files given)"
)
cmd_parser.add_argument(
"-I",
"--iters",
type=int,
default=200_000,
help="number of test iterations, only for remote instances (default 200,000)",
)
cmd_parser.add_argument("files", nargs="*", help="input test files")
args = cmd_parser.parse_args()
# Note pyboard support is copied over from run-tests.py, not tests, and likely needs revamping
pyb = run_tests_module.get_test_instance(
args.test_instance, args.baudrate, args.user, args.password
)
if len(args.files) == 0:
if args.test_dirs:
test_dirs = tuple(args.test_dirs)
else:
test_dirs = ("internal_bench",)
tests = sorted(
test_file
for test_files in (glob("{}/*.py".format(dir)) for dir in test_dirs)
for test_file in test_files
)
else:
# tests explicitly given
tests = sorted(args.files)
test_dict = defaultdict(lambda: [])
for t in tests:
m = re.match(r"(.+?)-(.+)\.py", t)
if not m:
continue
test_dict[m.group(1)].append([t, None])
if not run_tests(pyb, test_dict, args.iters):
sys.exit(1)
if __name__ == "__main__":
main()
|