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 targets 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 = targets.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 80 # Link libtest-rpath-multi.so. 81 out_file = os.path.join(cls.test_dir, 'libtest-rpath-multi.so') 82 target.link(out_file, [obj_file], 83 ['-shared', '-lc', '-Wl,-rpath,/system/lib:/vendor/lib']) 84 85 # Link libtest-runpath.so. 86 out_file = os.path.join(cls.test_dir, 'libtest-runpath.so') 87 target.link(out_file, [obj_file], 88 ['-shared', '-lc', '-Wl,-rpath,$ORIGIN/../lib', 89 '-Wl,--enable-new-dtags']) 90 91 # Link libtest-runpath-multi.so. 92 out_file = os.path.join(cls.test_dir, 'libtest-runpath-multi.so') 93 target.link(out_file, [obj_file], 94 ['-shared', '-lc', '-Wl,-rpath,/system/lib:/vendor/lib', 95 '-Wl,--enable-new-dtags']) 96 97 def _assert_equal_to_file(self, expected_file_name, actual): 98 actual = actual.splitlines(True) 99 expected_file_path = os.path.join(self.expected_dir, expected_file_name) 100 with open(expected_file_path, 'r') as f: 101 expected = f.readlines() 102 self.assertEqual(expected, actual) 103 104 def _test_main_out(self): 105 out_file = os.path.join(self.test_dir, 'main.out') 106 self._assert_equal_to_file('main.out.txt', run_elf_dump(out_file)) 107 108 def _test_libtest(self, expected_file_name, lib_name): 109 lib_file = os.path.join(self.test_dir, lib_name) 110 self._assert_equal_to_file(expected_file_name, run_elf_dump(lib_file)) 111 112 113 def create_target_test(target_name): 114 def test_main(self): 115 self._test_main_out() 116 117 def test_libtest(self): 118 self._test_libtest('libtest.so.txt', 'libtest.so') 119 120 def test_libtest_rpath(self): 121 self._test_libtest('libtest-rpath.so.txt', 'libtest-rpath.so') 122 123 def test_libtest_rpath_multi(self): 124 self._test_libtest('libtest-rpath-multi.so.txt', 125 'libtest-rpath-multi.so') 126 127 def test_libtest_runpath(self): 128 self._test_libtest('libtest-runpath.so.txt', 'libtest-runpath.so') 129 130 def test_libtest_runpath_multi(self): 131 self._test_libtest('libtest-runpath-multi.so.txt', 132 'libtest-runpath-multi.so') 133 134 class_name = 'ELFDumpTest_' + target_name 135 globals()[class_name] = type( 136 class_name, (ELFDumpTest,), 137 dict(test_main=test_main, 138 test_libtest=test_libtest, 139 test_libtest_rpath=test_libtest_rpath, 140 test_libtest_rpath_multi=test_libtest_rpath_multi, 141 test_libtest_runpath=test_libtest_runpath, 142 test_libtest_runpath_multi=test_libtest_runpath_multi, 143 target_name=target_name)) 144 145 146 for target in ('arm', 'arm64', 'mips', 'mips64', 'x86', 'x86_64'): 147 create_target_test(target) 148 149 150 def main(): 151 # Parse command line arguments. 152 parser = argparse.ArgumentParser() 153 parser.add_argument('--test-dir', help='directory for temporary files') 154 parser.add_argument('--expected-dir', help='directory with expected output') 155 args, unittest_args = parser.parse_known_args() 156 157 # Convert command line options. 158 global expected_dir 159 global test_dir_base 160 161 if args.expected_dir: 162 expected_dir = args.expected_dir 163 if args.test_dir: 164 test_dir_base = args.test_dir 165 166 # Run unit test. 167 unittest.main(argv=[sys.argv[0]] + unittest_args) 168 169 if __name__ == '__main__': 170 main() 171