diff --git a/vndk/tools/header-checker/tests/gen_all.py b/vndk/tools/header-checker/tests/gen_all.py index 7b4f5d893..e0e7122c4 100755 --- a/vndk/tools/header-checker/tests/gen_all.py +++ b/vndk/tools/header-checker/tests/gen_all.py @@ -12,6 +12,7 @@ from utils import run_header_abi_dumper from module import Module from test import INPUT_DIR from test import EXPECTED_DIR +from test import EXPORTED_HEADER_DIRS from test import make_and_copy_reference_dumps FILE_EXTENSIONS = ['h', 'hpp', 'hxx', 'cpp', 'cc', 'c'] @@ -34,11 +35,10 @@ def main(): output_path = os.path.join(EXPECTED_DIR, input_rel_path) print('generating', output_path, '...') - output_content = run_header_abi_dumper(input_path) - os.makedirs(os.path.dirname(output_path), exist_ok=True) - with open(output_path, 'w') as f: - f.write(output_content) + run_header_abi_dumper(input_path, output_path, + export_include_dirs=EXPORTED_HEADER_DIRS) + modules = Module.get_test_modules() for module in modules: print('Created abi dump at', make_and_copy_reference_dumps(module)) diff --git a/vndk/tools/header-checker/tests/module.py b/vndk/tools/header-checker/tests/module.py index d0ba0c2f4..d97585c4d 100755 --- a/vndk/tools/header-checker/tests/module.py +++ b/vndk/tools/header-checker/tests/module.py @@ -49,8 +49,8 @@ class Module(object): """Returns the module name followed by file extension.""" raise NotImplementedError() - def make_dump(self): - """Returns the dump content as a string.""" + def make_dump(self, output_path): + """Create a dump file.""" raise NotImplementedError() def mutate_for_arch(self, target_arch): @@ -88,9 +88,9 @@ class SdumpModule(Module): def get_dump_name(self): return self.name + '.sdump' - def make_dump(self): + def make_dump(self, output_path): return run_header_abi_dumper( - self.src, cflags=self.cflags, + self.src, output_path, cflags=self.cflags, export_include_dirs=self.export_include_dirs, flags=self.dumper_flags) @@ -114,25 +114,29 @@ class LsdumpModule(Module): def get_dump_name(self): return self.name + SOURCE_ABI_DUMP_EXT - def make_dump(self): + def make_dump(self, output_path): """For each source file, produce a .sdump file, and link them to form an lsump file.""" dumps_to_link = [] with tempfile.TemporaryDirectory() as tmp: - output_lsdump = os.path.join(tmp, self.get_dump_name()) for src in self.srcs: - output_path = os.path.join(tmp, - os.path.basename(src) + '.sdump') - dumps_to_link.append(output_path) - content = run_header_abi_dumper( - src, self.cflags + self.arch_cflags, + sdump_path = os.path.join(tmp, + os.path.basename(src) + '.sdump') + dumps_to_link.append(sdump_path) + run_header_abi_dumper( + src, sdump_path, self.cflags + self.arch_cflags, self.export_include_dirs, self.dumper_flags) - with open(output_path, 'w') as dump_file: - dump_file.write(content) - return run_header_abi_linker(output_lsdump, dumps_to_link, - self.version_script, self.api, - self.arch, self.linker_flags, - input_dir=tmp) + + lsdump_path = os.path.join(tmp, self.get_dump_name()) + run_header_abi_linker(dumps_to_link, lsdump_path, + self.version_script, self.api, self.arch, + self.linker_flags) + # Replace the absolute tmp paths in the type ID. + with open(lsdump_path, 'r') as lsdump_file: + content = lsdump_file.read().replace(tmp, '') + + with open(output_path, 'w') as output_file: + output_file.write(content) def mutate_for_arch(self, target_arch): return LsdumpModule(self.name, self.srcs, self.version_script, diff --git a/vndk/tools/header-checker/tests/test.py b/vndk/tools/header-checker/tests/test.py index 4d7b551d2..f4718843b 100755 --- a/vndk/tools/header-checker/tests/test.py +++ b/vndk/tools/header-checker/tests/test.py @@ -11,30 +11,30 @@ import_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) import_path = os.path.abspath(os.path.join(import_path, 'utils')) sys.path.insert(1, import_path) -from utils import (AOSP_DIR, read_output_content, run_abi_diff, - run_header_abi_dumper) +from utils import run_abi_diff, run_header_abi_dumper from module import Module SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__)) INPUT_DIR = os.path.join(SCRIPT_DIR, 'input') EXPECTED_DIR = os.path.join(SCRIPT_DIR, 'expected') +EXPORTED_HEADER_DIRS = (INPUT_DIR,) REF_DUMP_DIR = os.path.join(SCRIPT_DIR, 'reference_dumps') def make_and_copy_reference_dumps(module, reference_dump_dir=REF_DUMP_DIR): - output_content = module.make_dump() - dump_dir = os.path.join(reference_dump_dir, module.arch) os.makedirs(dump_dir, exist_ok=True) - dump_path = os.path.join(dump_dir, module.get_dump_name()) - with open(dump_path, 'w') as f: - f.write(output_content) - + module.make_dump(dump_path) return dump_path +def _read_output_content(dump_path): + with open(dump_path, 'r') as f: + return f.read() + + class HeaderCheckerTest(unittest.TestCase): @classmethod def setUpClass(cls): @@ -56,7 +56,12 @@ class HeaderCheckerTest(unittest.TestCase): def run_and_compare(self, input_path, expected_path, cflags=[]): with open(expected_path, 'r') as f: expected_output = f.read() - actual_output = run_header_abi_dumper(input_path, cflags) + with tempfile.NamedTemporaryFile(dir=self.get_tmp_dir(), + delete=False) as f: + output_path = f.name + run_header_abi_dumper(input_path, output_path, cflags, + EXPORTED_HEADER_DIRS) + actual_output = _read_output_content(output_path) self.assertEqual(actual_output, expected_output) def run_and_compare_name(self, name, cflags=[]): @@ -113,9 +118,8 @@ class HeaderCheckerTest(unittest.TestCase): self.assertEqual(old_module.arch, new_module.arch) old_ref_dump_path = self.get_or_create_ref_dump(old_module, False) new_ref_dump_path = self.get_or_create_ref_dump(new_module, True) - self.assertEqual( - read_output_content(old_ref_dump_path, AOSP_DIR), - read_output_content(new_ref_dump_path, AOSP_DIR)) + self.assertEqual(_read_output_content(old_ref_dump_path), + _read_output_content(new_ref_dump_path)) def test_example1_cpp(self): self.run_and_compare_name_cpp('example1.cpp') diff --git a/vndk/tools/header-checker/utils/utils.py b/vndk/tools/header-checker/utils/utils.py index d14320be4..9256e1800 100644 --- a/vndk/tools/header-checker/utils/utils.py +++ b/vndk/tools/header-checker/utils/utils.py @@ -2,6 +2,7 @@ import gzip import os +import shutil import subprocess import sys import tempfile @@ -24,11 +25,6 @@ BUILTIN_HEADERS_DIR = ( 'clang-headers'), ) -EXPORTED_HEADERS_DIR = ( - os.path.join(AOSP_DIR, 'development', 'vndk', 'tools', 'header-checker', - 'tests'), -) - SO_EXT = '.so' SOURCE_ABI_DUMP_EXT_END = '.lsdump' SOURCE_ABI_DUMP_EXT = SO_EXT + SOURCE_ABI_DUMP_EXT_END @@ -80,43 +76,33 @@ class Target(object): return self.get_arch_str() + cpu_variant +def _validate_dump_content(dump_path): + """Make sure that the dump contains relative source paths.""" + with open(dump_path, 'r') as f: + if AOSP_DIR in f.read(): + raise ValueError( + dump_path + ' contains absolute path to $ANDROID_BUILD_TOP.') + + def copy_reference_dump(lib_path, reference_dump_dir, compress): reference_dump_path = os.path.join( reference_dump_dir, os.path.basename(lib_path)) if compress: reference_dump_path += '.gz' os.makedirs(os.path.dirname(reference_dump_path), exist_ok=True) - output_content = read_output_content(lib_path, AOSP_DIR) + _validate_dump_content(lib_path) if compress: - with gzip.open(reference_dump_path, 'wb') as f: - f.write(bytes(output_content, 'utf-8')) + with open(lib_path, 'rb') as src_file: + with gzip.open(reference_dump_path, 'wb') as dst_file: + shutil.copyfileobj(src_file, dst_file) else: - with open(reference_dump_path, 'wb') as f: - f.write(bytes(output_content, 'utf-8')) + shutil.copyfile(lib_path, reference_dump_path) print('Created abi dump at', reference_dump_path) return reference_dump_path -def read_output_content(output_path, replace_str): - with open(output_path, 'r') as f: - return f.read().replace(replace_str, '') - - -def run_header_abi_dumper(input_path, cflags=tuple(), - export_include_dirs=EXPORTED_HEADERS_DIR, - flags=tuple()): - """Run header-abi-dumper to dump ABI from `input_path` and return the - output.""" - with tempfile.TemporaryDirectory() as tmp: - output_path = os.path.join(tmp, os.path.basename(input_path)) + '.dump' - _run_header_abi_dumper_on_file(input_path, output_path, - export_include_dirs, cflags, flags) - return read_output_content(output_path, AOSP_DIR) - - -def _run_header_abi_dumper_on_file(input_path, output_path, - export_include_dirs=tuple(), cflags=tuple(), - flags=tuple()): +def run_header_abi_dumper(input_path, output_path, cflags=tuple(), + export_include_dirs=tuple(), flags=tuple()): """Run header-abi-dumper to dump ABI from `input_path` and the output is written to `output_path`.""" input_ext = os.path.splitext(input_path)[1] @@ -141,10 +127,11 @@ def _run_header_abi_dumper_on_file(input_path, output_path, for dir in export_include_dirs: cmd += ['-I', dir] subprocess.check_call(cmd, cwd=AOSP_DIR) + _validate_dump_content(output_path) -def run_header_abi_linker(output_path, inputs, version_script, api, arch, - flags=tuple(), input_dir=AOSP_DIR): +def run_header_abi_linker(inputs, output_path, version_script, api, arch, + flags=tuple()): """Link inputs, taking version_script into account""" cmd = ['header-abi-linker', '-o', output_path, '-v', version_script, '-api', api, '-arch', arch] @@ -155,7 +142,7 @@ def run_header_abi_linker(output_path, inputs, version_script, api, arch, cmd += ['-output-format', DEFAULT_FORMAT] cmd += inputs subprocess.check_call(cmd, cwd=AOSP_DIR) - return read_output_content(output_path, input_dir) + _validate_dump_content(output_path) def make_targets(product, variant, targets):