Skip to content

Commit 2291045

Browse files
committed
tests/run-tests.py: Automatically skip tests that are too large.
Some tests are just too big for targets that don't have much heap memory, eg `tests/extmod/vfs_rom.py`. Other tests are too large because the target doesn't have enough IRAM for native code, eg esp8266 running `tests/micropython/viper_args.py`. Previously, such tests were explicitly skipped on targets known to have little memory, eg esp8266. But this doesn't scale to multiple targets, nor to more and more tests which are too large. This commit addresses that by adding logic to the test runner so it can automatically skip tests when they don't fit in the target's memory. It does this by prepending a `print('START TEST')` to every test, and if a `MemoryError` occurs before that line is printed then the test was too big. This works for standard tests, tests that go via .mpy files, and tests that run in native emitter mode via .mpy files. For tests that are too big, it prints `lrge <test name>` on the output, and at the end prints them on a separate line of skipped tests so they can be distinguished. They are also distinguished in the `_result.json` file as a skipped test with reason "too large". Signed-off-by: Damien George <damien@micropython.org>
1 parent 4c55b08 commit 2291045

File tree

2 files changed

+45
-10
lines changed

2 files changed

+45
-10
lines changed

tests/misc/print_exception.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# Test sys.print_exception (MicroPython) / traceback.print_exception (CPython).
2+
13
try:
24
import io
35
import sys

tests/run-tests.py

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -105,14 +105,11 @@ def open(self, path, mode):
105105
# These are tests that are difficult to detect that they should not be run on the given target.
106106
platform_tests_to_skip = {
107107
"esp8266": (
108-
"micropython/viper_args.py", # too large
109-
"micropython/viper_binop_arith.py", # too large
110-
"misc/rge_sm.py", # too large
108+
"misc/rge_sm.py", # incorrect values due to object representation C
111109
),
112110
"minimal": (
113111
"basics/class_inplace_op.py", # all special methods not supported
114112
"basics/subclass_native_init.py", # native subclassing corner cases not support
115-
"misc/rge_sm.py", # too large
116113
"micropython/opt_level.py", # don't assume line numbers are stored
117114
),
118115
"nrf": (
@@ -315,9 +312,21 @@ def prepare_script_for_target(args, *, script_filename=None, script_text=None, f
315312

316313

317314
def run_script_on_remote_target(pyb, args, test_file, is_special):
318-
had_crash, script = prepare_script_for_target(
319-
args, script_filename=test_file, force_plain=is_special
320-
)
315+
with open(test_file, "rb") as f:
316+
script = f.read()
317+
318+
# If the test is not a special test, prepend it with a print to indicate that it started.
319+
# If the print does not execute this means that the test did not even start, eg it was
320+
# too large for the target.
321+
prepend_start_test = not is_special
322+
if prepend_start_test:
323+
if script.startswith(b"#"):
324+
script = b"print('START TEST')" + script
325+
else:
326+
script = b"print('START TEST')\n" + script
327+
328+
had_crash, script = prepare_script_for_target(args, script_text=script, force_plain=is_special)
329+
321330
if had_crash:
322331
return True, script
323332

@@ -328,9 +337,19 @@ def run_script_on_remote_target(pyb, args, test_file, is_special):
328337
except pyboard.PyboardError as e:
329338
had_crash = True
330339
if not is_special and e.args[0] == "exception":
331-
output_mupy = e.args[1] + e.args[2] + b"CRASH"
340+
if prepend_start_test and e.args[1] == b"" and b"MemoryError" in e.args[2]:
341+
output_mupy = b"SKIP-TOO-LARGE\n"
342+
else:
343+
output_mupy = e.args[1] + e.args[2] + b"CRASH"
332344
else:
333345
output_mupy = bytes(e.args[0], "ascii") + b"\nCRASH"
346+
347+
if prepend_start_test:
348+
if output_mupy.startswith(b"START TEST\r\n"):
349+
output_mupy = output_mupy.removeprefix(b"START TEST\r\n")
350+
else:
351+
had_crash = True
352+
334353
return had_crash, output_mupy
335354

336355

@@ -474,7 +493,7 @@ def send_get(what):
474493
output_mupy = output_mupy.replace(b"\r\n", b"\n")
475494

476495
# don't try to convert the output if we should skip this test
477-
if had_crash or output_mupy in (b"SKIP\n", b"CRASH"):
496+
if had_crash or output_mupy in (b"SKIP\n", b"SKIP-TOO-LARGE\n", b"CRASH"):
478497
return output_mupy
479498

480499
# skipped special tests will output "SKIP" surrounded by other interpreter debug output
@@ -911,6 +930,10 @@ def run_one_test(test_file):
911930
print("skip ", test_file)
912931
test_results.append((test_name, test_file, "skip", ""))
913932
return
933+
elif output_mupy == b"SKIP-TOO-LARGE\n":
934+
print("lrge ", test_file)
935+
test_results.append((test_name, test_file, "skip", "too large"))
936+
return
914937

915938
# Look at the output of the test to see if unittest was used.
916939
uses_unittest = False
@@ -1035,7 +1058,10 @@ def run_one_test(test_file):
10351058

10361059
test_results = test_results.value
10371060
passed_tests = list(r for r in test_results if r[2] == "pass")
1038-
skipped_tests = list(r for r in test_results if r[2] == "skip")
1061+
skipped_tests = list(r for r in test_results if r[2] == "skip" and r[3] != "too large")
1062+
skipped_tests_too_large = list(
1063+
r for r in test_results if r[2] == "skip" and r[3] == "too large"
1064+
)
10391065
failed_tests = list(r for r in test_results if r[2] == "fail")
10401066

10411067
print(
@@ -1052,6 +1078,13 @@ def run_one_test(test_file):
10521078
)
10531079
)
10541080

1081+
if len(skipped_tests_too_large) > 0:
1082+
print(
1083+
"{} tests skipped because they are too large: {}".format(
1084+
len(skipped_tests_too_large), " ".join(test[0] for test in skipped_tests_too_large)
1085+
)
1086+
)
1087+
10551088
if len(failed_tests) > 0:
10561089
print(
10571090
"{} tests failed: {}".format(

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy