OLD | NEW |
---|---|
1 # Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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 """Generates test runner factory and tests for GTests.""" | 5 """Generates test runner factory and tests for GTests.""" |
6 # pylint: disable=W0212 | 6 # pylint: disable=W0212 |
7 | 7 |
8 import logging | 8 import logging |
9 import os | 9 import os |
10 import sys | 10 import sys |
11 | 11 |
12 from pylib import constants | 12 from pylib import constants |
13 from pylib import valgrind_tools | |
14 | 13 |
14 from pylib.base import base_setup | |
15 from pylib.base import base_test_result | 15 from pylib.base import base_test_result |
16 from pylib.base import test_dispatcher | 16 from pylib.base import test_dispatcher |
17 from pylib.device import device_utils | 17 from pylib.device import device_utils |
18 from pylib.gtest import test_package_apk | 18 from pylib.gtest import test_package_apk |
19 from pylib.gtest import test_package_exe | 19 from pylib.gtest import test_package_exe |
20 from pylib.gtest import test_runner | 20 from pylib.gtest import test_runner |
21 from pylib.utils import isolator | |
22 | 21 |
23 sys.path.insert(0, | 22 sys.path.insert(0, |
24 os.path.join(constants.DIR_SOURCE_ROOT, 'build', 'util', 'lib', | 23 os.path.join(constants.DIR_SOURCE_ROOT, 'build', 'util', 'lib', |
25 'common')) | 24 'common')) |
26 import unittest_util # pylint: disable=F0401 | 25 import unittest_util # pylint: disable=F0401 |
27 | 26 |
28 | 27 |
29 _ISOLATE_FILE_PATHS = { | 28 ISOLATE_FILE_PATHS = { |
30 'base_unittests': 'base/base_unittests.isolate', | 29 'base_unittests': 'base/base_unittests.isolate', |
31 'blink_heap_unittests': | 30 'blink_heap_unittests': |
32 'third_party/WebKit/Source/platform/heap/BlinkHeapUnitTests.isolate', | 31 'third_party/WebKit/Source/platform/heap/BlinkHeapUnitTests.isolate', |
33 'breakpad_unittests': 'breakpad/breakpad_unittests.isolate', | 32 'breakpad_unittests': 'breakpad/breakpad_unittests.isolate', |
34 'cc_perftests': 'cc/cc_perftests.isolate', | 33 'cc_perftests': 'cc/cc_perftests.isolate', |
35 'components_unittests': 'components/components_unittests.isolate', | 34 'components_unittests': 'components/components_unittests.isolate', |
36 'content_browsertests': 'content/content_browsertests.isolate', | 35 'content_browsertests': 'content/content_browsertests.isolate', |
37 'content_unittests': 'content/content_unittests.isolate', | 36 'content_unittests': 'content/content_unittests.isolate', |
38 'media_perftests': 'media/media_perftests.isolate', | 37 'media_perftests': 'media/media_perftests.isolate', |
39 'media_unittests': 'media/media_unittests.isolate', | 38 'media_unittests': 'media/media_unittests.isolate', |
40 'net_unittests': 'net/net_unittests.isolate', | 39 'net_unittests': 'net/net_unittests.isolate', |
41 'sql_unittests': 'sql/sql_unittests.isolate', | 40 'sql_unittests': 'sql/sql_unittests.isolate', |
42 'ui_base_unittests': 'ui/base/ui_base_tests.isolate', | 41 'ui_base_unittests': 'ui/base/ui_base_tests.isolate', |
43 'ui_unittests': 'ui/base/ui_base_tests.isolate', | 42 'ui_unittests': 'ui/base/ui_base_tests.isolate', |
44 'unit_tests': 'chrome/unit_tests.isolate', | 43 'unit_tests': 'chrome/unit_tests.isolate', |
45 'webkit_unit_tests': | 44 'webkit_unit_tests': |
46 'third_party/WebKit/Source/web/WebKitUnitTests.isolate', | 45 'third_party/WebKit/Source/web/WebKitUnitTests.isolate', |
47 } | 46 } |
48 | 47 |
49 # Used for filtering large data deps at a finer grain than what's allowed in | 48 # Used for filtering large data deps at a finer grain than what's allowed in |
50 # isolate files since pushing deps to devices is expensive. | 49 # isolate files since pushing deps to devices is expensive. |
51 # Wildcards are allowed. | 50 # Wildcards are allowed. |
52 _DEPS_EXCLUSION_LIST = [ | 51 DEPS_EXCLUSION_LIST = [ |
53 'chrome/test/data/extensions/api_test', | 52 'chrome/test/data/extensions/api_test', |
54 'chrome/test/data/extensions/secure_shell', | 53 'chrome/test/data/extensions/secure_shell', |
55 'chrome/test/data/firefox*', | 54 'chrome/test/data/firefox*', |
56 'chrome/test/data/gpu', | 55 'chrome/test/data/gpu', |
57 'chrome/test/data/image_decoding', | 56 'chrome/test/data/image_decoding', |
58 'chrome/test/data/import', | 57 'chrome/test/data/import', |
59 'chrome/test/data/page_cycler', | 58 'chrome/test/data/page_cycler', |
60 'chrome/test/data/perf', | 59 'chrome/test/data/perf', |
61 'chrome/test/data/pyauto_private', | 60 'chrome/test/data/pyauto_private', |
62 'chrome/test/data/safari_import', | 61 'chrome/test/data/safari_import', |
63 'chrome/test/data/scroll', | 62 'chrome/test/data/scroll', |
64 'chrome/test/data/third_party', | 63 'chrome/test/data/third_party', |
65 'third_party/hunspell_dictionaries/*.dic', | 64 'third_party/hunspell_dictionaries/*.dic', |
66 # crbug.com/258690 | 65 # crbug.com/258690 |
67 'webkit/data/bmp_decoder', | 66 'webkit/data/bmp_decoder', |
68 'webkit/data/ico_decoder', | 67 'webkit/data/ico_decoder', |
69 ] | 68 ] |
70 | 69 |
71 | 70 |
72 def _GenerateDepsDirUsingIsolate(suite_name, isolate_file_path=None): | |
73 """Generate the dependency dir for the test suite using isolate. | |
74 | |
75 Args: | |
76 suite_name: Name of the test suite (e.g. base_unittests). | |
77 isolate_file_path: .isolate file path to use. If there is a default .isolate | |
78 file path for the suite_name, this will override it. | |
79 """ | |
80 if isolate_file_path: | |
81 if os.path.isabs(isolate_file_path): | |
82 isolate_abs_path = isolate_file_path | |
83 else: | |
84 isolate_abs_path = os.path.join(constants.DIR_SOURCE_ROOT, | |
85 isolate_file_path) | |
86 else: | |
87 isolate_rel_path = _ISOLATE_FILE_PATHS.get(suite_name) | |
88 if not isolate_rel_path: | |
89 logging.info('Did not find an isolate file for the test suite.') | |
90 return | |
91 isolate_abs_path = os.path.join(constants.DIR_SOURCE_ROOT, isolate_rel_path) | |
92 | |
93 isolated_abs_path = os.path.join( | |
94 constants.GetOutDirectory(), '%s.isolated' % suite_name) | |
95 assert os.path.exists(isolate_abs_path), 'Cannot find %s' % isolate_abs_path | |
96 | |
97 i = isolator.Isolator(constants.ISOLATE_DEPS_DIR) | |
98 i.Clear() | |
99 i.Remap(isolate_abs_path, isolated_abs_path) | |
100 # We're relying on the fact that timestamps are preserved | |
101 # by the remap command (hardlinked). Otherwise, all the data | |
102 # will be pushed to the device once we move to using time diff | |
103 # instead of md5sum. Perform a sanity check here. | |
104 i.VerifyHardlinks() | |
105 i.PurgeExcluded(_DEPS_EXCLUSION_LIST) | |
106 i.MoveOutputDeps() | |
107 | |
108 | |
109 def _GetDisabledTestsFilterFromFile(suite_name): | 71 def _GetDisabledTestsFilterFromFile(suite_name): |
110 """Returns a gtest filter based on the *_disabled file. | 72 """Returns a gtest filter based on the *_disabled file. |
111 | 73 |
112 Args: | 74 Args: |
113 suite_name: Name of the test suite (e.g. base_unittests). | 75 suite_name: Name of the test suite (e.g. base_unittests). |
114 | 76 |
115 Returns: | 77 Returns: |
116 A gtest filter which excludes disabled tests. | 78 A gtest filter which excludes disabled tests. |
117 Example: '*-StackTrace.*:StringPrintfTest.StringPrintfMisc' | 79 Example: '*-StackTrace.*:StringPrintfTest.StringPrintfMisc' |
118 """ | 80 """ |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
212 List of tests remaining. | 174 List of tests remaining. |
213 """ | 175 """ |
214 tests = _FilterTestsUsingPrefixes( | 176 tests = _FilterTestsUsingPrefixes( |
215 tests, has_gtest_filter, has_gtest_filter) | 177 tests, has_gtest_filter, has_gtest_filter) |
216 tests = unittest_util.FilterTestNames( | 178 tests = unittest_util.FilterTestNames( |
217 tests, _GetDisabledTestsFilterFromFile(suite_name)) | 179 tests, _GetDisabledTestsFilterFromFile(suite_name)) |
218 | 180 |
219 return tests | 181 return tests |
220 | 182 |
221 | 183 |
222 def PushDataDeps(device, test_options, test_package): | |
223 valgrind_tools.PushFilesForTool(test_options.tool, device) | |
224 if os.path.exists(constants.ISOLATE_DEPS_DIR): | |
225 device_dir = ( | |
226 constants.TEST_EXECUTABLE_DIR | |
227 if test_package.suite_name == 'breakpad_unittests' | |
228 else device.GetExternalStoragePath()) | |
229 device.PushChangedFiles([ | |
230 (os.path.join(constants.ISOLATE_DEPS_DIR, p), | |
231 '%s/%s' % (device_dir, p)) | |
232 for p in os.listdir(constants.ISOLATE_DEPS_DIR)]) | |
233 | |
234 | |
235 def Setup(test_options, devices): | 184 def Setup(test_options, devices): |
236 """Create the test runner factory and tests. | 185 """Create the test runner factory and tests. |
237 | 186 |
238 Args: | 187 Args: |
239 test_options: A GTestOptions object. | 188 test_options: A GTestOptions object. |
240 devices: A list of attached devices. | 189 devices: A list of attached devices. |
241 | 190 |
242 Returns: | 191 Returns: |
243 A tuple of (TestRunnerFactory, tests). | 192 A tuple of (TestRunnerFactory, tests). |
244 """ | 193 """ |
245 test_package = test_package_apk.TestPackageApk(test_options.suite_name) | 194 test_package = test_package_apk.TestPackageApk(test_options.suite_name) |
246 if not os.path.exists(test_package.suite_path): | 195 if not os.path.exists(test_package.suite_path): |
247 exe_test_package = test_package_exe.TestPackageExecutable( | 196 exe_test_package = test_package_exe.TestPackageExecutable( |
248 test_options.suite_name) | 197 test_options.suite_name) |
249 if not os.path.exists(exe_test_package.suite_path): | 198 if not os.path.exists(exe_test_package.suite_path): |
250 raise Exception( | 199 raise Exception( |
251 'Did not find %s target. Ensure it has been built.\n' | 200 'Did not find %s target. Ensure it has been built.\n' |
252 '(not found at %s or %s)' | 201 '(not found at %s or %s)' |
253 % (test_options.suite_name, | 202 % (test_options.suite_name, |
254 test_package.suite_path, | 203 test_package.suite_path, |
255 exe_test_package.suite_path)) | 204 exe_test_package.suite_path)) |
256 test_package = exe_test_package | 205 test_package = exe_test_package |
257 logging.warning('Found target %s', test_package.suite_path) | 206 logging.warning('Found target %s', test_package.suite_path) |
258 | 207 |
259 _GenerateDepsDirUsingIsolate(test_options.suite_name, | 208 base_setup.GenerateDepsDirUsingIsolate(test_options.suite_name, |
260 test_options.isolate_file_path) | 209 test_options.isolate_file_path, |
261 | 210 ISOLATE_FILE_PATHS, |
262 device_utils.DeviceUtils.parallel(devices).pMap( | 211 DEPS_EXCLUSION_LIST) |
263 PushDataDeps, test_options, test_package) | 212 def PushDataDepsToDeviceDir(device): |
jbudorick
2014/11/11 16:31:47
nit: I've been moving toward naming local function
mikecase (-- gone --)
2014/11/11 23:23:21
Done.
| |
213 device_dir = (constants.TEST_EXECUTABLE_DIR | |
214 if test_package.suite_name == 'breakpad_unittests' | |
jbudorick
2014/11/11 16:31:47
nit: 4 space indent for continuation lines
mikecase (-- gone --)
2014/11/11 23:23:21
Done.
| |
215 else device.GetExternalStoragePath()) | |
216 base_setup.PushDataDeps(device, device_dir, test_options) | |
217 device_utils.DeviceUtils.parallel(devices).pMap(PushDataDepsToDeviceDir) | |
264 | 218 |
265 tests = _GetTests(test_options, test_package, devices) | 219 tests = _GetTests(test_options, test_package, devices) |
266 | 220 |
267 # Constructs a new TestRunner with the current options. | 221 # Constructs a new TestRunner with the current options. |
268 def TestRunnerFactory(device, _shard_index): | 222 def TestRunnerFactory(device, _shard_index): |
269 return test_runner.TestRunner( | 223 return test_runner.TestRunner( |
270 test_options, | 224 test_options, |
271 device, | 225 device, |
272 test_package) | 226 test_package) |
273 | 227 |
274 if test_options.run_disabled: | 228 if test_options.run_disabled: |
275 test_options = test_options._replace( | 229 test_options = test_options._replace( |
276 test_arguments=('%s --gtest_also_run_disabled_tests' % | 230 test_arguments=('%s --gtest_also_run_disabled_tests' % |
277 test_options.test_arguments)) | 231 test_options.test_arguments)) |
278 else: | 232 else: |
279 tests = _FilterDisabledTests(tests, test_options.suite_name, | 233 tests = _FilterDisabledTests(tests, test_options.suite_name, |
280 bool(test_options.gtest_filter)) | 234 bool(test_options.gtest_filter)) |
281 if test_options.gtest_filter: | 235 if test_options.gtest_filter: |
282 tests = unittest_util.FilterTestNames(tests, test_options.gtest_filter) | 236 tests = unittest_util.FilterTestNames(tests, test_options.gtest_filter) |
283 | 237 |
284 # Coalesce unit tests into a single test per device | 238 # Coalesce unit tests into a single test per device |
285 if test_options.suite_name != 'content_browsertests': | 239 if test_options.suite_name != 'content_browsertests': |
286 num_devices = len(devices) | 240 num_devices = len(devices) |
287 tests = [':'.join(tests[i::num_devices]) for i in xrange(num_devices)] | 241 tests = [':'.join(tests[i::num_devices]) for i in xrange(num_devices)] |
288 tests = [t for t in tests if t] | 242 tests = [t for t in tests if t] |
289 | 243 |
290 return (TestRunnerFactory, tests) | 244 return (TestRunnerFactory, tests) |
OLD | NEW |