diff --git a/vndk/tools/definition-tool/tests/test_generic_refs.py b/vndk/tools/definition-tool/tests/test_generic_refs.py index 77f20bd67..dd59f8163 100755 --- a/vndk/tools/definition-tool/tests/test_generic_refs.py +++ b/vndk/tools/definition-tool/tests/test_generic_refs.py @@ -13,72 +13,91 @@ from compat import TemporaryDirectory, makedirs from vndk_definition_tool import GenericRefs -test_dir = None +test_dir_base = None + + +class MockELF(object): + def __init__(self, exported_symbols): + self.exported_symbols = exported_symbols + + +class MockLib(object): + def __init__(self, path, exported_symbols): + self.path = path + self.elf = MockELF(exported_symbols) + class GenericRefsTest(unittest.TestCase): - @classmethod - def setUpClass(cls): - if test_dir: - cls.test_dir = test_dir - else: - cls.tmp_dir = TemporaryDirectory() - cls.test_dir = cls.tmp_dir.name - - cls._build_fixtures() - - @classmethod - def tearDownClass(cls): - if not test_dir: - cls.tmp_dir.cleanup() - - @classmethod - def _build_fixture(cls, path, content): + def _build_file_fixture(self, path, content): makedirs(os.path.dirname(path), exist_ok=True) with open(path, 'w') as f: f.write(content) - @classmethod - def _build_fixtures(cls): - lib32 = os.path.join(cls.test_dir, 'system', 'lib') - lib64 = os.path.join(cls.test_dir, 'system', 'lib64') + def _build_dir_fixtures(self, test_dir): + lib32 = os.path.join(test_dir, 'system', 'lib') + lib64 = os.path.join(test_dir, 'system', 'lib64') for lib_dir in (lib32, lib64): - cls._build_fixture(os.path.join(lib_dir, 'libc.so.sym'), - 'fclose\nfopen\nfread\nfwrite\n') - cls._build_fixture(os.path.join(lib_dir, 'libm.so.sym'), - 'cos\nsin\ntan\n') + self._build_file_fixture(os.path.join(lib_dir, 'libc.so.sym'), + 'fclose\nfopen\nfread\nfwrite\n') + self._build_file_fixture(os.path.join(lib_dir, 'libm.so.sym'), + 'cos\nsin\ntan\n') + + def _build_fixture(self): + res = GenericRefs() + res.add('/system/lib/libc.so', {'fclose', 'fopen', 'fread', 'fwrite'}) + res.add('/system/lib/libm.so', {'cos', 'sin', 'tan'}) + res.add('/system/lib64/libc.so', {'fclose', 'fopen', 'fread', 'fwrite'}) + res.add('/system/lib64/libm.so', {'cos', 'sin', 'tan'}) + return res def test_create_from_dir(self): - g = GenericRefs.create_from_dir(self.test_dir) - self.assertEqual(4, len(g.refs)) + try: + if test_dir_base: + test_dir = test_dir_base + else: + tmp_dir = TemporaryDirectory() + test_dir = tmp_dir.name - self.assertIn('/system/lib/libc.so', g.refs) - self.assertIn('/system/lib/libm.so', g.refs) - self.assertIn('/system/lib64/libc.so', g.refs) - self.assertIn('/system/lib64/libm.so', g.refs) + self._build_dir_fixtures(test_dir) + g = GenericRefs.create_from_dir(test_dir) + self.assertEqual(4, len(g.refs)) - self.assertEqual({'fclose', 'fopen', 'fread', 'fwrite'}, - g.refs['/system/lib/libc.so']) - self.assertEqual({'fclose', 'fopen', 'fread', 'fwrite'}, - g.refs['/system/lib64/libc.so']) + self.assertIn('/system/lib/libc.so', g.refs) + self.assertIn('/system/lib/libm.so', g.refs) + self.assertIn('/system/lib64/libc.so', g.refs) + self.assertIn('/system/lib64/libm.so', g.refs) - self.assertEqual({'cos', 'sin', 'tan'}, - g.refs['/system/lib/libm.so']) - self.assertEqual({'cos', 'sin', 'tan'}, - g.refs['/system/lib64/libm.so']) + self.assertEqual({'fclose', 'fopen', 'fread', 'fwrite'}, + g.refs['/system/lib/libc.so']) + self.assertEqual({'fclose', 'fopen', 'fread', 'fwrite'}, + g.refs['/system/lib64/libc.so']) + self.assertEqual({'cos', 'sin', 'tan'}, + g.refs['/system/lib/libm.so']) + self.assertEqual({'cos', 'sin', 'tan'}, + g.refs['/system/lib64/libm.so']) + finally: + if not test_dir_base: + tmp_dir.cleanup() + + def test_classify_lib(self): + g = self._build_fixture() + + libc_sub = MockLib('/system/lib/libc.so', {'fclose', 'fopen', 'fread'}) + libc_sup = MockLib('/system/lib/libc.so', + {'fclose', 'fopen', 'fread', 'fwrite', 'open'}) + libc_eq = MockLib('/system/lib/libc.so', + {'fclose', 'fopen', 'fread', 'fwrite'}) + libfoo = MockLib('/system/lib/libfoo.so', {}) + + self.assertEqual(GenericRefs.MODIFIED, g.classify_lib(libc_sub)) + self.assertEqual(GenericRefs.EXPORT_SUPER_SET, g.classify_lib(libc_sup)) + self.assertEqual(GenericRefs.EXPORT_EQUAL, g.classify_lib(libc_eq)) + self.assertEqual(GenericRefs.NEW_LIB, g.classify_lib(libfoo)) def test_is_equivalent_lib(self): - g = GenericRefs.create_from_dir(self.test_dir) - - class MockELF(object): - def __init__(self, exported_symbols): - self.exported_symbols = exported_symbols - - class MockLib(object): - def __init__(self, path, exported_symbols): - self.path = path - self.elf = MockELF(exported_symbols) + g = self._build_fixture() libc_sub = MockLib('/system/lib/libc.so', {'fclose', 'fopen', 'fread'}) libc_sup = MockLib('/system/lib/libc.so', @@ -99,10 +118,10 @@ def main(): args, unittest_args = parser.parse_known_args() # Convert command line options. - global test_dir + global test_dir_base if args.test_dir: - test_dir = args.test_dir + test_dir_base = args.test_dir # Run unit test. unittest.main(argv=[sys.argv[0]] + unittest_args) diff --git a/vndk/tools/definition-tool/vndk_definition_tool.py b/vndk/tools/definition-tool/vndk_definition_tool.py index c74e69b45..1eeca88bc 100755 --- a/vndk/tools/definition-tool/vndk_definition_tool.py +++ b/vndk/tools/definition-tool/vndk_definition_tool.py @@ -864,9 +864,17 @@ class ELFLinker(object): #------------------------------------------------------------------------------ class GenericRefs(object): + NEW_LIB = 0 + EXPORT_EQUAL = 1 + EXPORT_SUPER_SET = 2 + MODIFIED = 3 + def __init__(self): self.refs = dict() + def add(self, name, symbols): + self.refs[name] = symbols + def _load_from_dir(self, root): root = os.path.abspath(root) prefix_len = len(root) + 1 @@ -877,7 +885,7 @@ class GenericRefs(object): path = os.path.join(base, filename) lib_name = '/' + path[prefix_len:-4] with open(path, 'r') as f: - self.refs[lib_name] = set(line.strip() for line in f) + self.add(lib_name, set(line.strip() for line in f)) @staticmethod def create_from_dir(root): @@ -885,8 +893,19 @@ class GenericRefs(object): result._load_from_dir(root) return result + def classify_lib(self, lib): + ref_lib_symbols = self.refs.get(lib.path) + if not ref_lib_symbols: + return GenericRefs.NEW_LIB + exported_symbols = lib.elf.exported_symbols + if exported_symbols == ref_lib_symbols: + return GenericRefs.EXPORT_EQUAL + if exported_symbols > ref_lib_symbols: + return GenericRefs.EXPORT_SUPER_SET + return GenericRefs.MODIFIED + def is_equivalent_lib(self, lib): - return self.refs.get(lib.path) == lib.elf.exported_symbols + return self.classify_lib(lib) == GenericRefs.EXPORT_EQUAL #------------------------------------------------------------------------------