|
7 | 7 | import sys |
8 | 8 | import os |
9 | 9 | import subprocess as SP |
| 10 | +import argparse |
| 11 | +import xml.etree.ElementTree as ET |
10 | 12 |
|
11 | | -test_all = True |
12 | | -test_root = os.path.dirname(os.path.realpath(__file__)) |
| 13 | +# handle command line args |
| 14 | +parser = argparse.ArgumentParser( |
| 15 | + description='ChakraCore *nix Test Script', |
| 16 | + formatter_class=argparse.RawDescriptionHelpFormatter, |
| 17 | + epilog='''\ |
| 18 | +Samples: |
| 19 | +
|
| 20 | +test all folders: |
| 21 | + {0} |
| 22 | +
|
| 23 | +test only Array: |
| 24 | + {0} Array |
| 25 | +
|
| 26 | +test a single file: |
| 27 | + {0} Basics/hello.js |
| 28 | +'''.format(sys.argv[0])) |
| 29 | + |
| 30 | +parser.add_argument('folders', metavar='folder', nargs='*', |
| 31 | + help='folder subset to run tests') |
| 32 | +parser.add_argument('-b', '--binary', metavar='bin', help='ch full path') |
| 33 | +parser.add_argument('-d', '--debug', action='store_true', |
| 34 | + help='use debug build'); |
| 35 | +parser.add_argument('-t', '--test', action='store_true', help='use test build') |
| 36 | +parser.add_argument('--x86', action='store_true', help='use x86 build') |
| 37 | +parser.add_argument('--x64', action='store_true', help='use x64 build') |
| 38 | +args = parser.parse_args() |
13 | 39 |
|
14 | | -# ugly trick |
15 | | -ch_path = os.path.join(os.path.dirname(test_root), "BuildLinux/ch") |
16 | 40 |
|
17 | | -if not os.path.isfile(ch_path): |
18 | | - print "BuildLinux/ch not found. Did you run ./build.sh already?" |
| 41 | +test_root = os.path.dirname(os.path.realpath(__file__)) |
| 42 | +repo_root = os.path.dirname(test_root) |
| 43 | + |
| 44 | +# arch: x86, x64 |
| 45 | +arch = 'x86' if args.x86 else ('x64' if args.x64 else None) |
| 46 | +if arch == None: |
| 47 | + arch = os.environ.get('_BuildArch', 'x86') |
| 48 | + |
| 49 | +# flavor: debug, test, release |
| 50 | +type_flavor = {'chk':'debug', 'test':'test', 'fre':'release'} |
| 51 | +flavor = 'debug' if args.debug else ('test' if args.test else None) |
| 52 | +if flavor == None: |
| 53 | + flavor = type_flavor[os.environ.get('_BuildType', 'fre')] |
| 54 | + |
| 55 | +# binary: full ch path |
| 56 | +binary = args.binary |
| 57 | +if binary == None: |
| 58 | + if sys.platform == 'win32': |
| 59 | + binary = 'Build/VcBuild/bin/{}_{}/ch.exe'.format(arch, flavor) |
| 60 | + else: |
| 61 | + binary = 'BuildLinux/ch' |
| 62 | + binary = os.path.join(repo_root, binary) |
| 63 | +if not os.path.isfile(binary): |
| 64 | + print('{} not found. Did you run ./build.sh already?'.format(binary)) |
19 | 65 | sys.exit(1) |
20 | 66 |
|
21 | | -if len(sys.argv) > 1: |
22 | | - if sys.argv[1] in ['-?', '--help']: |
23 | | - print "ChakraCore *nix Test Script\n" |
24 | 67 |
|
25 | | - print "Usage:" |
26 | | - print "test.py <optional test path>\n" |
| 68 | +# records pass_count/fail_count |
| 69 | +class PassFailCount(object): |
| 70 | + def __init__(self): |
| 71 | + self.pass_count = 0 |
| 72 | + self.fail_count = 0 |
| 73 | + |
| 74 | + def __str__(self): |
| 75 | + return 'passed {}, failed {}'.format(self.pass_count, self.fail_count) |
| 76 | + |
| 77 | +# records total and individual folder's pass_count/fail_count |
| 78 | +class TestResult(PassFailCount): |
| 79 | + def __init__(self): |
| 80 | + super(self.__class__, self).__init__() |
| 81 | + self.folders = {} |
27 | 82 |
|
28 | | - print "-?, --help : Show help\n" |
| 83 | + def _get_folder_result(self, folder): |
| 84 | + r = self.folders.get(folder) |
| 85 | + if not r: |
| 86 | + r = PassFailCount() |
| 87 | + self.folders[folder] = r |
| 88 | + return r |
29 | 89 |
|
30 | | - print "Samples:" |
31 | | - print "test only Array:" |
32 | | - print "\t./test.py Array\n" |
33 | | - |
34 | | - print "test a single file:" |
35 | | - print "\t./test.py Basics/hello.js\n" |
| 90 | + def log(self, filename=None, folder=None, fail=False): |
| 91 | + if not folder: |
| 92 | + folder = os.path.basename(os.path.dirname(filename)) |
| 93 | + r = self._get_folder_result(folder) |
| 94 | + if fail: |
| 95 | + r.fail_count += 1 |
| 96 | + self.fail_count += 1 |
| 97 | + else: |
| 98 | + r.pass_count += 1 |
| 99 | + self.pass_count += 1 |
36 | 100 |
|
37 | | - print "test all folders:" |
38 | | - print "\t./test.py" |
39 | | - sys.exit(0) |
40 | | - test_all = None |
| 101 | +test_result = TestResult() |
41 | 102 |
|
42 | | -test_dirs=[''] |
43 | | -if test_all: |
44 | | - test_dirs = os.listdir(test_root) |
45 | | -else: |
46 | | - test_dirs[0] = sys.argv[1] |
47 | 103 |
|
48 | 104 | def show_failed(filename, output, exit_code, expected_output): |
49 | | - print "\nFailed ->", filename |
| 105 | + print("\nFailed -> {}".format(filename)) |
50 | 106 | if expected_output == None: |
51 | | - print "\nOutput:" |
52 | | - print "----------------------------" |
53 | | - print output |
54 | | - print "----------------------------" |
| 107 | + print("\nOutput:") |
| 108 | + print("----------------------------") |
| 109 | + print(output) |
| 110 | + print("----------------------------") |
55 | 111 | else: |
56 | 112 | lst_output = output.split('\n') |
57 | 113 | lst_expected = expected_output.split('\n') |
58 | 114 | ln = min(len(lst_output), len(lst_expected)) |
59 | 115 | for i in range(0, ln): |
60 | 116 | if lst_output[i] != lst_expected[i]: |
61 | | - print "Output: (at line " + str(i) + ")" |
62 | | - print "----------------------------" |
63 | | - print lst_output[i] |
64 | | - print "----------------------------" |
65 | | - print "Expected Output:" |
66 | | - print "----------------------------" |
67 | | - print lst_expected[i] |
68 | | - print "----------------------------" |
| 117 | + print("Output: (at line " + str(i) + ")") |
| 118 | + print("----------------------------") |
| 119 | + print(lst_output[i]) |
| 120 | + print("----------------------------") |
| 121 | + print("Expected Output:") |
| 122 | + print("----------------------------") |
| 123 | + print(lst_expected[i]) |
| 124 | + print("----------------------------") |
69 | 125 | break |
70 | 126 |
|
71 | | - print "exit code:", exit_code |
72 | | - print "\nFailed!" |
73 | | - sys.exit(exit_code) |
| 127 | + print("exit code: {}".format(exit_code)) |
| 128 | + test_result.log(filename, fail=True) |
74 | 129 |
|
75 | | -def test_path(folder, is_file): |
76 | | - files=[''] |
77 | | - if is_file == False: |
78 | | - print "Testing ->", os.path.basename(folder) |
79 | | - files = os.listdir(folder) |
| 130 | +def test_path(path): |
| 131 | + if os.path.isfile(path): |
| 132 | + folder, file = os.path.dirname(path), os.path.basename(path) |
80 | 133 | else: |
81 | | - files[0] = folder |
82 | | - |
83 | | - for js_file in files: |
84 | | - if is_file or os.path.splitext(js_file)[1] == '.js': |
85 | | - js_file = os.path.join(folder, js_file) |
86 | | - js_output = "" |
87 | | - |
88 | | - if not os.path.isfile(js_file): |
89 | | - print "Javascript file doesn't exist (" + js_file + ")" |
90 | | - sys.exit(1) |
91 | | - |
92 | | - p = SP.Popen([ch_path, js_file], stdout=SP.PIPE, stderr=SP.STDOUT, close_fds=True) |
93 | | - js_output = p.communicate()[0].replace('\r','') |
94 | | - exit_code = p.wait() |
95 | | - |
96 | | - if exit_code != 0: |
97 | | - show_failed(js_file, js_output, exit_code, None) |
98 | | - else: #compare outputs |
99 | | - baseline = os.path.splitext(js_file)[0] + '.baseline' |
100 | | - baseline = os.path.join(folder, baseline) |
101 | | - if os.path.isfile(baseline): |
102 | | - expected_output = None |
103 | | - with open(baseline, 'r') as bs_file: |
104 | | - expected_output = bs_file.read().replace('\r', '') |
105 | | - # todo: compare line by line and use/implement wild cards support |
106 | | - # todo: by default we discard line endings (xplat), make this optional |
107 | | - if expected_output.replace('\n', '') != js_output.replace('\n', ''): |
108 | | - show_failed(js_file, js_output, exit_code, expected_output) |
109 | | - |
110 | | - if not is_file: |
111 | | - print "\tPassed ->", os.path.basename(js_file) |
112 | | - |
113 | | -is_file = len(test_dirs) == 1 and os.path.splitext(test_dirs[0])[1] == '.js' |
114 | | - |
115 | | -for folder in test_dirs: |
116 | | - full_path = os.path.join(test_root, folder) |
117 | | - if os.path.isdir(full_path) or is_file: |
118 | | - test_path(full_path, is_file) |
119 | | - |
120 | | -print 'Success!' |
| 134 | + folder, file = path, None |
| 135 | + |
| 136 | + tests = load_tests(folder, file) |
| 137 | + if len(tests) == 0: |
| 138 | + return |
| 139 | + |
| 140 | + print("Testing -> " + os.path.basename(folder)) |
| 141 | + for test in tests: |
| 142 | + test_one(folder, test) |
| 143 | + |
| 144 | +def test_one(folder, test): |
| 145 | + js_file = os.path.join(folder, test['files']) |
| 146 | + js_output = "" |
| 147 | + |
| 148 | + flags = test.get('compile-flags') |
| 149 | + cmd = [binary, '-WERExceptionSupport', '-ExtendedErrorStackForTestHost'] \ |
| 150 | + + (flags.split() if flags else []) \ |
| 151 | + + [js_file] |
| 152 | + p = SP.Popen(cmd, stdout=SP.PIPE, stderr=SP.STDOUT) |
| 153 | + js_output = p.communicate()[0].replace('\r','') |
| 154 | + exit_code = p.wait() |
| 155 | + |
| 156 | + if exit_code != 0: |
| 157 | + return show_failed(js_file, js_output, exit_code, None) |
| 158 | + else: #compare outputs |
| 159 | + baseline = os.path.splitext(js_file)[0] + '.baseline' |
| 160 | + if os.path.isfile(baseline): |
| 161 | + expected_output = None |
| 162 | + with open(baseline, 'r') as bs_file: |
| 163 | + expected_output = bs_file.read().replace('\r', '') |
| 164 | + # todo: compare line by line and use/implement wild cards support |
| 165 | + # todo: by default we discard line endings (xplat), make this optional |
| 166 | + if expected_output.replace('\n', '') != js_output.replace('\n', ''): |
| 167 | + return show_failed(js_file, js_output, exit_code, expected_output) |
| 168 | + |
| 169 | + print("\tPassed -> " + os.path.basename(js_file)) |
| 170 | + test_result.log(folder=folder) |
| 171 | + |
| 172 | +def load_tests(folder, file): |
| 173 | + try: |
| 174 | + xmlpath = os.path.join(folder, 'rlexe.xml') |
| 175 | + xml = ET.parse(xmlpath).getroot() |
| 176 | + except IOError: |
| 177 | + return [] |
| 178 | + |
| 179 | + tests = [load_test(x) for x in xml] |
| 180 | + if file != None: |
| 181 | + tests = [x for x in tests if x['files'] == file] |
| 182 | + if len(tests) == 0 and is_jsfile(file): |
| 183 | + tests = [{'files':file}] |
| 184 | + return tests |
| 185 | + |
| 186 | +def load_test(testXml): |
| 187 | + test = dict() |
| 188 | + for c in testXml.find('default'): |
| 189 | + test[c.tag] = c.text |
| 190 | + return test |
| 191 | + |
| 192 | +def is_jsfile(path): |
| 193 | + return os.path.splitext(path)[1] == '.js' |
| 194 | + |
| 195 | +def main(): |
| 196 | + # By default run all tests |
| 197 | + if len(args.folders) == 0: |
| 198 | + args.folders = [os.path.join(test_root, x) |
| 199 | + for x in sorted(os.listdir(test_root))] |
| 200 | + |
| 201 | + for folder in args.folders: |
| 202 | + test_path(folder) |
| 203 | + |
| 204 | + print('\n') |
| 205 | + print('============================') |
| 206 | + for folder, result in sorted(test_result.folders.items()): |
| 207 | + print('{}: {}'.format(folder, result)) |
| 208 | + print('============================') |
| 209 | + print('Total: {}'.format(test_result)) |
| 210 | + print('Success!' if test_result.fail_count == 0 else 'Failed!') |
| 211 | + return 0 |
| 212 | + |
| 213 | +if __name__ == '__main__': |
| 214 | + sys.exit(main()) |
0 commit comments