 Chromium Code Reviews
 Chromium Code Reviews Issue 1414403002:
  Add CommandLineArgumentParameter and use it for WebView tests  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@fix-cr-526885-read-nested-annotations
    
  
    Issue 1414403002:
  Add CommandLineArgumentParameter and use it for WebView tests  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@fix-cr-526885-read-nested-annotations| 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 |