| OLD | NEW |
| (Empty) |
| 1 # Copyright 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 """Generates test runner factory and tests for GTests.""" | |
| 6 # pylint: disable=W0212 | |
| 7 | |
| 8 import logging | |
| 9 import os | |
| 10 import sys | |
| 11 | |
| 12 from devil.android import device_utils | |
| 13 from pylib import constants | |
| 14 from pylib.base import base_setup | |
| 15 from pylib.base import base_test_result | |
| 16 from pylib.base import test_dispatcher | |
| 17 from pylib.gtest import gtest_test_instance | |
| 18 from pylib.gtest import test_package_apk | |
| 19 from pylib.gtest import test_package_exe | |
| 20 from pylib.gtest import test_runner | |
| 21 | |
| 22 sys.path.insert(0, | |
| 23 os.path.join(constants.DIR_SOURCE_ROOT, 'build', 'util', 'lib', | |
| 24 'common')) | |
| 25 import unittest_util # pylint: disable=F0401 | |
| 26 | |
| 27 | |
| 28 ISOLATE_FILE_PATHS = gtest_test_instance._DEFAULT_ISOLATE_FILE_PATHS | |
| 29 | |
| 30 | |
| 31 # Used for filtering large data deps at a finer grain than what's allowed in | |
| 32 # isolate files since pushing deps to devices is expensive. | |
| 33 # Wildcards are allowed. | |
| 34 DEPS_EXCLUSION_LIST = [ | |
| 35 'chrome/test/data/extensions/api_test', | |
| 36 'chrome/test/data/extensions/secure_shell', | |
| 37 'chrome/test/data/firefox*', | |
| 38 'chrome/test/data/gpu', | |
| 39 'chrome/test/data/image_decoding', | |
| 40 'chrome/test/data/import', | |
| 41 'chrome/test/data/page_cycler', | |
| 42 'chrome/test/data/perf', | |
| 43 'chrome/test/data/pyauto_private', | |
| 44 'chrome/test/data/safari_import', | |
| 45 'chrome/test/data/scroll', | |
| 46 'chrome/test/data/third_party', | |
| 47 'third_party/hunspell_dictionaries/*.dic', | |
| 48 # crbug.com/258690 | |
| 49 'webkit/data/bmp_decoder', | |
| 50 'webkit/data/ico_decoder', | |
| 51 ] | |
| 52 | |
| 53 | |
| 54 def _GetDisabledTestsFilterFromFile(suite_name): | |
| 55 """Returns a gtest filter based on the *_disabled file. | |
| 56 | |
| 57 Args: | |
| 58 suite_name: Name of the test suite (e.g. base_unittests). | |
| 59 | |
| 60 Returns: | |
| 61 A gtest filter which excludes disabled tests. | |
| 62 Example: '*-StackTrace.*:StringPrintfTest.StringPrintfMisc' | |
| 63 """ | |
| 64 filter_file_path = os.path.join( | |
| 65 os.path.abspath(os.path.dirname(__file__)), | |
| 66 'filter', '%s_disabled' % suite_name) | |
| 67 | |
| 68 if not filter_file_path or not os.path.exists(filter_file_path): | |
| 69 logging.info('No filter file found at %s', filter_file_path) | |
| 70 return '*' | |
| 71 | |
| 72 filters = [x for x in [x.strip() for x in file(filter_file_path).readlines()] | |
| 73 if x and x[0] != '#'] | |
| 74 disabled_filter = '*-%s' % ':'.join(filters) | |
| 75 logging.info('Applying filter "%s" obtained from %s', | |
| 76 disabled_filter, filter_file_path) | |
| 77 return disabled_filter | |
| 78 | |
| 79 | |
| 80 def _GetTests(test_options, test_package, devices): | |
| 81 """Get a list of tests. | |
| 82 | |
| 83 Args: | |
| 84 test_options: A GTestOptions object. | |
| 85 test_package: A TestPackageApk object. | |
| 86 devices: A list of attached devices. | |
| 87 | |
| 88 Returns: | |
| 89 A list of all the tests in the test suite. | |
| 90 """ | |
| 91 class TestListResult(base_test_result.BaseTestResult): | |
| 92 def __init__(self): | |
| 93 super(TestListResult, self).__init__( | |
| 94 'gtest_list_tests', base_test_result.ResultType.PASS) | |
| 95 self.test_list = [] | |
| 96 | |
| 97 def TestListerRunnerFactory(device, _shard_index): | |
| 98 class TestListerRunner(test_runner.TestRunner): | |
| 99 def RunTest(self, _test): | |
| 100 result = TestListResult() | |
| 101 self.test_package.Install(self.device) | |
| 102 result.test_list = self.test_package.GetAllTests(self.device) | |
| 103 results = base_test_result.TestRunResults() | |
| 104 results.AddResult(result) | |
| 105 return results, None | |
| 106 return TestListerRunner(test_options, device, test_package) | |
| 107 | |
| 108 results, _ = test_dispatcher.RunTests( | |
| 109 ['gtest_list_tests'], TestListerRunnerFactory, devices) | |
| 110 tests = [] | |
| 111 for r in results.GetAll(): | |
| 112 tests.extend(r.test_list) | |
| 113 return tests | |
| 114 | |
| 115 | |
| 116 def _FilterTestsUsingPrefixes(all_tests, pre=False, manual=False): | |
| 117 """Removes tests with disabled prefixes. | |
| 118 | |
| 119 Args: | |
| 120 all_tests: List of tests to filter. | |
| 121 pre: If True, include tests with PRE_ prefix. | |
| 122 manual: If True, include tests with MANUAL_ prefix. | |
| 123 | |
| 124 Returns: | |
| 125 List of tests remaining. | |
| 126 """ | |
| 127 filtered_tests = [] | |
| 128 filter_prefixes = ['DISABLED_', 'FLAKY_', 'FAILS_'] | |
| 129 | |
| 130 if not pre: | |
| 131 filter_prefixes.append('PRE_') | |
| 132 | |
| 133 if not manual: | |
| 134 filter_prefixes.append('MANUAL_') | |
| 135 | |
| 136 for t in all_tests: | |
| 137 test_case, test = t.split('.', 1) | |
| 138 if not any([test_case.startswith(prefix) or test.startswith(prefix) for | |
| 139 prefix in filter_prefixes]): | |
| 140 filtered_tests.append(t) | |
| 141 return filtered_tests | |
| 142 | |
| 143 | |
| 144 def _FilterDisabledTests(tests, suite_name, has_gtest_filter): | |
| 145 """Removes disabled tests from |tests|. | |
| 146 | |
| 147 Applies the following filters in order: | |
| 148 1. Remove tests with disabled prefixes. | |
| 149 2. Remove tests specified in the *_disabled files in the 'filter' dir | |
| 150 | |
| 151 Args: | |
| 152 tests: List of tests. | |
| 153 suite_name: Name of the test suite (e.g. base_unittests). | |
| 154 has_gtest_filter: Whether a gtest_filter is provided. | |
| 155 | |
| 156 Returns: | |
| 157 List of tests remaining. | |
| 158 """ | |
| 159 tests = _FilterTestsUsingPrefixes( | |
| 160 tests, has_gtest_filter, has_gtest_filter) | |
| 161 tests = unittest_util.FilterTestNames( | |
| 162 tests, _GetDisabledTestsFilterFromFile(suite_name)) | |
| 163 | |
| 164 return tests | |
| 165 | |
| 166 | |
| 167 def Setup(test_options, devices): | |
| 168 """Create the test runner factory and tests. | |
| 169 | |
| 170 Args: | |
| 171 test_options: A GTestOptions object. | |
| 172 devices: A list of attached devices. | |
| 173 | |
| 174 Returns: | |
| 175 A tuple of (TestRunnerFactory, tests). | |
| 176 """ | |
| 177 test_package = test_package_apk.TestPackageApk(test_options.suite_name) | |
| 178 if not os.path.exists(test_package.suite_path): | |
| 179 exe_test_package = test_package_exe.TestPackageExecutable( | |
| 180 test_options.suite_name) | |
| 181 if not os.path.exists(exe_test_package.suite_path): | |
| 182 raise Exception( | |
| 183 'Did not find %s target. Ensure it has been built.\n' | |
| 184 '(not found at %s or %s)' | |
| 185 % (test_options.suite_name, | |
| 186 test_package.suite_path, | |
| 187 exe_test_package.suite_path)) | |
| 188 test_package = exe_test_package | |
| 189 logging.warning('Found target %s', test_package.suite_path) | |
| 190 | |
| 191 i = base_setup.GenerateDepsDirUsingIsolate(test_options.suite_name, | |
| 192 test_options.isolate_file_path, | |
| 193 ISOLATE_FILE_PATHS, | |
| 194 DEPS_EXCLUSION_LIST) | |
| 195 def push_data_deps_to_device_dir(device): | |
| 196 device_dir = (constants.TEST_EXECUTABLE_DIR | |
| 197 if test_package.suite_name == 'breakpad_unittests' | |
| 198 else device.GetExternalStoragePath()) | |
| 199 base_setup.PushDataDeps(device, device_dir, test_options) | |
| 200 device_utils.DeviceUtils.parallel(devices).pMap(push_data_deps_to_device_dir) | |
| 201 if i: | |
| 202 i.Clear() | |
| 203 | |
| 204 tests = _GetTests(test_options, test_package, devices) | |
| 205 | |
| 206 # Constructs a new TestRunner with the current options. | |
| 207 def TestRunnerFactory(device, _shard_index): | |
| 208 return test_runner.TestRunner( | |
| 209 test_options, | |
| 210 device, | |
| 211 test_package) | |
| 212 | |
| 213 if test_options.run_disabled: | |
| 214 test_options = test_options._replace( | |
| 215 test_arguments=('%s --gtest_also_run_disabled_tests' % | |
| 216 test_options.test_arguments)) | |
| 217 else: | |
| 218 tests = _FilterDisabledTests(tests, test_options.suite_name, | |
| 219 bool(test_options.gtest_filter)) | |
| 220 if test_options.gtest_filter: | |
| 221 tests = unittest_util.FilterTestNames(tests, test_options.gtest_filter) | |
| 222 | |
| 223 # Coalesce unit tests into a single test per device | |
| 224 if test_options.suite_name not in gtest_test_instance.BROWSER_TEST_SUITES: | |
| 225 num_devices = len(devices) | |
| 226 tests = [':'.join(tests[i::num_devices]) for i in xrange(num_devices)] | |
| 227 tests = [t for t in tests if t] | |
| 228 | |
| 229 return (TestRunnerFactory, tests) | |
| OLD | NEW |