1 #!/usr/bin/env python3 2 3 from __future__ import print_function 4 5 import argparse 6 import collections 7 import difflib 8 import os 9 import subprocess 10 import sys 11 import unittest 12 13 from compat import TemporaryDirectory, makedirs 14 import ndk_toolchain 15 16 17 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) 18 VNDK_DEF_TOOL = os.path.join(SCRIPT_DIR, '..', 'vndk_definition_tool.py') 19 20 INPUT_DIR = os.path.join(SCRIPT_DIR ,'testdata', 'test_elfdump', 'input') 21 EXPECTED_DIR = os.path.join(SCRIPT_DIR, 'testdata', 'test_elfdump', 'expected') 22 test_dir_base = None 23 24 25 def run_elf_dump(path): 26 cmd = [sys.executable, VNDK_DEF_TOOL, 'elfdump', path] 27 return subprocess.check_output(cmd, universal_newlines=True) 28 29 30 class ELFDumpTest(unittest.TestCase): 31 @classmethod 32 def setUpClass(cls): 33 cls.targets = ndk_toolchain.create_targets() 34 35 if test_dir_base: 36 cls.test_dir_base = test_dir_base 37 else: 38 cls.tmp_dir = TemporaryDirectory() 39 cls.test_dir_base = cls.tmp_dir.name 40 41 cls._build_fixtures(cls.target_name) 42 43 @classmethod 44 def tearDownClass(cls): 45 if not test_dir_base: 46 cls.tmp_dir.cleanup() 47 48 @classmethod 49 def _build_fixtures(cls, target_name): 50 target = cls.targets[target_name] 51 52 cls.expected_dir = os.path.join(EXPECTED_DIR, target_name) 53 cls.test_dir = os.path.join(cls.test_dir_base, target_name) 54 55 makedirs(cls.test_dir, exist_ok=True) 56 57 # Compile main.o. 58 src_file = os.path.join(INPUT_DIR, 'main.c') 59 obj_file = os.path.join(cls.test_dir, 'main.o') 60 target.compile(obj_file, src_file, []) 61 62 # Link main.out. 63 out_file = os.path.join(cls.test_dir, 'main.out') 64 target.link(out_file, [obj_file], ['-ldl', '-lc', '-lstdc++']) 65 66 # Compile test.o. 67 src_file = os.path.join(INPUT_DIR, 'test.c') 68 obj_file = os.path.join(cls.test_dir, 'test.o') 69 target.compile(obj_file, src_file, []) 70 71 # Link libtest.so. 72 out_file = os.path.join(cls.test_dir, 'libtest.so') 73 target.link(out_file, [obj_file], ['-shared', '-lc']) 74 75 # Link libtest-rpath.so. 76 out_file = os.path.join(cls.test_dir, 'libtest-rpath.so') 77 target.link(out_file, [obj_file], 78 ['-shared', '-lc', '-Wl,-rpath,$ORIGIN/../lib', 79 '-Wl,--disable-new-dtags']) 80 81 # Link libtest-rpath-multi.so. 82 out_file = os.path.join(cls.test_dir, 'libtest-rpath-multi.so') 83 target.link(out_file, [obj_file], 84 ['-shared', '-lc', '-Wl,-rpath,/system/lib:/vendor/lib', 85 '-Wl,--disable-new-dtags']) 86 87 # Link libtest-runpath.so. 88 out_file = os.path.join(cls.test_dir, 'libtest-runpath.so') 89 target.link(out_file, [obj_file], 90 ['-shared', '-lc', '-Wl,-rpath,$ORIGIN/../lib', 91 '-Wl,--enable-new-dtags']) 92 93 # Link libtest-runpath-multi.so. 94 out_file = os.path.join(cls.test_dir, 'libtest-runpath-multi.so') 95 target.link(out_file, [obj_file], 96 ['-shared', '-lc', '-Wl,-rpath,/system/lib:/vendor/lib', 97 '-Wl,--enable-new-dtags']) 98 99 def _assert_equal_to_file(self, expected_file_name, actual): 100 actual = actual.splitlines(True) 101 expected_file_path = os.path.join(self.expected_dir, expected_file_name) 102 with open(expected_file_path, 'r') as f: 103 expected = f.readlines() 104 self.assertEqual(expected, actual) 105 106 def _test_main_out(self): 107 out_file = os.path.join(self.test_dir, 'main.out') 108 self._assert_equal_to_file('main.out.txt', run_elf_dump(out_file)) 109 110 def _test_libtest(self, expected_file_name, lib_name): 111 lib_file = os.path.join(self.test_dir, lib_name) 112 self._assert_equal_to_file(expected_file_name, run_elf_dump(lib_file)) 113 114 115 def create_target_test(target_name): 116 def test_main(self): 117 self._test_main_out() 118 119 def test_libtest(self): 120 self._test_libtest('libtest.so.txt', 'libtest.so') 121 122 def test_libtest_rpath(self): 123 self._test_libtest('libtest-rpath.so.txt', 'libtest-rpath.so') 124 125 def test_libtest_rpath_multi(self): 126 self._test_libtest('libtest-rpath-multi.so.txt', 127 'libtest-rpath-multi.so') 128 129 def test_libtest_runpath(self): 130 self._test_libtest('libtest-runpath.so.txt', 'libtest-runpath.so') 131 132 def test_libtest_runpath_multi(self): 133 self._test_libtest('libtest-runpath-multi.so.txt', 134 'libtest-runpath-multi.so') 135 136 class_name = 'ELFDumpTest_' + target_name 137 globals()[class_name] = type( 138 class_name, (ELFDumpTest,), 139 dict(test_main=test_main, 140 test_libtest=test_libtest, 141 test_libtest_rpath=test_libtest_rpath, 142 test_libtest_rpath_multi=test_libtest_rpath_multi, 143 test_libtest_runpath=test_libtest_runpath, 144 test_libtest_runpath_multi=test_libtest_runpath_multi, 145 target_name=target_name)) 146 147 148 for target in ('arm', 'arm64', 'mips', 'mips64', 'x86', 'x86_64'): 149 create_target_test(target) 150 151 152 def main(): 153 # Parse command line arguments. 154 parser = argparse.ArgumentParser() 155 parser.add_argument('--test-dir', help='directory for temporary files') 156 parser.add_argument('--expected-dir', help='directory with expected output') 157 args, unittest_args = parser.parse_known_args() 158 159 # Convert command line options. 160 global expected_dir 161 global test_dir_base 162 163 if args.expected_dir: 164 expected_dir = args.expected_dir 165 if args.test_dir: 166 test_dir_base = args.test_dir 167 168 # Run unit test. 169 unittest.main(argv=[sys.argv[0]] + unittest_args) 170 171 if __name__ == '__main__': 172 main() 173