OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2015 The Chromium Authors. All rights reserved. | 2 # Copyright 2015 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 | 6 |
7 import argparse | |
8 import glob | 7 import glob |
9 import os | 8 import os |
10 import subprocess | 9 import subprocess |
11 import sys | 10 import sys |
12 | 11 |
13 | 12 |
14 def run_test(test_base_name, cmd, reset_results): | 13 def run_test(test_base_name, cmd): |
15 """Run a test case. | 14 """Run a test case. |
16 | 15 |
17 Args: | 16 Args: |
18 test_base_name: The name for the test C++ source file without the extension. | 17 test_base_name: The name for the test C++ source file without the extension. |
19 cmd: The actual command to run for the test. | 18 cmd: The actual command to run for the test. |
20 reset_results: True if the results should be overwritten in place. | |
21 | 19 |
22 Returns: | 20 Returns: |
23 None on pass, or a str with the description of the failure. | 21 None on pass, or a str with the description of the failure. |
24 """ | 22 """ |
25 try: | 23 try: |
26 actual = subprocess.check_output(cmd, stderr=subprocess.STDOUT) | 24 actual = subprocess.check_output(cmd, stderr=subprocess.STDOUT) |
27 except subprocess.CalledProcessError as e: | 25 except subprocess.CalledProcessError as e: |
28 # Some of the Blink GC plugin tests intentionally trigger compile errors, so | 26 # Some of the Blink GC plugin tests intentionally trigger compile errors, so |
29 # just ignore an exit code that indicates failure. | 27 # just ignore an exit code that indicates failure. |
30 actual = e.output | 28 actual = e.output |
(...skipping 11 matching lines...) Expand all Loading... |
42 except subprocess.CalledProcessError, e: | 40 except subprocess.CalledProcessError, e: |
43 # The graph processing script returns a failure exit code if the graph is | 41 # The graph processing script returns a failure exit code if the graph is |
44 # 'bad' (e.g. it has a cycle). The output still needs to be captured in | 42 # 'bad' (e.g. it has a cycle). The output still needs to be captured in |
45 # that case, since the expected results capture the errors. | 43 # that case, since the expected results capture the errors. |
46 actual = e.output | 44 actual = e.output |
47 finally: | 45 finally: |
48 # Clean up the .graph.json file to prevent false passes from stale results | 46 # Clean up the .graph.json file to prevent false passes from stale results |
49 # from a previous run. | 47 # from a previous run. |
50 os.remove('%s.graph.json' % test_base_name) | 48 os.remove('%s.graph.json' % test_base_name) |
51 | 49 |
| 50 # TODO(dcheng): Remove the rstrip() and just rebaseline the tests to match. |
| 51 actual = actual.rstrip() |
| 52 |
52 # On Windows, clang emits CRLF as the end of line marker. Normalize it to LF | 53 # On Windows, clang emits CRLF as the end of line marker. Normalize it to LF |
53 # to match posix systems. | 54 # to match posix systems. |
54 actual = actual.replace('\r\n', '\n') | 55 actual = actual.replace('\r\n', '\n') |
55 | 56 |
56 result_file = '%s.txt%s' % ( | |
57 test_base_name, '' if reset_results else '.actual') | |
58 try: | 57 try: |
59 expected = open('%s.txt' % test_base_name).read() | 58 expected = open('%s.txt' % test_base_name).read().rstrip() |
60 except IOError: | 59 except IOError: |
61 open(result_file, 'w').write(actual) | 60 open('%s.txt.actual' % test_base_name, 'w').write(actual) |
62 return 'no expected file found' | 61 return 'no expected file found' |
63 | 62 |
64 if expected != actual: | 63 if expected != actual: |
65 open(result_file, 'w').write(actual) | 64 open('%s.txt.actual' % test_base_name, 'w').write(actual) |
66 return 'expected and actual differed' | 65 return 'expected and actual differed' |
67 | 66 |
68 | 67 |
69 def run_tests(clang_path, plugin_path, reset_results): | 68 def run_tests(clang_path, plugin_path): |
70 """Runs the tests. | 69 """Runs the tests. |
71 | 70 |
72 Args: | 71 Args: |
73 clang_path: The path to the clang binary to be tested. | 72 clang_path: The path to the clang binary to be tested. |
74 plugin_path: An optional path to the plugin to test. This may be None, if | 73 plugin_path: An optional path to the plugin to test. This may be None, if |
75 plugin is built directly into clang, like on Windows. | 74 plugin is built directly into clang, like on Windows. |
76 reset_results: True if the results should be overwritten in place. | |
77 | 75 |
78 Returns: | 76 Returns: |
79 (passing, failing): Two lists containing the base names of the passing and | 77 (passing, failing): Two lists containing the base names of the passing and |
80 failing tests respectively. | 78 failing tests respectively. |
81 """ | 79 """ |
82 passing = [] | 80 passing = [] |
83 failing = [] | 81 failing = [] |
84 | 82 |
85 # The plugin option to dump the object graph is incompatible with | 83 # The plugin option to dump the object graph is incompatible with |
86 # -fsyntax-only. It generates the .graph.json file based on the name of the | 84 # -fsyntax-only. It generates the .graph.json file based on the name of the |
87 # output file, but there is no output filename with -fsyntax-only. | 85 # output file, but there is no output filename with -fsyntax-only. |
88 base_cmd = [clang_path, '-c', '-std=c++11'] | 86 base_cmd = [clang_path, '-c', '-std=c++11'] |
89 base_cmd.extend(['-Wno-inaccessible-base']) | 87 base_cmd.extend(['-Wno-inaccessible-base']) |
90 if plugin_path: | 88 if plugin_path: |
91 base_cmd.extend(['-Xclang', '-load', '-Xclang', plugin_path]) | 89 base_cmd.extend(['-Xclang', '-load', '-Xclang', plugin_path]) |
92 base_cmd.extend(['-Xclang', '-add-plugin', '-Xclang', 'blink-gc-plugin']) | 90 base_cmd.extend(['-Xclang', '-add-plugin', '-Xclang', 'blink-gc-plugin']) |
93 | 91 |
94 tests = glob.glob('*.cpp') | 92 tests = glob.glob('*.cpp') |
95 for test in tests: | 93 for test in tests: |
96 sys.stdout.write('Testing %s... ' % test) | 94 sys.stdout.write('Testing %s... ' % test) |
97 test_base_name, _ = os.path.splitext(test) | 95 test_base_name, _ = os.path.splitext(test) |
98 | 96 |
99 cmd = base_cmd[:] | 97 cmd = base_cmd[:] |
100 try: | 98 try: |
101 cmd.extend(file('%s.flags' % test_base_name).read().split()) | 99 cmd.extend(file('%s.flags' % test_base_name).read().split()) |
102 except IOError: | 100 except IOError: |
103 pass | 101 pass |
104 cmd.append(test) | 102 cmd.append(test) |
105 | 103 |
106 failure_message = run_test(test_base_name, cmd, reset_results) | 104 failure_message = run_test(test_base_name, cmd) |
107 if failure_message: | 105 if failure_message: |
108 print 'failed: %s' % failure_message | 106 print 'failed: %s' % failure_message |
109 failing.append(test_base_name) | 107 failing.append(test_base_name) |
110 else: | 108 else: |
111 print 'passed!' | 109 print 'passed!' |
112 passing.append(test_base_name) | 110 passing.append(test_base_name) |
113 | 111 |
114 return passing, failing | 112 return passing, failing |
115 | 113 |
116 | 114 |
117 def main(): | 115 def main(): |
118 parser = argparse.ArgumentParser() | 116 if len(sys.argv) < 2: |
119 parser.add_argument( | 117 print 'Usage: <path to clang>[ <path to plugin>]' |
120 '--reset-results', action='store_true', | 118 return -1 |
121 help='If specified, overwrites the expected results in place.') | |
122 parser.add_argument('clang_path', help='The path to the clang binary.') | |
123 parser.add_argument('plugin_path', nargs='?', | |
124 help='The path to the plugin library, if any.') | |
125 args = parser.parse_args() | |
126 | 119 |
127 os.chdir(os.path.dirname(os.path.realpath(__file__))) | 120 os.chdir(os.path.dirname(os.path.realpath(__file__))) |
128 | 121 |
129 print 'Using clang %s...' % args.clang_path | 122 clang_path = sys.argv[1] |
130 print 'Using plugin %s...' % args.plugin_path | 123 plugin_path = sys.argv[2] if len(sys.argv) > 2 else None |
| 124 print 'Using clang %s...' % clang_path |
| 125 print 'Using plugin %s...' % plugin_path |
131 | 126 |
132 passing, failing = run_tests(args.clang_path, | 127 passing, failing = run_tests(clang_path, plugin_path) |
133 args.plugin_path, | |
134 args.reset_results) | |
135 print 'Ran %d tests: %d succeeded, %d failed' % ( | 128 print 'Ran %d tests: %d succeeded, %d failed' % ( |
136 len(passing) + len(failing), len(passing), len(failing)) | 129 len(passing) + len(failing), len(passing), len(failing)) |
137 for test in failing: | 130 for test in failing: |
138 print ' %s' % test | 131 print ' %s' % test |
139 return len(failing) | 132 return len(failing) |
140 | 133 |
141 | 134 |
142 if __name__ == '__main__': | 135 if __name__ == '__main__': |
143 sys.exit(main()) | 136 sys.exit(main()) |
OLD | NEW |