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

Side by Side Diff: build/android/pylib/gtest/test_runner.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: more frank nits 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
« no previous file with comments | « build/android/pylib/gtest/dispatch.py ('k') | build/android/pylib/gtest/test_sharder.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 import glob 5 import glob
6 import logging 6 import logging
7 import os 7 import os
8 import sys
9 8
10 from pylib import android_commands 9 from pylib import android_commands
11 from pylib import constants 10 from pylib import constants
12 from pylib import perf_tests_helper 11 from pylib import perf_tests_helper
13 from pylib.android_commands import errors 12 from pylib.android_commands import errors
14 from pylib.base.base_test_runner import BaseTestRunner 13 from pylib.base import new_base_test_runner as base_test_runner
15 from pylib.base.test_result import BaseTestResult, TestResults 14 from pylib.base import test_result
16 from pylib.utils import run_tests_helper 15 from pylib.utils import run_tests_helper
17 16
18 from test_package_apk import TestPackageApk 17 import test_package_apk
19 from test_package_executable import TestPackageExecutable 18 import test_package_executable
20
21
22 CURFILE_PATH = os.path.abspath(os.path.dirname(__file__))
23 19
24 20
25 def _GetDataFilesForTestSuite(test_suite_basename): 21 def _GetDataFilesForTestSuite(test_suite_basename):
26 """Returns a list of data files/dirs needed by the test suite. 22 """Returns a list of data files/dirs needed by the test suite.
27 23
28 Args: 24 Args:
29 test_suite_basename: The test suite basename for which to return file paths. 25 test_suite_basename: The test suite basename for which to return file paths.
30 26
31 Returns: 27 Returns:
32 A list of test file and directory paths. 28 A list of test file and directory paths.
33 """ 29 """
34 # Ideally, we'd just push all test data. However, it has >100MB, and a lot 30 # Ideally, we'd just push all test data. However, it has >100MB, and a lot
35 # of the files are not relevant (some are used for browser_tests, others for 31 # of the files are not relevant (some are used for browser_tests, others for
36 # features not supported, etc..). 32 # features not supported, etc..).
37 if test_suite_basename in ['base_unittests', 33 if test_suite_basename in ['base_unittests', 'sql_unittests', 'unit_tests']:
38 'sql_unittests',
39 'unit_tests']:
40 test_files = [ 34 test_files = [
41 'base/data/file_util_unittest', 35 'base/data/file_util_unittest',
42 'base/data/json/bom_feff.json', 36 'base/data/json/bom_feff.json',
43 'base/prefs/test/data/pref_service', 37 'base/prefs/test/data/pref_service',
44 'chrome/test/data/download-test1.lib', 38 'chrome/test/data/download-test1.lib',
45 'chrome/test/data/extensions/bad_magic.crx', 39 'chrome/test/data/extensions/bad_magic.crx',
46 'chrome/test/data/extensions/good.crx', 40 'chrome/test/data/extensions/good.crx',
47 'chrome/test/data/extensions/icon1.png', 41 'chrome/test/data/extensions/icon1.png',
48 'chrome/test/data/extensions/icon2.png', 42 'chrome/test/data/extensions/icon2.png',
49 'chrome/test/data/extensions/icon3.png', 43 'chrome/test/data/extensions/icon3.png',
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 return [ 117 return [
124 'media/test/data', 118 'media/test/data',
125 ] 119 ]
126 elif test_suite_basename == 'cc_perftests': 120 elif test_suite_basename == 'cc_perftests':
127 return [ 121 return [
128 'cc/test/data', 122 'cc/test/data',
129 ] 123 ]
130 return [] 124 return []
131 125
132 126
133 class TestRunner(BaseTestRunner): 127 def _TestSuiteRequiresMockTestServer(test_suite_basename):
128 """Returns True if the test suite requires mock test server."""
129 tests_require_net_test_server = ['unit_tests', 'net_unittests',
130 'content_unittests']
131 return (test_suite_basename in
132 tests_require_net_test_server)
133
134
135 class TestRunner(base_test_runner.BaseTestRunner):
134 """Single test suite attached to a single device. 136 """Single test suite attached to a single device.
135 137
136 Args: 138 Args:
137 device: Device to run the tests. 139 device: Device to run the tests.
138 test_suite: A specific test suite to run, empty to run all. 140 test_suite: A specific test suite to run, empty to run all.
139 gtest_filter: A gtest_filter flag.
140 test_arguments: Additional arguments to pass to the test binary. 141 test_arguments: Additional arguments to pass to the test binary.
141 timeout: Timeout for each test. 142 timeout: Timeout for each test.
142 cleanup_test_files: Whether or not to cleanup test files on device. 143 cleanup_test_files: Whether or not to cleanup test files on device.
143 tool: Name of the Valgrind tool. 144 tool_name: Name of the Valgrind tool.
144 shard_index: index number of the shard on which the test suite will run.
145 build_type: 'Release' or 'Debug'. 145 build_type: 'Release' or 'Debug'.
146 in_webkit_checkout: Whether the suite is being run from a WebKit checkout. 146 in_webkit_checkout: Whether the suite is being run from a WebKit checkout.
147 """ 147 """
148 148
149 def __init__(self, device, test_suite, gtest_filter, test_arguments, timeout, 149 def __init__(self, device, test_suite, test_arguments, timeout,
150 cleanup_test_files, tool_name, shard_index, build_type, 150 cleanup_test_files, tool_name, build_type,
151 in_webkit_checkout): 151 in_webkit_checkout):
152 BaseTestRunner.__init__(self, device, tool_name, shard_index, build_type) 152 super(TestRunner, self).__init__(device, tool_name, build_type)
153 self._running_on_emulator = self.device.startswith('emulator') 153 self._running_on_emulator = self.device.startswith('emulator')
154 self._gtest_filter = gtest_filter
155 self._test_arguments = test_arguments 154 self._test_arguments = test_arguments
156 self.test_results = TestResults()
157 self.in_webkit_checkout = in_webkit_checkout 155 self.in_webkit_checkout = in_webkit_checkout
156 self._cleanup_test_files = cleanup_test_files
158 157
159 logging.warning('Test suite: ' + test_suite) 158 logging.warning('Test suite: ' + test_suite)
160 if os.path.splitext(test_suite)[1] == '.apk': 159 if os.path.splitext(test_suite)[1] == '.apk':
161 self.test_package = TestPackageApk( 160 self.test_package = test_package_apk.TestPackageApk(
162 self.adb, 161 self.adb,
163 device, 162 device,
164 test_suite, 163 test_suite,
165 timeout, 164 timeout,
166 cleanup_test_files, 165 self._cleanup_test_files,
167 self.tool) 166 self.tool)
168 else: 167 else:
169 # Put a copy into the android out/target directory, to allow stack trace 168 # Put a copy into the android out/target directory, to allow stack trace
170 # generation. 169 # generation.
171 symbols_dir = os.path.join(constants.CHROME_DIR, 'out', build_type, 170 symbols_dir = os.path.join(constants.CHROME_DIR, 'out', build_type,
172 'lib.target') 171 'lib.target')
173 self.test_package = TestPackageExecutable( 172 self.test_package = test_package_executable.TestPackageExecutable(
174 self.adb, 173 self.adb,
175 device, 174 device,
176 test_suite, timeout, 175 test_suite,
177 cleanup_test_files, 176 timeout,
177 self._cleanup_test_files,
178 self.tool, 178 self.tool,
179 symbols_dir) 179 symbols_dir)
180 180
181 def _TestSuiteRequiresMockTestServer(self):
182 """Returns True if the test suite requires mock test server."""
183 tests_require_net_test_server = ['unit_tests', 'net_unittests',
184 'content_unittests']
185 return (self.test_package.test_suite_basename in
186 tests_require_net_test_server)
187
188 def GetDisabledTests(self):
189 """Returns a list of disabled tests.
190
191 Returns:
192 A list of disabled tests obtained from 'filter' subdirectory.
193 """
194 gtest_filter_base_path = os.path.join(
195 CURFILE_PATH, 'filter', self.test_package.test_suite_basename)
196 disabled_tests = run_tests_helper.GetExpectations(
197 gtest_filter_base_path + '_disabled')
198 if self._running_on_emulator:
199 # Append emulator's filter file.
200 disabled_tests.extend(run_tests_helper.GetExpectations(
201 gtest_filter_base_path + '_emulator_additional_disabled'))
202 return disabled_tests
203
204 def LaunchHelperToolsForTestSuite(self):
205 """Launches helper tools for the test suite.
206
207 Sometimes one test may need to run some helper tools first in order to
208 successfully complete the test.
209 """
210 if self._TestSuiteRequiresMockTestServer():
211 self.LaunchChromeTestServerSpawner()
212 181
213 def StripAndCopyFiles(self): 182 def StripAndCopyFiles(self):
214 """Strips and copies the required data files for the test suite.""" 183 """Strips and copies the required data files for the test suite."""
215 self.test_package.StripAndCopyExecutable() 184 self.test_package.StripAndCopyExecutable()
216 self.test_package.PushDataAndPakFiles() 185 self.test_package.PushDataAndPakFiles()
217 self.tool.CopyFiles() 186 self.tool.CopyFiles()
218 test_data = _GetDataFilesForTestSuite(self.test_package.test_suite_basename) 187 test_data = _GetDataFilesForTestSuite(self.test_package.test_suite_basename)
219 if test_data: 188 if test_data:
220 # Make sure SD card is ready. 189 # Make sure SD card is ready.
221 self.adb.WaitForSdCardReady(20) 190 self.adb.WaitForSdCardReady(20)
(...skipping 11 matching lines...) Expand all
233 webkit_src = os.path.join(constants.CHROME_DIR, 'third_party', 'WebKit') 202 webkit_src = os.path.join(constants.CHROME_DIR, 'third_party', 'WebKit')
234 if self.in_webkit_checkout: 203 if self.in_webkit_checkout:
235 webkit_src = os.path.join(constants.CHROME_DIR, '..', '..', '..') 204 webkit_src = os.path.join(constants.CHROME_DIR, '..', '..', '..')
236 205
237 self.adb.PushIfNeeded( 206 self.adb.PushIfNeeded(
238 os.path.join(webkit_src, 'Source/WebKit/chromium/tests/data'), 207 os.path.join(webkit_src, 'Source/WebKit/chromium/tests/data'),
239 os.path.join( 208 os.path.join(
240 self.adb.GetExternalStorage(), 209 self.adb.GetExternalStorage(),
241 'third_party/WebKit/Source/WebKit/chromium/tests/data')) 210 'third_party/WebKit/Source/WebKit/chromium/tests/data'))
242 211
243 def RunTests(self): 212 # TODO(craigdh): There is no reason for this to be part of TestRunner.
244 """Runs tests on a single device. 213 def GetDisabledTests(self):
214 """Returns a list of disabled tests.
245 215
246 Returns: 216 Returns:
247 A TestResults object. 217 A list of disabled tests obtained from 'filter' subdirectory.
248 """ 218 """
249 if self._gtest_filter: 219 gtest_filter_base_path = os.path.join(
250 try: 220 os.path.abspath(os.path.dirname(__file__)),
251 self.test_package.CreateTestRunnerScript(self._gtest_filter, 221 'filter',
252 self._test_arguments) 222 self.test_package.test_suite_basename)
253 self.test_results = self.test_package.RunTestsAndListResults() 223 disabled_tests = run_tests_helper.GetExpectations(
254 except errors.DeviceUnresponsiveError as e: 224 gtest_filter_base_path + '_disabled')
255 # Make sure this device is not attached 225 if self._running_on_emulator:
256 logging.warning(e) 226 # Append emulator's filter file.
257 if android_commands.IsDeviceAttached(self.device): 227 disabled_tests.extend(run_tests_helper.GetExpectations(
258 raise e 228 gtest_filter_base_path + '_emulator_additional_disabled'))
259 self.test_results.device_exception = device_exception 229 return disabled_tests
260 # Calculate unknown test results. 230
261 finally: 231 def RunTest(self, test):
262 # TODO(frankf): Do not break TestResults encapsulation. 232 """Runs a test on a single device.
263 all_tests = set(self._gtest_filter.split(':')) 233
264 all_tests_ran = set([t.name for t in self.test_results.GetAll()]) 234 Args:
265 unknown_tests = all_tests - all_tests_ran 235 test: a gtest filter string to run.
266 self.test_results.unknown = [BaseTestResult(t, '') for t in 236
267 unknown_tests] 237 Returns:
268 return self.test_results 238 Tuple: (TestResults, test to retry or None)
239 """
240 test_results = test_result.TestResults()
241 if not test:
242 return test_results, None
243
244 try:
245 self.test_package.CreateTestRunnerScript(test, self._test_arguments)
246 test_results = self.test_package.RunTestsAndListResults()
247 except errors.DeviceUnresponsiveError as e:
248 # Make sure this device is not attached
249 logging.warning(e)
250 if android_commands.IsDeviceAttached(self.device):
251 raise
252 test_results.device_exception = device_exception
253 # Calculate unknown test results.
254 # TODO(frankf): Do not break TestResults encapsulation.
255 all_tests = set(test.split(':'))
256 all_tests_ran = set([t.name for t in test_results.GetAll()])
257 unknown_tests = all_tests - all_tests_ran
258 test_results.unknown = [test_result.BaseTestResult(t, '') for t in
259 unknown_tests]
260 retry = ':'.join([t.name for t in test_results.GetAllBroken()])
261 return test_results, retry
269 262
270 def SetUp(self): 263 def SetUp(self):
271 """Sets up necessary test enviroment for the test suite.""" 264 """Sets up necessary test enviroment for the test suite."""
272 super(TestRunner, self).SetUp() 265 super(TestRunner, self).SetUp()
273 self.adb.ClearApplicationState(constants.CHROME_PACKAGE) 266 self.adb.ClearApplicationState(constants.CHROME_PACKAGE)
274 self.StripAndCopyFiles() 267 self.StripAndCopyFiles()
275 self.LaunchHelperToolsForTestSuite() 268 if _TestSuiteRequiresMockTestServer(self.test_package.test_suite_basename):
269 self.LaunchChromeTestServerSpawner()
276 self.tool.SetupEnvironment() 270 self.tool.SetupEnvironment()
277 271
278 def TearDown(self): 272 def TearDown(self):
279 """Cleans up the test enviroment for the test suite.""" 273 """Cleans up the test enviroment for the test suite."""
280 self.tool.CleanUpEnvironment() 274 self.tool.CleanUpEnvironment()
281 if self.test_package.cleanup_test_files: 275 if self._cleanup_test_files:
282 self.adb.RemovePushedFiles() 276 self.adb.RemovePushedFiles()
283 super(TestRunner, self).TearDown() 277 super(TestRunner, self).TearDown()
OLDNEW
« no previous file with comments | « build/android/pylib/gtest/dispatch.py ('k') | build/android/pylib/gtest/test_sharder.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698