Home | History | Annotate | Download | only in tests
      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