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

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

Issue 12278020: [Android] Re-write the gtest TestRunner and introduce a new generic sharder. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: raise an exception if there are no devices visible Created 7 years, 10 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 # 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
3 # found in the LICENSE file.
4
5 """Implements test sharding logic."""
6
7 import logging
8 import sys
9 import threading
10
11 from pylib import android_commands
12 from pylib import forwarder
13
14 import test_result
15
16
17 class _Worker(threading.Thread):
18 """Runs tests from the test_queue using the given runner in a separate thread.
19
20 Places results in the results_list.
frankf 2013/02/20 18:55:31 results_list -> out_results
craigdh 2013/02/20 19:38:09 Done.
21 """
22 def __init__(self, runner, test_queue, out_results, out_retry):
23 """Initializes the worker.
24
25 Args:
26 runner: A TestRunner object used to run the tests.
27 test_queue: A list from which to get tests to run.
28 out_results: A list to add TestResults to.
29 out_retry: A list to add tests to retry.
30 """
31 super(_Worker, self).__init__()
32 self.daemon = True
33 self._exc_info = None
34 self._runner = runner
35 self._test_queue = test_queue
36 self._out_results = out_results
37 self._out_retry = out_retry
38
39 def run(self):
40 """Run tests from the queue until it is empty, storing results.
frankf 2013/02/20 18:55:31 be more precise than "storing results" :)
craigdh 2013/02/20 19:38:09 Done.
41
42 Overriden from threading.Thread, runs in a separate thread.
frankf 2013/02/20 18:55:31 I think we do something like #Override before the
craigdh 2013/02/20 19:38:09 Done.
43 """
44 try:
45 while True:
46 test = self._test_queue.pop()
47 result, retry = self._runner.Run(test)
48 self._out_results.append(result)
49 if retry:
50 self._out_retry.append(retry)
51 except IndexError:
52 pass
53 except:
54 self._exc_info = sys.exc_info()
55 raise
56
57 def Reraise(self):
58 """Reraise an exception raised in the thread."""
frankf 2013/02/20 18:55:31 Reraise _if_ an exception... Maybe rename to bett
craigdh 2013/02/20 19:38:09 Done.
59 if self._exc_info:
60 raise self._exc_info[0], self._exc_info[1], self._exc_info[2]
61
62
63 def _RunAllTests(runners, tests):
64 """Run all tests using the given TestRunners.
65
66 Args:
67 runners: a list of TestRunner objects.
68 tests: a list of Tests to run using the given TestRunners.
69
70 Returns:
71 Tuple: (list of TestResults, list of tests to retry)
72 """
73 tests_queue = list(tests)
74 workers = []
75 results = []
76 retry = []
77 for r in runners:
78 worker = _Worker(r, tests_queue, results, retry)
79 worker.start()
80 workers.append(worker)
81 while workers:
82 for w in workers[:]:
83 # Allow the main thread to periodically check for keyboard interrupts.
84 w.join(0.1)
85 if not w.isAlive():
86 w.Reraise()
87 workers.remove(w)
88 return (results, retry)
89
90
91 def _CreateRunners(runner_factory, devices):
92 """Creates a test runner for each device.
93
94 Note: if a device is unresponsive the corresponding TestRunner will not be
95 included in the returned list.
96
97 Args:
98 runner_factory: callable that takes a device and returns a TestRunner.
99 devices: list of device serial numbers as strings.
100
101 Returns:
102 A list of TestRunner objects.
103 """
104 test_runners = []
105 for index, device in enumerate(devices):
106 logging.warning('*' * 80)
107 logging.warning('Creating shard %d for %s', index, device)
108 logging.warning('*' * 80)
109 try:
110 test_runners.append(runner_factory(device))
111 except android_commands.errors.DeviceUnresponsiveError as e:
112 logging.warning('****Failed to create a shard: [%s]', e)
frankf 2013/02/20 18:55:31 Does this print the device that failed?
craigdh 2013/02/20 19:38:09 I'm not sure if the exception message includes the
113 return test_runners
114
115
116 def ShardAndRunTests(
117 runner_factory, devices, tests, build_type='Debug', tries=3,
118 get_attached_devices_callable=android_commands.GetAttachedDevices):
119 """Run all tests on attached devices, retrying tests that don't pass.
120
121 Args:
122 runner_factory: callable that takes a device and returns a TestRunner.
123 devices: list of attached device serial numbers as strings.
124 tests: list of tests to run.
125 build_type: either 'Debug' or 'Release'.
126 retries: number of retries before accepting failure.
frankf 2013/02/20 18:55:31 update this.
craigdh 2013/02/20 19:38:09 Done.
127 get_attached_devices_callable: only override default value for testing.
frankf 2013/02/20 18:55:31 Can you use pymox to mock out the calls to adb ins
craigdh 2013/02/20 19:38:09 Removed this, it was a trivial one-liner to mock o
128
129 Returns:
130 A test_result.TestResults object.
131 """
132 final_results = test_result.TestResults()
133 results = test_result.TestResults()
134 forwarder.Forwarder.KillHost(build_type)
135 try_count = 0
136 while tests:
137 devices = set(devices).intersection(get_attached_devices_callable())
138 if not devices:
139 logging.critical('No devices attached and visible to run tests!')
frankf 2013/02/20 18:55:31 msg = ...
craigdh 2013/02/20 19:38:09 Done.
140 raise Exception('No devices attached and visible to run tests!')
141 if try_count >= tries:
frankf 2013/02/20 18:55:31 Add some comments for these termination conditions
craigdh 2013/02/20 19:38:09 Done.
142 results.ok = final_results.ok
143 final_results = results
144 break
145 try_count += 1
146 runners = _CreateRunners(runner_factory, devices)
147 try:
148 results_list, tests = _RunAllTests(runners, tests)
149 results = test_result.TestResults.FromTestResults(results_list)
150 final_results.ok += results.ok
151 except android_commands.errors.DeviceUnresponsiveError as e:
152 logging.warning('****Failed to run test: [%s]', e)
153 forwarder.Forwarder.KillHost(build_type)
154 return final_results
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698