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

Side by Side Diff: build/android/pylib/base/shard.py

Issue 12378048: [Android] Switch instrumentation tests to the new shard/runner paradigm. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 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
1 # Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """Implements test sharding logic.""" 5 """Implements test sharding logic."""
6 6
7 import logging 7 import logging
8 import threading 8 import threading
9 9
10 from pylib import android_commands 10 from pylib import android_commands
11 from pylib import forwarder 11 from pylib import forwarder
12 from pylib.utils import reraiser_thread 12 from pylib.utils import reraiser_thread
13 13
14 import test_result 14 import test_result
15 15
16 16
17 class _ThreadSafeCounter(object):
18 """A threadsafe counter."""
19 def __init__(self):
20 self._lock = threading.Lock()
21 self._value = 0
22
23 def GetAndIncrement(self):
24 """Get the current value and increment it atomically.
25
26 Returns:
27 The value before incrementing.
28 """
29 with self._lock:
30 pre_increment = self._value
31 self._value += 1
32 return pre_increment
33
34
17 class _Test(object): 35 class _Test(object):
18 """Holds a test with additional metadata.""" 36 """Holds a test with additional metadata."""
19 def __init__(self, test, tries=0): 37 def __init__(self, test, tries=0):
20 """Initializes the _Test object. 38 """Initializes the _Test object.
21 39
22 Args: 40 Args:
23 test: the test. 41 test: the test.
24 tries: number of tries so far. 42 tries: number of tries so far.
25 """ 43 """
26 self.test = test 44 self.test = test
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 except: 146 except:
129 # An unhandleable exception, ensure tests get run by another device and 147 # An unhandleable exception, ensure tests get run by another device and
130 # reraise this exception on the main thread. 148 # reraise this exception on the main thread.
131 test_collection.add(test) 149 test_collection.add(test)
132 raise 150 raise
133 finally: 151 finally:
134 # Retries count as separate tasks so always mark the popped test as done. 152 # Retries count as separate tasks so always mark the popped test as done.
135 test_collection.test_completed() 153 test_collection.test_completed()
136 154
137 155
138 def _SetUp(runner_factory, device, out_runners): 156 def _SetUp(runner_factory, device, out_runners, threadsafe_counter):
139 """Creates a test runner for each device and calls SetUp() in parallel. 157 """Creates a test runner for each device and calls SetUp() in parallel.
140 158
141 Note: if a device is unresponsive the corresponding TestRunner will not be 159 Note: if a device is unresponsive the corresponding TestRunner will not be
142 added to out_runners. 160 added to out_runners.
143 161
144 Args: 162 Args:
145 runner_factory: callable that takes a device and returns a TestRunner. 163 runner_factory: callable that takes a device and index and returns a
164 TestRunner object.
146 device: the device serial number to set up. 165 device: the device serial number to set up.
147 out_runners: list to add the successfully set up TestRunner object. 166 out_runners: list to add the successfully set up TestRunner object.
167 threadsafe_counter: a _ThreadSafeCounter object used to get shard indices.
148 """ 168 """
149 try: 169 try:
150 logging.warning('*****Creating shard for %s.', device) 170 index = threadsafe_counter.GetAndIncrement()
151 runner = runner_factory(device) 171 logging.warning('*****Creating shard %s for device %s.', index, device)
172 runner = runner_factory(device, index)
152 runner.SetUp() 173 runner.SetUp()
153 out_runners.append(runner) 174 out_runners.append(runner)
154 except android_commands.errors.DeviceUnresponsiveError as e: 175 except android_commands.errors.DeviceUnresponsiveError as e:
155 logging.warning('****Failed to create shard for %s: [%s]', (device, e)) 176 logging.warning('****Failed to create shard for %s: [%s]', device, e)
156 177
157 178
158 def _RunAllTests(runners, tests): 179 def _RunAllTests(runners, tests):
159 """Run all tests using the given TestRunners. 180 """Run all tests using the given TestRunners.
160 181
161 Args: 182 Args:
162 runners: a list of TestRunner objects. 183 runners: a list of TestRunner objects.
163 tests: a list of Tests to run using the given TestRunners. 184 tests: a list of Tests to run using the given TestRunners.
164 185
165 Returns: 186 Returns:
(...skipping 10 matching lines...) Expand all
176 return test_result.TestResults.FromTestResults(results) 197 return test_result.TestResults.FromTestResults(results)
177 198
178 199
179 def _CreateRunners(runner_factory, devices): 200 def _CreateRunners(runner_factory, devices):
180 """Creates a test runner for each device and calls SetUp() in parallel. 201 """Creates a test runner for each device and calls SetUp() in parallel.
181 202
182 Note: if a device is unresponsive the corresponding TestRunner will not be 203 Note: if a device is unresponsive the corresponding TestRunner will not be
183 included in the returned list. 204 included in the returned list.
184 205
185 Args: 206 Args:
186 runner_factory: callable that takes a device and returns a TestRunner. 207 runner_factory: callable that takes a device and index and returns a
208 TestRunner object.
187 devices: list of device serial numbers as strings. 209 devices: list of device serial numbers as strings.
188 210
189 Returns: 211 Returns:
190 A list of TestRunner objects. 212 A list of TestRunner objects.
191 """ 213 """
192 logging.warning('****Creating %s test runners.' % len(devices)) 214 logging.warning('****Creating %s test runners.' % len(devices))
193 test_runners = [] 215 runners = []
216 counter = _ThreadSafeCounter()
194 threads = reraiser_thread.ReraiserThreadGroup( 217 threads = reraiser_thread.ReraiserThreadGroup(
195 [reraiser_thread.ReraiserThread(_SetUp, [runner_factory, d, test_runners]) 218 [reraiser_thread.ReraiserThread(_SetUp, [runner_factory, d, runners,
219 counter])
196 for d in devices]) 220 for d in devices])
197 threads.StartAll() 221 threads.StartAll()
198 threads.JoinAll() 222 threads.JoinAll()
199 return test_runners 223 return runners
200 224
201 225
202 def _TearDownRunners(runners): 226 def _TearDownRunners(runners):
203 """Calls TearDown() for each test runner in parallel. 227 """Calls TearDown() for each test runner in parallel.
204 Args: 228 Args:
205 runners: a list of TestRunner objects. 229 runners: a list of TestRunner objects.
206 """ 230 """
207 threads = reraiser_thread.ReraiserThreadGroup( 231 threads = reraiser_thread.ReraiserThreadGroup(
208 [reraiser_thread.ReraiserThread(runner.TearDown) 232 [reraiser_thread.ReraiserThread(runner.TearDown)
209 for runner in runners]) 233 for runner in runners])
210 threads.StartAll() 234 threads.StartAll()
211 threads.JoinAll() 235 threads.JoinAll()
212 236
213 237
214 def ShardAndRunTests(runner_factory, devices, tests, build_type='Debug'): 238 def ShardAndRunTests(runner_factory, devices, tests, build_type='Debug'):
215 """Run all tests on attached devices, retrying tests that don't pass. 239 """Run all tests on attached devices, retrying tests that don't pass.
216 240
217 Args: 241 Args:
218 runner_factory: callable that takes a device and returns a TestRunner. 242 runner_factory: callable that takes a device and index and returns a
243 TestRunner object.
219 devices: list of attached device serial numbers as strings. 244 devices: list of attached device serial numbers as strings.
220 tests: list of tests to run. 245 tests: list of tests to run.
221 build_type: either 'Debug' or 'Release'. 246 build_type: either 'Debug' or 'Release'.
222 247
223 Returns: 248 Returns:
224 A test_result.TestResults object. 249 A test_result.TestResults object.
225 """ 250 """
226 forwarder.Forwarder.KillHost(build_type) 251 forwarder.Forwarder.KillHost(build_type)
227 runners = _CreateRunners(runner_factory, devices) 252 runners = _CreateRunners(runner_factory, devices)
228 try: 253 try:
229 return _RunAllTests(runners, tests) 254 return _RunAllTests(runners, tests)
230 finally: 255 finally:
231 try: 256 try:
232 _TearDownRunners(runners) 257 _TearDownRunners(runners)
233 except android_commands.errors.DeviceUnresponsiveError as e: 258 except android_commands.errors.DeviceUnresponsiveError as e:
234 logging.warning('****Device unresponsive during TearDown: [%s]', e) 259 logging.warning('****Device unresponsive during TearDown: [%s]', e)
235 finally: 260 finally:
236 forwarder.Forwarder.KillHost(build_type) 261 forwarder.Forwarder.KillHost(build_type)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698