 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 logging | 5 import logging | 
| 6 import os | 6 import os | 
| 7 import pickle | 7 import pickle | 
| 8 import re | 8 import re | 
| 9 import sys | 9 import sys | 
| 10 from collections import namedtuple | |
| 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_instance | 16 from pylib.base import test_instance | 
| 16 from pylib.instrumentation import test_result | 17 from pylib.instrumentation import test_result | 
| 17 from pylib.instrumentation import instrumentation_parser | 18 from pylib.instrumentation import instrumentation_parser | 
| 18 from pylib.utils import proguard | 19 from pylib.utils import proguard | 
| 19 | 20 | 
| (...skipping 14 matching lines...) Expand all Loading... | |
| 34 'org.chromium.chrome.test.ChromeInstrumentationTestRunner.' | 35 'org.chromium.chrome.test.ChromeInstrumentationTestRunner.' | 
| 35 + 'EnableTestHttpServer') | 36 + 'EnableTestHttpServer') | 
| 36 _EXTRA_DRIVER_TEST_LIST = ( | 37 _EXTRA_DRIVER_TEST_LIST = ( | 
| 37 'org.chromium.test.driver.OnDeviceInstrumentationDriver.TestList') | 38 'org.chromium.test.driver.OnDeviceInstrumentationDriver.TestList') | 
| 38 _EXTRA_DRIVER_TEST_LIST_FILE = ( | 39 _EXTRA_DRIVER_TEST_LIST_FILE = ( | 
| 39 'org.chromium.test.driver.OnDeviceInstrumentationDriver.TestListFile') | 40 'org.chromium.test.driver.OnDeviceInstrumentationDriver.TestListFile') | 
| 40 _EXTRA_DRIVER_TARGET_PACKAGE = ( | 41 _EXTRA_DRIVER_TARGET_PACKAGE = ( | 
| 41 'org.chromium.test.driver.OnDeviceInstrumentationDriver.TargetPackage') | 42 'org.chromium.test.driver.OnDeviceInstrumentationDriver.TargetPackage') | 
| 42 _EXTRA_DRIVER_TARGET_CLASS = ( | 43 _EXTRA_DRIVER_TARGET_CLASS = ( | 
| 43 'org.chromium.test.driver.OnDeviceInstrumentationDriver.TargetClass') | 44 'org.chromium.test.driver.OnDeviceInstrumentationDriver.TargetClass') | 
| 45 _PARAMETERIZED_TEST_ANNOTATION = 'ParameterizedTest' | |
| 46 _PARAMETERIZED_TEST_SET_ANNOTATION = 'ParameterizedTest$Set' | |
| 47 _COMMAND_LINE_PARAMETER = 'cmdlinearg-parameter' | |
| 44 _NATIVE_CRASH_RE = re.compile('native crash', re.IGNORECASE) | 48 _NATIVE_CRASH_RE = re.compile('native crash', re.IGNORECASE) | 
| 45 _PICKLE_FORMAT_VERSION = 10 | 49 _PICKLE_FORMAT_VERSION = 10 | 
| 46 | 50 | 
| 47 | 51 | 
| 48 # TODO(jbudorick): Make these private class methods of | 52 # TODO(jbudorick): Make these private class methods of | 
| 49 # InstrumentationTestInstance once the instrumentation test_runner is | 53 # InstrumentationTestInstance once the instrumentation test_runner is | 
| 50 # deprecated. | 54 # deprecated. | 
| 51 def ParseAmInstrumentRawOutput(raw_output): | 55 def ParseAmInstrumentRawOutput(raw_output): | 
| 52 """Parses the output of an |am instrument -r| call. | 56 """Parses the output of an |am instrument -r| call. | 
| 53 | 57 | 
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 127 and any(_NATIVE_CRASH_RE.search(l) | 131 and any(_NATIVE_CRASH_RE.search(l) | 
| 128 for l in result_bundle.itervalues())) | 132 for l in result_bundle.itervalues())) | 
| 129 if crashed: | 133 if crashed: | 
| 130 current_result.SetType(base_test_result.ResultType.CRASH) | 134 current_result.SetType(base_test_result.ResultType.CRASH) | 
| 131 | 135 | 
| 132 results.append(current_result) | 136 results.append(current_result) | 
| 133 | 137 | 
| 134 return results | 138 return results | 
| 135 | 139 | 
| 136 | 140 | 
| 141 def ParseCommandLineFlagParameters(annotations): | |
| 142 """Determines whether the test is parameterized to be run with different | |
| 143 command-line flags. | |
| 144 | |
| 145 Args: | |
| 146 annotations: The annotations of the test. | |
| 147 | |
| 148 Returns: | |
| 149 If the test is parameterized, returns a list of named tuples | |
| 150 with lists of flags, e.g.: | |
| 151 | |
| 152 [(add=['--flag-to-add']), (remove=['--flag-to-remove']), ()] | |
| 153 | |
| 154 That means, the test must be run three times, the first time with | |
| 155 "--flag-to-add" added to command-line, the second time with | |
| 156 "--flag-to-remove" to be removed from command-line, and the third time | |
| 157 with default command-line args. If the same flag is listed both for adding | |
| 158 and for removing, it is left unchanged. | |
| 159 | |
| 160 If the test is not parametrized, returns None. | |
| 161 | |
| 162 """ | |
| 163 ParamsTuple = namedtuple('ParamsTuple', ['add', 'remove']) | |
| 164 parameterized_tests = [] | |
| 165 if _PARAMETERIZED_TEST_ANNOTATION in annotations: | |
| 166 parameterized_tests = [annotations[_PARAMETERIZED_TEST_ANNOTATION]] | |
| 167 elif _PARAMETERIZED_TEST_SET_ANNOTATION in annotations: | |
| 168 if annotations[_PARAMETERIZED_TEST_SET_ANNOTATION]: | |
| 169 parameterized_tests = annotations[ | |
| 170 _PARAMETERIZED_TEST_SET_ANNOTATION].get('tests', []) | |
| 171 else: | |
| 172 return None | |
| 173 | |
| 174 result = [] | |
| 175 for pt in parameterized_tests: | |
| 176 if not pt: | |
| 177 continue | |
| 178 for p in pt['parameters']: | |
| 179 if p['tag'] == _COMMAND_LINE_PARAMETER: | |
| 180 to_add = [] | |
| 181 to_remove = [] | |
| 182 if 'arguments' in p: | |
| 
jbudorick
2015/11/02 14:49:46
nit: combine these two lines into
  for a in p.ge
 
