| 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 """A helper module to run Legion multi-machine tests. | 6 """A helper module to run Legion multi-machine tests. |
| 7 | 7 |
| 8 Example usage with 1 task machine: | 8 Example usage with 1 task machine: |
| 9 $ testing/legion/tools/legion.py run \ | 9 $ testing/legion/tools/legion.py run \ |
| 10 --controller-isolated out/Release/example_test_controller.isolated \ | 10 --controller-isolated out/Release/example_test_controller.isolated \ |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 45 | 45 |
| 46 | 46 |
| 47 class Error(Exception): | 47 class Error(Exception): |
| 48 pass | 48 pass |
| 49 | 49 |
| 50 | 50 |
| 51 class ArgumentError(Error): | 51 class ArgumentError(Error): |
| 52 pass | 52 pass |
| 53 | 53 |
| 54 | 54 |
| 55 def GetArgs(): | 55 def GetArgs(cmd_args): |
| 56 parser = argparse.ArgumentParser(description=__doc__) | 56 parser = argparse.ArgumentParser(description=__doc__) |
| 57 parser.add_argument('action', choices=['run', 'trigger'], | 57 parser.add_argument('action', choices=['run', 'trigger'], |
| 58 help='The swarming action to perform.') | 58 help='The swarming action to perform.') |
| 59 parser.add_argument('-f', '--format-only', action='store_true', | 59 parser.add_argument('-f', '--format-only', action='store_true', |
| 60 help='If true the .isolated files are archived but ' | 60 help='If true the .isolated files are archived but ' |
| 61 'swarming is not called, only the command line is built.') | 61 'swarming is not called, only the command line is built.') |
| 62 parser.add_argument('--controller-isolated', required=True, | 62 parser.add_argument('--controller-isolated', required=True, |
| 63 help='The isolated file for the test controller.') | 63 help='The isolated file for the test controller.') |
| 64 parser.add_argument('--isolate-server', help='Optional. The isolated server ' | 64 parser.add_argument('--isolate-server', help='Optional. The isolated server ' |
| 65 'to use.', default=os.environ.get('ISOLATE_SERVER', '')) | 65 'to use.', default=os.environ.get('ISOLATE_SERVER', '')) |
| 66 parser.add_argument('--swarming-server', help='Optional. The swarming server ' | 66 parser.add_argument('--swarming-server', help='Optional. The swarming server ' |
| 67 'to use.', default=os.environ.get('SWARMING_SERVER', '')) | 67 'to use.', default=os.environ.get('SWARMING_SERVER', '')) |
| 68 parser.add_argument('--task-name', help='Optional. The swarming task name ' | 68 parser.add_argument('--task-name', help='Optional. The swarming task name ' |
| 69 'to use.') | 69 'to use.') |
| 70 parser.add_argument('--dimension', action='append', dest='dimensions', | 70 parser.add_argument('--dimension', action='append', dest='dimensions', |
| 71 nargs=2, default=[], help='Dimensions to pass to ' | 71 nargs=2, default=[], help='Dimensions to pass to ' |
| 72 'swarming.py. This is in the form of --dimension key ' | 72 'swarming.py. This is in the form of --dimension key ' |
| 73 'value. The minimum required is --dimension os <OS>') | 73 'value. The minimum required is --dimension os <OS>') |
| 74 parser.add_argument('--task', action='append', dest='tasks', | 74 parser.add_argument('--task', action='append', dest='tasks', |
| 75 nargs=2, default=[], help='List of task names used in ' | 75 nargs=2, default=[], help='List of task names used in ' |
| 76 'the test controller. This is in the form of --task name ' | 76 'the test controller. This is in the form of --task name ' |
| 77 '.isolated and is passed to the controller as --name ' | 77 '.isolated and is passed to the controller as --name ' |
| 78 '<ISOLATED HASH>.') | 78 '<ISOLATED HASH>.') |
| 79 parser.add_argument('--controller-var', action='append', | 79 parser.add_argument('--controller-var', action='append', |
| 80 dest='controller_vars', nargs=2, default=[], | 80 dest='controller_vars', nargs=2, default=[], |
| 81 help='Command line vars to pass to the controller. These ' | 81 help='Command line vars to pass to the controller. These ' |
| 82 'are in the form of --controller-var name value and are ' | 82 'are in the form of --controller-var name value and are ' |
| 83 'passed to the controller as --name value.') | 83 'passed to the controller as --name value.') |
| 84 parser.add_argument('-v', '--verbosity', default=0, action='count') | 84 parser.add_argument('-v', '--verbosity', default=0, action='count') |
| 85 return parser.parse_args() | 85 return parser.parse_args(cmd_args) |
| 86 | 86 |
| 87 | 87 |
| 88 def RunCommand(cmd, stream_stdout=False): | 88 def RunCommand(cmd, stream_stdout=False): |
| 89 """Runs the command line and streams stdout if requested.""" | 89 """Runs the command line and streams stdout if requested.""" |
| 90 kwargs = { | 90 kwargs = { |
| 91 'args': cmd, | 91 'args': cmd, |
| 92 'stderr': subprocess.PIPE, | 92 'stderr': subprocess.PIPE, |
| 93 } | 93 } |
| 94 if not stream_stdout: | 94 if not stream_stdout: |
| 95 kwargs['stdout'] = subprocess.PIPE | 95 kwargs['stdout'] = subprocess.PIPE |
| (...skipping 13 matching lines...) Expand all Loading... |
| 109 sys.executable, | 109 sys.executable, |
| 110 ISOLATE_PY, | 110 ISOLATE_PY, |
| 111 'archive', | 111 'archive', |
| 112 '--isolated', isolated, | 112 '--isolated', isolated, |
| 113 ] | 113 ] |
| 114 cmd.extend(['--isolate-server', isolate_server]) | 114 cmd.extend(['--isolate-server', isolate_server]) |
| 115 print ' '.join(cmd) | 115 print ' '.join(cmd) |
| 116 return RunCommand(cmd).split()[0] # The isolated hash | 116 return RunCommand(cmd).split()[0] # The isolated hash |
| 117 | 117 |
| 118 | 118 |
| 119 def GetSwarmingCommandLine(args): | 119 def GetSwarmingCommandLine(args, extra_args): |
| 120 """Builds and returns the command line for swarming.py run|trigger.""" | 120 """Builds and returns the command line for swarming.py run|trigger.""" |
| 121 cmd = [ | 121 cmd = [ |
| 122 sys.executable, | 122 sys.executable, |
| 123 SWARMING_PY, | 123 SWARMING_PY, |
| 124 args.action, | 124 args.action, |
| 125 args.controller_isolated, | 125 args.controller_isolated, |
| 126 ] | 126 ] |
| 127 cmd.extend(['--isolate-server', args.isolate_server]) | 127 cmd.extend(['--isolate-server', args.isolate_server]) |
| 128 cmd.extend(['--swarming', args.swarming_server]) | 128 cmd.extend(['--swarming', args.swarming_server]) |
| 129 if args.task_name: | 129 if args.task_name: |
| 130 cmd.extend(['--task-name', args.task_name]) | 130 cmd.extend(['--task-name', args.task_name]) |
| 131 # swarming.py dimensions | 131 # swarming.py dimensions |
| 132 for name, value in args.dimensions: | 132 for name, value in args.dimensions: |
| 133 cmd.extend(['--dimension', name, value]) | 133 cmd.extend(['--dimension', name, value]) |
| 134 | 134 |
| 135 cmd.append('--') | 135 cmd.append('--') |
| 136 | 136 cmd.extend(extra_args) |
| 137 cmd.extend(['--swarming-server', args.swarming_server]) | 137 cmd.extend(['--swarming-server', args.swarming_server]) |
| 138 cmd.extend(['--isolate-server', args.isolate_server]) | 138 cmd.extend(['--isolate-server', args.isolate_server]) |
| 139 # Specify the output dir | 139 # Specify the output dir |
| 140 cmd.extend(['--output-dir', '${ISOLATED_OUTDIR}']) | 140 cmd.extend(['--output-dir', '${ISOLATED_OUTDIR}']) |
| 141 # Task name/hash values | 141 # Task name/hash values |
| 142 for name, isolated in args.tasks: | 142 for name, isolated in args.tasks: |
| 143 cmd.extend(['--' + name, Archive(isolated, args.isolate_server)]) | 143 if args.format_only: |
| 144 cmd.extend(['--' + name, isolated + '_test_only']) |
| 145 else: |
| 146 cmd.extend(['--' + name, Archive(isolated, args.isolate_server)]) |
| 144 # Test controller args | 147 # Test controller args |
| 145 for name, value in args.controller_vars: | 148 for name, value in args.controller_vars: |
| 146 cmd.extend(['--' + name, value]) | 149 cmd.extend(['--' + name, value]) |
| 147 print ' '.join(cmd) | 150 print ' '.join(cmd) |
| 148 return cmd | 151 return cmd |
| 149 | 152 |
| 150 | 153 |
| 151 def main(): | 154 def main(): |
| 152 args = GetArgs() | 155 if '--' not in sys.argv: |
| 156 cmd_args = sys.argv[1:] |
| 157 extra_args = [] |
| 158 else: |
| 159 index = sys.argv.index('--') |
| 160 cmd_args = sys.argv[1:index] |
| 161 extra_args = sys.argv[index+1:] |
| 162 args = GetArgs(cmd_args) |
| 153 if not args.swarming_server: | 163 if not args.swarming_server: |
| 154 raise ArgumentError('Missing required argument: --swarming-server') | 164 raise ArgumentError('Missing required argument: --swarming-server') |
| 155 if not args.isolate_server: | 165 if not args.isolate_server: |
| 156 raise ArgumentError('Missing required argument: --isolate-server') | 166 raise ArgumentError('Missing required argument: --isolate-server') |
| 157 logging.basicConfig( | 167 logging.basicConfig( |
| 158 format='%(asctime)s %(filename)s:%(lineno)s %(levelname)s] %(message)s', | 168 format='%(asctime)s %(filename)s:%(lineno)s %(levelname)s] %(message)s', |
| 159 datefmt='%H:%M:%S', | 169 datefmt='%H:%M:%S', |
| 160 level=LOGGING_LEVELS[len(LOGGING_LEVELS)-args.verbosity-1]) | 170 level=LOGGING_LEVELS[len(LOGGING_LEVELS)-args.verbosity-1]) |
| 161 cmd = GetSwarmingCommandLine(args) | 171 cmd = GetSwarmingCommandLine(args, extra_args) |
| 162 if not args.format_only: | 172 if not args.format_only: |
| 163 RunCommand(cmd, True) | 173 RunCommand(cmd, True) |
| 164 return 0 | 174 return 0 |
| 165 | 175 |
| 166 | 176 |
| 167 if __name__ == '__main__': | 177 if __name__ == '__main__': |
| 168 sys.exit(main()) | 178 sys.exit(main()) |
| OLD | NEW |