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 | |
Chris Angelico | 047db22 | 2014-06-06 07:45:55 +1000 | [diff] [blame] | 30 | skip_tests = set() |
Damien | 39977a5 | 2013-12-29 22:34:42 +0000 | [diff] [blame] | 31 | |
Chris Angelico | 047db22 | 2014-06-06 07:45:55 +1000 | [diff] [blame] | 32 | # Some tests shouldn't be run under Travis CI |
| 33 | if os.getenv('TRAVIS') == 'true': |
| 34 | skip_tests.add('basics/memoryerror.py') |
Damien George | 2309369 | 2014-04-03 22:44:51 +0100 | [diff] [blame] | 35 | |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 36 | for test_file in tests: |
Chris Angelico | 88b11b5 | 2014-06-06 07:41:30 +1000 | [diff] [blame] | 37 | test_basename = os.path.basename(test_file) |
| 38 | test_name = os.path.splitext(test_basename)[0] |
| 39 | |
Chris Angelico | 047db22 | 2014-06-06 07:45:55 +1000 | [diff] [blame] | 40 | if test_file in skip_tests: |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 41 | print("skip ", test_file) |
Paul Sokolovsky | 43d4a6f | 2014-05-10 16:52:58 +0300 | [diff] [blame] | 42 | skipped_tests.append(test_name) |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 43 | continue |
Andrew Scheller | 1b997d5 | 2014-04-16 03:28:40 +0100 | [diff] [blame] | 44 | |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 45 | # get expected output |
| 46 | test_file_expected = test_file + '.exp' |
| 47 | if os.path.isfile(test_file_expected): |
| 48 | # expected output given by a file, so read that in |
| 49 | with open(test_file_expected, 'rb') as f: |
| 50 | output_expected = f.read() |
stijn | a4dbc73 | 2014-05-11 12:45:02 +0200 | [diff] [blame] | 51 | if os.name == 'nt': |
| 52 | output_expected = output_expected.replace(b'\n', b'\r\n') |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 53 | else: |
stijn | a4dbc73 | 2014-05-11 12:45:02 +0200 | [diff] [blame] | 54 | # run CPython to work out expected output |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 55 | try: |
| 56 | output_expected = subprocess.check_output([CPYTHON3, '-B', test_file]) |
| 57 | except subprocess.CalledProcessError: |
| 58 | output_expected = b'CPYTHON3 CRASH' |
Damien | 39977a5 | 2013-12-29 22:34:42 +0000 | [diff] [blame] | 59 | |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 60 | # run Micro Python |
| 61 | if pyb is None: |
| 62 | # run on PC |
| 63 | try: |
| 64 | output_mupy = subprocess.check_output([MICROPYTHON, '-X', 'emit=bytecode', test_file]) |
| 65 | except subprocess.CalledProcessError: |
| 66 | output_mupy = b'CRASH' |
| 67 | else: |
| 68 | # run on pyboard |
| 69 | pyb.enter_raw_repl() |
| 70 | try: |
| 71 | output_mupy = pyb.execfile(test_file).replace(b'\r\n', b'\n') |
| 72 | except pyboard.PyboardError: |
| 73 | output_mupy = b'CRASH' |
Damien George | 4b34c76 | 2014-04-03 23:51:16 +0100 | [diff] [blame] | 74 | |
Paul Sokolovsky | 43d4a6f | 2014-05-10 16:52:58 +0300 | [diff] [blame] | 75 | if output_mupy == b'SKIP\n': |
| 76 | print("skip ", test_file) |
| 77 | skipped_tests.append(test_name) |
| 78 | continue |
| 79 | |
| 80 | testcase_count += len(output_expected.splitlines()) |
| 81 | |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 82 | filename_expected = test_basename + ".exp" |
| 83 | filename_mupy = test_basename + ".out" |
| 84 | |
| 85 | if output_expected == output_mupy: |
| 86 | print("pass ", test_file) |
| 87 | passed_count += 1 |
| 88 | rm_f(filename_expected) |
| 89 | rm_f(filename_mupy) |
| 90 | else: |
Damien George | 41736f8 | 2014-06-28 10:29:12 +0100 | [diff] [blame^] | 91 | with open(filename_expected, "wb") as f: |
| 92 | f.write(output_expected) |
| 93 | with open(filename_mupy, "wb") as f: |
| 94 | f.write(output_mupy) |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 95 | print("FAIL ", test_file) |
| 96 | failed_tests.append(test_name) |
| 97 | |
| 98 | test_count += 1 |
| 99 | |
| 100 | print("{} tests performed ({} individual testcases)".format(test_count, testcase_count)) |
| 101 | print("{} tests passed".format(passed_count)) |
| 102 | |
Paul Sokolovsky | 43d4a6f | 2014-05-10 16:52:58 +0300 | [diff] [blame] | 103 | if len(skipped_tests) > 0: |
| 104 | print("{} tests skipped: {}".format(len(skipped_tests), ' '.join(skipped_tests))) |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 105 | if len(failed_tests) > 0: |
| 106 | print("{} tests failed: {}".format(len(failed_tests), ' '.join(failed_tests))) |
| 107 | return False |
| 108 | |
| 109 | # all tests succeeded |
| 110 | return True |
| 111 | |
| 112 | def main(): |
| 113 | cmd_parser = argparse.ArgumentParser(description='Run tests for Micro Python.') |
| 114 | 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] | 115 | 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] | 116 | cmd_parser.add_argument('files', nargs='*', help='input test files') |
| 117 | args = cmd_parser.parse_args() |
| 118 | |
| 119 | if args.pyboard: |
| 120 | import pyboard |
| 121 | pyb = pyboard.Pyboard('/dev/ttyACM0') |
Damien George | b636d02 | 2014-04-13 13:48:33 +0100 | [diff] [blame] | 122 | pyb.enter_raw_repl() |
Damien George | b636d02 | 2014-04-13 13:48:33 +0100 | [diff] [blame] | 123 | else: |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 124 | pyb = None |
Damien | 39977a5 | 2013-12-29 22:34:42 +0000 | [diff] [blame] | 125 | |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 126 | if len(args.files) == 0: |
stijn | 8ac3b57 | 2014-05-28 14:27:54 +0200 | [diff] [blame] | 127 | if args.test_dirs is None: |
| 128 | if pyb is None: |
| 129 | # run PC tests |
| 130 | test_dirs = ('basics', 'micropython', 'float', 'import', 'io', 'misc') |
| 131 | else: |
| 132 | # run pyboard tests |
Damien George | 4297fed | 2014-06-08 13:46:03 +0100 | [diff] [blame] | 133 | test_dirs = ('basics', 'micropython', 'float', 'pyb', 'pybnative', 'inlineasm') |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 134 | else: |
stijn | 8ac3b57 | 2014-05-28 14:27:54 +0200 | [diff] [blame] | 135 | # run tests from these directories |
| 136 | test_dirs = args.test_dirs |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 137 | 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] | 138 | else: |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 139 | # tests explicitly given |
| 140 | tests = args.files |
Markus Siemens | 19ccc6b | 2014-01-27 22:53:28 +0100 | [diff] [blame] | 141 | |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 142 | if not run_tests(pyb, tests): |
| 143 | sys.exit(1) |
Markus Siemens | 19ccc6b | 2014-01-27 22:53:28 +0100 | [diff] [blame] | 144 | |
Damien George | 41f768f | 2014-05-03 16:43:27 +0100 | [diff] [blame] | 145 | if __name__ == "__main__": |
| 146 | main() |