media/webrtc/trunk/build/android/pylib/apk_info.py

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/media/webrtc/trunk/build/android/pylib/apk_info.py	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,142 @@
     1.4 +# Copyright (c) 2012 The Chromium Authors. All rights reserved.
     1.5 +# Use of this source code is governed by a BSD-style license that can be
     1.6 +# found in the LICENSE file.
     1.7 +
     1.8 +"""Gathers information about APKs."""
     1.9 +
    1.10 +import collections
    1.11 +import os
    1.12 +import re
    1.13 +
    1.14 +import cmd_helper
    1.15 +
    1.16 +
    1.17 +class ApkInfo(object):
    1.18 +  """Helper class for inspecting APKs."""
    1.19 +  _PROGUARD_PATH = os.path.join(os.environ['ANDROID_SDK_ROOT'],
    1.20 +                                'tools/proguard/bin/proguard.sh')
    1.21 +  if not os.path.exists(_PROGUARD_PATH):
    1.22 +    _PROGUARD_PATH = os.path.join(os.environ['ANDROID_BUILD_TOP'],
    1.23 +                                  'external/proguard/bin/proguard.sh')
    1.24 +  _PROGUARD_CLASS_RE = re.compile(r'\s*?- Program class:\s*([\S]+)$')
    1.25 +  _PROGUARD_METHOD_RE = re.compile(r'\s*?- Method:\s*(\S*)[(].*$')
    1.26 +  _PROGUARD_ANNOTATION_RE = re.compile(r'\s*?- Annotation \[L(\S*);\]:$')
    1.27 +  _PROGUARD_ANNOTATION_CONST_RE = re.compile(r'\s*?- Constant element value.*$')
    1.28 +  _PROGUARD_ANNOTATION_VALUE_RE = re.compile(r'\s*?- \S+? \[(.*)\]$')
    1.29 +  _AAPT_PACKAGE_NAME_RE = re.compile(r'package: .*name=\'(\S*)\'')
    1.30 +
    1.31 +  def __init__(self, apk_path, jar_path):
    1.32 +    if not os.path.exists(apk_path):
    1.33 +      raise Exception('%s not found, please build it' % apk_path)
    1.34 +    self._apk_path = apk_path
    1.35 +    if not os.path.exists(jar_path):
    1.36 +      raise Exception('%s not found, please build it' % jar_path)
    1.37 +    self._jar_path = jar_path
    1.38 +    self._annotation_map = collections.defaultdict(list)
    1.39 +    self._test_methods = []
    1.40 +    self._Initialize()
    1.41 +
    1.42 +  def _Initialize(self):
    1.43 +    proguard_output = cmd_helper.GetCmdOutput([self._PROGUARD_PATH,
    1.44 +                                               '-injars', self._jar_path,
    1.45 +                                               '-dontshrink',
    1.46 +                                               '-dontoptimize',
    1.47 +                                               '-dontobfuscate',
    1.48 +                                               '-dontpreverify',
    1.49 +                                               '-dump',
    1.50 +                                              ]).split('\n')
    1.51 +    clazz = None
    1.52 +    method = None
    1.53 +    annotation = None
    1.54 +    has_value = False
    1.55 +    qualified_method = None
    1.56 +    for line in proguard_output:
    1.57 +      m = self._PROGUARD_CLASS_RE.match(line)
    1.58 +      if m:
    1.59 +        clazz = m.group(1).replace('/', '.')  # Change package delim.
    1.60 +        annotation = None
    1.61 +        continue
    1.62 +      m = self._PROGUARD_METHOD_RE.match(line)
    1.63 +      if m:
    1.64 +        method = m.group(1)
    1.65 +        annotation = None
    1.66 +        qualified_method = clazz + '#' + method
    1.67 +        if method.startswith('test') and clazz.endswith('Test'):
    1.68 +          self._test_methods += [qualified_method]
    1.69 +        continue
    1.70 +      m = self._PROGUARD_ANNOTATION_RE.match(line)
    1.71 +      if m:
    1.72 +        assert qualified_method
    1.73 +        annotation = m.group(1).split('/')[-1]  # Ignore the annotation package.
    1.74 +        self._annotation_map[qualified_method].append(annotation)
    1.75 +        has_value = False
    1.76 +        continue
    1.77 +      if annotation:
    1.78 +        assert qualified_method
    1.79 +        if not has_value:
    1.80 +          m = self._PROGUARD_ANNOTATION_CONST_RE.match(line)
    1.81 +          if m:
    1.82 +            has_value = True
    1.83 +        else:
    1.84 +          m = self._PROGUARD_ANNOTATION_VALUE_RE.match(line)
    1.85 +          if m:
    1.86 +            value = m.group(1)
    1.87 +            self._annotation_map[qualified_method].append(
    1.88 +                annotation + ':' + value)
    1.89 +            has_value = False
    1.90 +
    1.91 +  def _GetAnnotationMap(self):
    1.92 +    return self._annotation_map
    1.93 +
    1.94 +  def _IsTestMethod(self, test):
    1.95 +    class_name, method = test.split('#')
    1.96 +    return class_name.endswith('Test') and method.startswith('test')
    1.97 +
    1.98 +  def GetApkPath(self):
    1.99 +    return self._apk_path
   1.100 +
   1.101 +  def GetPackageName(self):
   1.102 +    """Returns the package name of this APK."""
   1.103 +    aapt_output = cmd_helper.GetCmdOutput(
   1.104 +        ['aapt', 'dump', 'badging', self._apk_path]).split('\n')
   1.105 +    for line in aapt_output:
   1.106 +      m = self._AAPT_PACKAGE_NAME_RE.match(line)
   1.107 +      if m:
   1.108 +        return m.group(1)
   1.109 +    raise Exception('Failed to determine package name of %s' % self._apk_path)
   1.110 +
   1.111 +  def GetTestAnnotations(self, test):
   1.112 +    """Returns a list of all annotations for the given |test|. May be empty."""
   1.113 +    if not self._IsTestMethod(test):
   1.114 +      return []
   1.115 +    return self._GetAnnotationMap()[test]
   1.116 +
   1.117 +  def _AnnotationsMatchFilters(self, annotation_filter_list, annotations):
   1.118 +    """Checks if annotations match any of the filters."""
   1.119 +    if not annotation_filter_list:
   1.120 +      return True
   1.121 +    for annotation_filter in annotation_filter_list:
   1.122 +      filters = annotation_filter.split('=')
   1.123 +      if len(filters) == 2:
   1.124 +        key = filters[0]
   1.125 +        value_list = filters[1].split(',')
   1.126 +        for value in value_list:
   1.127 +          if key + ':' + value in annotations:
   1.128 +            return True
   1.129 +      elif annotation_filter in annotations:
   1.130 +        return True
   1.131 +    return False
   1.132 +
   1.133 +  def GetAnnotatedTests(self, annotation_filter_list):
   1.134 +    """Returns a list of all tests that match the given annotation filters."""
   1.135 +    return [test for test, annotations in self._GetAnnotationMap().iteritems()
   1.136 +            if self._IsTestMethod(test) and self._AnnotationsMatchFilters(
   1.137 +                annotation_filter_list, annotations)]
   1.138 +
   1.139 +  def GetTestMethods(self):
   1.140 +    """Returns a list of all test methods in this apk as Class#testMethod."""
   1.141 +    return self._test_methods
   1.142 +
   1.143 +  @staticmethod
   1.144 +  def IsPythonDrivenTest(test):
   1.145 +    return 'pythonDrivenTests' in test

mercurial