| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # Copyright 2016 The Chromium Authors. All rights reserved. | 2 # Copyright 2016 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """api_static_checks.py - Check Cronet implementation does not call through | 6 """api_static_checks.py - Enforce Cronet API requirements.""" |
| 7 API classes. | |
| 8 """ | |
| 9 | 7 |
| 10 import argparse | 8 import argparse |
| 11 import os | 9 import os |
| 12 import re | 10 import re |
| 13 import shutil | 11 import shutil |
| 14 import sys | 12 import sys |
| 15 import tempfile | 13 import tempfile |
| 16 | 14 |
| 17 REPOSITORY_ROOT = os.path.abspath(os.path.join( | 15 REPOSITORY_ROOT = os.path.abspath(os.path.join( |
| 18 os.path.dirname(__file__), '..', '..', '..')) | 16 os.path.dirname(__file__), '..', '..', '..')) |
| 19 | 17 |
| 20 sys.path.append(os.path.join(REPOSITORY_ROOT, 'build/android/gyp/util')) | 18 sys.path.append(os.path.join(REPOSITORY_ROOT, 'build/android/gyp/util')) |
| 21 import build_utils | 19 import build_utils |
| 22 | 20 |
| 21 sys.path.append(os.path.join(REPOSITORY_ROOT, 'components')) |
| 22 from cronet.tools import update_api |
| 23 |
| 24 |
| 23 # These regular expressions catch the beginning of lines that declare classes | 25 # These regular expressions catch the beginning of lines that declare classes |
| 24 # and methods. The first group returned by a match is the class or method name. | 26 # and methods. The first group returned by a match is the class or method name. |
| 25 CLASS_RE = re.compile(r'.*class ([^ ]*) .*\{') | 27 from cronet.tools.update_api import CLASS_RE |
| 26 METHOD_RE = re.compile(r'.* ([^ ]*)\(.*\);') | 28 METHOD_RE = re.compile(r'.* ([^ ]*)\(.*\);') |
| 27 | 29 |
| 28 # Allowed exceptions. Adding anything to this list is dangerous and should be | 30 # Allowed exceptions. Adding anything to this list is dangerous and should be |
| 29 # avoided if possible. For now these exceptions are for APIs that existed in | 31 # avoided if possible. For now these exceptions are for APIs that existed in |
| 30 # the first version of Cronet and will be supported forever. | 32 # the first version of Cronet and will be supported forever. |
| 31 # TODO(pauljensen): Remove these. | 33 # TODO(pauljensen): Remove these. |
| 32 ALLOWED_EXCEPTIONS = [ | 34 ALLOWED_EXCEPTIONS = [ |
| 33 'org.chromium.net.impl.CronetEngineBuilderImpl/build ->' | 35 'org.chromium.net.impl.CronetEngineBuilderImpl/build ->' |
| 34 ' org/chromium/net/ExperimentalCronetEngine/getVersionString:' | 36 ' org/chromium/net/ExperimentalCronetEngine/getVersionString:' |
| 35 '()Ljava/lang/String;', | 37 '()Ljava/lang/String;', |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 # Ignore VersionSafe calls | 99 # Ignore VersionSafe calls |
| 98 if 'VersionSafeCallbacks' in caller_class: | 100 if 'VersionSafeCallbacks' in caller_class: |
| 99 continue | 101 continue |
| 100 bad_call = '%s/%s -> %s/%s' % (caller_class, caller_method, | 102 bad_call = '%s/%s -> %s/%s' % (caller_class, caller_method, |
| 101 callee_class, callee_method) | 103 callee_class, callee_method) |
| 102 if bad_call in ALLOWED_EXCEPTIONS: | 104 if bad_call in ALLOWED_EXCEPTIONS: |
| 103 continue | 105 continue |
| 104 bad_calls += [bad_call] | 106 bad_calls += [bad_call] |
| 105 | 107 |
| 106 | 108 |
| 107 def main(args): | 109 def check_api_calls(opts): |
| 108 # Returns True if no calls through API classes in implementation. | 110 # Returns True if no calls through API classes in implementation. |
| 109 | 111 |
| 110 parser = argparse.ArgumentParser( | |
| 111 description='Check modules do not contain ARM Neon instructions.') | |
| 112 parser.add_argument('--api_jar', | |
| 113 help='Path to API jar (i.e. cronet_api.jar)', | |
| 114 required=True, | |
| 115 metavar='path/to/cronet_api.jar') | |
| 116 parser.add_argument('--impl_jar', | |
| 117 help='Path to implementation jar ' | |
| 118 '(i.e. cronet_impl_native_java.jar)', | |
| 119 required=True, | |
| 120 metavar='path/to/cronet_impl_native_java.jar', | |
| 121 action='append') | |
| 122 parser.add_argument('--stamp', help='Path to touch on success.') | |
| 123 opts = parser.parse_args(args) | |
| 124 | |
| 125 temp_dir = tempfile.mkdtemp() | 112 temp_dir = tempfile.mkdtemp() |
| 126 | 113 |
| 127 # Extract API class files from jar | 114 # Extract API class files from jar |
| 128 jar_cmd = ['jar', 'xf', os.path.abspath(opts.api_jar)] | 115 jar_cmd = ['jar', 'xf', os.path.abspath(opts.api_jar)] |
| 129 build_utils.CheckOutput(jar_cmd, cwd=temp_dir) | 116 build_utils.CheckOutput(jar_cmd, cwd=temp_dir) |
| 130 shutil.rmtree(os.path.join(temp_dir, 'META-INF')) | 117 shutil.rmtree(os.path.join(temp_dir, 'META-INF')) |
| 131 | 118 |
| 132 # Collect names of API classes | 119 # Collect names of API classes |
| 133 api_classes = [] | 120 api_classes = [] |
| 134 for dirpath, _, filenames in os.walk(temp_dir): | 121 for dirpath, _, filenames in os.walk(temp_dir): |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 167 find_api_calls(dump, api_classes, bad_api_calls) | 154 find_api_calls(dump, api_classes, bad_api_calls) |
| 168 | 155 |
| 169 shutil.rmtree(temp_dir) | 156 shutil.rmtree(temp_dir) |
| 170 | 157 |
| 171 if bad_api_calls: | 158 if bad_api_calls: |
| 172 print 'ERROR: Found the following calls from implementation classes through' | 159 print 'ERROR: Found the following calls from implementation classes through' |
| 173 print ' API classes. These could fail if older API is used that' | 160 print ' API classes. These could fail if older API is used that' |
| 174 print ' does not contain newer methods. Please call through a' | 161 print ' does not contain newer methods. Please call through a' |
| 175 print ' wrapper class from VersionSafeCallbacks.' | 162 print ' wrapper class from VersionSafeCallbacks.' |
| 176 print '\n'.join(bad_api_calls) | 163 print '\n'.join(bad_api_calls) |
| 177 | |
| 178 if not bad_api_calls and opts.stamp: | |
| 179 build_utils.Touch(opts.stamp) | |
| 180 return not bad_api_calls | 164 return not bad_api_calls |
| 181 | 165 |
| 182 | 166 |
| 167 def check_api_version(opts): |
| 168 if update_api.check_up_to_date(opts.api_jar): |
| 169 return True |
| 170 print 'ERROR: API file out of date. Please run this command:' |
| 171 print ' components/cronet/tools/update_api.py --api_jar %s' % ( |
| 172 os.path.abspath(opts.api_jar)) |
| 173 return False |
| 174 |
| 175 |
| 176 def main(args): |
| 177 parser = argparse.ArgumentParser( |
| 178 description='Enforce Cronet API requirements.') |
| 179 parser.add_argument('--api_jar', |
| 180 help='Path to API jar (i.e. cronet_api.jar)', |
| 181 required=True, |
| 182 metavar='path/to/cronet_api.jar') |
| 183 parser.add_argument('--impl_jar', |
| 184 help='Path to implementation jar ' |
| 185 '(i.e. cronet_impl_native_java.jar)', |
| 186 required=True, |
| 187 metavar='path/to/cronet_impl_native_java.jar', |
| 188 action='append') |
| 189 parser.add_argument('--stamp', help='Path to touch on success.') |
| 190 opts = parser.parse_args(args) |
| 191 |
| 192 ret = True |
| 193 ret = check_api_calls(opts) and ret |
| 194 ret = check_api_version(opts) and ret |
| 195 if ret and opts.stamp: |
| 196 build_utils.Touch(opts.stamp) |
| 197 return ret |
| 198 |
| 199 |
| 183 if __name__ == '__main__': | 200 if __name__ == '__main__': |
| 184 sys.exit(0 if main(sys.argv[1:]) else -1) | 201 sys.exit(0 if main(sys.argv[1:]) else -1) |
| OLD | NEW |