Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 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 """Gathers information about APKs.""" | 5 """Gathers information about APKs.""" |
| 6 | 6 |
| 7 import collections | 7 import collections |
| 8 import logging | |
| 8 import os | 9 import os |
| 10 import pickle | |
| 9 import re | 11 import re |
| 10 | 12 |
| 11 import cmd_helper | 13 import cmd_helper |
| 12 | 14 |
| 15 # If you change the cached output of proguard, increment this number | |
| 16 PICKLE_FORMAT_VERSION = 1 | |
| 13 | 17 |
| 14 def GetPackageNameForApk(apk_path): | 18 def GetPackageNameForApk(apk_path): |
| 15 """Returns the package name of the apk file.""" | 19 """Returns the package name of the apk file.""" |
| 16 aapt_output = cmd_helper.GetCmdOutput( | 20 aapt_output = cmd_helper.GetCmdOutput( |
| 17 ['aapt', 'dump', 'badging', apk_path]).split('\n') | 21 ['aapt', 'dump', 'badging', apk_path]).split('\n') |
| 18 package_name_re = re.compile(r'package: .*name=\'(\S*)\'') | 22 package_name_re = re.compile(r'package: .*name=\'(\S*)\'') |
| 19 for line in aapt_output: | 23 for line in aapt_output: |
| 20 m = package_name_re.match(line) | 24 m = package_name_re.match(line) |
| 21 if m: | 25 if m: |
| 22 return m.group(1) | 26 return m.group(1) |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 43 raise Exception('%s not found, please build it' % apk_path) | 47 raise Exception('%s not found, please build it' % apk_path) |
| 44 self._apk_path = apk_path | 48 self._apk_path = apk_path |
| 45 if not os.path.exists(jar_path): | 49 if not os.path.exists(jar_path): |
| 46 raise Exception('%s not found, please build it' % jar_path) | 50 raise Exception('%s not found, please build it' % jar_path) |
| 47 self._jar_path = jar_path | 51 self._jar_path = jar_path |
| 48 self._annotation_map = collections.defaultdict(list) | 52 self._annotation_map = collections.defaultdict(list) |
| 49 self._test_methods = [] | 53 self._test_methods = [] |
| 50 self._Initialize() | 54 self._Initialize() |
| 51 | 55 |
| 52 def _Initialize(self): | 56 def _Initialize(self): |
| 57 pickle_name = self._jar_path + "-proguard.pickle" | |
|
frankf
2012/11/22 03:03:48
single quotes here and below.
Yaron
2012/11/26 18:26:15
Done.
| |
| 58 if os.path.exists(pickle_name) and (os.stat(pickle_name).st_mtime > | |
| 59 os.stat(self._jar_path).st_mtime): | |
|
frankf
2012/11/22 03:03:48
os.path.getmtime() is slightly preferred.
Yaron
2012/11/26 18:26:15
Done.
| |
| 60 logging.info("Loading cached proguard output from %s", pickle_name) | |
|
bulach
2012/11/22 13:51:20
see below, probably best as:
try:
with open(pick
Yaron
2012/11/26 18:26:15
Done.
| |
| 61 unpickler = pickle.Unpickler(open(pickle_name)) | |
| 62 if PICKLE_FORMAT_VERSION == unpickler.load(): | |
|
bulach
2012/11/22 13:51:20
prefer to pickle one dict, see below..
Yaron
2012/11/26 18:26:15
Done.
| |
| 63 self._annotation_map = unpickler.load() | |
| 64 self._test_methods = unpickler.load() | |
| 65 return | |
| 66 else: | |
| 67 logging.warning("PICKLE_FORMAT_VERSION has changed, ignoring cache") | |
|
frankf
2012/11/22 03:03:48
Can you put this in a finally block with above lin
Yaron
2012/11/26 18:26:15
Done.
| |
| 68 | |
| 53 proguard_output = cmd_helper.GetCmdOutput([self._PROGUARD_PATH, | 69 proguard_output = cmd_helper.GetCmdOutput([self._PROGUARD_PATH, |
| 54 '-injars', self._jar_path, | 70 '-injars', self._jar_path, |
| 55 '-dontshrink', | 71 '-dontshrink', |
| 56 '-dontoptimize', | 72 '-dontoptimize', |
| 57 '-dontobfuscate', | 73 '-dontobfuscate', |
| 58 '-dontpreverify', | 74 '-dontpreverify', |
| 59 '-dump', | 75 '-dump', |
| 60 ]).split('\n') | 76 ]).split('\n') |
| 61 clazz = None | 77 clazz = None |
| 62 method = None | 78 method = None |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 91 if m: | 107 if m: |
| 92 has_value = True | 108 has_value = True |
| 93 else: | 109 else: |
| 94 m = self._PROGUARD_ANNOTATION_VALUE_RE.match(line) | 110 m = self._PROGUARD_ANNOTATION_VALUE_RE.match(line) |
| 95 if m: | 111 if m: |
| 96 value = m.group(1) | 112 value = m.group(1) |
| 97 self._annotation_map[qualified_method].append( | 113 self._annotation_map[qualified_method].append( |
| 98 annotation + ':' + value) | 114 annotation + ':' + value) |
| 99 has_value = False | 115 has_value = False |
| 100 | 116 |
| 117 logging.info("Storing proguard output to %s", pickle_name) | |
| 118 pickler = pickle.Pickler(open(pickle_name, 'w')) | |
|
bulach
2012/11/22 13:51:20
pickle.dumps with a dict works better, no need for
Yaron
2012/11/26 18:26:15
Done.
| |
| 119 pickler.dump(PICKLE_FORMAT_VERSION) | |
| 120 pickler.dump(self._annotation_map) | |
| 121 pickler.dump(self._test_methods) | |
| 122 | |
| 101 def _GetAnnotationMap(self): | 123 def _GetAnnotationMap(self): |
| 102 return self._annotation_map | 124 return self._annotation_map |
| 103 | 125 |
| 104 def _IsTestMethod(self, test): | 126 def _IsTestMethod(self, test): |
| 105 class_name, method = test.split('#') | 127 class_name, method = test.split('#') |
| 106 return class_name.endswith('Test') and method.startswith('test') | 128 return class_name.endswith('Test') and method.startswith('test') |
| 107 | 129 |
| 108 def GetApkPath(self): | 130 def GetApkPath(self): |
| 109 return self._apk_path | 131 return self._apk_path |
| 110 | 132 |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 140 if self._IsTestMethod(test) and self._AnnotationsMatchFilters( | 162 if self._IsTestMethod(test) and self._AnnotationsMatchFilters( |
| 141 annotation_filter_list, annotations)] | 163 annotation_filter_list, annotations)] |
| 142 | 164 |
| 143 def GetTestMethods(self): | 165 def GetTestMethods(self): |
| 144 """Returns a list of all test methods in this apk as Class#testMethod.""" | 166 """Returns a list of all test methods in this apk as Class#testMethod.""" |
| 145 return self._test_methods | 167 return self._test_methods |
| 146 | 168 |
| 147 @staticmethod | 169 @staticmethod |
| 148 def IsPythonDrivenTest(test): | 170 def IsPythonDrivenTest(test): |
| 149 return 'pythonDrivenTests' in test | 171 return 'pythonDrivenTests' in test |
| OLD | NEW |