Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 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 """Runs the Java tests. See more information on run_instrumentation_tests.py.""" | 5 """Runs the Java tests. See more information on run_instrumentation_tests.py.""" |
| 6 | 6 |
| 7 import fnmatch | 7 import fnmatch |
| 8 import logging | 8 import logging |
| 9 import os | 9 import os |
| 10 import re | 10 import re |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 33 """A fatal test exception.""" | 33 """A fatal test exception.""" |
| 34 pass | 34 pass |
| 35 | 35 |
| 36 | 36 |
| 37 def _TestNameToExpectation(test_name): | 37 def _TestNameToExpectation(test_name): |
| 38 # A test name is a Package.Path.Class#testName; convert to what we use in | 38 # A test name is a Package.Path.Class#testName; convert to what we use in |
| 39 # the expectation file. | 39 # the expectation file. |
| 40 return '.'.join(test_name.replace('#', '.').split('.')[-2:]) | 40 return '.'.join(test_name.replace('#', '.').split('.')[-2:]) |
| 41 | 41 |
| 42 | 42 |
| 43 # TODO(jaydeepmehta): FilterTests should be moved to a common file for | |
|
bulach
2012/09/24 10:40:49
ditto :)
in fact, I think we can remove this, ther
felipeg
2012/09/25 03:27:21
Done.
| |
| 44 # all integration tests. | |
| 43 def FilterTests(test_names, pattern_list, inclusive): | 45 def FilterTests(test_names, pattern_list, inclusive): |
| 44 """Filters |test_names| using a list of patterns. | 46 """Filters |test_names| using a list of patterns. |
| 45 | 47 |
| 46 Args: | 48 Args: |
| 47 test_names: A list of test names. | 49 test_names: A list of test names. |
| 48 pattern_list: A list of patterns. | 50 pattern_list: A list of patterns. |
| 49 inclusive: If True, returns the tests that match any pattern. if False, | 51 inclusive: If True, returns the tests that match any pattern. if False, |
| 50 returns the tests that do not match any pattern. | 52 returns the tests that do not match any pattern. |
| 51 Returns: | 53 Returns: |
| 52 A list of test names. | 54 A list of test names. |
| 53 """ | 55 """ |
| 54 ret = [] | 56 ret = [] |
| 55 for t in test_names: | 57 for t in test_names: |
| 56 has_match = False | 58 has_match = False |
| 57 for pattern in pattern_list: | 59 for pattern in pattern_list: |
| 58 has_match = has_match or fnmatch.fnmatch(_TestNameToExpectation(t), | 60 has_match = has_match or fnmatch.fnmatch(_TestNameToExpectation(t), |
| 59 pattern) | 61 pattern) |
| 60 if has_match == inclusive: | 62 if has_match == inclusive: |
| 61 ret += [t] | 63 ret += [t] |
| 62 return ret | 64 return ret |
| 63 | 65 |
| 64 | 66 |
| 65 class TestRunner(BaseTestRunner): | 67 class TestRunner(BaseTestRunner): |
| 66 """Responsible for running a series of tests connected to a single device.""" | 68 """Responsible for running a series of tests connected to a single device.""" |
| 67 | 69 |
| 68 _DEVICE_DATA_DIR = constants.TEST_DATA_DIR + '/chrome/test/data' | 70 _DEVICE_DATA_DIR = 'chrome/test/data' |
| 69 _EMMA_JAR = os.path.join(os.environ.get('ANDROID_BUILD_TOP', ''), | 71 _EMMA_JAR = os.path.join(os.environ.get('ANDROID_BUILD_TOP', ''), |
| 70 'external/emma/lib/emma.jar') | 72 'external/emma/lib/emma.jar') |
| 71 _COVERAGE_MERGED_FILENAME = 'unittest_coverage.es' | 73 _COVERAGE_MERGED_FILENAME = 'unittest_coverage.es' |
| 72 _COVERAGE_WEB_ROOT_DIR = os.environ.get('EMMA_WEB_ROOTDIR') | 74 _COVERAGE_WEB_ROOT_DIR = os.environ.get('EMMA_WEB_ROOTDIR') |
| 73 _COVERAGE_FILENAME = 'coverage.ec' | 75 _COVERAGE_FILENAME = 'coverage.ec' |
| 74 _COVERAGE_RESULT_PATH = ('/data/data/com.google.android.apps.chrome/files/' + | 76 _COVERAGE_RESULT_PATH = ('/data/data/com.google.android.apps.chrome/files/' + |
| 75 _COVERAGE_FILENAME) | 77 _COVERAGE_FILENAME) |
| 76 _COVERAGE_META_INFO_PATH = os.path.join(os.environ.get('ANDROID_BUILD_TOP', | 78 _COVERAGE_META_INFO_PATH = os.path.join(os.environ.get('ANDROID_BUILD_TOP', |
| 77 ''), | 79 ''), |
| 78 'out/target/common/obj/APPS', | 80 'out/target/common/obj/APPS', |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 123 self.wait_for_debugger = options.wait_for_debugger | 125 self.wait_for_debugger = options.wait_for_debugger |
| 124 | 126 |
| 125 self.tests_iter = tests_iter | 127 self.tests_iter = tests_iter |
| 126 self.coverage = coverage | 128 self.coverage = coverage |
| 127 self.apks = apks | 129 self.apks = apks |
| 128 self.test_apk = apks[0] | 130 self.test_apk = apks[0] |
| 129 self.instrumentation_class_path = self.test_apk.GetPackageName() | 131 self.instrumentation_class_path = self.test_apk.GetPackageName() |
| 130 self.ports_to_forward = ports_to_forward | 132 self.ports_to_forward = ports_to_forward |
| 131 | 133 |
| 132 self.test_results = TestResults() | 134 self.test_results = TestResults() |
| 133 # List of forwarders created by this instance of TestRunner. | 135 self.forwarder = None |
| 134 self.forwarders = [] | |
| 135 | 136 |
| 136 if self.coverage: | 137 if self.coverage: |
| 137 if os.path.exists(TestRunner._COVERAGE_MERGED_FILENAME): | 138 if os.path.exists(TestRunner._COVERAGE_MERGED_FILENAME): |
| 138 os.remove(TestRunner._COVERAGE_MERGED_FILENAME) | 139 os.remove(TestRunner._COVERAGE_MERGED_FILENAME) |
| 139 if not os.path.exists(TestRunner._COVERAGE_META_INFO_PATH): | 140 if not os.path.exists(TestRunner._COVERAGE_META_INFO_PATH): |
| 140 raise FatalTestException('FATAL ERROR in ' + sys.argv[0] + | 141 raise FatalTestException('FATAL ERROR in ' + sys.argv[0] + |
| 141 ' : Coverage meta info [' + | 142 ' : Coverage meta info [' + |
| 142 TestRunner._COVERAGE_META_INFO_PATH + | 143 TestRunner._COVERAGE_META_INFO_PATH + |
| 143 '] does not exist.') | 144 '] does not exist.') |
| 144 if (not TestRunner._COVERAGE_WEB_ROOT_DIR or | 145 if (not TestRunner._COVERAGE_WEB_ROOT_DIR or |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 155 self.tests_iter = (BaseTestSharder.tests_container) | 156 self.tests_iter = (BaseTestSharder.tests_container) |
| 156 assert self.tests_iter | 157 assert self.tests_iter |
| 157 return self.tests_iter | 158 return self.tests_iter |
| 158 | 159 |
| 159 def CopyTestFilesOnce(self): | 160 def CopyTestFilesOnce(self): |
| 160 """Pushes the test data files to the device. Installs the apk if opted.""" | 161 """Pushes the test data files to the device. Installs the apk if opted.""" |
| 161 if TestRunner._DEVICE_HAS_TEST_FILES.get(self.device, False): | 162 if TestRunner._DEVICE_HAS_TEST_FILES.get(self.device, False): |
| 162 logging.warning('Already copied test files to device %s, skipping.', | 163 logging.warning('Already copied test files to device %s, skipping.', |
| 163 self.device) | 164 self.device) |
| 164 return | 165 return |
| 165 host_test_files_path = (constants.CHROME_DIR + | 166 host_test_files = [ |
| 166 '/chrome/test/data/android/device_files') | 167 ('android_webview/test/data/device_files', 'webview'), |
| 167 if os.path.exists(host_test_files_path): | 168 ('content/test/data/android/device_files', 'content'), |
| 168 self.adb.PushIfNeeded(host_test_files_path, | 169 ('chrome/test/data/android/device_files', 'chrome') |
| 169 TestRunner._DEVICE_DATA_DIR) | 170 ] |
| 171 for (host_src, dst_layer) in host_test_files: | |
| 172 host_test_files_path = constants.CHROME_DIR + '/' + host_src | |
| 173 if os.path.exists(host_test_files_path): | |
| 174 self.adb.PushIfNeeded(host_test_files_path, | |
| 175 self.adb.GetExternalStorage() + '/' + | |
| 176 TestRunner._DEVICE_DATA_DIR + '/' + dst_layer) | |
| 170 if self.install_apk: | 177 if self.install_apk: |
| 171 for apk in self.apks: | 178 for apk in self.apks: |
| 172 self.adb.ManagedInstall(apk.GetApkPath(), | 179 self.adb.ManagedInstall(apk.GetApkPath(), |
| 173 package_name=apk.GetPackageName()) | 180 package_name=apk.GetPackageName()) |
| 174 self.tool.CopyFiles() | 181 self.tool.CopyFiles() |
| 175 TestRunner._DEVICE_HAS_TEST_FILES[self.device] = True | 182 TestRunner._DEVICE_HAS_TEST_FILES[self.device] = True |
| 176 | 183 |
| 177 def SaveCoverageData(self, test): | 184 def SaveCoverageData(self, test): |
| 178 """Saves the Emma coverage data before it's overwritten by the next test. | 185 """Saves the Emma coverage data before it's overwritten by the next test. |
| 179 | 186 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 230 def _GetInstrumentationArgs(self): | 237 def _GetInstrumentationArgs(self): |
| 231 ret = {} | 238 ret = {} |
| 232 if self.coverage: | 239 if self.coverage: |
| 233 ret['coverage'] = 'true' | 240 ret['coverage'] = 'true' |
| 234 if self.wait_for_debugger: | 241 if self.wait_for_debugger: |
| 235 ret['debug'] = 'true' | 242 ret['debug'] = 'true' |
| 236 return ret | 243 return ret |
| 237 | 244 |
| 238 def _TakeScreenshot(self, test): | 245 def _TakeScreenshot(self, test): |
| 239 """Takes a screenshot from the device.""" | 246 """Takes a screenshot from the device.""" |
| 240 screenshot_tool = os.path.join(os.getenv('ANDROID_HOST_OUT'), 'bin', | 247 screenshot_tool = os.path.join(constants.CHROME_DIR, |
|
bulach
2012/09/24 10:40:49
don't quite understand this diff, you probably nee
felipeg
2012/09/25 03:27:21
yep, sorry
It was some confusion in my git client
| |
| 241 'screenshot2') | 248 'third_party/android_tools/sdk/tools/monkeyrunner') |
| 249 screenshot_script = os.path.join(constants.CHROME_DIR, | |
| 250 'build/android/monkeyrunner_screenshot.py') | |
| 242 screenshot_path = os.path.join(constants.CHROME_DIR, | 251 screenshot_path = os.path.join(constants.CHROME_DIR, |
| 243 'out_screenshots') | 252 'out_screenshots') |
| 244 if not os.path.exists(screenshot_path): | 253 if not os.path.exists(screenshot_path): |
| 245 os.mkdir(screenshot_path) | 254 os.mkdir(screenshot_path) |
| 246 screenshot_name = os.path.join(screenshot_path, test + '.png') | 255 screenshot_name = os.path.join(screenshot_path, test + '.png') |
| 247 logging.info('Taking screenshot named %s', screenshot_name) | 256 logging.info('Taking screenshot named %s', screenshot_name) |
| 248 cmd_helper.RunCmd([screenshot_tool, '-s', self.device, screenshot_name]) | 257 cmd_helper.RunCmd([screenshot_tool, screenshot_script, |
| 258 '--serial', self.device, | |
| 259 '--file', screenshot_name]) | |
| 249 | 260 |
| 250 def SetUp(self): | 261 def SetUp(self): |
| 251 """Sets up the test harness and device before all tests are run.""" | 262 """Sets up the test harness and device before all tests are run.""" |
| 252 super(TestRunner, self).SetUp() | 263 super(TestRunner, self).SetUp() |
| 253 if not self.adb.IsRootEnabled(): | 264 if not self.adb.IsRootEnabled(): |
| 254 logging.warning('Unable to enable java asserts for %s, non rooted device', | 265 logging.warning('Unable to enable java asserts for %s, non rooted device', |
| 255 self.device) | 266 self.device) |
| 256 else: | 267 else: |
| 257 if self.adb.SetJavaAssertsEnabled(enable=True): | 268 if self.adb.SetJavaAssertsEnabled(enable=True): |
| 258 self.adb.Reboot(full_reboot=False) | 269 self.adb.Reboot(full_reboot=False) |
| 259 | 270 |
| 260 # We give different default value to launch HTTP server based on shard index | 271 # We give different default value to launch HTTP server based on shard index |
| 261 # because it may have race condition when multiple processes are trying to | 272 # because it may have race condition when multiple processes are trying to |
| 262 # launch lighttpd with same port at same time. | 273 # launch lighttpd with same port at same time. |
| 263 # This line *must* come before the forwarding below, as it nukes all | 274 # This line *must* come before the forwarding below, as it nukes all |
| 264 # the other forwarders. A more comprehensive fix might be to pull the | 275 # the other forwarders. A more comprehensive fix might be to pull the |
| 265 # forwarder-killing line up to here, but that might violate assumptions | 276 # forwarder-killing line up to here, but that might violate assumptions |
| 266 # implicit in other places. | 277 # implicit in other places. |
| 267 self.LaunchTestHttpServer(os.path.join(constants.CHROME_DIR), | 278 self.LaunchTestHttpServer(os.path.join(constants.CHROME_DIR), |
| 268 (constants.LIGHTTPD_RANDOM_PORT_FIRST + | 279 (constants.LIGHTTPD_RANDOM_PORT_FIRST + |
| 269 self.shard_index)) | 280 self.shard_index)) |
| 270 | 281 print "====================================== " + str(self.ports_to_forward) |
|
bulach
2012/09/24 10:40:49
spurious?
felipeg
2012/09/25 03:27:21
Done.
| |
| 282 port_pairs = [] | |
| 271 if self.ports_to_forward: | 283 if self.ports_to_forward: |
| 272 for port in self.ports_to_forward: | 284 for port in self.ports_to_forward: |
| 273 self.forwarders.append(Forwarder( | 285 port_pairs.append([(port, port)]) |
| 274 self.adb, [(port, port)], self.tool, '127.0.0.1', self.build_type)) | 286 self.forwarder = Forwarder( |
| 287 self.adb, port_pairs, self.tool, '127.0.0.1', self.build_type) | |
| 275 self.CopyTestFilesOnce() | 288 self.CopyTestFilesOnce() |
| 276 self.flags.AddFlags(['--enable-test-intents']) | 289 self.flags.AddFlags(['--enable-test-intents']) |
| 277 | 290 |
| 278 def TearDown(self): | 291 def TearDown(self): |
| 279 """Cleans up the test harness and saves outstanding data from test run.""" | 292 """Cleans up the test harness and saves outstanding data from test run.""" |
| 280 if self.forwarders: | 293 if self.forwarder: |
| 281 for forwarder in self.forwarders: | 294 forwarder.Close() |
| 282 forwarder.Close() | |
| 283 self.GenerateCoverageReportIfNeeded() | 295 self.GenerateCoverageReportIfNeeded() |
| 284 super(TestRunner, self).TearDown() | 296 super(TestRunner, self).TearDown() |
| 285 | 297 |
| 286 def TestSetup(self, test): | 298 def TestSetup(self, test): |
| 287 """Sets up the test harness for running a particular test. | 299 """Sets up the test harness for running a particular test. |
| 288 | 300 |
| 289 Args: | 301 Args: |
| 290 test: The name of the test that will be run. | 302 test: The name of the test that will be run. |
| 291 """ | 303 """ |
| 292 self.SetupPerfMonitoringIfNeeded(test) | 304 self.SetupPerfMonitoringIfNeeded(test) |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 346 Args: | 358 Args: |
| 347 test: The name of the test that was just run. | 359 test: The name of the test that was just run. |
| 348 Raises: | 360 Raises: |
| 349 FatalTestException: if there's anything wrong with the perf data. | 361 FatalTestException: if there's anything wrong with the perf data. |
| 350 """ | 362 """ |
| 351 if not self._IsPerfTest(test): | 363 if not self._IsPerfTest(test): |
| 352 return | 364 return |
| 353 raw_test_name = test.split('#')[1] | 365 raw_test_name = test.split('#')[1] |
| 354 | 366 |
| 355 # Wait and grab annotation data so we can figure out which traces to parse | 367 # Wait and grab annotation data so we can figure out which traces to parse |
| 368 # TODO(tonyg): Is there an error log line to watch for here? | |
|
bulach
2012/09/24 10:40:49
:)
felipeg
2012/09/25 03:27:21
Done.
| |
| 356 regex = self.adb.WaitForLogMatch(re.compile('\*\*PERFANNOTATION\(' + | 369 regex = self.adb.WaitForLogMatch(re.compile('\*\*PERFANNOTATION\(' + |
| 357 raw_test_name + | 370 raw_test_name + |
| 358 '\)\:(.*)'), None) | 371 '\)\:(.*)'), None) |
| 359 | 372 |
| 360 # If the test is set to run on a specific device type only (IE: only | 373 # If the test is set to run on a specific device type only (IE: only |
| 361 # tablet or phone) and it is being run on the wrong device, the test | 374 # tablet or phone) and it is being run on the wrong device, the test |
| 362 # just quits and does not do anything. The java test harness will still | 375 # just quits and does not do anything. The java test harness will still |
| 363 # print the appropriate annotation for us, but will add --NORUN-- for | 376 # print the appropriate annotation for us, but will add --NORUN-- for |
| 364 # us so we know to ignore the results. | 377 # us so we know to ignore the results. |
| 365 # The --NORUN-- tag is managed by MainActivityTestBase.java | 378 # The --NORUN-- tag is managed by MainActivityTestBase.java |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 577 | 590 |
| 578 logging.info('Will run: %s', str(tests)) | 591 logging.info('Will run: %s', str(tests)) |
| 579 | 592 |
| 580 if len(attached_devices) > 1 and (coverage or options.wait_for_debugger): | 593 if len(attached_devices) > 1 and (coverage or options.wait_for_debugger): |
| 581 logging.warning('Coverage / debugger can not be sharded, ' | 594 logging.warning('Coverage / debugger can not be sharded, ' |
| 582 'using first available device') | 595 'using first available device') |
| 583 attached_devices = attached_devices[:1] | 596 attached_devices = attached_devices[:1] |
| 584 sharder = TestSharder(attached_devices, options, tests, apks) | 597 sharder = TestSharder(attached_devices, options, tests, apks) |
| 585 test_results = sharder.RunShardedTests() | 598 test_results = sharder.RunShardedTests() |
| 586 return test_results | 599 return test_results |
| OLD | NEW |