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

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

Issue 11557016: Clean up Android gtest runners. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed docstring 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/test_package.py » ('j') | build/android/run_tests.py » ('J')
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 8 import sys
9 9
10 import android_commands
11 from android_commands import errors
10 from base_test_runner import BaseTestRunner 12 from base_test_runner import BaseTestRunner
11 import android_commands 13 import constants
12 import debug_info 14 import debug_info
13 import constants
14 import perf_tests_helper 15 import perf_tests_helper
15 import run_tests_helper 16 import run_tests_helper
16 from android_commands import errors
17 from test_package_apk import TestPackageApk 17 from test_package_apk import TestPackageApk
18 from test_package_executable import TestPackageExecutable 18 from test_package_executable import TestPackageExecutable
19 from test_result import BaseTestResult, TestResults 19 from test_result import BaseTestResult, TestResults
20 20
21 21
22 class SingleTestRunner(BaseTestRunner): 22 class SingleTestRunner(BaseTestRunner):
23 """Single test suite attached to a single device. 23 """Single test suite attached to a single device.
24 24
25 Args: 25 Args:
26 device: Device to run the tests. 26 device: Device to run the tests.
27 test_suite: A specific test suite to run, empty to run all. 27 test_suite: A specific test suite to run, empty to run all.
28 gtest_filter: A gtest_filter flag. 28 gtest_filter: A gtest_filter flag.
29 test_arguments: Additional arguments to pass to the test binary. 29 test_arguments: Additional arguments to pass to the test binary.
30 timeout: Timeout for each test. 30 timeout: Timeout for each test.
31 rebaseline: Whether or not to run tests in isolation and update the filter.
32 performance_test: Whether or not performance test(s). 31 performance_test: Whether or not performance test(s).
33 cleanup_test_files: Whether or not to cleanup test files on device. 32 cleanup_test_files: Whether or not to cleanup test files on device.
34 tool: Name of the Valgrind tool. 33 tool: Name of the Valgrind tool.
35 shard_index: index number of the shard on which the test suite will run. 34 shard_index: index number of the shard on which the test suite will run.
36 dump_debug_info: Whether or not to dump debug information. 35 dump_debug_info: Whether or not to dump debug information.
37 build_type: 'Release' or 'Debug'. 36 build_type: 'Release' or 'Debug'.
38 in_webkit_checkout: Whether the suite is being run from a WebKit checkout. 37 in_webkit_checkout: Whether the suite is being run from a WebKit checkout.
39 """ 38 """
40 39
41 def __init__(self, device, test_suite, gtest_filter, test_arguments, timeout, 40 def __init__(self, device, test_suite, gtest_filter, test_arguments, timeout,
42 rebaseline, performance_test, cleanup_test_files, tool_name, 41 performance_test, cleanup_test_files, tool_name,
43 shard_index, dump_debug_info, fast_and_loose, build_type, 42 shard_index, dump_debug_info, fast_and_loose, build_type,
44 in_webkit_checkout): 43 in_webkit_checkout):
45 BaseTestRunner.__init__(self, device, tool_name, shard_index, build_type) 44 BaseTestRunner.__init__(self, device, tool_name, shard_index, build_type)
46 self._running_on_emulator = self.device.startswith('emulator') 45 self._running_on_emulator = self.device.startswith('emulator')
47 self._gtest_filter = gtest_filter 46 self._gtest_filter = gtest_filter
48 self._test_arguments = test_arguments 47 self._test_arguments = test_arguments
49 self.test_results = TestResults() 48 self.test_results = TestResults()
50 if dump_debug_info: 49 if dump_debug_info:
51 self.dump_debug_info = debug_info.GTestDebugInfo(self.adb, device, 50 self.dump_debug_info = debug_info.GTestDebugInfo(
52 os.path.basename(test_suite), gtest_filter) 51 self.adb, device,
52 os.path.basename(test_suite), gtest_filter)
53 else: 53 else:
54 self.dump_debug_info = None 54 self.dump_debug_info = None
55 self.fast_and_loose = fast_and_loose 55 self.fast_and_loose = fast_and_loose
56 self.in_webkit_checkout = in_webkit_checkout 56 self.in_webkit_checkout = in_webkit_checkout
57 57
58 logging.warning('Test suite: ' + test_suite) 58 logging.warning('Test suite: ' + test_suite)
59 if os.path.splitext(test_suite)[1] == '.apk': 59 if os.path.splitext(test_suite)[1] == '.apk':
60 self.test_package = TestPackageApk(self.adb, device, 60 self.test_package = TestPackageApk(
61 test_suite, timeout, rebaseline, performance_test, cleanup_test_files, 61 self.adb,
62 self.tool, self.dump_debug_info) 62 device,
63 test_suite,
64 timeout,
65 performance_test,
66 cleanup_test_files,
67 self.tool,
68 self.dump_debug_info)
63 else: 69 else:
64 # Put a copy into the android out/target directory, to allow stack trace 70 # Put a copy into the android out/target directory, to allow stack trace
65 # generation. 71 # generation.
66 symbols_dir = os.path.join(constants.CHROME_DIR, 'out', build_type, 72 symbols_dir = os.path.join(constants.CHROME_DIR, 'out', build_type,
67 'lib.target') 73 'lib.target')
68 self.test_package = TestPackageExecutable( 74 self.test_package = TestPackageExecutable(
69 self.adb, device, 75 self.adb,
70 test_suite, timeout, rebaseline, performance_test, cleanup_test_files, 76 device,
71 self.tool, self.dump_debug_info, symbols_dir) 77 test_suite, timeout,
78 performance_test,
79 cleanup_test_files,
80 self.tool,
81 self.dump_debug_info,
82 symbols_dir)
72 self._performance_test_setup = None 83 self._performance_test_setup = None
73 if performance_test: 84 if performance_test:
74 self._performance_test_setup = perf_tests_helper.PerfTestSetup(self.adb) 85 self._performance_test_setup = perf_tests_helper.PerfTestSetup(self.adb)
75 86
76 def _TestSuiteRequiresMockTestServer(self): 87 def _TestSuiteRequiresMockTestServer(self):
77 """Returns True if the test suite requires mock test server.""" 88 """Returns True if the test suite requires mock test server."""
78 tests_require_net_test_server = ['unit_tests', 'net_unittests', 89 tests_require_net_test_server = ['unit_tests', 'net_unittests',
79 'content_unittests'] 90 'content_unittests']
80 return (self.test_package.test_suite_basename in 91 return (self.test_package.test_suite_basename in
81 tests_require_net_test_server) 92 tests_require_net_test_server)
82 93
83 def _GetFilterFileName(self): 94 def _GetFilterFileName(self):
84 """Returns the filename of gtest filter.""" 95 """Returns the filename of gtest filter."""
85 return os.path.join(sys.path[0], 'gtest_filter', 96 return os.path.join(
97 sys.path[0], 'gtest_filter',
86 self.test_package.test_suite_basename + '_disabled') 98 self.test_package.test_suite_basename + '_disabled')
87 99
88 def _GetAdditionalEmulatorFilterName(self): 100 def _GetAdditionalEmulatorFilterName(self):
89 """Returns the filename of additional gtest filter for emulator.""" 101 """Returns the filename of additional gtest filter for emulator."""
90 return os.path.join(sys.path[0], 'gtest_filter', 102 return os.path.join(
103 sys.path[0], 'gtest_filter',
91 self.test_package.test_suite_basename + 104 self.test_package.test_suite_basename +
92 '_emulator_additional_disabled') 105 '_emulator_additional_disabled')
93 106
94 def GetDisabledTests(self): 107 def GetDisabledTests(self):
95 """Returns a list of disabled tests. 108 """Returns a list of disabled tests.
96 109
97 Returns: 110 Returns:
98 A list of disabled tests obtained from gtest_filter/test_suite_disabled. 111 A list of disabled tests obtained from gtest_filter/test_suite_disabled.
99 """ 112 """
100 disabled_tests = run_tests_helper.GetExpectations(self._GetFilterFileName()) 113 disabled_tests = run_tests_helper.GetExpectations(self._GetFilterFileName())
101 if self._running_on_emulator: 114 if self._running_on_emulator:
102 # Append emulator's filter file. 115 # Append emulator's filter file.
103 disabled_tests.extend(run_tests_helper.GetExpectations( 116 disabled_tests.extend(run_tests_helper.GetExpectations(
104 self._GetAdditionalEmulatorFilterName())) 117 self._GetAdditionalEmulatorFilterName()))
105 return disabled_tests 118 return disabled_tests
106 119
107 def UpdateFilter(self, failed_tests):
108 """Updates test_suite_disabled file with the new filter (deletes if empty).
109
110 If running in Emulator, only the failed tests which are not in the normal
111 filter returned by _GetFilterFileName() are written to emulator's
112 additional filter file.
113
114 Args:
115 failed_tests: A sorted list of failed tests.
116 """
117 disabled_tests = []
118 if not self._running_on_emulator:
119 filter_file_name = self._GetFilterFileName()
120 else:
121 filter_file_name = self._GetAdditionalEmulatorFilterName()
122 disabled_tests.extend(
123 run_tests_helper.GetExpectations(self._GetFilterFileName()))
124 logging.info('About to update emulator\'s additional filter (%s).'
125 % filter_file_name)
126
127 new_failed_tests = []
128 if failed_tests:
129 for test in failed_tests:
130 if test.name not in disabled_tests:
131 new_failed_tests.append(test.name)
132
133 if not new_failed_tests:
134 if os.path.exists(filter_file_name):
135 os.unlink(filter_file_name)
136 return
137
138 filter_file = file(filter_file_name, 'w')
139 if self._running_on_emulator:
140 filter_file.write('# Addtional list of suppressions from emulator\n')
141 else:
142 filter_file.write('# List of suppressions\n')
143 filter_file.write('# This file was automatically generated by %s\n'
144 % sys.argv[0])
145 filter_file.write('\n'.join(sorted(new_failed_tests)))
146 filter_file.write('\n')
147 filter_file.close()
148
149 def GetDataFilesForTestSuite(self): 120 def GetDataFilesForTestSuite(self):
150 """Returns a list of data files/dirs needed by the test suite.""" 121 """Returns a list of data files/dirs needed by the test suite."""
151 # Ideally, we'd just push all test data. However, it has >100MB, and a lot 122 # Ideally, we'd just push all test data. However, it has >100MB, and a lot
152 # of the files are not relevant (some are used for browser_tests, others for 123 # of the files are not relevant (some are used for browser_tests, others for
153 # features not supported, etc..). 124 # features not supported, etc..).
154 if self.test_package.test_suite_basename in ['base_unittests', 125 if self.test_package.test_suite_basename in ['base_unittests',
155 'sql_unittests', 126 'sql_unittests',
156 'unit_tests']: 127 'unit_tests']:
157 test_files = [ 128 test_files = [
158 'base/data/file_util_unittest', 129 'base/data/file_util_unittest',
(...skipping 29 matching lines...) Expand all
188 'chrome/test/data/web_app_info/', 159 'chrome/test/data/web_app_info/',
189 'chrome/test/data/web_database', 160 'chrome/test/data/web_database',
190 'chrome/test/data/webui/', 161 'chrome/test/data/webui/',
191 'chrome/test/data/zip', 162 'chrome/test/data/zip',
192 'chrome/third_party/mock4js/', 163 'chrome/third_party/mock4js/',
193 'content/browser/gpu/software_rendering_list.json', 164 'content/browser/gpu/software_rendering_list.json',
194 'net/data/cache_tests/insert_load1', 165 'net/data/cache_tests/insert_load1',
195 'net/data/cache_tests/dirty_entry5', 166 'net/data/cache_tests/dirty_entry5',
196 'net/data/ssl/certificates/', 167 'net/data/ssl/certificates/',
197 'ui/base/test/data/data_pack_unittest', 168 'ui/base/test/data/data_pack_unittest',
198 ] 169 ]
199 if self.test_package.test_suite_basename == 'unit_tests': 170 if self.test_package.test_suite_basename == 'unit_tests':
200 test_files += ['chrome/test/data/simple_open_search.xml'] 171 test_files += ['chrome/test/data/simple_open_search.xml']
201 # The following are spell check data. Now only list the data under 172 # The following are spell check data. Now only list the data under
202 # third_party/hunspell_dictionaries which are used by unit tests. 173 # third_party/hunspell_dictionaries which are used by unit tests.
203 old_cwd = os.getcwd() 174 old_cwd = os.getcwd()
204 os.chdir(constants.CHROME_DIR) 175 os.chdir(constants.CHROME_DIR)
205 test_files += glob.glob('third_party/hunspell_dictionaries/*.bdic') 176 test_files += glob.glob('third_party/hunspell_dictionaries/*.bdic')
206 os.chdir(old_cwd) 177 os.chdir(old_cwd)
207 return test_files 178 return test_files
208 elif self.test_package.test_suite_basename == 'media_unittests': 179 elif self.test_package.test_suite_basename == 'media_unittests':
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 241
271 The path of this directory is different when the suite is being run as 242 The path of this directory is different when the suite is being run as
272 part of a WebKit check-out. 243 part of a WebKit check-out.
273 """ 244 """
274 webkit_src = os.path.join(constants.CHROME_DIR, 'third_party', 'WebKit') 245 webkit_src = os.path.join(constants.CHROME_DIR, 'third_party', 'WebKit')
275 if self.in_webkit_checkout: 246 if self.in_webkit_checkout:
276 webkit_src = os.path.join(constants.CHROME_DIR, '..', '..', '..') 247 webkit_src = os.path.join(constants.CHROME_DIR, '..', '..', '..')
277 248
278 self.adb.PushIfNeeded( 249 self.adb.PushIfNeeded(
279 os.path.join(webkit_src, 'Source/WebKit/chromium/tests/data'), 250 os.path.join(webkit_src, 'Source/WebKit/chromium/tests/data'),
280 os.path.join(self.adb.GetExternalStorage(), 251 os.path.join(
252 self.adb.GetExternalStorage(),
281 'third_party/WebKit/Source/WebKit/chromium/tests/data')) 253 'third_party/WebKit/Source/WebKit/chromium/tests/data'))
282 254
283 def RunTestsWithFilter(self):
284 """Runs a tests via a small, temporary shell script."""
285 self.test_package.CreateTestRunnerScript(self._gtest_filter,
286 self._test_arguments)
287 self.test_results = self.test_package.RunTestsAndListResults()
288
289 def RebaselineTests(self):
290 """Runs all available tests, restarting in case of failures."""
291 if self._gtest_filter:
292 all_tests = set(self._gtest_filter.split(':'))
293 else:
294 all_tests = set(self.test_package.GetAllTests())
295 failed_results = set()
296 executed_results = set()
297 while True:
298 executed_names = set([f.name for f in executed_results])
299 self._gtest_filter = ':'.join(all_tests - executed_names)
300 self.RunTestsWithFilter()
301 failed_results.update(self.test_results.crashed,
302 self.test_results.failed)
303 executed_results.update(self.test_results.crashed,
304 self.test_results.failed,
305 self.test_results.ok)
306 executed_names = set([f.name for f in executed_results])
307 logging.info('*' * 80)
308 logging.info(self.device)
309 logging.info('Executed: ' + str(len(executed_names)) + ' of ' +
310 str(len(all_tests)))
311 logging.info('Failed so far: ' + str(len(failed_results)) + ' ' +
312 str([f.name for f in failed_results]))
313 logging.info('Remaining: ' + str(len(all_tests - executed_names)) + ' ' +
314 str(all_tests - executed_names))
315 logging.info('*' * 80)
316 if executed_names == all_tests:
317 break
318 self.test_results = TestResults.FromRun(
319 ok=list(executed_results - failed_results),
320 failed=list(failed_results))
321
322 def RunTests(self): 255 def RunTests(self):
323 """Runs all tests (in rebaseline mode, runs each test in isolation). 256 """Runs tests on a single device.
324 257
325 Returns: 258 Returns:
326 A TestResults object. 259 A TestResults object.
327 """ 260 """
328 try: 261 try:
329 if self.test_package.rebaseline: 262 self.test_package.CreateTestRunnerScript(self._gtest_filter,
330 self.RebaselineTests() 263 self._test_arguments)
331 else: 264 self.test_results = self.test_package.RunTestsAndListResults()
332 self.RunTestsWithFilter()
333 except errors.DeviceUnresponsiveError as e: 265 except errors.DeviceUnresponsiveError as e:
334 # Make sure this device is not attached 266 # Make sure this device is not attached
335 if android_commands.IsDeviceAttached(self.device): 267 if android_commands.IsDeviceAttached(self.device):
336 raise e 268 raise e
337 269
270 # TODO(frankf): We should report these as "skipped" not "failures".
338 # Wrap the results 271 # Wrap the results
339 logging.warning(e) 272 logging.warning(e)
340 failed_tests = [] 273 failed_tests = []
341 for t in self._gtest_filter.split(':'): 274 for t in self._gtest_filter.split(':'):
342 failed_tests += [BaseTestResult(t, '')] 275 failed_tests += [BaseTestResult(t, '')]
343 self.test_results = TestResults.FromRun( 276 self.test_results = TestResults.FromRun(
344 failed=failed_tests, device_exception=self.device) 277 failed=failed_tests, device_exception=self.device)
345 278
346 return self.test_results 279 return self.test_results
347 280
(...skipping 14 matching lines...) Expand all
362 self.tool.CleanUpEnvironment() 295 self.tool.CleanUpEnvironment()
363 if self.test_package.cleanup_test_files: 296 if self.test_package.cleanup_test_files:
364 self.adb.RemovePushedFiles() 297 self.adb.RemovePushedFiles()
365 if self.dump_debug_info: 298 if self.dump_debug_info:
366 self.dump_debug_info.StopRecordingLog() 299 self.dump_debug_info.StopRecordingLog()
367 if self._performance_test_setup: 300 if self._performance_test_setup:
368 self._performance_test_setup.TearDown() 301 self._performance_test_setup.TearDown()
369 if self.dump_debug_info: 302 if self.dump_debug_info:
370 self.dump_debug_info.ArchiveNewCrashFiles() 303 self.dump_debug_info.ArchiveNewCrashFiles()
371 super(SingleTestRunner, self).TearDown() 304 super(SingleTestRunner, self).TearDown()
OLDNEW
« no previous file with comments | « no previous file | build/android/pylib/test_package.py » ('j') | build/android/run_tests.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698