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 fnmatch | |
9 import glob | |
10 import logging | 8 import logging |
11 import os | 9 import os |
12 import shutil | |
13 import sys | 10 import sys |
14 | 11 |
15 from pylib import cmd_helper | |
16 from pylib import constants | 12 from pylib import constants |
17 from pylib import valgrind_tools | 13 from pylib import valgrind_tools |
18 | 14 |
19 from pylib.base import base_test_result | 15 from pylib.base import base_test_result |
20 from pylib.base import test_dispatcher | 16 from pylib.base import test_dispatcher |
21 from pylib.device import device_utils | 17 from pylib.device import device_utils |
22 from pylib.gtest import test_package_apk | 18 from pylib.gtest import test_package_apk |
23 from pylib.gtest import test_package_exe | 19 from pylib.gtest import test_package_exe |
24 from pylib.gtest import test_runner | 20 from pylib.gtest import test_runner |
| 21 from pylib.utils import isolator |
25 | 22 |
26 sys.path.insert(0, | 23 sys.path.insert(0, |
27 os.path.join(constants.DIR_SOURCE_ROOT, 'build', 'util', 'lib', | 24 os.path.join(constants.DIR_SOURCE_ROOT, 'build', 'util', 'lib', |
28 'common')) | 25 'common')) |
29 import unittest_util # pylint: disable=F0401 | 26 import unittest_util # pylint: disable=F0401 |
30 | 27 |
31 | 28 |
32 _ISOLATE_FILE_PATHS = { | 29 _ISOLATE_FILE_PATHS = { |
33 'base_unittests': 'base/base_unittests.isolate', | 30 'base_unittests': 'base/base_unittests.isolate', |
34 'blink_heap_unittests': | 31 'blink_heap_unittests': |
(...skipping 29 matching lines...) Expand all Loading... |
64 'chrome/test/data/pyauto_private', | 61 'chrome/test/data/pyauto_private', |
65 'chrome/test/data/safari_import', | 62 'chrome/test/data/safari_import', |
66 'chrome/test/data/scroll', | 63 'chrome/test/data/scroll', |
67 'chrome/test/data/third_party', | 64 'chrome/test/data/third_party', |
68 'third_party/hunspell_dictionaries/*.dic', | 65 'third_party/hunspell_dictionaries/*.dic', |
69 # crbug.com/258690 | 66 # crbug.com/258690 |
70 'webkit/data/bmp_decoder', | 67 'webkit/data/bmp_decoder', |
71 'webkit/data/ico_decoder', | 68 'webkit/data/ico_decoder', |
72 ] | 69 ] |
73 | 70 |
74 _ISOLATE_SCRIPT = os.path.join( | |
75 constants.DIR_SOURCE_ROOT, 'tools', 'swarming_client', 'isolate.py') | |
76 | |
77 | 71 |
78 def _GenerateDepsDirUsingIsolate(suite_name, isolate_file_path=None): | 72 def _GenerateDepsDirUsingIsolate(suite_name, isolate_file_path=None): |
79 """Generate the dependency dir for the test suite using isolate. | 73 """Generate the dependency dir for the test suite using isolate. |
80 | 74 |
81 Args: | 75 Args: |
82 suite_name: Name of the test suite (e.g. base_unittests). | 76 suite_name: Name of the test suite (e.g. base_unittests). |
83 isolate_file_path: .isolate file path to use. If there is a default .isolate | 77 isolate_file_path: .isolate file path to use. If there is a default .isolate |
84 file path for the suite_name, this will override it. | 78 file path for the suite_name, this will override it. |
85 """ | 79 """ |
86 if os.path.isdir(constants.ISOLATE_DEPS_DIR): | |
87 shutil.rmtree(constants.ISOLATE_DEPS_DIR) | |
88 | |
89 if isolate_file_path: | 80 if isolate_file_path: |
90 if os.path.isabs(isolate_file_path): | 81 if os.path.isabs(isolate_file_path): |
91 isolate_abs_path = isolate_file_path | 82 isolate_abs_path = isolate_file_path |
92 else: | 83 else: |
93 isolate_abs_path = os.path.join(constants.DIR_SOURCE_ROOT, | 84 isolate_abs_path = os.path.join(constants.DIR_SOURCE_ROOT, |
94 isolate_file_path) | 85 isolate_file_path) |
95 else: | 86 else: |
96 isolate_rel_path = _ISOLATE_FILE_PATHS.get(suite_name) | 87 isolate_rel_path = _ISOLATE_FILE_PATHS.get(suite_name) |
97 if not isolate_rel_path: | 88 if not isolate_rel_path: |
98 logging.info('Did not find an isolate file for the test suite.') | 89 logging.info('Did not find an isolate file for the test suite.') |
99 return | 90 return |
100 isolate_abs_path = os.path.join(constants.DIR_SOURCE_ROOT, isolate_rel_path) | 91 isolate_abs_path = os.path.join(constants.DIR_SOURCE_ROOT, isolate_rel_path) |
101 | 92 |
102 isolated_abs_path = os.path.join( | 93 isolated_abs_path = os.path.join( |
103 constants.GetOutDirectory(), '%s.isolated' % suite_name) | 94 constants.GetOutDirectory(), '%s.isolated' % suite_name) |
104 assert os.path.exists(isolate_abs_path), 'Cannot find %s' % isolate_abs_path | 95 assert os.path.exists(isolate_abs_path), 'Cannot find %s' % isolate_abs_path |
105 # This needs to be kept in sync with the cmd line options for isolate.py | |
106 # in src/build/isolate.gypi. | |
107 isolate_cmd = [ | |
108 'python', _ISOLATE_SCRIPT, | |
109 'remap', | |
110 '--isolate', isolate_abs_path, | |
111 '--isolated', isolated_abs_path, | |
112 '--outdir', constants.ISOLATE_DEPS_DIR, | |
113 | 96 |
114 '--path-variable', 'DEPTH', constants.DIR_SOURCE_ROOT, | 97 i = isolator.Isolator(constants.ISOLATE_DEPS_DIR) |
115 '--path-variable', 'PRODUCT_DIR', constants.GetOutDirectory(), | 98 i.Clear() |
116 | 99 i.Remap(isolate_abs_path, isolated_abs_path) |
117 '--config-variable', 'OS', 'android', | |
118 '--config-variable', 'CONFIGURATION_NAME', constants.GetBuildType(), | |
119 '--config-variable', 'asan', '0', | |
120 '--config-variable', 'chromeos', '0', | |
121 '--config-variable', 'component', 'static_library', | |
122 '--config-variable', 'fastbuild', '0', | |
123 '--config-variable', 'icu_use_data_file_flag', '1', | |
124 '--config-variable', 'libpeer_target_type', 'static_library', | |
125 '--config-variable', 'v8_use_external_startup_data', '0', | |
126 '--config-variable', 'lsan', '0', | |
127 # TODO(maruel): This may not be always true. | |
128 '--config-variable', 'target_arch', 'arm', | |
129 '--config-variable', 'use_openssl', '0', | |
130 '--config-variable', 'use_ozone', '0', | |
131 ] | |
132 assert not cmd_helper.RunCmd(isolate_cmd) | |
133 | |
134 # We're relying on the fact that timestamps are preserved | 100 # We're relying on the fact that timestamps are preserved |
135 # by the remap command (hardlinked). Otherwise, all the data | 101 # by the remap command (hardlinked). Otherwise, all the data |
136 # will be pushed to the device once we move to using time diff | 102 # will be pushed to the device once we move to using time diff |
137 # instead of md5sum. Perform a sanity check here. | 103 # instead of md5sum. Perform a sanity check here. |
138 for root, _, filenames in os.walk(constants.ISOLATE_DEPS_DIR): | 104 i.VerifyHardlinks() |
139 if filenames: | 105 i.PurgeExcluded(_DEPS_EXCLUSION_LIST) |
140 linked_file = os.path.join(root, filenames[0]) | 106 i.MoveOutputDeps() |
141 orig_file = os.path.join( | |
142 constants.DIR_SOURCE_ROOT, | |
143 os.path.relpath(linked_file, constants.ISOLATE_DEPS_DIR)) | |
144 if os.stat(linked_file).st_ino == os.stat(orig_file).st_ino: | |
145 break | |
146 else: | |
147 raise Exception('isolate remap command did not use hardlinks.') | |
148 | |
149 # Delete excluded files as defined by _DEPS_EXCLUSION_LIST. | |
150 old_cwd = os.getcwd() | |
151 try: | |
152 os.chdir(constants.ISOLATE_DEPS_DIR) | |
153 excluded_paths = [x for y in _DEPS_EXCLUSION_LIST for x in glob.glob(y)] | |
154 if excluded_paths: | |
155 logging.info('Excluding the following from dependency list: %s', | |
156 excluded_paths) | |
157 for p in excluded_paths: | |
158 if os.path.isdir(p): | |
159 shutil.rmtree(p) | |
160 else: | |
161 os.remove(p) | |
162 finally: | |
163 os.chdir(old_cwd) | |
164 | |
165 # On Android, all pak files need to be in the top-level 'paks' directory. | |
166 paks_dir = os.path.join(constants.ISOLATE_DEPS_DIR, 'paks') | |
167 os.mkdir(paks_dir) | |
168 | |
169 deps_out_dir = os.path.join( | |
170 constants.ISOLATE_DEPS_DIR, | |
171 os.path.relpath(os.path.join(constants.GetOutDirectory(), os.pardir), | |
172 constants.DIR_SOURCE_ROOT)) | |
173 for root, _, filenames in os.walk(deps_out_dir): | |
174 for filename in fnmatch.filter(filenames, '*.pak'): | |
175 shutil.move(os.path.join(root, filename), paks_dir) | |
176 | |
177 # Move everything in PRODUCT_DIR to top level. | |
178 deps_product_dir = os.path.join(deps_out_dir, constants.GetBuildType()) | |
179 if os.path.isdir(deps_product_dir): | |
180 for p in os.listdir(deps_product_dir): | |
181 shutil.move(os.path.join(deps_product_dir, p), constants.ISOLATE_DEPS_DIR) | |
182 os.rmdir(deps_product_dir) | |
183 os.rmdir(deps_out_dir) | |
184 | 107 |
185 | 108 |
186 def _GetDisabledTestsFilterFromFile(suite_name): | 109 def _GetDisabledTestsFilterFromFile(suite_name): |
187 """Returns a gtest filter based on the *_disabled file. | 110 """Returns a gtest filter based on the *_disabled file. |
188 | 111 |
189 Args: | 112 Args: |
190 suite_name: Name of the test suite (e.g. base_unittests). | 113 suite_name: Name of the test suite (e.g. base_unittests). |
191 | 114 |
192 Returns: | 115 Returns: |
193 A gtest filter which excludes disabled tests. | 116 A gtest filter which excludes disabled tests. |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
353 if test_options.gtest_filter: | 276 if test_options.gtest_filter: |
354 tests = unittest_util.FilterTestNames(tests, test_options.gtest_filter) | 277 tests = unittest_util.FilterTestNames(tests, test_options.gtest_filter) |
355 | 278 |
356 # Coalesce unit tests into a single test per device | 279 # Coalesce unit tests into a single test per device |
357 if test_options.suite_name != 'content_browsertests': | 280 if test_options.suite_name != 'content_browsertests': |
358 num_devices = len(devices) | 281 num_devices = len(devices) |
359 tests = [':'.join(tests[i::num_devices]) for i in xrange(num_devices)] | 282 tests = [':'.join(tests[i::num_devices]) for i in xrange(num_devices)] |
360 tests = [t for t in tests if t] | 283 tests = [t for t in tests if t] |
361 | 284 |
362 return (TestRunnerFactory, tests) | 285 return (TestRunnerFactory, tests) |
OLD | NEW |