Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright 2015 The Chromium Authors. All rights reserved. | 1 # Copyright 2015 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 import copy | 5 import copy |
| 6 import json | |
| 6 import logging | 7 import logging |
| 7 import os | 8 import os |
| 8 import pickle | 9 import pickle |
| 9 import re | 10 import re |
| 10 | 11 |
| 11 from devil.android import apk_helper | 12 from devil.android import apk_helper |
| 12 from devil.android import md5sum | 13 from devil.android import md5sum |
| 13 from pylib import constants | 14 from pylib import constants |
| 14 from pylib.base import base_test_result | 15 from pylib.base import base_test_result |
| 15 from pylib.base import test_exception | 16 from pylib.base import test_exception |
| 16 from pylib.base import test_instance | 17 from pylib.base import test_instance |
| 17 from pylib.constants import host_paths | 18 from pylib.constants import host_paths |
| 18 from pylib.instrumentation import test_result | 19 from pylib.instrumentation import test_result |
| 19 from pylib.instrumentation import instrumentation_parser | 20 from pylib.instrumentation import instrumentation_parser |
| 20 from pylib.utils import dexdump | 21 from pylib.utils import dexdump |
| 21 from pylib.utils import proguard | 22 from pylib.utils import proguard |
| 22 from pylib.utils import shared_preference_utils | 23 from pylib.utils import shared_preference_utils |
| 24 from py_utils import tempfile_ext | |
| 23 | 25 |
| 24 with host_paths.SysPath(host_paths.BUILD_COMMON_PATH): | 26 with host_paths.SysPath(host_paths.BUILD_COMMON_PATH): |
| 25 import unittest_util # pylint: disable=import-error | 27 import unittest_util # pylint: disable=import-error |
| 26 | 28 |
| 27 # Ref: http://developer.android.com/reference/android/app/Activity.html | 29 # Ref: http://developer.android.com/reference/android/app/Activity.html |
| 28 _ACTIVITY_RESULT_CANCELED = 0 | 30 _ACTIVITY_RESULT_CANCELED = 0 |
| 29 _ACTIVITY_RESULT_OK = -1 | 31 _ACTIVITY_RESULT_OK = -1 |
| 30 | 32 |
| 31 _COMMAND_LINE_PARAMETER = 'cmdlinearg-parameter' | 33 _COMMAND_LINE_PARAMETER = 'cmdlinearg-parameter' |
| 32 _DEFAULT_ANNOTATIONS = [ | 34 _DEFAULT_ANNOTATIONS = [ |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 178 unqualified_class_test = { | 180 unqualified_class_test = { |
| 179 'class': t['class'].split('.')[-1], | 181 'class': t['class'].split('.')[-1], |
| 180 'method': t['method'] | 182 'method': t['method'] |
| 181 } | 183 } |
| 182 names = [ | 184 names = [ |
| 183 GetTestName(t, sep='.'), | 185 GetTestName(t, sep='.'), |
| 184 GetTestName(unqualified_class_test, sep='.'), | 186 GetTestName(unqualified_class_test, sep='.'), |
| 185 GetUniqueTestName(t, sep='.') | 187 GetUniqueTestName(t, sep='.') |
| 186 ] | 188 ] |
| 187 | 189 |
| 190 if t['is_junit4']: | |
| 191 names += [ | |
| 192 GetTestNameWithoutParameterPostfix(t, sep='.'), | |
|
jbudorick
2017/07/14 18:43:55
These make it so that, if someone passes the test
the real yoland
2017/07/18 04:20:21
I think this just makes that if someone pass in te
| |
| 193 GetTestNameWithoutParameterPostfix(unqualified_class_test, sep='.') | |
| 194 ] | |
| 195 | |
| 188 pattern_groups = test_filter.split('-') | 196 pattern_groups = test_filter.split('-') |
| 189 if len(pattern_groups) > 1: | 197 if len(pattern_groups) > 1: |
| 190 negative_filter = pattern_groups[1] | 198 negative_filter = pattern_groups[1] |
| 191 if unittest_util.FilterTestNames(names, negative_filter): | 199 if unittest_util.FilterTestNames(names, negative_filter): |
| 192 return [] | 200 return [] |
| 193 | 201 |
| 194 positive_filter = pattern_groups[0] | 202 positive_filter = pattern_groups[0] |
| 195 return unittest_util.FilterTestNames(names, positive_filter) | 203 return unittest_util.FilterTestNames(names, positive_filter) |
| 196 | 204 |
| 197 def annotation_filter(all_annotations): | 205 def annotation_filter(all_annotations): |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 232 | 240 |
| 233 if (not annotation_filter(t['annotations']) | 241 if (not annotation_filter(t['annotations']) |
| 234 or not excluded_annotation_filter(t['annotations'])): | 242 or not excluded_annotation_filter(t['annotations'])): |
| 235 continue | 243 continue |
| 236 | 244 |
| 237 filtered_tests.append(t) | 245 filtered_tests.append(t) |
| 238 | 246 |
| 239 return filtered_tests | 247 return filtered_tests |
| 240 | 248 |
| 241 | 249 |
| 250 def GetAllTestsFromRunner(device, test_apk_path, test_package, filename, | |
| 251 test_runner=None, test_runner_junit4=None): | |
| 252 pickle_path = '%s-runner.pickle' % test_apk_path | |
| 253 try: | |
| 254 tests = _GetAllTestsFromRunner(device, test_package, filename, | |
|
jbudorick
2017/07/14 18:43:55
What's going on here? Why does it get the tests fr
the real yoland
2017/07/18 04:20:21
oops, my bad
Done
| |
| 255 test_runner, test_runner_junit4) | |
| 256 tests = _GetTestsFromPickle(pickle_path, test_apk_path) | |
| 257 except TestListPickleException as e: | |
| 258 logging.info('Could not get tests from pickle: %s', e) | |
| 259 logging.info('Getting tests by print tests in instrumentation runner') | |
| 260 tests = _GetAllTestsFromRunner(device, test_package, filename, | |
| 261 test_runner, test_runner_junit4) | |
| 262 _SaveTestsToPickle(pickle_path, test_apk_path, tests) | |
| 263 return tests | |
| 264 | |
| 265 | |
| 266 # TODO(yolandyan): remove this once the tests are converted to junit4 | |
| 242 def GetAllTestsFromJar(test_jar): | 267 def GetAllTestsFromJar(test_jar): |
| 243 pickle_path = '%s-proguard.pickle' % test_jar | 268 pickle_path = '%s-proguard.pickle' % test_jar |
| 244 try: | 269 try: |
| 245 tests = _GetTestsFromPickle(pickle_path, test_jar) | 270 tests = _GetTestsFromPickle(pickle_path, test_jar) |
| 246 except TestListPickleException as e: | 271 except TestListPickleException as e: |
| 247 logging.info('Could not get tests from pickle: %s', e) | 272 logging.info('Could not get tests from pickle: %s', e) |
| 248 logging.info('Getting tests from JAR via proguard.') | 273 logging.info('Getting tests from JAR via proguard.') |
| 249 tests = _GetTestsFromProguard(test_jar) | 274 tests = _GetTestsFromProguard(test_jar) |
| 250 _SaveTestsToPickle(pickle_path, test_jar, tests) | 275 _SaveTestsToPickle(pickle_path, test_jar, tests) |
| 251 return tests | 276 return tests |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 329 for class_name, class_info in package_info['classes'].iteritems(): | 354 for class_name, class_info in package_info['classes'].iteritems(): |
| 330 if class_name.endswith('Test'): | 355 if class_name.endswith('Test'): |
| 331 tests.append({ | 356 tests.append({ |
| 332 'class': '%s.%s' % (package_name, class_name), | 357 'class': '%s.%s' % (package_name, class_name), |
| 333 'annotations': {}, | 358 'annotations': {}, |
| 334 'methods': get_test_methods(class_info['methods']), | 359 'methods': get_test_methods(class_info['methods']), |
| 335 'superclass': class_info['superclass'], | 360 'superclass': class_info['superclass'], |
| 336 }) | 361 }) |
| 337 return tests | 362 return tests |
| 338 | 363 |
| 364 def _GetAllTestsFromRunner(device, test_package, filename, | |
| 365 test_runner=None, test_runner_junit4=None): | |
| 366 device_path = os.path.join(device.GetExternalStoragePath(), | |
|
jbudorick
2017/07/14 18:43:55
just use a device temp file: https://codesearch.ch
the real yoland
2017/07/18 04:20:22
Done
| |
| 367 'chromium_tests_root', filename) | |
| 368 device.RunShellCommand(['rm', device_path], check_return=False) | |
| 369 if test_runner is None and test_runner_junit4 is None: | |
| 370 raise Exception('Test runner does NOT exist for this test apk') | |
| 371 if test_runner_junit4: | |
|
jbudorick
2017/07/14 18:43:56
If there is no test_runner_junit4, it looks like w
the real yoland
2017/07/18 04:20:21
Done
| |
| 372 extras = {} | |
| 373 extras['listAllTests'] = filename | |
| 374 extras['log'] = 'true' | |
| 375 extras['package'] = 'org.chromium' | |
| 376 target = '%s/%s' % (test_package, test_runner_junit4) | |
| 377 output_string = ''.join(device.StartInstrumentation( | |
| 378 target, extras=extras, timeout=30, retries=0)) | |
|
jbudorick
2017/07/14 18:43:55
No retries?
the real yoland
2017/07/18 04:20:22
Set retries to 2?
Done
| |
| 379 if output_string: | |
| 380 raise Exception('Test listing through %s failed on device:\n%s' % ( | |
| 381 test_runner_junit4, output_string)) | |
| 382 with tempfile_ext.NamedTemporaryDirectory() as host_dir: | |
| 383 host_file = os.path.join(host_dir, filename) | |
| 384 device.PullFile(device_path, host_dir) | |
| 385 with open(host_file, 'r') as f: | |
| 386 json_string = f.read() | |
| 387 return json.loads(json_string) | |
| 388 | |
| 339 | 389 |
| 340 def _SaveTestsToPickle(pickle_path, jar_path, tests): | 390 def _SaveTestsToPickle(pickle_path, jar_path, tests): |
| 341 jar_md5 = md5sum.CalculateHostMd5Sums(jar_path)[jar_path] | 391 jar_md5 = md5sum.CalculateHostMd5Sums(jar_path)[jar_path] |
| 342 pickle_data = { | 392 pickle_data = { |
| 343 'VERSION': _PICKLE_FORMAT_VERSION, | 393 'VERSION': _PICKLE_FORMAT_VERSION, |
| 344 'JAR_MD5SUM': jar_md5, | 394 'JAR_MD5SUM': jar_md5, |
| 345 'TEST_METHODS': tests, | 395 'TEST_METHODS': tests, |
| 346 } | 396 } |
| 347 with open(pickle_path, 'w') as pickle_file: | 397 with open(pickle_path, 'w') as pickle_file: |
| 348 pickle.dump(pickle_data, pickle_file) | 398 pickle.dump(pickle_data, pickle_file) |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 372 | 422 |
| 373 Args: | 423 Args: |
| 374 test: the instrumentation test dict. | 424 test: the instrumentation test dict. |
| 375 sep: the character(s) that should join the class name and the method name. | 425 sep: the character(s) that should join the class name and the method name. |
| 376 Returns: | 426 Returns: |
| 377 The test name as a string. | 427 The test name as a string. |
| 378 """ | 428 """ |
| 379 return '%s%s%s' % (test['class'], sep, test['method']) | 429 return '%s%s%s' % (test['class'], sep, test['method']) |
| 380 | 430 |
| 381 | 431 |
| 432 def GetTestNameWithoutParameterPostfix( | |
| 433 test, sep='#', parameter_postfix='__'): | |
| 434 """Gets the name of the given JUnit4 test withouth parameter postfix. | |
| 435 | |
| 436 For most WebView JUnit4 javatests, each test is parameterizatized with | |
| 437 "__sandboxed_mode" to run in both non-sandboxed mode and sandboxed mode. | |
| 438 | |
| 439 This function returns the name of the test without parameterization | |
| 440 so test filters can match both parameterized and non-parameterized tests. | |
| 441 | |
| 442 Args: | |
| 443 test: the instrumentation test dict. | |
| 444 sep: the character(s) that should join the class name and the method name. | |
| 445 parameterization_sep: the character(s) that seperate method name and method | |
| 446 parameterization postfix. | |
| 447 Returns: | |
| 448 The test name without parameter postfix as a string. | |
| 449 """ | |
| 450 name = GetTestName(test, sep=sep) | |
| 451 return name.split(parameter_postfix)[0] | |
| 452 | |
| 453 | |
| 382 def GetUniqueTestName(test, sep='#'): | 454 def GetUniqueTestName(test, sep='#'): |
| 383 """Gets the unique name of the given test. | 455 """Gets the unique name of the given test. |
| 384 | 456 |
| 385 This will include text to disambiguate between tests for which GetTestName | 457 This will include text to disambiguate between tests for which GetTestName |
| 386 would return the same name. | 458 would return the same name. |
| 387 | 459 |
| 388 Args: | 460 Args: |
| 389 test: the instrumentation test dict. | 461 test: the instrumentation test dict. |
| 390 sep: the character(s) that should join the class name and the method name. | 462 sep: the character(s) that should join the class name and the method name. |
| 391 Returns: | 463 Returns: |
| (...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 761 return 'instrumentation' | 833 return 'instrumentation' |
| 762 | 834 |
| 763 #override | 835 #override |
| 764 def SetUp(self): | 836 def SetUp(self): |
| 765 self._data_deps.extend( | 837 self._data_deps.extend( |
| 766 self._data_deps_delegate(self._runtime_deps_path)) | 838 self._data_deps_delegate(self._runtime_deps_path)) |
| 767 | 839 |
| 768 def GetDataDependencies(self): | 840 def GetDataDependencies(self): |
| 769 return self._data_deps | 841 return self._data_deps |
| 770 | 842 |
| 771 def GetTests(self): | 843 def GetTests(self, device=None): |
| 772 if self.test_jar: | 844 filename = 'list_all_tests.json' |
| 845 if self._test_runner_junit4 and device: | |
| 846 tests = GetAllTestsFromRunner( | |
| 847 device, self.test_apk.path, self.test_package, filename, | |
| 848 test_runner=self._test_runner, | |
| 849 test_runner_junit4=self.test_runner_junit4) | |
| 850 elif self.test_jar: | |
| 773 tests = GetAllTestsFromJar(self.test_jar) | 851 tests = GetAllTestsFromJar(self.test_jar) |
| 774 else: | 852 else: |
| 775 tests = GetAllTestsFromApk(self.test_apk.path) | 853 tests = GetAllTestsFromApk(self.test_apk.path) |
| 776 inflated_tests = self._ParameterizeTestsWithFlags(self._InflateTests(tests)) | 854 inflated_tests = self._ParameterizeTestsWithFlags(self._InflateTests(tests)) |
| 777 if self._test_runner_junit4 is None and any( | 855 if self._test_runner_junit4 is None and any( |
| 778 t['is_junit4'] for t in inflated_tests): | 856 t['is_junit4'] for t in inflated_tests): |
| 779 raise MissingJUnit4RunnerException() | 857 raise MissingJUnit4RunnerException() |
| 780 filtered_tests = FilterTests( | 858 filtered_tests = FilterTests( |
| 781 inflated_tests, self._test_filter, self._annotations, | 859 inflated_tests, self._test_filter, self._annotations, |
| 782 self._excluded_annotations) | 860 self._excluded_annotations) |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 840 | 918 |
| 841 @staticmethod | 919 @staticmethod |
| 842 def GenerateTestResults( | 920 def GenerateTestResults( |
| 843 result_code, result_bundle, statuses, start_ms, duration_ms): | 921 result_code, result_bundle, statuses, start_ms, duration_ms): |
| 844 return GenerateTestResults(result_code, result_bundle, statuses, | 922 return GenerateTestResults(result_code, result_bundle, statuses, |
| 845 start_ms, duration_ms) | 923 start_ms, duration_ms) |
| 846 | 924 |
| 847 #override | 925 #override |
| 848 def TearDown(self): | 926 def TearDown(self): |
| 849 pass | 927 pass |
| OLD | NEW |