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

Side by Side Diff: bin/cros_run_parallel_vm_tests.py

Issue 6602098: [crosutils] Add --quiet to cros_run_parallel_vm_tests (Closed) Base URL: http://git.chromium.org/git/crosutils.git@master
Patch Set: 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 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 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 """Runs tests on VMs in parallel.""" 6 """Runs tests on VMs in parallel."""
7 7
8 import optparse 8 import optparse
9 import os 9 import os
10 import subprocess 10 import subprocess
11 import sys 11 import sys
12 import tempfile 12 import tempfile
13 13
14 sys.path.append(os.path.join(os.path.dirname(__file__), '../lib')) 14 sys.path.append(os.path.join(os.path.dirname(__file__), '../lib'))
15 from cros_build_lib import Die 15 from cros_build_lib import Die
16 from cros_build_lib import Info 16 from cros_build_lib import Info
17 17
18 18
19 _DEFAULT_BASE_SSH_PORT = 9222 19 _DEFAULT_BASE_SSH_PORT = 9222
20 20
21 class ParallelTestRunner(object): 21 class ParallelTestRunner(object):
22 """Runs tests on VMs in parallel. 22 """Runs tests on VMs in parallel.
23 23
24 This class is a simple wrapper around cros_run_vm_test that provides an easy 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 25 way to spawn several test instances in parallel and aggregate the results when
26 the tests complete. 26 the tests complete.
27 """ 27 """
28 28
29 def __init__(self, tests, base_ssh_port=_DEFAULT_BASE_SSH_PORT, board=None, 29 def __init__(self, tests, base_ssh_port=_DEFAULT_BASE_SSH_PORT, board=None,
30 image_path=None, order_output=False, results_dir_root=None, 30 image_path=None, order_output=False, quiet=False,
31 use_emerged=False): 31 results_dir_root=None, use_emerged=False):
32 """Constructs and initializes the test runner class. 32 """Constructs and initializes the test runner class.
33 33
34 Args: 34 Args:
35 tests: A list of test names (see run_remote_tests.sh). 35 tests: A list of test names (see run_remote_tests.sh).
36 base_ssh_port: The base SSH port. Spawned VMs listen to localhost SSH 36 base_ssh_port: The base SSH port. Spawned VMs listen to localhost SSH
37 ports incrementally allocated starting from the base one. 37 ports incrementally allocated starting from the base one.
38 board: The target board. If none, cros_run_vm_tests will use the default 38 board: The target board. If none, cros_run_vm_tests will use the default
39 board. 39 board.
40 image_path: Full path to the VM image. If none, cros_run_vm_tests will use 40 image_path: Full path to the VM image. If none, cros_run_vm_tests will use
41 the latest image. 41 the latest image.
42 order_output: If True, output of individual VMs will be piped to 42 order_output: If True, output of individual VMs will be piped to
43 temporary files and emitted at the end. 43 temporary files and emitted at the end.
44 results_dir_root: The results directory root. If provided, the results 44 results_dir_root: The results directory root. If provided, the results
45 directory root for each test will be created under it with the SSH port 45 directory root for each test will be created under it with the SSH port
46 appended to the test name. 46 appended to the test name.
47 use_emerged: Force use of emerged autotest packages.
47 """ 48 """
48 self._tests = tests 49 self._tests = tests
49 self._base_ssh_port = base_ssh_port 50 self._base_ssh_port = base_ssh_port
50 self._board = board 51 self._board = board
51 self._image_path = image_path 52 self._image_path = image_path
52 self._order_output = order_output 53 self._order_output = order_output
54 self._quiet = quiet
petkov 2011/03/02 23:08:34 document quiet too?
Chris Masone 2011/03/02 23:27:28 Done.
53 self._results_dir_root = results_dir_root 55 self._results_dir_root = results_dir_root
54 self._use_emerged = use_emerged 56 self._use_emerged = use_emerged
55 57
56 def _SpawnTests(self): 58 def _SpawnTests(self):
57 """Spawns VMs and starts the test runs on them. 59 """Spawns VMs and starts the test runs on them.
58 60
59 Runs all tests in |self._tests|. Each test is executed on a separate VM. 61 Runs all tests in |self._tests|. Each test is executed on a separate VM.
60 62
61 Returns: 63 Returns:
62 A list of test process info objects containing the following dictionary 64 A list of test process info objects containing the following dictionary
63 entries: 65 entries:
64 'test': the test name; 66 'test': the test name;
65 'proc': the Popen process instance for this test run. 67 'proc': the Popen process instance for this test run.
66 """ 68 """
67 ssh_port = self._base_ssh_port 69 ssh_port = self._base_ssh_port
68 spawned_tests = [] 70 spawned_tests = []
69 for test in self._tests: 71 for test in self._tests:
70 args = [ os.path.join(os.path.dirname(__file__), 'cros_run_vm_test'), 72 args = [ os.path.join(os.path.dirname(__file__), 'cros_run_vm_test'),
71 '--snapshot', # The image is shared so don't modify it. 73 '--snapshot', # The image is shared so don't modify it.
72 '--no_graphics', 74 '--no_graphics',
73 '--ssh_port=%d' % ssh_port ] 75 '--ssh_port=%d' % ssh_port ]
74 if self._board: args.append('--board=%s' % self._board) 76 if self._board: args.append('--board=%s' % self._board)
75 if self._image_path: args.append('--image_path=%s' % self._image_path) 77 if self._image_path: args.append('--image_path=%s' % self._image_path)
78 results_dir = '%s/%s.%d' % (self._results_dir_root, test, ssh_port)
petkov 2011/03/02 23:08:34 subtle... it took me a while to think through the
Chris Masone 2011/03/02 23:27:28 Done.
76 if self._results_dir_root: 79 if self._results_dir_root:
77 args.append('--results_dir_root=%s/%s.%d' % 80 args.append('--results_dir_root=%s' % results_dir)
78 (self._results_dir_root, test, ssh_port))
79 if self._use_emerged: args.append('--use_emerged') 81 if self._use_emerged: args.append('--use_emerged')
80 args.append(test) 82 args.append(test)
81 Info('Running %r...' % args) 83 Info('Running %r...' % args)
82 output = None 84 output = None
83 if self._order_output: 85 if self._order_output:
84 output = tempfile.NamedTemporaryFile(prefix='parallel_vm_test_') 86 output = tempfile.NamedTemporaryFile(prefix='parallel_vm_test_')
85 Info('Piping output to %s.' % output.name) 87 Info('Piping output to %s.' % output.name)
88 if self._quiet:
petkov 2011/03/02 23:08:34 can you move this up and do "elif self._order_outp
Chris Masone 2011/03/02 23:27:28 Done.
89 output = open('/dev/null', mode='w')
90 Info('Output is in %s' % results_dir)
petkov 2011/03/02 23:08:34 You mean the log files are there?
Chris Masone 2011/03/02 23:27:28 Yes.
86 proc = subprocess.Popen(args, stdout=output, stderr=output) 91 proc = subprocess.Popen(args, stdout=output, stderr=output)
87 test_info = { 'test': test, 92 test_info = { 'test': test,
88 'proc': proc, 93 'proc': proc,
89 'output': output } 94 'output': output }
90 spawned_tests.append(test_info) 95 spawned_tests.append(test_info)
91 ssh_port = ssh_port + 1 96 ssh_port = ssh_port + 1
92 return spawned_tests 97 return spawned_tests
93 98
94 def _WaitForCompletion(self, spawned_tests): 99 def _WaitForCompletion(self, spawned_tests):
95 """Waits for tests to complete and returns a list of failed tests. 100 """Waits for tests to complete and returns a list of failed tests.
96 101
97 If the test output was piped to a file, dumps the file contents to stdout. 102 If the test output was piped to a file, dumps the file contents to stdout.
98 103
99 Args: 104 Args:
100 spawned_tests: A list of test info objects (see _SpawnTests). 105 spawned_tests: A list of test info objects (see _SpawnTests).
101 106
102 Returns: 107 Returns:
103 A list of failed test names. 108 A list of failed test names.
104 """ 109 """
105 failed_tests = [] 110 failed_tests = []
106 for test_info in spawned_tests: 111 for test_info in spawned_tests:
107 proc = test_info['proc'] 112 proc = test_info['proc']
108 proc.wait() 113 proc.wait()
109 if proc.returncode: failed_tests.append(test_info['test']) 114 if proc.returncode: failed_tests.append(test_info['test'])
110 output = test_info['output'] 115 output = test_info['output']
111 if output: 116 if output and not self._quiet:
112 test = test_info['test'] 117 test = test_info['test']
113 Info('------ START %s:%s ------' % (test, output.name)) 118 Info('------ START %s:%s ------' % (test, output.name))
114 output.seek(0) 119 output.seek(0)
115 for line in output: 120 for line in output:
116 print line, 121 print line,
117 Info('------ END %s:%s ------' % (test, output.name)) 122 Info('------ END %s:%s ------' % (test, output.name))
118 return failed_tests 123 return failed_tests
119 124
120 def Run(self): 125 def Run(self):
121 """Runs the tests in |self._tests| on separate VMs in parallel.""" 126 """Runs the tests in |self._tests| on separate VMs in parallel."""
(...skipping 13 matching lines...) Expand all
135 parser.add_option('--board', 140 parser.add_option('--board',
136 help='The target board. If none specified, ' 141 help='The target board. If none specified, '
137 'cros_run_vm_test will use the default board.') 142 'cros_run_vm_test will use the default board.')
138 parser.add_option('--image_path', 143 parser.add_option('--image_path',
139 help='Full path to the VM image. If none specified, ' 144 help='Full path to the VM image. If none specified, '
140 'cros_run_vm_test will use the latest image.') 145 'cros_run_vm_test will use the latest image.')
141 parser.add_option('--order_output', action='store_true', default=False, 146 parser.add_option('--order_output', action='store_true', default=False,
142 help='Rather than emitting interleaved progress output ' 147 help='Rather than emitting interleaved progress output '
143 'from the individual VMs, accumulate the outputs in ' 148 'from the individual VMs, accumulate the outputs in '
144 'temporary files and dump them at the end.') 149 'temporary files and dump them at the end.')
150 parser.add_option('--quiet', action='store_true', default=False,
151 help='Emits no output from the VMs. Forces --order_output'
152 'to be false, and requires specifying --results_dir_root')
145 parser.add_option('--results_dir_root', 153 parser.add_option('--results_dir_root',
146 help='Root results directory. If none specified, each test ' 154 help='Root results directory. If none specified, each test '
147 'will store its results in a separate /tmp directory.') 155 'will store its results in a separate /tmp directory.')
148 parser.add_option('--use_emerged', action='store_true', default=False, 156 parser.add_option('--use_emerged', action='store_true', default=False,
149 help='Force use of emerged autotest packages') 157 help='Force use of emerged autotest packages')
150 (options, args) = parser.parse_args() 158 (options, args) = parser.parse_args()
151 159
152 if not args: 160 if not args:
153 parser.print_help() 161 parser.print_help()
154 Die('no tests provided') 162 Die('no tests provided')
155 163
164 if options.quiet:
165 options.order_output = False
166 if not options.results_dir_root:
167 Die('--quiet requires --results_dir_root')
156 runner = ParallelTestRunner(args, options.base_ssh_port, options.board, 168 runner = ParallelTestRunner(args, options.base_ssh_port, options.board,
157 options.image_path, options.order_output, 169 options.image_path, options.order_output,
158 options.results_dir_root, options.use_emerged) 170 options.quiet, options.results_dir_root,
171 options.use_emerged)
159 runner.Run() 172 runner.Run()
160 173
161 174
162 if __name__ == '__main__': 175 if __name__ == '__main__':
163 main() 176 main()
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698