158 lines
4.6 KiB
Python
Executable file
158 lines
4.6 KiB
Python
Executable file
#! /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()
|