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

Side by Side Diff: build/android/pylib/base_test_sharder.py

Issue 11421149: Ensure host_forwarder is killed when setting up/tearing down sharding. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address Marcus' comments Created 8 years 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 | build/android/pylib/forwarder.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2012 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 5
6 import android_commands 6 import android_commands
7 import logging 7 import logging
8 import multiprocessing 8 import multiprocessing
9 9
10 from android_commands import errors 10 from android_commands import errors
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 device: Device serial where this shard will run 59 device: Device serial where this shard will run
60 index: Index of this device in the pool. 60 index: Index of this device in the pool.
61 61
62 Returns: 62 Returns:
63 An object of BaseTestRunner type (that can provide a "Run()" method). 63 An object of BaseTestRunner type (that can provide a "Run()" method).
64 """ 64 """
65 pass 65 pass
66 66
67 def SetupSharding(self, tests): 67 def SetupSharding(self, tests):
68 """Called before starting the shards.""" 68 """Called before starting the shards."""
69 Forwarder.KillHost(self.build_type) 69 pass
70 70
71 def OnTestsCompleted(self, test_runners, test_results): 71 def OnTestsCompleted(self, test_runners, test_results):
72 """Notifies that we completed the tests.""" 72 """Notifies that we completed the tests."""
73 pass
74
75 def _KillHostForwarder(self):
73 Forwarder.KillHost(self.build_type) 76 Forwarder.KillHost(self.build_type)
74 77
75 def RunShardedTests(self): 78 def RunShardedTests(self):
76 """Runs the tests in all connected devices. 79 """Runs the tests in all connected devices.
77 80
78 Returns: 81 Returns:
79 A TestResults object. 82 A TestResults object.
80 """ 83 """
81 logging.warning('*' * 80) 84 logging.warning('*' * 80)
82 logging.warning('Sharding in ' + str(len(self.attached_devices)) + 85 logging.warning('Sharding in ' + str(len(self.attached_devices)) +
83 ' devices.') 86 ' devices.')
84 logging.warning('Note that the output is not synchronized.') 87 logging.warning('Note that the output is not synchronized.')
85 logging.warning('Look for the "Final result" banner in the end.') 88 logging.warning('Look for the "Final result" banner in the end.')
86 logging.warning('*' * 80) 89 logging.warning('*' * 80)
87 final_results = TestResults() 90 final_results = TestResults()
88 for retry in xrange(self.retries): 91 self._KillHostForwarder()
89 logging.warning('Try %d of %d', retry + 1, self.retries) 92 try:
bulach 2012/11/29 18:36:24 hmm, this try..finally block is really long and ma
Philippe 2012/11/30 09:01:54 Done. Yes I agree. It's not worth making the code
90 self.SetupSharding(self.tests) 93 for retry in xrange(self.retries):
91 test_runners = [] 94 logging.warning('Try %d of %d', retry + 1, self.retries)
95 self.SetupSharding(self.tests)
96 test_runners = []
92 97
93 # Try to create N shards, and retrying on failure. 98 # Try to create N shards, and retrying on failure.
94 try: 99 try:
95 for index, device in enumerate(self.attached_devices): 100 for index, device in enumerate(self.attached_devices):
96 logging.warning('*' * 80) 101 logging.warning('*' * 80)
97 logging.warning('Creating shard %d for %s', index, device) 102 logging.warning('Creating shard %d for %s', index, device)
98 logging.warning('*' * 80) 103 logging.warning('*' * 80)
99 test_runner = self.CreateShardedTestRunner(device, index) 104 test_runner = self.CreateShardedTestRunner(device, index)
100 test_runners += [test_runner] 105 test_runners += [test_runner]
101 except errors.DeviceUnresponsiveError as e: 106 except errors.DeviceUnresponsiveError as e:
102 logging.critical('****Failed to create a shard: [%s]', e) 107 logging.critical('****Failed to create a shard: [%s]', e)
103 self.attached_devices.remove(device) 108 self.attached_devices.remove(device)
104 continue 109 continue
105 110
106 logging.warning('Starting...') 111 logging.warning('Starting...')
107 pool = multiprocessing.Pool(len(self.attached_devices), 112 pool = multiprocessing.Pool(len(self.attached_devices),
108 SetTestsContainer, 113 SetTestsContainer,
109 [BaseTestSharder.tests_container]) 114 [BaseTestSharder.tests_container])
110 # map can't handle KeyboardInterrupt exception. It's a python bug. 115 # map can't handle KeyboardInterrupt exception. It's a python bug.
111 # So use map_async instead. 116 # So use map_async instead.
112 async_results = pool.map_async(_ShardedTestRunnable, test_runners) 117 async_results = pool.map_async(_ShardedTestRunnable, test_runners)
113 try: 118 try:
114 results_lists = async_results.get(999999) 119 results_lists = async_results.get(999999)
115 except errors.DeviceUnresponsiveError as e: 120 except errors.DeviceUnresponsiveError as e:
116 logging.critical('****Failed to run test: [%s]', e) 121 logging.critical('****Failed to run test: [%s]', e)
117 self.attached_devices = android_commands.GetAttachedDevices() 122 self.attached_devices = android_commands.GetAttachedDevices()
118 continue 123 continue
119 test_results = TestResults.FromTestResults(results_lists) 124 test_results = TestResults.FromTestResults(results_lists)
120 # Re-check the attached devices for some devices may 125 # Re-check the attached devices for some devices may
121 # become offline 126 # become offline
122 retry_devices = set(android_commands.GetAttachedDevices()) 127 retry_devices = set(android_commands.GetAttachedDevices())
123 # Remove devices that had exceptions. 128 # Remove devices that had exceptions.
124 retry_devices -= TestResults.DeviceExceptions(results_lists) 129 retry_devices -= TestResults.DeviceExceptions(results_lists)
125 # Retry on devices that didn't have any exception. 130 # Retry on devices that didn't have any exception.
126 self.attached_devices = list(retry_devices) 131 self.attached_devices = list(retry_devices)
127 if (retry == self.retries - 1 or 132 if (retry == self.retries - 1 or
128 len(self.attached_devices) == 0): 133 len(self.attached_devices) == 0):
129 all_passed = final_results.ok + test_results.ok 134 all_passed = final_results.ok + test_results.ok
130 final_results = test_results 135 final_results = test_results
131 final_results.ok = all_passed 136 final_results.ok = all_passed
132 break 137 break
138 else:
139 final_results.ok += test_results.ok
140 self.tests = []
141 for t in test_results.GetAllBroken():
142 self.tests += [t.name]
143 if not self.tests:
144 break
133 else: 145 else:
134 final_results.ok += test_results.ok 146 # We ran out retries, possibly out of healthy devices.
135 self.tests = [] 147 # There's no recovery at this point.
136 for t in test_results.GetAllBroken(): 148 raise Exception('Unrecoverable error while retrying test runs.')
137 self.tests += [t.name] 149 self.OnTestsCompleted(test_runners, final_results)
138 if not self.tests: 150 finally:
139 break 151 self._KillHostForwarder()
140 else: 152
141 # We ran out retries, possibly out of healthy devices.
142 # There's no recovery at this point.
143 raise Exception('Unrecoverable error while retrying test runs.')
144 self.OnTestsCompleted(test_runners, final_results)
145 return final_results 153 return final_results
OLDNEW
« no previous file with comments | « no previous file | build/android/pylib/forwarder.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698