Index: components/cronet/tools/api_static_checks_unittest.py |
diff --git a/components/cronet/tools/api_static_checks_unittest.py b/components/cronet/tools/api_static_checks_unittest.py |
index a6907e6dabbb43f1c7d46235a7853e5a3c6a4f95..db4f5c8d901a573a91f849c60a0cf61de5d21cff 100755 |
--- a/components/cronet/tools/api_static_checks_unittest.py |
+++ b/components/cronet/tools/api_static_checks_unittest.py |
@@ -14,10 +14,14 @@ import sys |
import tempfile |
import unittest |
-from tools import api_static_checks |
+REPOSITORY_ROOT = os.path.abspath(os.path.join( |
+ os.path.dirname(__file__), '..', '..', '..')) |
+sys.path.append(os.path.join(REPOSITORY_ROOT, 'components')) |
+from cronet.tools import api_static_checks |
-ERROR_PREFIX = ( |
+ |
+ERROR_PREFIX_CHECK_API_CALLS = ( |
"""ERROR: Found the following calls from implementation classes through |
API classes. These could fail if older API is used that |
does not contain newer methods. Please call through a |
@@ -25,6 +29,28 @@ ERROR_PREFIX = ( |
""") |
+ERROR_PREFIX_UPDATE_API = ( |
+"""ERROR: This API was modified or removed: |
+ """) |
+ |
+ |
+ERROR_SUFFIX_UPDATE_API = ( |
+""" |
+ |
+ Cronet API methods and classes cannot be modified. |
+""") |
+ |
+ |
+CHECK_API_VERSION_PREFIX = ( |
+"""DO NOT EDIT THIS FILE, USE update_api.py TO UPDATE IT |
+ |
+""") |
+ |
+ |
+API_FILENAME = './android/api.txt' |
+API_VERSION_FILENAME = './android/api_version.txt' |
+ |
+ |
@contextlib.contextmanager |
def capture_output(): |
# A contextmanger that collects the stdout and stderr of wrapped code |
@@ -44,6 +70,12 @@ class ApiStaticCheckUnitTest(unittest.TestCase): |
def setUp(self): |
self.temp_dir = tempfile.mkdtemp() |
os.chdir(self.temp_dir) |
+ os.mkdir('android') |
+ with open(API_VERSION_FILENAME, 'w') as api_version_file: |
+ api_version_file.write('0') |
+ with open(API_FILENAME, 'w') as api_file: |
+ api_file.write('}\n') |
+ shutil.copytree(os.path.dirname(__file__), 'tools') |
def tearDown(self): |
@@ -55,7 +87,7 @@ class ApiStaticCheckUnitTest(unittest.TestCase): |
# return jar filename. |
java_filename = class_name + '.java' |
- class_filename = class_name + '.class' |
+ class_filenames = class_name + '*.class' |
jar_filename = class_name + '.jar' |
with open(java_filename, 'w') as java_file: |
@@ -63,33 +95,141 @@ class ApiStaticCheckUnitTest(unittest.TestCase): |
java_file.write(java) |
java_file.write('}') |
os.system('javac %s' % java_filename) |
- os.system('jar cf %s %s' % (jar_filename, class_filename)) |
+ os.system('jar cf %s %s' % (jar_filename, class_filenames)) |
return jar_filename |
- def run_test(self, api_java, impl_java): |
- api_jar = self.make_jar(api_java, 'Api') |
- impl_jar = self.make_jar(impl_java, 'Impl') |
+ def run_check_api_calls(self, api_java, impl_java): |
+ test = self |
+ class MockOpts(object): |
+ def __init__(self): |
+ self.api_jar = test.make_jar(api_java, 'Api') |
+ self.impl_jar = [test.make_jar(impl_java, 'Impl')] |
+ opts = MockOpts() |
with capture_output() as return_output: |
- return_code = api_static_checks.main( |
- ['--api_jar', api_jar, '--impl_jar', impl_jar]) |
+ return_code = api_static_checks.check_api_calls(opts) |
return [return_code, return_output[0]] |
- def test_success(self): |
+ def test_check_api_calls_success(self): |
# Test simple classes with functions |
- self.assertEqual(self.run_test('void a(){}', 'void b(){}'), [True, '']) |
+ self.assertEqual(self.run_check_api_calls( |
+ 'void a(){}', 'void b(){}'), [True, '']) |
# Test simple classes with functions calling themselves |
- self.assertEqual(self.run_test( |
+ self.assertEqual(self.run_check_api_calls( |
'void a(){} void b(){a();}', 'void c(){} void d(){c();}'), [True, '']) |
- def test_failure(self): |
+ def test_check_api_calls_failure(self): |
# Test static call |
- self.assertEqual(self.run_test( |
+ self.assertEqual(self.run_check_api_calls( |
'public static void a(){}', 'void b(){Api.a();}'), |
- [False, ERROR_PREFIX + 'Impl/b -> Api/a:()V\n']) |
+ [False, ERROR_PREFIX_CHECK_API_CALLS + 'Impl/b -> Api/a:()V\n']) |
# Test virtual call |
- self.assertEqual(self.run_test( |
+ self.assertEqual(self.run_check_api_calls( |
'public void a(){}', 'void b(){new Api().a();}'), |
- [False, ERROR_PREFIX + 'Impl/b -> Api/a:()V\n']) |
+ [False, ERROR_PREFIX_CHECK_API_CALLS + 'Impl/b -> Api/a:()V\n']) |
+ |
+ |
+ def run_check_api_version(self, java): |
+ OUT_FILENAME = 'out.txt' |
+ return_code = os.system('./tools/update_api.py --api_jar %s > %s' % |
+ (self.make_jar(java, 'Api'), OUT_FILENAME)) |
+ with open(API_FILENAME, 'r') as api_file: |
+ api = api_file.read() |
+ with open(API_VERSION_FILENAME, 'r') as api_version_file: |
+ api_version = api_version_file.read() |
+ with open(OUT_FILENAME, 'r') as out_file: |
+ output = out_file.read() |
+ return [return_code == 0, output, api, api_version] |
+ |
+ |
+ def test_update_api_success(self): |
+ # Test simple new API |
+ self.assertEqual(self.run_check_api_version( |
+ 'public void a(){}'), |
+ [True, '', CHECK_API_VERSION_PREFIX + """public class Api { |
+ public Api(); |
+ public void a(); |
+} |
+""", '1']) |
+ # Test version number not increased when API not changed |
+ self.assertEqual(self.run_check_api_version( |
+ 'public void a(){}'), |
+ [True, '', CHECK_API_VERSION_PREFIX + """public class Api { |
+ public Api(); |
+ public void a(); |
+} |
+""", '1']) |
+ # Test acceptable API method addition |
+ self.assertEqual(self.run_check_api_version( |
+ 'public void a(){} public void b(){}'), |
+ [True, '', CHECK_API_VERSION_PREFIX + """public class Api { |
+ public Api(); |
+ public void a(); |
+ public void b(); |
+} |
+""", '2']) |
+ # Test version number not increased when API not changed |
+ self.assertEqual(self.run_check_api_version( |
+ 'public void a(){} public void b(){}'), |
+ [True, '', CHECK_API_VERSION_PREFIX + """public class Api { |
+ public Api(); |
+ public void a(); |
+ public void b(); |
+} |
+""", '2']) |
+ # Test acceptable API class addition |
+ self.assertEqual(self.run_check_api_version( |
+ 'public void a(){} public void b(){} public class C {}'), |
+ [True, '', CHECK_API_VERSION_PREFIX + """public class Api$C { |
+ public Api$C(Api); |
+} |
+public class Api { |
+ public Api(); |
+ public void a(); |
+ public void b(); |
+} |
+""", '3']) |
+ # Test version number not increased when API not changed |
+ self.assertEqual(self.run_check_api_version( |
+ 'public void a(){} public void b(){} public class C {}'), |
+ [True, '', CHECK_API_VERSION_PREFIX + """public class Api$C { |
+ public Api$C(Api); |
+} |
+public class Api { |
+ public Api(); |
+ public void a(); |
+ public void b(); |
+} |
+""", '3']) |
+ |
+ |
+ def test_update_api_failure(self): |
+ # Create a simple new API |
+ self.assertEqual(self.run_check_api_version( |
+ 'public void a(){}'), |
+ [True, '', CHECK_API_VERSION_PREFIX + """public class Api { |
+ public Api(); |
+ public void a(); |
+} |
+""", '1']) |
+ # Test removing API method not allowed |
+ self.assertEqual(self.run_check_api_version(''), |
+ [False, ERROR_PREFIX_UPDATE_API + 'public void a();' |
+ + ERROR_SUFFIX_UPDATE_API, |
+ CHECK_API_VERSION_PREFIX + """public class Api { |
+ public Api(); |
+ public void a(); |
+} |
+""", '1']) |
+ # Test modifying API method not allowed |
+ self.assertEqual(self.run_check_api_version( |
+ 'public void a(int x){}'), |
+ [False, ERROR_PREFIX_UPDATE_API + 'public void a();' |
+ + ERROR_SUFFIX_UPDATE_API, |
+ CHECK_API_VERSION_PREFIX + """public class Api { |
+ public Api(); |
+ public void a(); |
+} |
+""", '1']) |