summaryrefslogtreecommitdiffstats
path: root/build
diff options
context:
space:
mode:
authoraberent <aberent@chromium.org>2014-11-18 06:06:19 -0800
committerCommit bot <commit-bot@chromium.org>2014-11-18 14:07:26 +0000
commit8ac3033db57d03c862f71fde5f0c7c95e24bac54 (patch)
tree70de454f6ef9fedf64e93b49478d12e75dc99dbb /build
parent8430b8f712c590cc73b46352c48df24eb694bf10 (diff)
downloadchromium_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.py146
-rw-r--r--build/android/pylib/instrumentation/test_runner.py13
-rw-r--r--build/android/pylib/uiautomator/test_runner.py3
-rw-r--r--build/android/pylib/utils/proguard.py144
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
-