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