Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(53)

Side by Side Diff: bin/cros_run_parallel_vm_tests.py

Issue 6730012: Remove testing utilities and fix symlinks. (Closed) Base URL: http://git.chromium.org/git/crosutils.git@master
Patch Set: Fix common Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 #!/usr/bin/python
2 # Copyright (c) 2010 The Chromium OS 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.
5
6 """Runs tests on VMs in parallel."""
7
8 import optparse
9 import os
10 import subprocess
11 import sys
12 import tempfile
13
14 sys.path.append(os.path.join(os.path.dirname(__file__), '../lib'))
15 from cros_build_lib import Die
16 from cros_build_lib import Info
17
18
19 _DEFAULT_BASE_SSH_PORT = 9222
20
21 class ParallelTestRunner(object):
22 """Runs tests on VMs in parallel.
23
24 This class is a simple wrapper around cros_run_vm_test that provides an easy
25 way to spawn several test instances in parallel and aggregate the results when
26 the tests complete. Only uses emerged autotest packaged, as trying to pull
27 from the caller's source tree creates races that cause tests to fail.
28 """
29
30 def __init__(self, tests, base_ssh_port=_DEFAULT_BASE_SSH_PORT, board=None,
31 image_path=None, order_output=False, quiet=False,
32 results_dir_root=None):
33 """Constructs and initializes the test runner class.
34
35 Args:
36 tests: A list of test names (see run_remote_tests.sh).
37 base_ssh_port: The base SSH port. Spawned VMs listen to localhost SSH
38 ports incrementally allocated starting from the base one.
39 board: The target board. If none, cros_run_vm_tests will use the default
40 board.
41 image_path: Full path to the VM image. If none, cros_run_vm_tests will use
42 the latest image.
43 order_output: If True, output of individual VMs will be piped to
44 temporary files and emitted at the end.
45 quiet: Emits no output from the VMs. Forces --order_output to be false,
46 and requires specifying --results_dir_root
47 results_dir_root: The results directory root. If provided, the results
48 directory root for each test will be created under it with the SSH port
49 appended to the test name.
50 """
51 self._tests = tests
52 self._base_ssh_port = base_ssh_port
53 self._board = board
54 self._image_path = image_path
55 self._order_output = order_output
56 self._quiet = quiet
57 self._results_dir_root = results_dir_root
58
59 def _SpawnTests(self):
60 """Spawns VMs and starts the test runs on them.
61
62 Runs all tests in |self._tests|. Each test is executed on a separate VM.
63
64 Returns:
65 A list of test process info objects containing the following dictionary
66 entries:
67 'test': the test name;
68 'proc': the Popen process instance for this test run.
69 """
70 ssh_port = self._base_ssh_port
71 spawned_tests = []
72 for test in self._tests:
73 args = [ os.path.join(os.path.dirname(__file__), 'cros_run_vm_test'),
74 '--snapshot', # The image is shared so don't modify it.
75 '--no_graphics',
76 '--use_emerged',
77 '--ssh_port=%d' % ssh_port ]
78 if self._board: args.append('--board=%s' % self._board)
79 if self._image_path: args.append('--image_path=%s' % self._image_path)
80 results_dir = None
81 if self._results_dir_root:
82 results_dir = '%s/%s.%d' % (self._results_dir_root, test, ssh_port)
83 args.append('--results_dir_root=%s' % results_dir)
84 args.append(test)
85 Info('Running %r...' % args)
86 output = None
87 if self._quiet:
88 output = open('/dev/null', mode='w')
89 Info('Log files are in %s' % results_dir)
90 elif self._order_output:
91 output = tempfile.NamedTemporaryFile(prefix='parallel_vm_test_')
92 Info('Piping output to %s.' % output.name)
93 proc = subprocess.Popen(args, stdout=output, stderr=output)
94 test_info = { 'test': test,
95 'proc': proc,
96 'output': output }
97 spawned_tests.append(test_info)
98 ssh_port = ssh_port + 1
99 return spawned_tests
100
101 def _WaitForCompletion(self, spawned_tests):
102 """Waits for tests to complete and returns a list of failed tests.
103
104 If the test output was piped to a file, dumps the file contents to stdout.
105
106 Args:
107 spawned_tests: A list of test info objects (see _SpawnTests).
108
109 Returns:
110 A list of failed test names.
111 """
112 failed_tests = []
113 for test_info in spawned_tests:
114 proc = test_info['proc']
115 proc.wait()
116 if proc.returncode: failed_tests.append(test_info['test'])
117 output = test_info['output']
118 if output and not self._quiet:
119 test = test_info['test']
120 Info('------ START %s:%s ------' % (test, output.name))
121 output.seek(0)
122 for line in output:
123 print line,
124 Info('------ END %s:%s ------' % (test, output.name))
125 return failed_tests
126
127 def Run(self):
128 """Runs the tests in |self._tests| on separate VMs in parallel."""
129 spawned_tests = self._SpawnTests()
130 failed_tests = self._WaitForCompletion(spawned_tests)
131 if failed_tests: Die('Tests failed: %r' % failed_tests)
132
133
134 def main():
135 usage = 'Usage: %prog [options] tests...'
136 parser = optparse.OptionParser(usage=usage)
137 parser.add_option('--base_ssh_port', type='int',
138 default=_DEFAULT_BASE_SSH_PORT,
139 help='Base SSH port. Spawned VMs listen to localhost SSH '
140 'ports incrementally allocated starting from the base one. '
141 '[default: %default]')
142 parser.add_option('--board',
143 help='The target board. If none specified, '
144 'cros_run_vm_test will use the default board.')
145 parser.add_option('--image_path',
146 help='Full path to the VM image. If none specified, '
147 'cros_run_vm_test will use the latest image.')
148 parser.add_option('--order_output', action='store_true', default=False,
149 help='Rather than emitting interleaved progress output '
150 'from the individual VMs, accumulate the outputs in '
151 'temporary files and dump them at the end.')
152 parser.add_option('--quiet', action='store_true', default=False,
153 help='Emits no output from the VMs. Forces --order_output'
154 'to be false, and requires specifying --results_dir_root')
155 parser.add_option('--results_dir_root',
156 help='Root results directory. If none specified, each test '
157 'will store its results in a separate /tmp directory.')
158 (options, args) = parser.parse_args()
159
160 if not args:
161 parser.print_help()
162 Die('no tests provided')
163
164 if options.quiet:
165 options.order_output = False
166 if not options.results_dir_root:
167 Die('--quiet requires --results_dir_root')
168 runner = ParallelTestRunner(args, options.base_ssh_port, options.board,
169 options.image_path, options.order_output,
170 options.quiet, options.results_dir_root)
171 runner.Run()
172
173
174 if __name__ == '__main__':
175 main()
OLDNEW
« no previous file with comments | « bin/cros_run_parallel_vm_tests ('k') | bin/cros_run_vm_test » ('j') | common.sh » ('J')

Powered by Google App Engine
This is Rietveld 408576698