diff options
author | aberent <aberent@chromium.org> | 2014-11-18 06:06:19 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-11-18 14:07:26 +0000 |
commit | 8ac3033db57d03c862f71fde5f0c7c95e24bac54 (patch) | |
tree | 70de454f6ef9fedf64e93b49478d12e75dc99dbb /build | |
parent | 8430b8f712c590cc73b46352c48df24eb694bf10 (diff) | |
download | chromium_src-8ac3033db57d03c862f71fde5f0c7c95e24bac54.zip chromium_src-8ac3033db57d03c862f71fde5f0c7c95e24bac54.tar.gz chromium_src-8ac3033db57d03c862f71fde5f0c7c95e24bac54.tar.bz2 |
Revert of [Android] Reland of proguard logic extraction. (patchset #2 id:20001 of https://codereview.chromium.org/737543002/)
Reason for revert:
Following this CL the -A and -E options on test_runner.py with Feature=... don't work. This kills the nakasi-enormous downstream Android bot.
BUG=434340
Original issue's description:
> [Android] Reland of proguard logic extraction.
>
> Originally reviewed here: https://codereview.chromium.org/729993003/
> and reverted here: https://codereview.chromium.org/730033003/
>
> BUG=428729
>
> Committed: https://crrev.com/6dd1f4f2fb335a69c7b0ec2d5d0f711cf1d51852
> Cr-Commit-Position: refs/heads/master@{#304543}
TBR=klundberg@chromium.org,jbudorick@chromium.org
NOTREECHECKS=true
NOTRY=true
BUG=428729
Review URL: https://codereview.chromium.org/735723002
Cr-Commit-Position: refs/heads/master@{#304597}
Diffstat (limited to 'build')
-rw-r--r-- | build/android/pylib/instrumentation/test_jar.py | 146 | ||||
-rw-r--r-- | build/android/pylib/instrumentation/test_runner.py | 13 | ||||
-rw-r--r-- | build/android/pylib/uiautomator/test_runner.py | 3 | ||||
-rw-r--r-- | build/android/pylib/utils/proguard.py | 144 |
4 files changed, 121 insertions, 185 deletions
diff --git a/build/android/pylib/instrumentation/test_jar.py b/build/android/pylib/instrumentation/test_jar.py index a3d8849..d83d00a 100644 --- a/build/android/pylib/instrumentation/test_jar.py +++ b/build/android/pylib/instrumentation/test_jar.py @@ -10,11 +10,11 @@ import os import pickle import re import sys +import tempfile from pylib import cmd_helper from pylib import constants from pylib.device import device_utils -from pylib.utils import proguard sys.path.insert(0, os.path.join(constants.DIR_SOURCE_ROOT, @@ -23,7 +23,7 @@ sys.path.insert(0, import unittest_util # pylint: disable=F0401 # If you change the cached output of proguard, increment this number -PICKLE_FORMAT_VERSION = 4 +PICKLE_FORMAT_VERSION = 3 class TestJar(object): @@ -86,30 +86,111 @@ class TestJar(object): def _GetProguardData(self): logging.info('Retrieving test methods via proguard.') - p = proguard.Dump(self._jar_path) - - class_lookup = dict((c['class'], c) for c in p['classes']) - def recursive_get_annotations(c): - s = c['superclass'] - if s in class_lookup: - a = recursive_get_annotations(class_lookup[s]) - else: - a = {} - a.update(c['annotations']) - return a - - test_classes = (c for c in p['classes'] - if c['class'].endswith('Test')) - for c in test_classes: - class_annotations = recursive_get_annotations(c) - test_methods = (m for m in c['methods'] - if m['method'].startswith('test')) - for m in test_methods: - qualified_method = '%s#%s' % (c['class'], m['method']) - annotations = dict(class_annotations) - annotations.update(m['annotations']) - self._test_methods[qualified_method] = m - self._test_methods[qualified_method]['annotations'] = annotations + with tempfile.NamedTemporaryFile() as proguard_output: + cmd_helper.RunCmd(['java', '-jar', + self._PROGUARD_PATH, + '-injars', self._jar_path, + '-dontshrink', + '-dontoptimize', + '-dontobfuscate', + '-dontpreverify', + '-dump', proguard_output.name]) + + clazzez = {} + + annotation = None + annotation_has_value = False + clazz = None + method = None + + for line in proguard_output: + if len(line) == 0: + annotation = None + annotation_has_value = False + method = None + continue + + m = self._PROGUARD_CLASS_RE.match(line) + if m: + clazz = m.group(1).replace('/', '.') + clazzez[clazz] = { + 'methods': {}, + 'annotations': {} + } + annotation = None + annotation_has_value = False + method = None + continue + + if not clazz: + continue + + m = self._PROGUARD_SUPERCLASS_RE.match(line) + if m: + clazzez[clazz]['superclass'] = m.group(1).replace('/', '.') + continue + + if clazz.endswith('Test'): + m = self._PROGUARD_METHOD_RE.match(line) + if m: + method = m.group(1) + clazzez[clazz]['methods'][method] = {'annotations': {}} + annotation = None + annotation_has_value = False + continue + + m = self._PROGUARD_ANNOTATION_RE.match(line) + if m: + # Ignore the annotation package. + annotation = m.group(1).split('/')[-1] + if method: + clazzez[clazz]['methods'][method]['annotations'][annotation] = None + else: + clazzez[clazz]['annotations'][annotation] = None + continue + + if annotation: + if not annotation_has_value: + m = self._PROGUARD_ANNOTATION_CONST_RE.match(line) + annotation_has_value = bool(m) + else: + m = self._PROGUARD_ANNOTATION_VALUE_RE.match(line) + if m: + if method: + clazzez[clazz]['methods'][method]['annotations'][annotation] = ( + m.group(1)) + else: + clazzez[clazz]['annotations'][annotation] = m.group(1) + annotation_has_value = None + + test_clazzez = ((n, i) for n, i in clazzez.items() if n.endswith('Test')) + for clazz_name, clazz_info in test_clazzez: + logging.info('Processing %s' % clazz_name) + c = clazz_name + min_sdk_level = None + + while c in clazzez: + c_info = clazzez[c] + if not min_sdk_level: + min_sdk_level = c_info['annotations'].get('MinAndroidSdkLevel', None) + c = c_info.get('superclass', None) + + for method_name, method_info in clazz_info['methods'].items(): + if method_name.startswith('test'): + qualified_method = '%s#%s' % (clazz_name, method_name) + method_annotations = [] + for annotation_name, annotation_value in ( + method_info['annotations'].items()): + method_annotations.append(annotation_name) + if annotation_value: + method_annotations.append( + annotation_name + ':' + annotation_value) + self._test_methods[qualified_method] = { + 'annotations': method_annotations + } + if min_sdk_level is not None: + self._test_methods[qualified_method]['min_sdk_level'] = ( + int(min_sdk_level)) logging.info('Storing proguard output to %s', self._pickled_proguard_name) d = {'VERSION': PICKLE_FORMAT_VERSION, @@ -118,6 +199,7 @@ class TestJar(object): with open(self._pickled_proguard_name, 'w') as f: f.write(pickle.dumps(d)) + @staticmethod def _IsTestMethod(test): class_name, method = test.split('#') @@ -140,7 +222,7 @@ class TestJar(object): key = filters[0] value_list = filters[1].split(',') for value in value_list: - if key in annotations and value == annotations['key']: + if key + ':' + value in annotations: return True elif annotation_filter in annotations: return True @@ -148,9 +230,9 @@ class TestJar(object): def GetAnnotatedTests(self, annotation_filter_list): """Returns a list of all tests that match the given annotation filters.""" - return [test for test in self.GetTestMethods() + return [test for test, attr in self.GetTestMethods().iteritems() if self._IsTestMethod(test) and self._AnnotationsMatchFilters( - annotation_filter_list, self.GetTestAnnotations(test))] + annotation_filter_list, attr['annotations'])] def GetTestMethods(self): """Returns a dict of all test methods and relevant attributes. @@ -163,15 +245,15 @@ class TestJar(object): """Get a list of test methods with no known annotations.""" tests_missing_annotations = [] for test_method in self.GetTestMethods().iterkeys(): - annotations_ = frozenset(self.GetTestAnnotations(test_method).iterkeys()) + annotations_ = frozenset(self.GetTestAnnotations(test_method)) if (annotations_.isdisjoint(self._ANNOTATIONS) and not self.IsHostDrivenTest(test_method)): tests_missing_annotations.append(test_method) return sorted(tests_missing_annotations) def _IsTestValidForSdkRange(self, test_name, attached_min_sdk_level): - required_min_sdk_level = int( - self.GetTestAnnotations(test_name).get('MinAndroidSdkLevel', 0)) + required_min_sdk_level = self.GetTestMethods()[test_name].get( + 'min_sdk_level', None) return (required_min_sdk_level is None or attached_min_sdk_level >= required_min_sdk_level) diff --git a/build/android/pylib/instrumentation/test_runner.py b/build/android/pylib/instrumentation/test_runner.py index f2808da..60e00f3 100644 --- a/build/android/pylib/instrumentation/test_runner.py +++ b/build/android/pylib/instrumentation/test_runner.py @@ -208,8 +208,8 @@ class TestRunner(base_test_runner.BaseTestRunner): Returns: Whether the feature being tested is FirstRunExperience. """ - annotations = self.test_pkg.GetTestAnnotations(test) - return ('FirstRunExperience' == annotations.get('Feature', None)) + freFeature = 'Feature:FirstRunExperience' + return freFeature in self.test_pkg.GetTestAnnotations(test) def _IsPerfTest(self, test): """Determines whether a test is a performance test. @@ -329,11 +329,10 @@ class TestRunner(base_test_runner.BaseTestRunner): annotations = self.test_pkg.GetTestAnnotations(test) timeout_scale = 1 if 'TimeoutScale' in annotations: - try: - timeout_scale = int(annotations['TimeoutScale']) - except ValueError: - logging.warning('Non-integer value of TimeoutScale ignored. (%s)' - % annotations['TimeoutScale']) + for annotation in annotations: + scale_match = re.match('TimeoutScale:([0-9]+)', annotation) + if scale_match: + timeout_scale = int(scale_match.group(1)) if self.options.wait_for_debugger: timeout_scale *= 100 return timeout_scale diff --git a/build/android/pylib/uiautomator/test_runner.py b/build/android/pylib/uiautomator/test_runner.py index c7239b4..f4e5730 100644 --- a/build/android/pylib/uiautomator/test_runner.py +++ b/build/android/pylib/uiautomator/test_runner.py @@ -63,8 +63,7 @@ class TestRunner(instr_test_runner.TestRunner): def _RunTest(self, test, timeout): self.device.ClearApplicationState(self._package) if self.flags: - annotations = self.test_pkg.GetTestAnnotations(test) - if ('FirstRunExperience' == annotations(test).get('Feature', None)): + if 'Feature:FirstRunExperience' in self.test_pkg.GetTestAnnotations(test): self.flags.RemoveFlags(['--disable-fre']) else: self.flags.AddFlags(['--disable-fre']) diff --git a/build/android/pylib/utils/proguard.py b/build/android/pylib/utils/proguard.py deleted file mode 100644 index 02db03e..0000000 --- a/build/android/pylib/utils/proguard.py +++ /dev/null @@ -1,144 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import os -import re -import tempfile - -from pylib import constants -from pylib import cmd_helper - - -_PROGUARD_CLASS_RE = re.compile(r'\s*?- Program class:\s*([\S]+)$') -_PROGUARD_SUPERCLASS_RE = re.compile(r'\s*? Superclass:\s*([\S]+)$') -_PROGUARD_METHOD_RE = re.compile(r'\s*?- Method:\s*(\S*)[(].*$') -_PROGUARD_ANNOTATION_RE = re.compile(r'\s*?- Annotation \[L(\S*);\]:$') -_PROGUARD_ANNOTATION_CONST_RE = ( - re.compile(r'\s*?- Constant element value.*$')) -_PROGUARD_ANNOTATION_VALUE_RE = re.compile(r'\s*?- \S+? \[(.*)\]$') - -_PROGUARD_PATH_SDK = os.path.join( - constants.ANDROID_SDK_ROOT, 'tools', 'proguard', 'lib', 'proguard.jar') -_PROGUARD_PATH_BUILT = ( - os.path.join(os.environ['ANDROID_BUILD_TOP'], 'external', 'proguard', - 'lib', 'proguard.jar') - if 'ANDROID_BUILD_TOP' in os.environ else None) -_PROGUARD_PATH = ( - _PROGUARD_PATH_SDK if os.path.exists(_PROGUARD_PATH_SDK) - else _PROGUARD_PATH_BUILT) - - -def Dump(jar_path): - """Dumps class and method information from a JAR into a dict via proguard. - - Args: - jar_path: An absolute path to the JAR file to dump. - Returns: - A dict in the following format: - { - 'classes': [ - { - 'class': '', - 'superclass': '', - 'annotations': {}, - 'methods': [ - { - 'method': '', - 'annotations': {}, - }, - ... - ], - }, - ... - ], - } - """ - - with tempfile.NamedTemporaryFile() as proguard_output: - cmd_helper.RunCmd(['java', '-jar', - _PROGUARD_PATH, - '-injars', jar_path, - '-dontshrink', - '-dontoptimize', - '-dontobfuscate', - '-dontpreverify', - '-dump', proguard_output.name]) - - - results = { - 'classes': [], - } - - annotation = None - annotation_has_value = False - class_result = None - method_result = None - - for line in proguard_output: - line = line.strip('\r\n') - - if len(line) == 0: - annotation = None - annotation_has_value = False - method_result = None - continue - - m = _PROGUARD_CLASS_RE.match(line) - if m: - class_result = { - 'class': m.group(1).replace('/', '.'), - 'superclass': '', - 'annotations': {}, - 'methods': [], - } - results['classes'].append(class_result) - annotation = None - annotation_has_value = False - method_result = None - continue - - if not class_result: - continue - - m = _PROGUARD_SUPERCLASS_RE.match(line) - if m: - class_result['superclass'] = m.group(1).replace('/', '.') - continue - - m = _PROGUARD_METHOD_RE.match(line) - if m: - method_result = { - 'method': m.group(1), - 'annotations': {}, - } - class_result['methods'].append(method_result) - annotation = None - annotation_has_value = False - continue - - m = _PROGUARD_ANNOTATION_RE.match(line) - if m: - # Ignore the annotation package. - annotation = m.group(1).split('/')[-1] - if method_result: - method_result['annotations'][annotation] = None - else: - class_result['annotations'][annotation] = None - continue - - if annotation: - if not annotation_has_value: - m = _PROGUARD_ANNOTATION_CONST_RE.match(line) - annotation_has_value = bool(m) - else: - m = _PROGUARD_ANNOTATION_VALUE_RE.match(line) - if m: - if method_result: - method_result['annotations'][annotation] = m.group(1) - else: - class_result['annotations'][annotation] = m.group(1) - annotation_has_value = None - - return results - |