Damien George | 929a675 | 2014-04-02 15:31:39 +0100 | [diff] [blame] | 1 | #! /usr/bin/env python3 |
Damien | 39977a5 | 2013-12-29 22:34:42 +0000 | [diff] [blame] | 2 | |
Markus Siemens | 19ccc6b | 2014-01-27 22:53:28 +0100 | [diff] [blame] | 3 | import os |
| 4 | import subprocess |
| 5 | import sys |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 6 | import argparse |
Markus Siemens | 19ccc6b | 2014-01-27 22:53:28 +0100 | [diff] [blame] | 7 | from glob import glob |
Damien | 39977a5 | 2013-12-29 22:34:42 +0000 | [diff] [blame] | 8 | |
Paul Sokolovsky | a7752a4 | 2014-04-04 17:28:34 +0300 | [diff] [blame] | 9 | # Tests require at least CPython 3.3. If your default python3 executable |
| 10 | # is of lower version, you can point MICROPY_CPYTHON3 environment var |
| 11 | # to the correct executable. |
Markus Siemens | 19ccc6b | 2014-01-27 22:53:28 +0100 | [diff] [blame] | 12 | if os.name == 'nt': |
Paul Sokolovsky | a7752a4 | 2014-04-04 17:28:34 +0300 | [diff] [blame] | 13 | CPYTHON3 = os.getenv('MICROPY_CPYTHON3', 'python3.exe') |
Andrew Scheller | 5709453 | 2014-04-17 01:22:45 +0100 | [diff] [blame] | 14 | MICROPYTHON = os.getenv('MICROPY_MICROPYTHON', '../windows/micropython.exe') |
Markus Siemens | 19ccc6b | 2014-01-27 22:53:28 +0100 | [diff] [blame] | 15 | else: |
Paul Sokolovsky | 34e1199 | 2014-04-03 22:06:35 +0300 | [diff] [blame] | 16 | CPYTHON3 = os.getenv('MICROPY_CPYTHON3', 'python3') |
Andrew Scheller | 5709453 | 2014-04-17 01:22:45 +0100 | [diff] [blame] | 17 | MICROPYTHON = os.getenv('MICROPY_MICROPYTHON', '../unix/micropython') |
Damien | 39977a5 | 2013-12-29 22:34:42 +0000 | [diff] [blame] | 18 | |
Paul Sokolovsky | fd232c3 | 2014-03-23 01:07:30 +0200 | [diff] [blame] | 19 | def rm_f(fname): |
| 20 | if os.path.exists(fname): |
| 21 | os.remove(fname) |
| 22 | |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 23 | def run_tests(pyb, tests): |
| 24 | test_count = 0 |
| 25 | testcase_count = 0 |
| 26 | passed_count = 0 |
| 27 | failed_tests = [] |
Paul Sokolovsky | 43d4a6f | 2014-05-10 16:52:58 +0300 | [diff] [blame] | 28 | skipped_tests = [] |
Damien | 39977a5 | 2013-12-29 22:34:42 +0000 | [diff] [blame] | 29 | |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 30 | running_under_travis = os.getenv('TRAVIS') == 'true' |
Damien | 39977a5 | 2013-12-29 22:34:42 +0000 | [diff] [blame] | 31 | |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 32 | # Set of tests that we shouldn't run under Travis CI |
| 33 | skip_travis_tests = set(['basics/memoryerror.py']) |
Damien George | 2309369 | 2014-04-03 22:44:51 +0100 | [diff] [blame] | 34 | |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 35 | for test_file in tests: |
| 36 | if running_under_travis and test_file in skip_travis_tests: |
| 37 | print("skip ", test_file) |
Paul Sokolovsky | 43d4a6f | 2014-05-10 16:52:58 +0300 | [diff] [blame] | 38 | skipped_tests.append(test_name) |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 39 | continue |
Andrew Scheller | 1b997d5 | 2014-04-16 03:28:40 +0100 | [diff] [blame] | 40 | |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 41 | # get expected output |
| 42 | test_file_expected = test_file + '.exp' |
| 43 | if os.path.isfile(test_file_expected): |
| 44 | # expected output given by a file, so read that in |
| 45 | with open(test_file_expected, 'rb') as f: |
| 46 | output_expected = f.read() |
stijn | a4dbc73 | 2014-05-11 12:45:02 +0200 | [diff] [blame] | 47 | if os.name == 'nt': |
| 48 | output_expected = output_expected.replace(b'\n', b'\r\n') |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 49 | else: |
stijn | a4dbc73 | 2014-05-11 12:45:02 +0200 | [diff] [blame] | 50 | # run CPython to work out expected output |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 51 | try: |
| 52 | output_expected = subprocess.check_output([CPYTHON3, '-B', test_file]) |
| 53 | except subprocess.CalledProcessError: |
| 54 | output_expected = b'CPYTHON3 CRASH' |
Damien | 39977a5 | 2013-12-29 22:34:42 +0000 | [diff] [blame] | 55 | |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 56 | # run Micro Python |
| 57 | if pyb is None: |
| 58 | # run on PC |
| 59 | try: |
| 60 | output_mupy = subprocess.check_output([MICROPYTHON, '-X', 'emit=bytecode', test_file]) |
| 61 | except subprocess.CalledProcessError: |
| 62 | output_mupy = b'CRASH' |
| 63 | else: |
| 64 | # run on pyboard |
| 65 | pyb.enter_raw_repl() |
| 66 | try: |
| 67 | output_mupy = pyb.execfile(test_file).replace(b'\r\n', b'\n') |
| 68 | except pyboard.PyboardError: |
| 69 | output_mupy = b'CRASH' |
Damien George | 4b34c76 | 2014-04-03 23:51:16 +0100 | [diff] [blame] | 70 | |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 71 | test_basename = os.path.basename(test_file) |
| 72 | test_name = os.path.splitext(test_basename)[0] |
Paul Sokolovsky | 43d4a6f | 2014-05-10 16:52:58 +0300 | [diff] [blame] | 73 | |
| 74 | if output_mupy == b'SKIP\n': |
| 75 | print("skip ", test_file) |
| 76 | skipped_tests.append(test_name) |
| 77 | continue |
| 78 | |
| 79 | testcase_count += len(output_expected.splitlines()) |
| 80 | |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 81 | filename_expected = test_basename + ".exp" |
| 82 | filename_mupy = test_basename + ".out" |
| 83 | |
| 84 | if output_expected == output_mupy: |
| 85 | print("pass ", test_file) |
| 86 | passed_count += 1 |
| 87 | rm_f(filename_expected) |
| 88 | rm_f(filename_mupy) |
| 89 | else: |
| 90 | with open(filename_expected, "w") as f: |
| 91 | f.write(str(output_expected, "ascii")) |
| 92 | with open(filename_mupy, "w") as f: |
| 93 | f.write(str(output_mupy, "ascii")) |
| 94 | print("FAIL ", test_file) |
| 95 | failed_tests.append(test_name) |
| 96 | |
| 97 | test_count += 1 |
| 98 | |
| 99 | print("{} tests performed ({} individual testcases)".format(test_count, testcase_count)) |
| 100 | print("{} tests passed".format(passed_count)) |
| 101 | |
Paul Sokolovsky | 43d4a6f | 2014-05-10 16:52:58 +0300 | [diff] [blame] | 102 | if len(skipped_tests) > 0: |
| 103 | print("{} tests skipped: {}".format(len(skipped_tests), ' '.join(skipped_tests))) |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 104 | if len(failed_tests) > 0: |
| 105 | print("{} tests failed: {}".format(len(failed_tests), ' '.join(failed_tests))) |
| 106 | return False |
| 107 | |
| 108 | # all tests succeeded |
| 109 | return True |
| 110 | |
| 111 | def main(): |
| 112 | cmd_parser = argparse.ArgumentParser(description='Run tests for Micro Python.') |
| 113 | cmd_parser.add_argument('--pyboard', action='store_true', help='run the tests on the pyboard') |
Damien George | a053e37 | 2014-05-31 18:11:01 +0100 | [diff] [blame^] | 114 | cmd_parser.add_argument('-d', '--test-dirs', nargs='*', help='input test directories (if no files given)') |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 115 | cmd_parser.add_argument('files', nargs='*', help='input test files') |
| 116 | args = cmd_parser.parse_args() |
| 117 | |
| 118 | if args.pyboard: |
| 119 | import pyboard |
| 120 | pyb = pyboard.Pyboard('/dev/ttyACM0') |
Damien George | b636d02 | 2014-04-13 13:48:33 +0100 | [diff] [blame] | 121 | pyb.enter_raw_repl() |
Damien George | b636d02 | 2014-04-13 13:48:33 +0100 | [diff] [blame] | 122 | else: |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 123 | pyb = None |
Damien | 39977a5 | 2013-12-29 22:34:42 +0000 | [diff] [blame] | 124 | |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 125 | if len(args.files) == 0: |
stijn | 8ac3b57 | 2014-05-28 14:27:54 +0200 | [diff] [blame] | 126 | if args.test_dirs is None: |
| 127 | if pyb is None: |
| 128 | # run PC tests |
| 129 | test_dirs = ('basics', 'micropython', 'float', 'import', 'io', 'misc') |
| 130 | else: |
| 131 | # run pyboard tests |
| 132 | test_dirs = ('basics', 'float', 'pyb', 'pybnative', 'inlineasm') |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 133 | else: |
stijn | 8ac3b57 | 2014-05-28 14:27:54 +0200 | [diff] [blame] | 134 | # run tests from these directories |
| 135 | test_dirs = args.test_dirs |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 136 | tests = sorted(test_file for test_files in (glob('{}/*.py'.format(dir)) for dir in test_dirs) for test_file in test_files) |
Markus Siemens | 19ccc6b | 2014-01-27 22:53:28 +0100 | [diff] [blame] | 137 | else: |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 138 | # tests explicitly given |
| 139 | tests = args.files |
Markus Siemens | 19ccc6b | 2014-01-27 22:53:28 +0100 | [diff] [blame] | 140 | |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 141 | if not run_tests(pyb, tests): |
| 142 | sys.exit(1) |
Markus Siemens | 19ccc6b | 2014-01-27 22:53:28 +0100 | [diff] [blame] | 143 | |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 144 | if __name__ == "__main__": |
| 145 | main() |