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

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: Address comments per petkov 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 quiet: Emits no output from the VMs. Forces --order_output to be false,
45 and requires specifying --results_dir_root
44 results_dir_root: The results directory root. If provided, the results 46 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 47 directory root for each test will be created under it with the SSH port
46 appended to the test name. 48 appended to the test name.
49 use_emerged: Force use of emerged autotest packages.
47 """ 50 """
48 self._tests = tests 51 self._tests = tests
49 self._base_ssh_port = base_ssh_port 52 self._base_ssh_port = base_ssh_port
50 self._board = board 53 self._board = board
51 self._image_path = image_path 54 self._image_path = image_path
52 self._order_output = order_output 55 self._order_output = order_output
56 self._quiet = quiet
53 self._results_dir_root = results_dir_root 57 self._results_dir_root = results_dir_root
54 self._use_emerged = use_emerged 58 self._use_emerged = use_emerged
55 59
56 def _SpawnTests(self): 60 def _SpawnTests(self):
57 """Spawns VMs and starts the test runs on them. 61 """Spawns VMs and starts the test runs on them.
58 62
59 Runs all tests in |self._tests|. Each test is executed on a separate VM. 63 Runs all tests in |self._tests|. Each test is executed on a separate VM.
60 64
61 Returns: 65 Returns:
62 A list of test process info objects containing the following dictionary 66 A list of test process info objects containing the following dictionary
63 entries: 67 entries:
64 'test': the test name; 68 'test': the test name;
65 'proc': the Popen process instance for this test run. 69 'proc': the Popen process instance for this test run.
66 """ 70 """
67 ssh_port = self._base_ssh_port 71 ssh_port = self._base_ssh_port
68 spawned_tests = [] 72 spawned_tests = []
69 for test in self._tests: 73 for test in self._tests:
70 args = [ os.path.join(os.path.dirname(__file__), 'cros_run_vm_test'), 74 args = [ os.path.join(os.path.dirname(__file__), 'cros_run_vm_test'),
71 '--snapshot', # The image is shared so don't modify it. 75 '--snapshot', # The image is shared so don't modify it.
72 '--no_graphics', 76 '--no_graphics',
73 '--ssh_port=%d' % ssh_port ] 77 '--ssh_port=%d' % ssh_port ]
74 if self._board: args.append('--board=%s' % self._board) 78 if self._board: args.append('--board=%s' % self._board)
75 if self._image_path: args.append('--image_path=%s' % self._image_path) 79 if self._image_path: args.append('--image_path=%s' % self._image_path)
80 results_dir = None
76 if self._results_dir_root: 81 if self._results_dir_root:
77 args.append('--results_dir_root=%s/%s.%d' % 82 results_dir = '%s/%s.%d' % (self._results_dir_root, test, ssh_port)
78 (self._results_dir_root, test, ssh_port)) 83 args.append('--results_dir_root=%s' % results_dir)
79 if self._use_emerged: args.append('--use_emerged') 84 if self._use_emerged: args.append('--use_emerged')
80 args.append(test) 85 args.append(test)
81 Info('Running %r...' % args) 86 Info('Running %r...' % args)
82 output = None 87 output = None
83 if self._order_output: 88 if self._quiet:
89 output = open('/dev/null', mode='w')
90 Info('Log files are in %s' % results_dir)
91 elif self._order_output:
84 output = tempfile.NamedTemporaryFile(prefix='parallel_vm_test_') 92 output = tempfile.NamedTemporaryFile(prefix='parallel_vm_test_')
85 Info('Piping output to %s.' % output.name) 93 Info('Piping output to %s.' % output.name)
86 proc = subprocess.Popen(args, stdout=output, stderr=output) 94 proc = subprocess.Popen(args, stdout=output, stderr=output)
87 test_info = { 'test': test, 95 test_info = { 'test': test,
88 'proc': proc, 96 'proc': proc,
89 'output': output } 97 'output': output }
90 spawned_tests.append(test_info) 98 spawned_tests.append(test_info)
91 ssh_port = ssh_port + 1 99 ssh_port = ssh_port + 1
92 return spawned_tests 100 return spawned_tests
93 101
94 def _WaitForCompletion(self, spawned_tests): 102 def _WaitForCompletion(self, spawned_tests):
95 """Waits for tests to complete and returns a list of failed tests. 103 """Waits for tests to complete and returns a list of failed tests.
96 104
97 If the test output was piped to a file, dumps the file contents to stdout. 105 If the test output was piped to a file, dumps the file contents to stdout.
98 106
99 Args: 107 Args:
100 spawned_tests: A list of test info objects (see _SpawnTests). 108 spawned_tests: A list of test info objects (see _SpawnTests).
101 109
102 Returns: 110 Returns:
103 A list of failed test names. 111 A list of failed test names.
104 """ 112 """
105 failed_tests = [] 113 failed_tests = []
106 for test_info in spawned_tests: 114 for test_info in spawned_tests:
107 proc = test_info['proc'] 115 proc = test_info['proc']
108 proc.wait() 116 proc.wait()
109 if proc.returncode: failed_tests.append(test_info['test']) 117 if proc.returncode: failed_tests.append(test_info['test'])
110 output = test_info['output'] 118 output = test_info['output']
111 if output: 119 if output and not self._quiet:
112 test = test_info['test'] 120 test = test_info['test']
113 Info('------ START %s:%s ------' % (test, output.name)) 121 Info('------ START %s:%s ------' % (test, output.name))
114 output.seek(0) 122 output.seek(0)
115 for line in output: 123 for line in output:
116 print line, 124 print line,
117 Info('------ END %s:%s ------' % (test, output.name)) 125 Info('------ END %s:%s ------' % (test, output.name))
118 return failed_tests 126 return failed_tests
119 127
120 def Run(self): 128 def Run(self):
121 """Runs the tests in |self._tests| on separate VMs in parallel.""" 129 """Runs the tests in |self._tests| on separate VMs in parallel."""
(...skipping 13 matching lines...) Expand all
135 parser.add_option('--board', 143 parser.add_option('--board',
136 help='The target board. If none specified, ' 144 help='The target board. If none specified, '
137 'cros_run_vm_test will use the default board.') 145 'cros_run_vm_test will use the default board.')
138 parser.add_option('--image_path', 146 parser.add_option('--image_path',
139 help='Full path to the VM image. If none specified, ' 147 help='Full path to the VM image. If none specified, '
140 'cros_run_vm_test will use the latest image.') 148 'cros_run_vm_test will use the latest image.')
141 parser.add_option('--order_output', action='store_true', default=False, 149 parser.add_option('--order_output', action='store_true', default=False,
142 help='Rather than emitting interleaved progress output ' 150 help='Rather than emitting interleaved progress output '
143 'from the individual VMs, accumulate the outputs in ' 151 'from the individual VMs, accumulate the outputs in '
144 'temporary files and dump them at the end.') 152 'temporary files and dump them at the end.')
153 parser.add_option('--quiet', action='store_true', default=False,
154 help='Emits no output from the VMs. Forces --order_output'
155 'to be false, and requires specifying --results_dir_root')
145 parser.add_option('--results_dir_root', 156 parser.add_option('--results_dir_root',
146 help='Root results directory. If none specified, each test ' 157 help='Root results directory. If none specified, each test '
147 'will store its results in a separate /tmp directory.') 158 'will store its results in a separate /tmp directory.')
148 parser.add_option('--use_emerged', action='store_true', default=False, 159 parser.add_option('--use_emerged', action='store_true', default=False,
149 help='Force use of emerged autotest packages') 160 help='Force use of emerged autotest packages')
150 (options, args) = parser.parse_args() 161 (options, args) = parser.parse_args()
151 162
152 if not args: 163 if not args:
153 parser.print_help() 164 parser.print_help()
154 Die('no tests provided') 165 Die('no tests provided')
155 166
167 if options.quiet:
168 options.order_output = False
169 if not options.results_dir_root:
170 Die('--quiet requires --results_dir_root')
156 runner = ParallelTestRunner(args, options.base_ssh_port, options.board, 171 runner = ParallelTestRunner(args, options.base_ssh_port, options.board,
157 options.image_path, options.order_output, 172 options.image_path, options.order_output,
158 options.results_dir_root, options.use_emerged) 173 options.quiet, options.results_dir_root,
174 options.use_emerged)
159 runner.Run() 175 runner.Run()
160 176
161 177
162 if __name__ == '__main__': 178 if __name__ == '__main__':
163 main() 179 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