mnaganov (inactive)
2015/11/02 19:03:54
Done.
 | |
| 183 for a in p['arguments']: | |
| 184 if a['name'] == 'add': | |
| 185 to_add = [('--' + f) for f in a['stringArray']] | |
| 
jbudorick
2015/11/02 14:49:46
nit: ['--%s' % f for f in a['stringArray']]
 
mnaganov (inactive)
2015/11/02 19:03:53
Done.
 | |
| 186 elif a['name'] == 'remove': | |
| 187 to_remove = [('--' + f) for f in a['stringArray']] | |
| 
jbudorick
2015/11/02 14:49:46
nit: same
 
mnaganov (inactive)
2015/11/02 19:03:53
Done.
 | |
| 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._InflateTests(self._FilterTests(tests)) | 
| 
jbudorick
2015/11/02 14:49:45
re below: add the separate function call here.
 
mnaganov (inactive)
2015/11/02 19:03:54
Done.
 | |
| 396 | 451 | 
| 397 class ProguardPickleException(Exception): | 452 class ProguardPickleException(Exception): | 
| 398 pass | 453 pass | 
| 399 | 454 | 
| 400 def _GetTestsFromPickle(self, pickle_path, jar_path): | 455 def _GetTestsFromPickle(self, pickle_path, jar_path): | 
| 401 if not os.path.exists(pickle_path): | 456 if not os.path.exists(pickle_path): | 
| 402 raise self.ProguardPickleException('%s does not exist.' % pickle_path) | 457 raise self.ProguardPickleException('%s does not exist.' % pickle_path) | 
| 403 if os.path.getmtime(pickle_path) <= os.path.getmtime(jar_path): | 458 if os.path.getmtime(pickle_path) <= os.path.getmtime(jar_path): | 
| 404 raise self.ProguardPickleException( | 459 raise self.ProguardPickleException( | 
| 405 '%s newer than %s.' % (jar_path, pickle_path)) | 460 '%s newer than %s.' % (jar_path, pickle_path)) | 
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 503 filtered_classes.append(filtered_class) | 558 filtered_classes.append(filtered_class) | 
| 504 | 559 | 
| 505 return filtered_classes | 560 return filtered_classes | 
| 506 | 561 | 
| 507 def _InflateTests(self, tests): | 562 def _InflateTests(self, tests): | 
| 508 inflated_tests = [] | 563 inflated_tests = [] | 
| 509 for c in tests: | 564 for c in tests: | 
| 510 for m in c['methods']: | 565 for m in c['methods']: | 
| 511 a = dict(c['annotations']) | 566 a = dict(c['annotations']) | 
| 512 a.update(m['annotations']) | 567 a.update(m['annotations']) | 
| 513 inflated_tests.append({ | 568 parameters = ParseCommandLineFlagParameters(a) | 
| 
jbudorick
2015/11/02 14:49:46
Do this in a separate function.
 
mnaganov (inactive)
2015/11/02 19:03:53
Done.
 | |
| 569 if parameters: | |
| 570 for p in parameters: | |
| 571 inflated_tests.append({ | |
| 572 'class': c['class'], | |
| 573 'method': m['method'], | |
| 574 'annotations': a, | |
| 575 'flags': p, | |
| 576 }) | |
| 577 else: | |
| 578 inflated_tests.append({ | |
| 514 'class': c['class'], | 579 'class': c['class'], | 
| 515 'method': m['method'], | 580 'method': m['method'], | 
| 516 'annotations': a, | 581 'annotations': a, | 
| 517 }) | 582 }) | 
| 518 return inflated_tests | 583 return inflated_tests | 
| 519 | 584 | 
| 520 @staticmethod | 585 @staticmethod | 
| 521 def GetHttpServerEnvironmentVars(): | 586 def GetHttpServerEnvironmentVars(): | 
| 522 return { | 587 return { | 
| 523 _EXTRA_ENABLE_HTTP_SERVER: None, | 588 _EXTRA_ENABLE_HTTP_SERVER: None, | 
| 524 } | 589 } | 
| 525 | 590 | 
| 526 def GetDriverEnvironmentVars( | 591 def GetDriverEnvironmentVars( | 
| 527 self, test_list=None, test_list_file_path=None): | 592 self, test_list=None, test_list_file_path=None): | 
| (...skipping 19 matching lines...) Expand all Loading... | |
| 547 def GenerateTestResults( | 612 def GenerateTestResults( | 
| 548 result_code, result_bundle, statuses, start_ms, duration_ms): | 613 result_code, result_bundle, statuses, start_ms, duration_ms): | 
| 549 return GenerateTestResults(result_code, result_bundle, statuses, | 614 return GenerateTestResults(result_code, result_bundle, statuses, | 
| 550 start_ms, duration_ms) | 615 start_ms, duration_ms) | 
| 551 | 616 | 
| 552 #override | 617 #override | 
| 553 def TearDown(self): | 618 def TearDown(self): | 
| 554 if self._isolate_delegate: | 619 if self._isolate_delegate: | 
| 555 self._isolate_delegate.Clear() | 620 self._isolate_delegate.Clear() | 
| 556 | 621 | 
| OLD | NEW |