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 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