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
4 # found in the LICENSE file.
6 """A helper module to run Legion multi-machine tests.
8 Example usage with 1 task machine:
9 $ testing/legion/tools/legion.py run \
10 --controller-isolated out/Release/example_test_controller.isolated \
11 --dimension os Ubuntu-14.04 \
12 --task-name test-task-name \
13 --task task_machine out/Release/example_task_machine.isolated
15 Example usage with 2 task machines with the same isolated file:
16 $ testing/legion/tools/legion.py run \
17 --controller-isolated out/Release/example_test_controller.isolated \
18 --dimension os Ubuntu-14.04 \
19 --task-name test-task-name \
20 --task task_machine_1 out/Release/example_task_machine.isolated \
21 --task task_machine_2 out/Release/example_task_machine.isolated
23 Example usage with 2 task machines with different isolated file:
24 $ testing/legion/tools/legion.py run \
25 --controller-isolated out/Release/example_test_controller.isolated \
26 --dimension os Ubuntu-14.04 \
27 --task-name test-task-name \
28 --task task_machine_1 out/Release/example_task_machine_1.isolated \
29 --task task_machine_2 out/Release/example_task_machine_2.isolated
39 THIS_DIR
= os
.path
.split(__file__
)[0]
40 SWARMING_DIR
= os
.path
.join(THIS_DIR
, '..', '..', '..', 'tools',
42 ISOLATE_PY
= os
.path
.join(SWARMING_DIR
, 'isolate.py')
43 SWARMING_PY
= os
.path
.join(SWARMING_DIR
, 'swarming.py')
44 LOGGING_LEVELS
= ['DEBUG', 'INFO', 'WARNING', 'ERROR']
47 class Error(Exception):
52 parser
= argparse
.ArgumentParser(description
=__doc__
)
53 parser
.add_argument('action', choices
=['run', 'trigger'],
54 help='The swarming action to perform.')
55 parser
.add_argument('-f', '--format-only', action
='store_true',
56 help='If true the .isolated files are archived but '
57 'swarming is not called, only the command line is built.')
58 parser
.add_argument('--controller-isolated', required
=True,
59 help='The isolated file for the test controller.')
60 parser
.add_argument('--isolate-server', help='Optional. The isolated server '
62 parser
.add_argument('--swarming-server', help='Optional. The swarming server '
64 parser
.add_argument('--task-name', help='Optional. The swarming task name '
66 parser
.add_argument('--dimension', action
='append', dest
='dimensions',
67 nargs
=2, default
=[], help='Dimensions to pass to '
68 'swarming.py. This is in the form of --dimension key '
69 'value. The minimum required is --dimension os <OS>')
70 parser
.add_argument('--task', action
='append', dest
='tasks',
71 nargs
=2, default
=[], help='List of task names used in '
72 'the test controller. This is in the form of --task name '
73 '.isolated and is passed to the controller as --name '
75 parser
.add_argument('--controller-var', action
='append',
76 dest
='controller_vars', nargs
=2, default
=[],
77 help='Command line vars to pass to the controller. These '
78 'are in the form of --controller-var name value and are '
79 'passed to the controller as --name value.')
80 parser
.add_argument('-v', '--verbosity', default
=0, action
='count')
81 return parser
.parse_args()
84 def RunCommand(cmd
, stream_stdout
=False):
85 """Runs the command line and streams stdout if requested."""
88 'stderr': subprocess
.PIPE
,
91 kwargs
['stdout'] = subprocess
.PIPE
93 p
= subprocess
.Popen(**kwargs
)
94 stdout
, stderr
= p
.communicate()
102 def Archive(isolated
, isolate_server
=None):
103 """Calls isolate.py archive with the given args."""
108 '--isolated', isolated
,
111 cmd
.extend(['--isolate-server', isolate_server
])
113 return RunCommand(cmd
).split()[0] # The isolated hash
116 def GetSwarmingCommandLine(args
):
117 """Builds and returns the command line for swarming.py run|trigger."""
122 args
.controller_isolated
,
124 if args
.isolate_server
:
125 cmd
.extend(['--isolate-server', args
.isolate_server
])
126 if args
.swarming_server
:
127 cmd
.extend(['--swarming', args
.swarming_server
])
129 cmd
.extend(['--task-name', args
.task_name
])
130 # swarming.py dimensions
131 for name
, value
in args
.dimensions
:
132 cmd
.extend(['--dimension', name
, value
])
136 # Specify the output dir
137 cmd
.extend(['--output-dir', '${ISOLATED_OUTDIR}'])
138 # Task name/hash values
139 for name
, isolated
in args
.tasks
:
140 cmd
.extend(['--' + name
, Archive(isolated
, args
.isolate_server
)])
141 # Test controller args
142 for name
, value
in args
.controller_vars
:
143 cmd
.extend(['--' + name
, value
])
151 format
='%(asctime)s %(filename)s:%(lineno)s %(levelname)s] %(message)s',
153 level
=LOGGING_LEVELS
[len(LOGGING_LEVELS
)-args
.verbosity
-1])
154 cmd
= GetSwarmingCommandLine(args
)
155 if not args
.format_only
:
156 RunCommand(cmd
, True)
160 if __name__
== '__main__':