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 logging | 6 import logging |
| 6 import os | 7 import os |
| 7 import pickle | 8 import pickle |
| 8 import re | 9 import re |
| 9 import sys | 10 import sys |
| 11 from collections import namedtuple | |
|
jbudorick
2015/11/04 16:34:34
nit: import the module rather than the function (s
mnaganov (inactive)
2015/11/04 17:51:03
Done.
| |
| 10 | 12 |
| 11 from devil.android import apk_helper | 13 from devil.android import apk_helper |
| 12 from devil.android import md5sum | 14 from devil.android import md5sum |
| 13 from pylib import constants | 15 from pylib import constants |
| 14 from pylib.base import base_test_result | 16 from pylib.base import base_test_result |
| 15 from pylib.base import test_instance | 17 from pylib.base import test_instance |
| 16 from pylib.instrumentation import test_result | 18 from pylib.instrumentation import test_result |
| 17 from pylib.instrumentation import instrumentation_parser | 19 from pylib.instrumentation import instrumentation_parser |
| 18 from pylib.utils import proguard | 20 from pylib.utils import proguard |
| 19 | 21 |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 34 'org.chromium.chrome.test.ChromeInstrumentationTestRunner.' | 36 'org.chromium.chrome.test.ChromeInstrumentationTestRunner.' |
| 35 + 'EnableTestHttpServer') | 37 + 'EnableTestHttpServer') |
| 36 _EXTRA_DRIVER_TEST_LIST = ( | 38 _EXTRA_DRIVER_TEST_LIST = ( |
| 37 'org.chromium.test.driver.OnDeviceInstrumentationDriver.TestList') | 39 'org.chromium.test.driver.OnDeviceInstrumentationDriver.TestList') |
| 38 _EXTRA_DRIVER_TEST_LIST_FILE = ( | 40 _EXTRA_DRIVER_TEST_LIST_FILE = ( |
| 39 'org.chromium.test.driver.OnDeviceInstrumentationDriver.TestListFile') | 41 'org.chromium.test.driver.OnDeviceInstrumentationDriver.TestListFile') |
| 40 _EXTRA_DRIVER_TARGET_PACKAGE = ( | 42 _EXTRA_DRIVER_TARGET_PACKAGE = ( |
| 41 'org.chromium.test.driver.OnDeviceInstrumentationDriver.TargetPackage') | 43 'org.chromium.test.driver.OnDeviceInstrumentationDriver.TargetPackage') |
| 42 _EXTRA_DRIVER_TARGET_CLASS = ( | 44 _EXTRA_DRIVER_TARGET_CLASS = ( |
| 43 'org.chromium.test.driver.OnDeviceInstrumentationDriver.TargetClass') | 45 'org.chromium.test.driver.OnDeviceInstrumentationDriver.TargetClass') |
| 46 _PARAMETERIZED_TEST_ANNOTATION = 'ParameterizedTest' | |
|
jbudorick
2015/11/04 16:34:34
nit: alphabetize these
mnaganov (inactive)
2015/11/04 17:51:03
Done.
| |
| 47 _PARAMETERIZED_TEST_SET_ANNOTATION = 'ParameterizedTest$Set' | |
| 48 _COMMAND_LINE_PARAMETER = 'cmdlinearg-parameter' | |
| 44 _NATIVE_CRASH_RE = re.compile('native crash', re.IGNORECASE) | 49 _NATIVE_CRASH_RE = re.compile('native crash', re.IGNORECASE) |
| 45 _PICKLE_FORMAT_VERSION = 10 | 50 _PICKLE_FORMAT_VERSION = 10 |
| 46 | 51 |
| 47 | 52 |
| 48 # TODO(jbudorick): Make these private class methods of | 53 # TODO(jbudorick): Make these private class methods of |
| 49 # InstrumentationTestInstance once the instrumentation test_runner is | 54 # InstrumentationTestInstance once the instrumentation test_runner is |
| 50 # deprecated. | 55 # deprecated. |
| 51 def ParseAmInstrumentRawOutput(raw_output): | 56 def ParseAmInstrumentRawOutput(raw_output): |
| 52 """Parses the output of an |am instrument -r| call. | 57 """Parses the output of an |am instrument -r| call. |
| 53 | 58 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 127 and any(_NATIVE_CRASH_RE.search(l) | 132 and any(_NATIVE_CRASH_RE.search(l) |
| 128 for l in result_bundle.itervalues())) | 133 for l in result_bundle.itervalues())) |
| 129 if crashed: | 134 if crashed: |
| 130 current_result.SetType(base_test_result.ResultType.CRASH) | 135 current_result.SetType(base_test_result.ResultType.CRASH) |
| 131 | 136 |
| 132 results.append(current_result) | 137 results.append(current_result) |
| 133 | 138 |
| 134 return results | 139 return results |
| 135 | 140 |
| 136 | 141 |
| 142 def ParseCommandLineFlagParameters(annotations): | |
| 143 """Determines whether the test is parameterized to be run with different | |
| 144 command-line flags. | |
| 145 | |
| 146 Args: | |
| 147 annotations: The annotations of the test. | |
| 148 | |
| 149 Returns: | |
| 150 If the test is parameterized, returns a list of named tuples | |
| 151 with lists of flags, e.g.: | |
| 152 | |
| 153 [(add=['--flag-to-add']), (remove=['--flag-to-remove']), ()] | |
| 154 | |
| 155 That means, the test must be run three times, the first time with | |
| 156 "--flag-to-add" added to command-line, the second time with | |
| 157 "--flag-to-remove" to be removed from command-line, and the third time | |
| 158 with default command-line args. If the same flag is listed both for adding | |
| 159 and for removing, it is left unchanged. | |
| 160 | |
| 161 If the test is not parametrized, returns None. | |
| 162 | |
| 163 """ | |
| 164 ParamsTuple = namedtuple('ParamsTuple', ['add', 'remove']) | |
| 165 parameterized_tests = [] | |
| 166 if _PARAMETERIZED_TEST_ANNOTATION in annotations: | |
| 167 parameterized_tests = [annotations[_PARAMETERIZED_TEST_ANNOTATION]] | |
| 168 elif _PARAMETERIZED_TEST_SET_ANNOTATION in annotations: | |
| 169 if annotations[_PARAMETERIZED_TEST_SET_ANNOTATION]: | |
| 170 parameterized_tests = annotations[ | |
| 171 _PARAMETERIZED_TEST_SET_ANNOTATION].get('tests', []) | |
| 172 else: | |
| 173 return None | |
| 174 | |
| 175 result = [] | |
| 176 for pt in parameterized_tests: | |
| 177 if not pt: | |
| 178 continue | |
| 179 for p in pt['parameters']: | |
| 180 if p['tag'] == _COMMAND_LINE_PARAMETER: | |
| 181 to_add = [] | |
| 182 to_remove = [] | |
| 183 for a in p.get('arguments', []): | |
| 184 if a['name'] == 'add': | |
| 185 to_add = ['--%s' % f for f in a['stringArray']] | |
| 186 elif a['name'] == 'remove': | |
| 187 to_remove = ['--%s' % f for f in a['stringArray']] | |
| 188 result.append(ParamsTuple(to_add, to_remove)) | |
| 189 return result if result else None | |
| 190 | |
| 191 | |
| 137 class InstrumentationTestInstance(test_instance.TestInstance): | 192 class InstrumentationTestInstance(test_instance.TestInstance): |
| 138 | 193 |
| 139 def __init__(self, args, isolate_delegate, error_func): | 194 def __init__(self, args, isolate_delegate, error_func): |
| 140 super(InstrumentationTestInstance, self).__init__() | 195 super(InstrumentationTestInstance, self).__init__() |
| 141 | 196 |
| 142 self._additional_apks = [] | 197 self._additional_apks = [] |
| 143 self._apk_under_test = None | 198 self._apk_under_test = None |
| 144 self._apk_under_test_permissions = None | 199 self._apk_under_test_permissions = None |
| 145 self._package_info = None | 200 self._package_info = None |
| 146 self._suite = None | 201 self._suite = None |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 385 return self._data_deps | 440 return self._data_deps |
| 386 | 441 |
| 387 def GetTests(self): | 442 def GetTests(self): |
| 388 pickle_path = '%s-proguard.pickle' % self.test_jar | 443 pickle_path = '%s-proguard.pickle' % self.test_jar |
| 389 try: | 444 try: |
| 390 tests = self._GetTestsFromPickle(pickle_path, self.test_jar) | 445 tests = self._GetTestsFromPickle(pickle_path, self.test_jar) |
| 391 except self.ProguardPickleException as e: | 446 except self.ProguardPickleException as e: |
| 392 logging.info('Getting tests from JAR via proguard. (%s)', str(e)) | 447 logging.info('Getting tests from JAR via proguard. (%s)', str(e)) |
| 393 tests = self._GetTestsFromProguard(self.test_jar) | 448 tests = self._GetTestsFromProguard(self.test_jar) |
| 394 self._SaveTestsToPickle(pickle_path, self.test_jar, tests) | 449 self._SaveTestsToPickle(pickle_path, self.test_jar, tests) |
| 395 return self._InflateTests(self._FilterTests(tests)) | 450 return self._ParametrizeTestsWithFlags( |
| 451 self._InflateTests(self._FilterTests(tests))) | |
|
jbudorick
2015/11/04 16:34:34
nit: 4 space indent
mnaganov (inactive)
2015/11/04 17:51:03
Done.
| |
| 396 | 452 |
| 397 class ProguardPickleException(Exception): | 453 class ProguardPickleException(Exception): |
| 398 pass | 454 pass |
| 399 | 455 |
| 400 def _GetTestsFromPickle(self, pickle_path, jar_path): | 456 def _GetTestsFromPickle(self, pickle_path, jar_path): |
| 401 if not os.path.exists(pickle_path): | 457 if not os.path.exists(pickle_path): |
| 402 raise self.ProguardPickleException('%s does not exist.' % pickle_path) | 458 raise self.ProguardPickleException('%s does not exist.' % pickle_path) |
| 403 if os.path.getmtime(pickle_path) <= os.path.getmtime(jar_path): | 459 if os.path.getmtime(pickle_path) <= os.path.getmtime(jar_path): |
| 404 raise self.ProguardPickleException( | 460 raise self.ProguardPickleException( |
| 405 '%s newer than %s.' % (jar_path, pickle_path)) | 461 '%s newer than %s.' % (jar_path, pickle_path)) |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 510 for m in c['methods']: | 566 for m in c['methods']: |
| 511 a = dict(c['annotations']) | 567 a = dict(c['annotations']) |
| 512 a.update(m['annotations']) | 568 a.update(m['annotations']) |
| 513 inflated_tests.append({ | 569 inflated_tests.append({ |
| 514 'class': c['class'], | 570 'class': c['class'], |
| 515 'method': m['method'], | 571 'method': m['method'], |
| 516 'annotations': a, | 572 'annotations': a, |
| 517 }) | 573 }) |
| 518 return inflated_tests | 574 return inflated_tests |
| 519 | 575 |
| 576 def _ParametrizeTestsWithFlags(self, tests): | |
| 577 new_tests = [] | |
| 578 for t in tests: | |
| 579 parameters = ParseCommandLineFlagParameters(t['annotations']) | |
| 580 if parameters: | |
| 581 t['flags'] = parameters[0] | |
| 582 for p in parameters[1:]: | |
| 583 parameterized_t = copy.copy(t) | |
| 584 parameterized_t['flags'] = p | |
| 585 new_tests.append(parameterized_t) | |
| 586 return tests + new_tests | |
| 587 | |
| 520 @staticmethod | 588 @staticmethod |
| 521 def GetHttpServerEnvironmentVars(): | 589 def GetHttpServerEnvironmentVars(): |
| 522 return { | 590 return { |
| 523 _EXTRA_ENABLE_HTTP_SERVER: None, | 591 _EXTRA_ENABLE_HTTP_SERVER: None, |
| 524 } | 592 } |
| 525 | 593 |
| 526 def GetDriverEnvironmentVars( | 594 def GetDriverEnvironmentVars( |
| 527 self, test_list=None, test_list_file_path=None): | 595 self, test_list=None, test_list_file_path=None): |
| 528 env = { | 596 env = { |
| 529 _EXTRA_DRIVER_TARGET_PACKAGE: self.test_package, | 597 _EXTRA_DRIVER_TARGET_PACKAGE: self.test_package, |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 547 def GenerateTestResults( | 615 def GenerateTestResults( |
| 548 result_code, result_bundle, statuses, start_ms, duration_ms): | 616 result_code, result_bundle, statuses, start_ms, duration_ms): |
| 549 return GenerateTestResults(result_code, result_bundle, statuses, | 617 return GenerateTestResults(result_code, result_bundle, statuses, |
| 550 start_ms, duration_ms) | 618 start_ms, duration_ms) |
| 551 | 619 |
| 552 #override | 620 #override |
| 553 def TearDown(self): | 621 def TearDown(self): |
| 554 if self._isolate_delegate: | 622 if self._isolate_delegate: |
| 555 self._isolate_delegate.Clear() | 623 self._isolate_delegate.Clear() |
| 556 | 624 |
| OLD | NEW |