@@ -89,9 +89,12 @@ def open(self, path, mode):
8989__import__('__injected_test')
9090"""
9191
92+ # Platforms associated with the unix port, values of `sys.platform`.
93+ PC_PLATFORMS = ("darwin" , "linux" , "win32" )
94+
9295# Tests to skip on specific targets.
9396# These are tests that are difficult to detect that they should not be run on the given target.
94- target_tests_to_skip = {
97+ platform_tests_to_skip = {
9598 "esp8266" : (
9699 "micropython/viper_args.py" , # too large
97100 "micropython/viper_binop_arith.py" , # too large
@@ -161,7 +164,7 @@ def open(self, path, mode):
161164 "micropython/extreme_exc.py" ,
162165 "micropython/heapalloc_exc_compressed_emg_exc.py" ,
163166 ),
164- "wipy " : (
167+ "WiPy " : (
165168 "misc/print_exception.py" , # requires error reporting full
166169 ),
167170 "zephyr" : (
@@ -197,6 +200,53 @@ def convert_regex_escapes(line):
197200 return bytes ("" .join (cs ), "utf8" )
198201
199202
203+ def get_test_instance (test_instance , baudrate , user , password ):
204+ if test_instance .startswith ("port:" ):
205+ _ , port = test_instance .split (":" , 1 )
206+ elif test_instance == "unix" :
207+ return None
208+ elif test_instance == "webassembly" :
209+ return PyboardNodeRunner ()
210+ elif test_instance .startswith ("a" ) and test_instance [1 :].isdigit ():
211+ port = "/dev/ttyACM" + test_instance [1 :]
212+ elif test_instance .startswith ("u" ) and test_instance [1 :].isdigit ():
213+ port = "/dev/ttyUSB" + test_instance [1 :]
214+ elif test_instance .startswith ("c" ) and test_instance [1 :].isdigit ():
215+ port = "COM" + test_instance [1 :]
216+ else :
217+ # Assume it's a device path.
218+ port = test_instance
219+
220+ global pyboard
221+ sys .path .append (base_path ("../tools" ))
222+ import pyboard
223+
224+ pyb = pyboard .Pyboard (port , baudrate , user , password )
225+ pyboard .Pyboard .run_script_on_remote_target = run_script_on_remote_target
226+ pyb .enter_raw_repl ()
227+ return pyb
228+
229+
230+ def detect_test_platform (pyb , args ):
231+ # Run a script to detect various bits of information about the target test instance.
232+ output = run_feature_check (pyb , args , "target_info.py" )
233+ if output .endswith (b"CRASH" ):
234+ raise ValueError ("cannot detect platform: {}" .format (output ))
235+ platform , arch = str (output , "ascii" ).strip ().split ()
236+ if arch == "None" :
237+ arch = None
238+
239+ args .platform = platform
240+ args .arch = arch
241+ if arch and not args .mpy_cross_flags :
242+ args .mpy_cross_flags = "-march=" + arch
243+
244+ print ("platform={}" .format (platform ), end = "" )
245+ if arch :
246+ print (" arch={}" .format (arch ), end = "" )
247+ print ()
248+
249+
200250def prepare_script_for_target (args , * , script_filename = None , script_text = None , force_plain = False ):
201251 if force_plain or (not args .via_mpy and args .emit == "bytecode" ):
202252 if script_filename is not None :
@@ -706,18 +756,18 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1):
706756 skip_tests .add ("extmod/ssl_poll.py" )
707757
708758 # Skip thread mutation tests on targets that don't have the GIL.
709- if args .target in ("rp2" , "unix" ):
759+ if args .platform in PC_PLATFORMS + ("rp2" ,):
710760 for t in tests :
711761 if t .startswith ("thread/mutate_" ):
712762 skip_tests .add (t )
713763
714764 # Some tests shouldn't be run on pyboard
715- if args .target != "unix" :
765+ if args .platform not in PC_PLATFORMS :
716766 skip_tests .add ("basics/exception_chain.py" ) # warning is not printed
717767 skip_tests .add ("micropython/meminfo.py" ) # output is very different to PC output
718768
719- # Skip target -specific tests.
720- skip_tests .update (target_tests_to_skip .get (args .target , ()))
769+ # Skip platform -specific tests.
770+ skip_tests .update (platform_tests_to_skip .get (args .platform , ()))
721771
722772 # Some tests are known to fail on 64-bit machines
723773 if pyb is None and platform .architecture ()[0 ] == "64bit" :
@@ -932,17 +982,38 @@ def main():
932982 formatter_class = argparse .RawDescriptionHelpFormatter ,
933983 description = """Run and manage tests for MicroPython.
934984
985+ By default the tests are run against the unix port of MicroPython. To run it
986+ against something else, use the -t option. See below for details.
987+
935988Tests are discovered by scanning test directories for .py files or using the
936989specified test files. If test files nor directories are specified, the script
937990expects to be ran in the tests directory (where this file is located) and the
938991builtin tests suitable for the target platform are ran.
992+
939993When running tests, run-tests.py compares the MicroPython output of the test with the output
940994produced by running the test through CPython unless a <test>.exp file is found, in which
941995case it is used as comparison.
996+
942997If a test fails, run-tests.py produces a pair of <test>.out and <test>.exp files in the result
943998directory with the MicroPython output and the expectations, respectively.
944999""" ,
9451000 epilog = """\
1001+ The -t option accepts the following for the test instance:
1002+ - unix - use the unix port of MicroPython, specified by the MICROPY_MICROPYTHON
1003+ environment variable (which defaults to the standard variant of either the unix
1004+ or windows ports, depending on the host platform)
1005+ - webassembly - use the webassembly port of MicroPython, specified by the
1006+ MICROPY_MICROPYTHON_MJS environment variable (which defaults to the standard
1007+ variant of the webassembly port)
1008+ - port:<device> - connect to and use the given serial port device
1009+ - a<n> - connect to and use /dev/ttyACM<n>
1010+ - u<n> - connect to and use /dev/ttyUSB<n>
1011+ - c<n> - connect to and use COM<n>
1012+ - exec:<command> - execute a command and attach to its stdin/stdout
1013+ - execpty:<command> - execute a command and attach to the printed /dev/pts/<n> device
1014+ - <a>.<b>.<c>.<d> - connect to the given IPv4 address
1015+ - anything else specifies a serial port
1016+
9461017Options -i and -e can be multiple and processed in the order given. Regex
9471018"search" (vs "match") operation is used. An action (include/exclude) of
9481019the last matching regex is used:
@@ -951,11 +1022,8 @@ def main():
9511022 run-tests.py -e async -i async_foo - include all, exclude async, yet still include async_foo
9521023""" ,
9531024 )
954- cmd_parser .add_argument ("--target" , default = "unix" , help = "the target platform" )
9551025 cmd_parser .add_argument (
956- "--device" ,
957- default = "/dev/ttyACM0" ,
958- help = "the serial device or the IP address of the pyboard" ,
1026+ "-t" , "--test-instance" , default = "unix" , help = "the MicroPython instance to test"
9591027 )
9601028 cmd_parser .add_argument (
9611029 "-b" , "--baudrate" , default = 115200 , help = "the baud rate of the serial device"
@@ -1039,43 +1107,11 @@ def main():
10391107
10401108 sys .exit (0 )
10411109
1042- LOCAL_TARGETS = (
1043- "unix" ,
1044- "webassembly" ,
1045- )
1046- EXTERNAL_TARGETS = (
1047- "pyboard" ,
1048- "wipy" ,
1049- "esp8266" ,
1050- "esp32" ,
1051- "minimal" ,
1052- "nrf" ,
1053- "qemu" ,
1054- "renesas-ra" ,
1055- "rp2" ,
1056- "zephyr" ,
1057- )
1058- if args .target in LOCAL_TARGETS :
1059- pyb = None
1060- if args .target == "webassembly" :
1061- pyb = PyboardNodeRunner ()
1062- elif args .target in EXTERNAL_TARGETS :
1063- global pyboard
1064- sys .path .append (base_path ("../tools" ))
1065- import pyboard
1066-
1067- pyb = pyboard .Pyboard (args .device , args .baudrate , args .user , args .password )
1068- pyboard .Pyboard .run_script_on_remote_target = run_script_on_remote_target
1069- pyb .enter_raw_repl ()
1070- else :
1071- raise ValueError ("target must be one of %s" % ", " .join (LOCAL_TARGETS + EXTERNAL_TARGETS ))
1110+ # Get the test instance to run on.
1111+ pyb = get_test_instance (args .test_instance , args .baudrate , args .user , args .password )
10721112
1073- # Automatically detect the native architecture for mpy-cross if not given.
1074- if not args .mpy_cross_flags :
1075- output = run_feature_check (pyb , args , "target_info.py" )
1076- arch = str (output , "ascii" ).strip ()
1077- if arch != "None" :
1078- args .mpy_cross_flags = "-march=" + arch
1113+ # Automatically detect the platform.
1114+ detect_test_platform (pyb , args )
10791115
10801116 if args .run_failures and (any (args .files ) or args .test_dirs is not None ):
10811117 raise ValueError (
@@ -1091,7 +1127,7 @@ def main():
10911127 tests = []
10921128 elif len (args .files ) == 0 :
10931129 test_extensions = ("*.py" ,)
1094- if args .target == "webassembly" :
1130+ if args .platform == "webassembly" :
10951131 test_extensions += ("*.js" , "*.mjs" )
10961132
10971133 if args .test_dirs is None :
@@ -1101,23 +1137,23 @@ def main():
11011137 "misc" ,
11021138 "extmod" ,
11031139 )
1104- if args .target == "pyboard" :
1140+ if args .platform == "pyboard" :
11051141 # run pyboard tests
11061142 test_dirs += ("float" , "stress" , "inlineasm" , "ports/stm32" )
1107- elif args .target in ( "renesas-ra" ) :
1143+ elif args .platform == "renesas-ra" :
11081144 test_dirs += ("float" , "inlineasm" , "ports/renesas-ra" )
1109- elif args .target == "rp2" :
1145+ elif args .platform == "rp2" :
11101146 test_dirs += ("float" , "stress" , "thread" , "ports/rp2" )
11111147 if "arm" in args .mpy_cross_flags :
11121148 test_dirs += ("inlineasm" ,)
1113- elif args .target == "esp32" :
1149+ elif args .platform == "esp32" :
11141150 test_dirs += ("float" , "stress" , "thread" )
1115- elif args .target in ("esp8266" , "minimal" , "nrf" ):
1151+ elif args .platform in ("esp8266" , "minimal" , "nrf" ):
11161152 test_dirs += ("float" ,)
1117- elif args .target == "wipy " :
1153+ elif args .platform == "WiPy " :
11181154 # run WiPy tests
11191155 test_dirs += ("ports/cc3200" ,)
1120- elif args .target == "unix" :
1156+ elif args .platform in PC_PLATFORMS :
11211157 # run PC tests
11221158 test_dirs += (
11231159 "float" ,
@@ -1128,13 +1164,13 @@ def main():
11281164 "cmdline" ,
11291165 "ports/unix" ,
11301166 )
1131- elif args .target == "qemu" :
1167+ elif args .platform == "qemu" :
11321168 test_dirs += (
11331169 "float" ,
11341170 "inlineasm" ,
11351171 "ports/qemu" ,
11361172 )
1137- elif args .target == "webassembly" :
1173+ elif args .platform == "webassembly" :
11381174 test_dirs += ("float" , "ports/webassembly" )
11391175 else :
11401176 # run tests from these directories
0 commit comments