@@ -308,7 +308,9 @@ def send_get(what):
308
308
309
309
else :
310
310
# run via pyboard interface
311
- had_crash , output_mupy = run_script_on_remote_target (pyb , args , test_file , is_special )
311
+ had_crash , output_mupy = pyb .run_script_on_remote_target (
312
+ args , test_file_abspath , is_special
313
+ )
312
314
313
315
# canonical form for all ports/platforms is to use \n for end-of-line
314
316
output_mupy = output_mupy .replace (b"\r \n " , b"\n " )
@@ -393,6 +395,51 @@ def value(self):
393
395
return self ._value
394
396
395
397
398
+ class PyboardNodeRunner :
399
+ def __init__ (self ):
400
+ mjs = os .getenv ("MICROPY_MICROPYTHON_MJS" )
401
+ if mjs is None :
402
+ mjs = base_path ("../ports/webassembly/build-standard/micropython.mjs" )
403
+ else :
404
+ mjs = os .path .abspath (mjs )
405
+ self .micropython_mjs = mjs
406
+
407
+ def close (self ):
408
+ pass
409
+
410
+ def run_script_on_remote_target (self , args , test_file , is_special ):
411
+ cwd = os .path .dirname (test_file )
412
+
413
+ # Create system command list.
414
+ cmdlist = ["node" ]
415
+ if test_file .endswith (".py" ):
416
+ # Run a Python script indirectly via "node micropython.mjs <script.py>".
417
+ cmdlist .append (self .micropython_mjs )
418
+ if args .heapsize is not None :
419
+ cmdlist .extend (["-X" , "heapsize=" + args .heapsize ])
420
+ cmdlist .append (test_file )
421
+ else :
422
+ # Run a js/mjs script directly with Node, passing in the path to micropython.mjs.
423
+ cmdlist .append (test_file )
424
+ cmdlist .append (self .micropython_mjs )
425
+
426
+ # Run the script.
427
+ try :
428
+ had_crash = False
429
+ output_mupy = subprocess .check_output (
430
+ cmdlist , stderr = subprocess .STDOUT , timeout = TEST_TIMEOUT , cwd = cwd
431
+ )
432
+ except subprocess .CalledProcessError as er :
433
+ had_crash = True
434
+ output_mupy = er .output + b"CRASH"
435
+ except subprocess .TimeoutExpired as er :
436
+ had_crash = True
437
+ output_mupy = (er .output or b"" ) + b"TIMEOUT"
438
+
439
+ # Return the results.
440
+ return had_crash , output_mupy
441
+
442
+
396
443
def run_tests (pyb , tests , args , result_dir , num_threads = 1 ):
397
444
test_count = ThreadSafeCounter ()
398
445
testcase_count = ThreadSafeCounter ()
@@ -631,6 +678,20 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1):
631
678
) # RA fsp rtc function doesn't support nano sec info
632
679
elif args .target == "qemu-arm" :
633
680
skip_tests .add ("misc/print_exception.py" ) # requires sys stdfiles
681
+ elif args .target == "webassembly" :
682
+ skip_tests .add ("basics/string_format_modulo.py" ) # can't print nulls to stdout
683
+ skip_tests .add ("basics/string_strip.py" ) # can't print nulls to stdout
684
+ skip_tests .add ("extmod/binascii_a2b_base64.py" )
685
+ skip_tests .add ("extmod/re_stack_overflow.py" )
686
+ skip_tests .add ("extmod/time_res.py" )
687
+ skip_tests .add ("extmod/vfs_posix.py" )
688
+ skip_tests .add ("extmod/vfs_posix_enoent.py" )
689
+ skip_tests .add ("extmod/vfs_posix_paths.py" )
690
+ skip_tests .add ("extmod/vfs_userfs.py" )
691
+ skip_tests .add ("micropython/emg_exc.py" )
692
+ skip_tests .add ("micropython/extreme_exc.py" )
693
+ skip_tests .add ("micropython/heapalloc_exc_compressed_emg_exc.py" )
694
+ skip_tests .add ("micropython/import_mpy_invalid.py" )
634
695
635
696
# Some tests are known to fail on 64-bit machines
636
697
if pyb is None and platform .architecture ()[0 ] == "64bit" :
@@ -977,6 +1038,7 @@ def main():
977
1038
LOCAL_TARGETS = (
978
1039
"unix" ,
979
1040
"qemu-arm" ,
1041
+ "webassembly" ,
980
1042
)
981
1043
EXTERNAL_TARGETS = (
982
1044
"pyboard" ,
@@ -997,6 +1059,8 @@ def main():
997
1059
args .mpy_cross_flags = "-march=host"
998
1060
elif args .target == "qemu-arm" :
999
1061
args .mpy_cross_flags = "-march=armv7m"
1062
+ if args .target == "webassembly" :
1063
+ pyb = PyboardNodeRunner ()
1000
1064
elif args .target in EXTERNAL_TARGETS :
1001
1065
global pyboard
1002
1066
sys .path .append (base_path ("../tools" ))
@@ -1015,6 +1079,7 @@ def main():
1015
1079
args .mpy_cross_flags = "-march=armv7m"
1016
1080
1017
1081
pyb = pyboard .Pyboard (args .device , args .baudrate , args .user , args .password )
1082
+ pyboard .Pyboard .run_script_on_remote_target = run_script_on_remote_target
1018
1083
pyb .enter_raw_repl ()
1019
1084
else :
1020
1085
raise ValueError ("target must be one of %s" % ", " .join (LOCAL_TARGETS + EXTERNAL_TARGETS ))
@@ -1032,6 +1097,10 @@ def main():
1032
1097
else :
1033
1098
tests = []
1034
1099
elif len (args .files ) == 0 :
1100
+ test_extensions = ("*.py" ,)
1101
+ if args .target == "webassembly" :
1102
+ test_extensions += ("*.js" , "*.mjs" )
1103
+
1035
1104
if args .test_dirs is None :
1036
1105
test_dirs = (
1037
1106
"basics" ,
@@ -1072,12 +1141,16 @@ def main():
1072
1141
"inlineasm" ,
1073
1142
"ports/qemu-arm" ,
1074
1143
)
1144
+ elif args .target == "webassembly" :
1145
+ test_dirs += ("float" ,)
1075
1146
else :
1076
1147
# run tests from these directories
1077
1148
test_dirs = args .test_dirs
1078
1149
tests = sorted (
1079
1150
test_file
1080
- for test_files in (glob ("{}/*.py" .format (dir )) for dir in test_dirs )
1151
+ for test_files in (
1152
+ glob (os .path .join (dir , ext )) for dir in test_dirs for ext in test_extensions
1153
+ )
1081
1154
for test_file in test_files
1082
1155
)
1083
1156
else :
0 commit comments