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

Side by Side Diff: build/android/pylib/gtest/dispatch.py

Issue 19479002: [Android] Clean up gtest filtering logic. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 5 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 """Dispatches GTests.""" 5 """Dispatches GTests."""
6 6
7 import copy 7 import copy
8 import fnmatch 8 import fnmatch
9 import glob 9 import glob
10 import logging 10 import logging
11 import os 11 import os
12 import shutil 12 import shutil
13 import sys
13 14
14 from pylib import android_commands 15 from pylib import android_commands
15 from pylib import cmd_helper 16 from pylib import cmd_helper
16 from pylib import constants 17 from pylib import constants
17 from pylib import ports 18 from pylib import ports
18 from pylib.base import base_test_result 19 from pylib.base import base_test_result
19 from pylib.base import shard 20 from pylib.base import shard
20 from pylib.utils import emulator 21 from pylib.utils import emulator
21 from pylib.utils import report_results 22 from pylib.utils import report_results
22 from pylib.utils import xvfb 23 from pylib.utils import xvfb
23 24
24 import gtest_config 25 import gtest_config
25 import test_runner 26 import test_runner
26 27
28 sys.path.insert(0,
29 os.path.join(constants.DIR_SOURCE_ROOT, 'build', 'util', 'lib'))
30 from common import unittest_util
31
27 32
28 # TODO(frankf): Add more test targets here after making sure we don't 33 # TODO(frankf): Add more test targets here after making sure we don't
29 # blow up the dependency size (and the world). 34 # blow up the dependency size (and the world).
30 _ISOLATE_FILE_PATHS = { 35 _ISOLATE_FILE_PATHS = {
31 'base_unittests': 'base/base_unittests.isolate', 36 'base_unittests': 'base/base_unittests.isolate',
32 'breakpad_unittests': 'breakpad/breakpad_unittests.isolate', 37 'breakpad_unittests': 'breakpad/breakpad_unittests.isolate',
33 'cc_perftests': 'cc/cc_perftests.isolate', 38 'cc_perftests': 'cc/cc_perftests.isolate',
34 'components_unittests': 'components/components_unittests.isolate', 39 'components_unittests': 'components/components_unittests.isolate',
35 'content_browsertests': 'content/content_browsertests.isolate', 40 'content_browsertests': 'content/content_browsertests.isolate',
36 'content_unittests': 'content/content_unittests.isolate', 41 'content_unittests': 'content/content_unittests.isolate',
(...skipping 27 matching lines...) Expand all
64 ] 69 ]
65 70
66 _ISOLATE_SCRIPT = os.path.join( 71 _ISOLATE_SCRIPT = os.path.join(
67 constants.DIR_SOURCE_ROOT, 'tools', 'swarm_client', 'isolate.py') 72 constants.DIR_SOURCE_ROOT, 'tools', 'swarm_client', 'isolate.py')
68 73
69 74
70 def _GenerateDepsDirUsingIsolate(test_suite, build_type): 75 def _GenerateDepsDirUsingIsolate(test_suite, build_type):
71 """Generate the dependency dir for the test suite using isolate. 76 """Generate the dependency dir for the test suite using isolate.
72 77
73 Args: 78 Args:
74 test_suite: The test suite basename (e.g. base_unittests). 79 test_suite: Name of the test suite (e.g. base_unittests).
75 build_type: Release/Debug 80 build_type: Release/Debug
76 """ 81 """
77 product_dir = os.path.join(cmd_helper.OutDirectory.get(), build_type) 82 product_dir = os.path.join(cmd_helper.OutDirectory.get(), build_type)
78 assert os.path.isabs(product_dir) 83 assert os.path.isabs(product_dir)
79 84
80 if os.path.isdir(constants.ISOLATE_DEPS_DIR): 85 if os.path.isdir(constants.ISOLATE_DEPS_DIR):
81 shutil.rmtree(constants.ISOLATE_DEPS_DIR) 86 shutil.rmtree(constants.ISOLATE_DEPS_DIR)
82 87
83 isolate_rel_path = _ISOLATE_FILE_PATHS.get(test_suite) 88 isolate_rel_path = _ISOLATE_FILE_PATHS.get(test_suite)
84 if not isolate_rel_path: 89 if not isolate_rel_path:
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 189
185 for t, q in qualified_test_suites: 190 for t, q in qualified_test_suites:
186 if not os.path.exists(q): 191 if not os.path.exists(q):
187 raise Exception('Test suite %s not found in %s.\n' 192 raise Exception('Test suite %s not found in %s.\n'
188 'Supported test suites:\n %s\n' 193 'Supported test suites:\n %s\n'
189 'Ensure it has been built.\n' % 194 'Ensure it has been built.\n' %
190 (t, q, [s.name for s in gtest_config.STABLE_TEST_SUITES])) 195 (t, q, [s.name for s in gtest_config.STABLE_TEST_SUITES]))
191 return qualified_test_suites 196 return qualified_test_suites
192 197
193 198
194 def GetTestsFromDevice(runner): 199 def _GetDisabledTestsFilterFromFile(test_suite):
195 """Get a list of tests from a device, excluding disabled tests. 200 """Returns a gtest filter based on the *_disabled file.
196 201
197 Args: 202 Args:
198 runner: a TestRunner. 203 test_suite: Name of the test suite (e.g. base_unittests).
204
199 Returns: 205 Returns:
200 All non-disabled tests on the device. 206 A gtest filter which excludes disabled tests.
207 Example: '*-StackTrace.*:StringPrintfTest.StringPrintfMisc'
201 """ 208 """
202 # The executable/apk needs to be copied before we can call GetAllTests. 209 filter_file_path = os.path.join(
203 runner.test_package.Install() 210 os.path.abspath(os.path.dirname(__file__)),
204 all_tests = runner.test_package.GetAllTests() 211 'filter', '%s_disabled' % test_suite)
205 # Only includes tests that do not have any match in the disabled list. 212
206 disabled_list = runner.GetDisabledTests() 213 if not filter_file_path or not os.path.exists(filter_file_path):
craigdh 2013/07/17 21:27:03 logging.info that no filter file was found?
frankf 2013/07/17 22:18:54 Done.
207 return filter(lambda t: not any([fnmatch.fnmatch(t, disabled_pattern) 214 return '*'
208 for disabled_pattern in disabled_list]), 215
209 all_tests) 216 filters = [x for x in [x.strip() for x in file(filter_file_path).readlines()]
217 if x and x[0] != '#']
218 disabled_filter = '*-%s' % ':'.join(filters)
219 logging.info('Applying filter "%s" obtained from %s',
220 disabled_filter, filter_file_path)
221 return disabled_filter
210 222
211 223
212 def GetAllEnabledTests(runner_factory, devices): 224 def _GetTestsFromDevice(runner_factory, devices):
213 """Get all enabled tests. 225 """Get a list of tests from a device.
214
215 Obtains a list of enabled tests from the test package on the device,
216 then filters it again using the disabled list on the host.
217 226
218 Args: 227 Args:
219 runner_factory: callable that takes a devices and returns a TestRunner. 228 runner_factory: Callable that takes a devices and returns a TestRunner.
craigdh 2013/07/17 21:27:03 devices -> device and shard index
frankf 2013/07/17 22:18:54 Done.
220 devices: list of devices. 229 devices: List of devices.
221 230
222 Returns: 231 Returns:
223 List of all enabled tests. 232 All the tests in the test suite.
224
225 Raises:
226 Exception: If no devices available.
227 """ 233 """
228 for device in devices: 234 for device in devices:
229 try: 235 try:
230 logging.info('Obtaining tests from %s', device) 236 logging.info('Obtaining tests from %s', device)
231 runner = runner_factory(device, 0) 237 runner = runner_factory(device, 0)
232 return GetTestsFromDevice(runner) 238 runner.test_package.Install()
239 return runner.test_package.GetAllTests()
233 except Exception as e: 240 except Exception as e:
234 logging.warning('Failed obtaining tests from %s with exception: %s', 241 logging.warning('Failed obtaining tests from %s with exception: %s',
235 device, e) 242 device, e)
236 raise Exception('No device available to get the list of tests.') 243 raise Exception('No device available to get the list of tests.')
craigdh 2013/07/17 21:27:03 This is a pain right now, because if there is an i
frankf 2013/07/17 22:18:54 The issue is that we're catching too general excep
237 244
238 245
246 def _FilterTestsUsingPrefixes(all_tests, pre=False, manual=False):
247 """Removes tests with disabled prefixes.
248
249 Args:
250 all_tests: List of tests to filter.
251 pre: If True, include tests with _PRE prefix.
252 manual: If True, include tests with _MANUAL prefix.
253
254 Returns:
255 List of tests remaining.
256 """
257 filtered_tests = []
258 filter_prefixes = ['DISABLED_', 'FLAKY_', 'FAILS_']
259
260 if not pre:
261 filter_prefixes.append('PRE_')
262
263 if not manual:
264 filter_prefixes.append('MANUAL_')
265
266 for t in all_tests:
267 test_case, test = t.split('.', 1)
268 if any([test_case.startswith(prefix) or test.startswith(prefix) for prefix
craigdh 2013/07/17 21:27:03 lose the continue, just do: if not any(...): fi
frankf 2013/07/17 22:18:54 Done.
269 in filter_prefixes]):
270 continue
271 filtered_tests.append(t)
272 return filtered_tests
273
274
275 def GetTestsFiltered(test_suite, gtest_filter, runner_factory, devices):
276 """Get all tests in the suite and filter them.
277
278 Obtains a list of tests from the test package on the device, and
279 applies the following filters in order:
280 1. Remove tests with disabled prefixes.
281 2. Remove tests specified in the *_disabled files in the 'filter' dir
282 3. Applies |gtest_filter|.
283
284 Args:
285 test_suite: Name of the test suite (e.g. base_unittests).
286 gtest_filter: A filter including negative or positive patterns.
287 runner_factory: Callable that takes a devices and returns a TestRunner.
288 devices: List of devices.
289
290 Returns:
291 List of tests remaining.
292 """
293 tests = _GetTestsFromDevice(runner_factory, devices)
294 tests = _FilterTestsUsingPrefixes(
295 tests, bool(gtest_filter), bool(gtest_filter))
296 tests = unittest_util.FilterTestNames(
297 tests, _GetDisabledTestsFilterFromFile(test_suite))
298
299 if gtest_filter:
300 tests = unittest_util.FilterTestNames(tests, gtest_filter)
301
302 return tests
303
304
239 def _RunATestSuite(options, suite_name): 305 def _RunATestSuite(options, suite_name):
240 """Run a single test suite. 306 """Run a single test suite.
241 307
242 Helper for Dispatch() to allow stop/restart of the emulator across 308 Helper for Dispatch() to allow stop/restart of the emulator across
243 test bundles. If using the emulator, we start it on entry and stop 309 test bundles. If using the emulator, we start it on entry and stop
244 it on exit. 310 it on exit.
245 311
246 Args: 312 Args:
247 options: options for running the tests. 313 options: options for running the tests.
248 suite_name: name of the test suite being run. 314 suite_name: name of the test suite being run.
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 options.cleanup_test_files, 353 options.cleanup_test_files,
288 options.tool, 354 options.tool,
289 options.build_type, 355 options.build_type,
290 options.webkit, 356 options.webkit,
291 options.push_deps, 357 options.push_deps,
292 constants.GTEST_TEST_PACKAGE_NAME, 358 constants.GTEST_TEST_PACKAGE_NAME,
293 constants.GTEST_TEST_ACTIVITY_NAME, 359 constants.GTEST_TEST_ACTIVITY_NAME,
294 constants.GTEST_COMMAND_LINE_FILE) 360 constants.GTEST_COMMAND_LINE_FILE)
295 361
296 # Get tests and split them up based on the number of devices. 362 # Get tests and split them up based on the number of devices.
297 if options.test_filter: 363 tests = GetTestsFiltered(suite_name, options.test_filter,
298 all_tests = [t for t in options.test_filter.split(':') if t] 364 RunnerFactory, attached_devices)
299 else:
300 all_tests = GetAllEnabledTests(RunnerFactory, attached_devices)
301 num_devices = len(attached_devices) 365 num_devices = len(attached_devices)
302 tests = [':'.join(all_tests[i::num_devices]) for i in xrange(num_devices)] 366 tests = [':'.join(tests[i::num_devices]) for i in xrange(num_devices)]
303 tests = [t for t in tests if t] 367 tests = [t for t in tests if t]
304 368
305 # Run tests. 369 # Run tests.
306 test_results, exit_code = shard.ShardAndRunTests( 370 test_results, exit_code = shard.ShardAndRunTests(
307 RunnerFactory, attached_devices, tests, options.build_type, 371 RunnerFactory, attached_devices, tests, options.build_type,
308 test_timeout=None, num_retries=options.num_retries) 372 test_timeout=None, num_retries=options.num_retries)
309 373
310 report_results.LogFull( 374 report_results.LogFull(
311 results=test_results, 375 results=test_results,
312 test_type='Unit test', 376 test_type='Unit test',
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 test_options.test_suite = suite_path 425 test_options.test_suite = suite_path
362 test_results, test_exit_code = _RunATestSuite(test_options, suite_name) 426 test_results, test_exit_code = _RunATestSuite(test_options, suite_name)
363 results.AddTestRunResults(test_results) 427 results.AddTestRunResults(test_results)
364 if test_exit_code and exit_code != constants.ERROR_EXIT_CODE: 428 if test_exit_code and exit_code != constants.ERROR_EXIT_CODE:
365 exit_code = test_exit_code 429 exit_code = test_exit_code
366 430
367 if options.use_xvfb: 431 if options.use_xvfb:
368 framebuffer.Stop() 432 framebuffer.Stop()
369 433
370 return (results, exit_code) 434 return (results, exit_code)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698