| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 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 """Traces each test cases of a google-test executable individually and generates | 6 """Traces each test cases of a google-test executable individually and generates |
| 7 or updates an .isolate file. | 7 or updates an .isolate file. |
| 8 | 8 |
| 9 If the trace hangs up, you can still take advantage of the traces up to the | 9 If the trace hangs up, you can still take advantage of the traces up to the |
| 10 points it got to by Ctrl-C'ing out, then running isolate.py merge -r | 10 points it got to by Ctrl-C'ing out, then running isolate.py merge -r |
| 11 out/release/foo_test.isolated. the reason it works is because both isolate.py | 11 out/release/foo_test.isolated. the reason it works is because both isolate.py |
| 12 and isolate_test_cases.py uses the same filename for the trace by default. | 12 and isolate_test_cases.py uses the same filename for the trace by default. |
| 13 """ | 13 """ |
| 14 | 14 |
| 15 import logging | 15 import logging |
| 16 import os | 16 import os |
| 17 import subprocess | 17 import subprocess |
| 18 import sys | 18 import sys |
| 19 | 19 |
| 20 ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
| 21 if not ROOT_DIR in sys.path: |
| 22 sys.path.insert(0, ROOT_DIR) |
| 23 |
| 20 import isolate | 24 import isolate |
| 25 import run_isolated |
| 21 import run_test_cases | 26 import run_test_cases |
| 22 import trace_inputs | 27 import trace_inputs |
| 23 import trace_test_cases | 28 import trace_test_cases |
| 24 | 29 |
| 25 BASE_DIR = os.path.dirname(os.path.abspath(__file__)) | |
| 26 | |
| 27 | 30 |
| 28 def isolate_test_cases( | 31 def isolate_test_cases( |
| 29 cmd, test_cases, jobs, isolated_file, isolate_file, | 32 cmd, test_cases, jobs, isolated_file, isolate_file, |
| 30 root_dir, reldir, variables): | 33 root_dir, reldir, variables): |
| 31 assert os.path.isabs(root_dir) and os.path.isdir(root_dir), root_dir | 34 assert os.path.isabs(root_dir) and os.path.isdir(root_dir), root_dir |
| 32 | 35 |
| 33 logname = isolated_file + '.log' | 36 logname = isolated_file + '.log' |
| 34 basename = isolated_file.rsplit('.', 1)[0] | 37 basename = isolated_file.rsplit('.', 1)[0] |
| 35 cwd_dir = os.path.join(root_dir, reldir) | 38 cwd_dir = os.path.join(root_dir, reldir) |
| 36 # Do the actual tracing. | 39 # Do the actual tracing. |
| (...skipping 29 matching lines...) Expand all Loading... |
| 66 out = basename + '.' + item['tracename'] + '.isolate' | 69 out = basename + '.' + item['tracename'] + '.isolate' |
| 67 with open(out, 'w') as f: | 70 with open(out, 'w') as f: |
| 68 isolate.pretty_print(value, f) | 71 isolate.pretty_print(value, f) |
| 69 inputs.append(out) | 72 inputs.append(out) |
| 70 | 73 |
| 71 # Merges back. Note that it is possible to blow up the command line | 74 # Merges back. Note that it is possible to blow up the command line |
| 72 # argument length here but writing the files is still useful. Convert to | 75 # argument length here but writing the files is still useful. Convert to |
| 73 # importing the module instead if necessary. | 76 # importing the module instead if necessary. |
| 74 merge_cmd = [ | 77 merge_cmd = [ |
| 75 sys.executable, | 78 sys.executable, |
| 76 os.path.join(BASE_DIR, 'isolate_merge.py'), | 79 os.path.join(ROOT_DIR, 'isolate_merge.py'), |
| 77 isolate_file, | 80 isolate_file, |
| 78 '-o', isolate_file, | 81 '-o', isolate_file, |
| 79 ] | 82 ] |
| 80 merge_cmd.extend(inputs) | 83 merge_cmd.extend(inputs) |
| 81 logging.info(merge_cmd) | 84 logging.info(merge_cmd) |
| 82 proc = subprocess.Popen(merge_cmd) | 85 proc = subprocess.Popen(merge_cmd) |
| 83 proc.communicate() | 86 proc.communicate() |
| 84 return proc.returncode | 87 return proc.returncode |
| 85 finally: | 88 finally: |
| 86 if exception: | 89 if exception: |
| 87 raise exception[0], exception[1], exception[2] | 90 raise exception[0], exception[1], exception[2] |
| 88 | 91 |
| 89 | 92 |
| 90 def test_xvfb(command, rel_dir): | 93 def test_xvfb(command, rel_dir): |
| 91 """Calls back ourself if not running inside Xvfb and it's on the command line | 94 """Calls back ourself if not running inside Xvfb and it's on the command line |
| 92 to run. | 95 to run. |
| 93 | 96 |
| 94 Otherwise the X session will die while trying to start too many Xvfb | 97 Otherwise the X session will die while trying to start too many Xvfb |
| 95 instances. | 98 instances. |
| 96 """ | 99 """ |
| 97 if os.environ.get('_CHROMIUM_INSIDE_XVFB') == '1': | 100 if os.environ.get('_CHROMIUM_INSIDE_XVFB') == '1': |
| 98 return | 101 return |
| 99 for index, item in enumerate(command): | 102 for index, item in enumerate(command): |
| 100 if item.endswith('xvfb.py'): | 103 if item.endswith('xvfb.py'): |
| 101 # Note this has inside knowledge about src/testing/xvfb.py. | 104 # Note this has inside knowledge about src/testing/xvfb.py. |
| 102 print('Restarting itself under Xvfb') | 105 print('Restarting itself under Xvfb') |
| 103 prefix = command[index:index+2] | 106 prefix = command[index:index+2] |
| 104 prefix[0] = os.path.normpath(os.path.join(rel_dir, prefix[0])) | 107 prefix[0] = os.path.normpath(os.path.join(rel_dir, prefix[0])) |
| 105 prefix[1] = os.path.normpath(os.path.join(rel_dir, prefix[1])) | 108 prefix[1] = os.path.normpath(os.path.join(rel_dir, prefix[1])) |
| 106 cmd = run_test_cases.fix_python_path(prefix + sys.argv) | 109 cmd = run_isolated.fix_python_path(prefix + sys.argv) |
| 107 sys.exit(subprocess.call(cmd)) | 110 sys.exit(subprocess.call(cmd)) |
| 108 | 111 |
| 109 | 112 |
| 110 def safely_load_isolated(parser, options): | 113 def safely_load_isolated(parser, options): |
| 111 """Loads a .isolated.state to extract the executable information. | 114 """Loads a .isolated.state to extract the executable information. |
| 112 | 115 |
| 113 Returns the CompleteState instance, the command and the list of test cases. | 116 Returns the CompleteState instance, the command and the list of test cases. |
| 114 """ | 117 """ |
| 115 config = isolate.CompleteState.load_files(options.isolated) | 118 config = isolate.CompleteState.load_files(options.isolated) |
| 116 logging.debug( | 119 logging.debug( |
| 117 'root_dir: %s relative_cwd: %s isolated: %s', | 120 'root_dir: %s relative_cwd: %s isolated: %s', |
| 118 config.root_dir, config.saved_state.relative_cwd, options.isolated) | 121 config.root_dir, config.saved_state.relative_cwd, options.isolated) |
| 119 reldir = os.path.join(config.root_dir, config.saved_state.relative_cwd) | 122 reldir = os.path.join(config.root_dir, config.saved_state.relative_cwd) |
| 120 command = config.saved_state.command | 123 command = config.saved_state.command |
| 121 test_cases = [] | 124 test_cases = [] |
| 122 if command: | 125 if command: |
| 123 command = run_test_cases.fix_python_path(command) | 126 command = run_isolated.fix_python_path(command) |
| 124 test_xvfb(command, reldir) | 127 test_xvfb(command, reldir) |
| 125 test_cases = parser.process_gtest_options(command, reldir, options) | 128 test_cases = parser.process_gtest_options(command, reldir, options) |
| 126 return config, command, test_cases | 129 return config, command, test_cases |
| 127 | 130 |
| 128 | 131 |
| 129 def main(): | 132 def main(): |
| 130 """CLI frontend to validate arguments.""" | 133 """CLI frontend to validate arguments.""" |
| 131 run_test_cases.run_isolated.disable_buffering() | 134 run_isolated.disable_buffering() |
| 132 parser = run_test_cases.OptionParserTestCases( | 135 parser = run_test_cases.OptionParserTestCases( |
| 133 usage='%prog <options> --isolated <.isolated>') | 136 usage='%prog <options> --isolated <.isolated>') |
| 134 parser.format_description = lambda *_: parser.description | 137 parser.format_description = lambda *_: parser.description |
| 135 isolate.add_variable_option(parser) | 138 isolate.add_variable_option(parser) |
| 136 # TODO(maruel): Add support for options.timeout. | 139 # TODO(maruel): Add support for options.timeout. |
| 137 parser.remove_option('--timeout') | 140 parser.remove_option('--timeout') |
| 138 options, args = parser.parse_args() | 141 options, args = parser.parse_args() |
| 139 if args: | 142 if args: |
| 140 parser.error('Unsupported arg: %s' % args) | 143 parser.error('Unsupported arg: %s' % args) |
| 141 isolate.parse_isolated_option(parser, options, os.getcwd(), True) | 144 isolate.parse_isolated_option(parser, options, os.getcwd(), True) |
| (...skipping 16 matching lines...) Expand all Loading... |
| 158 config.root_dir, | 161 config.root_dir, |
| 159 config.saved_state.relative_cwd, | 162 config.saved_state.relative_cwd, |
| 160 config.saved_state.variables) | 163 config.saved_state.variables) |
| 161 except isolate.ExecutionError, e: | 164 except isolate.ExecutionError, e: |
| 162 print >> sys.stderr, str(e) | 165 print >> sys.stderr, str(e) |
| 163 return 1 | 166 return 1 |
| 164 | 167 |
| 165 | 168 |
| 166 if __name__ == '__main__': | 169 if __name__ == '__main__': |
| 167 sys.exit(main()) | 170 sys.exit(main()) |
| OLD | NEW |