| 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 collections | 
|  | 6 import copy | 
| 5 import logging | 7 import logging | 
| 6 import os | 8 import os | 
| 7 import pickle | 9 import pickle | 
| 8 import re | 10 import re | 
| 9 import sys | 11 import sys | 
| 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 | 
| 20 sys.path.append( | 22 sys.path.append( | 
| 21     os.path.join(constants.DIR_SOURCE_ROOT, 'build', 'util', 'lib', 'common')) | 23     os.path.join(constants.DIR_SOURCE_ROOT, 'build', 'util', 'lib', 'common')) | 
| 22 import unittest_util # pylint: disable=import-error | 24 import unittest_util # pylint: disable=import-error | 
| 23 | 25 | 
| 24 # Ref: http://developer.android.com/reference/android/app/Activity.html | 26 # Ref: http://developer.android.com/reference/android/app/Activity.html | 
| 25 _ACTIVITY_RESULT_CANCELED = 0 | 27 _ACTIVITY_RESULT_CANCELED = 0 | 
| 26 _ACTIVITY_RESULT_OK = -1 | 28 _ACTIVITY_RESULT_OK = -1 | 
| 27 | 29 | 
|  | 30 _COMMAND_LINE_PARAMETER = 'cmdlinearg-parameter' | 
| 28 _DEFAULT_ANNOTATIONS = [ | 31 _DEFAULT_ANNOTATIONS = [ | 
| 29     'Smoke', 'SmallTest', 'MediumTest', 'LargeTest', | 32     'Smoke', 'SmallTest', 'MediumTest', 'LargeTest', | 
| 30     'EnormousTest', 'IntegrationTest'] | 33     'EnormousTest', 'IntegrationTest'] | 
| 31 _EXCLUDE_UNLESS_REQUESTED_ANNOTATIONS = [ | 34 _EXCLUDE_UNLESS_REQUESTED_ANNOTATIONS = [ | 
| 32     'DisabledTest', 'FlakyTest'] | 35     'DisabledTest', 'FlakyTest'] | 
| 33 _EXTRA_ENABLE_HTTP_SERVER = ( | 36 _EXTRA_ENABLE_HTTP_SERVER = ( | 
| 34     'org.chromium.chrome.test.ChromeInstrumentationTestRunner.' | 37     'org.chromium.chrome.test.ChromeInstrumentationTestRunner.' | 
| 35         + 'EnableTestHttpServer') | 38         + 'EnableTestHttpServer') | 
| 36 _EXTRA_DRIVER_TEST_LIST = ( | 39 _EXTRA_DRIVER_TEST_LIST = ( | 
| 37     'org.chromium.test.driver.OnDeviceInstrumentationDriver.TestList') | 40     'org.chromium.test.driver.OnDeviceInstrumentationDriver.TestList') | 
| 38 _EXTRA_DRIVER_TEST_LIST_FILE = ( | 41 _EXTRA_DRIVER_TEST_LIST_FILE = ( | 
| 39     'org.chromium.test.driver.OnDeviceInstrumentationDriver.TestListFile') | 42     'org.chromium.test.driver.OnDeviceInstrumentationDriver.TestListFile') | 
| 40 _EXTRA_DRIVER_TARGET_PACKAGE = ( | 43 _EXTRA_DRIVER_TARGET_PACKAGE = ( | 
| 41     'org.chromium.test.driver.OnDeviceInstrumentationDriver.TargetPackage') | 44     'org.chromium.test.driver.OnDeviceInstrumentationDriver.TargetPackage') | 
| 42 _EXTRA_DRIVER_TARGET_CLASS = ( | 45 _EXTRA_DRIVER_TARGET_CLASS = ( | 
| 43     'org.chromium.test.driver.OnDeviceInstrumentationDriver.TargetClass') | 46     'org.chromium.test.driver.OnDeviceInstrumentationDriver.TargetClass') | 
|  | 47 _PARAMETERIZED_TEST_ANNOTATION = 'ParameterizedTest' | 
|  | 48 _PARAMETERIZED_TEST_SET_ANNOTATION = 'ParameterizedTest$Set' | 
| 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 = collections.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))) | 
| 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 | 
|---|