Home | History | Annotate | Download | only in tests
      1 #!/usr/bin/env python3
      2 
      3 from __future__ import print_function
      4 
      5 import os
      6 import sys
      7 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
      8 
      9 import tempfile
     10 import unittest
     11 
     12 from compat import StringIO
     13 from vndk_definition_tool import TaggedDict, TaggedPathDict, TaggedLibDict, \
     14                                  NUM_PARTITIONS, PT_SYSTEM, PT_VENDOR
     15 
     16 
     17 _TEST_DATA = '''Path,Tag
     18 /system/lib/lib_ll_ndk.so,ll-ndk
     19 /system/lib/lib_ll_ndk_indirect.so,ll-ndk-indirect
     20 /system/lib/lib_vndk_sp.so,vndk-sp
     21 /system/lib/lib_vndk_sp_indirect.so,vndk-sp-indirect
     22 /system/lib/lib_vndk_sp_indirect_private.so,vndk-sp-indirect-private
     23 /system/lib/lib_vndk.so,vndk
     24 /system/lib/lib_fwk_only.so,fwk-only
     25 /system/lib/lib_fwk_only_rs.so,fwk-only-rs
     26 /vendor/lib/lib_sp_hal.so,sp-hal
     27 /vendor/lib/lib_sp_hal_dep.so,sp-hal-dep
     28 /vendor/lib/lib_vnd_only.so,vnd-only
     29 /system/lib/lib_remove.so,remove
     30 /system/lib/lib_hl_ndk.so,hl-ndk
     31 /system/lib/lib_vndk_indirect.so,vndk-indirect
     32 /system/lib/lib_vndk_sp_both.so,vndk-sp-both
     33 /system/lib/lib_vndk_sp_hal.so,vndk-sp-hal
     34 '''
     35 
     36 _TEST_DATA_ALIAS_PATHS = {
     37     '/system/lib/lib_hl_ndk.so',
     38     '/system/lib/lib_vndk_sp_both.so',
     39     '/system/lib/lib_vndk_sp_hal.so',
     40     '/system/lib/lib_vndk_indirect.so'
     41 }
     42 
     43 
     44 class TaggedDictTest(unittest.TestCase):
     45     def test_normalize_tag(self):
     46         self.assertEqual('ll_ndk', TaggedDict._normalize_tag('ll-ndk'))
     47         self.assertEqual('ll_ndk', TaggedDict._normalize_tag('LL-NDK'))
     48         self.assertEqual('ll_ndk', TaggedDict._normalize_tag('LL_NDK'))
     49         with self.assertRaises(ValueError):
     50             TaggedDict._normalize_tag('unknown-lib-tag')
     51 
     52 
     53     def _check_tag_visibility(self, d, from_tag, visible_tags):
     54         for to_tag in TaggedDict.TAGS:
     55             self.assertEqual(d.is_tag_visible(from_tag, to_tag),
     56                              to_tag in visible_tags)
     57 
     58 
     59     def test_is_tag_visible(self):
     60         d = TaggedDict()
     61 
     62         # LL-NDK
     63         visible_tags = {'ll_ndk', 'll_ndk_indirect'}
     64         self._check_tag_visibility(d, 'll_ndk', visible_tags)
     65         self._check_tag_visibility(d, 'll_ndk_indirect', visible_tags)
     66 
     67         # VNDK-SP
     68         visible_tags = {'ll_ndk', 'vndk_sp', 'vndk_sp_indirect',
     69                         'vndk_sp_indirect_private', 'fwk_only_rs'}
     70         self._check_tag_visibility(d, 'vndk_sp', visible_tags)
     71         self._check_tag_visibility(d, 'vndk_sp_indirect', visible_tags)
     72         self._check_tag_visibility(d, 'vndk_sp_indirect_private', visible_tags)
     73 
     74         # VNDK
     75         visible_tags = {'ll_ndk', 'vndk_sp', 'vndk_sp_indirect',
     76                         'vndk'}
     77         self._check_tag_visibility(d, 'vndk', visible_tags)
     78 
     79         # FWK-ONLY
     80         visible_tags = {'ll_ndk', 'll_ndk_indirect',
     81                         'vndk_sp', 'vndk_sp_indirect',
     82                         'vndk_sp_indirect_private', 'vndk', 'fwk_only',
     83                         'fwk_only_rs', 'sp_hal'}
     84         self._check_tag_visibility(d, 'fwk_only', visible_tags)
     85         self._check_tag_visibility(d, 'fwk_only_rs', visible_tags)
     86 
     87         # SP-HAL
     88         visible_tags = {'ll_ndk', 'vndk_sp', 'sp_hal', 'sp_hal_dep'}
     89         self._check_tag_visibility(d, 'sp_hal', visible_tags)
     90         self._check_tag_visibility(d, 'sp_hal_dep', visible_tags)
     91 
     92         # VND-ONLY
     93         visible_tags = {'ll_ndk', 'vndk_sp', 'vndk_sp_indirect',
     94                         'vndk', 'sp_hal', 'sp_hal_dep', 'vnd_only'}
     95         self._check_tag_visibility(d, 'vnd_only', visible_tags)
     96 
     97         # Remove
     98         self._check_tag_visibility(d, 'remove', set())
     99 
    100 
    101 class TaggedPathDictTest(unittest.TestCase):
    102     def test_enumerate_paths(self):
    103         tagged_paths = TaggedPathDict()
    104 
    105         self.assertEqual(
    106                 ['/system/lib/libc.so'],
    107                 list(tagged_paths._enumerate_paths('/system/lib/libc.so')))
    108 
    109         self.assertEqual(
    110                 ['/system/lib/libc.so', '/system/lib64/libc.so'],
    111                 list(tagged_paths._enumerate_paths('/system/${LIB}/libc.so')))
    112 
    113         self.assertEqual(
    114                 ['/system/lib/vndk/libutils.so',
    115                  '/system/lib64/vndk/libutils.so'],
    116                 list(tagged_paths._enumerate_paths(
    117                     '/system/${LIB}/vndk${VNDK_VER}/libutils.so')))
    118 
    119         tagged_paths = TaggedPathDict(['current', '27', '28'])
    120 
    121         self.assertEqual(
    122                 ['/system/lib/vndk/libutils.so',
    123                  '/system/lib64/vndk/libutils.so',
    124                  '/system/lib/vndk-27/libutils.so',
    125                  '/system/lib64/vndk-27/libutils.so',
    126                  '/system/lib/vndk-28/libutils.so',
    127                  '/system/lib64/vndk-28/libutils.so'],
    128                 list(tagged_paths._enumerate_paths(
    129                     '/system/${LIB}/vndk${VNDK_VER}/libutils.so')))
    130 
    131         self.assertEqual(
    132                 ['/system/lib/vndk/libutils.so',
    133                  '/system/lib/vndk-27/libutils.so',
    134                  '/system/lib/vndk-28/libutils.so'],
    135                 list(tagged_paths._enumerate_paths(
    136                     '/system/lib/vndk${VNDK_VER}/libutils.so')))
    137 
    138     def test_load_from_csv_empty(self):
    139         try:
    140             TaggedPathDict().load_from_csv(StringIO(''))
    141         except StopIteration:
    142             self.fail('empty file should be considered as a valid input')
    143 
    144 
    145     def test_load_from_csv_with_header(self):
    146         fp = StringIO('Path,Tag\nliba.so,fwk-only\n')
    147         d = TaggedPathDict()
    148         d.load_from_csv(fp)
    149         self.assertIn('liba.so', d.fwk_only)
    150 
    151         fp = StringIO('Tag,Path\nfwk-only,liba.so\n')
    152         d = TaggedPathDict()
    153         d.load_from_csv(fp)
    154         self.assertIn('liba.so', d.fwk_only)
    155 
    156 
    157     def test_load_from_csv_without_header(self):
    158         fp = StringIO('liba.so,fwk-only\n')
    159         d = TaggedPathDict()
    160         d.load_from_csv(fp)
    161         self.assertIn('liba.so', d.fwk_only)
    162 
    163 
    164     def _check_test_data_loaded(self, d):
    165         # Paths
    166         self.assertIn('/system/lib/lib_ll_ndk.so', d.ll_ndk)
    167         self.assertIn('/system/lib/lib_ll_ndk_indirect.so', d.ll_ndk_indirect)
    168         self.assertIn('/system/lib/lib_vndk_sp.so', d.vndk_sp)
    169         self.assertIn('/system/lib/lib_vndk_sp_indirect.so', d.vndk_sp_indirect)
    170         self.assertIn('/system/lib/lib_vndk_sp_indirect_private.so',
    171                       d.vndk_sp_indirect_private)
    172         self.assertIn('/system/lib/lib_vndk.so', d.vndk)
    173         self.assertIn('/system/lib/lib_fwk_only.so', d.fwk_only)
    174         self.assertIn('/system/lib/lib_fwk_only_rs.so', d.fwk_only_rs)
    175         self.assertIn('/vendor/lib/lib_sp_hal.so', d.sp_hal)
    176         self.assertIn('/vendor/lib/lib_sp_hal_dep.so', d.sp_hal_dep)
    177         self.assertIn('/vendor/lib/lib_vnd_only.so', d.vnd_only)
    178         self.assertIn('/system/lib/lib_remove.so', d.remove)
    179 
    180         # Aliases
    181         self.assertIn('/system/lib/lib_hl_ndk.so', d.fwk_only)
    182         self.assertIn('/system/lib/lib_vndk_sp_both.so', d.vndk_sp)
    183         self.assertIn('/system/lib/lib_vndk_sp_hal.so', d.vndk_sp)
    184         self.assertIn('/system/lib/lib_vndk_indirect.so', d.vndk)
    185 
    186 
    187     def test_load_from_csv_tags(self):
    188         fp = StringIO(_TEST_DATA)
    189         d = TaggedPathDict()
    190         d.load_from_csv(fp)
    191         self._check_test_data_loaded(d)
    192 
    193 
    194     def test_create_from_csv(self):
    195         d = TaggedPathDict.create_from_csv(StringIO(_TEST_DATA))
    196         self._check_test_data_loaded(d)
    197 
    198 
    199     def test_create_from_csv_path(self):
    200         with tempfile.NamedTemporaryFile('w+') as f:
    201             f.write(_TEST_DATA)
    202             f.flush()
    203 
    204             d = TaggedPathDict.create_from_csv_path(f.name)
    205             self._check_test_data_loaded(d)
    206 
    207 
    208     def test_get_path_tag(self):
    209         fp = StringIO(_TEST_DATA)
    210         d = TaggedPathDict()
    211         d.load_from_csv(fp)
    212 
    213         self.assertEqual('ll_ndk', d.get_path_tag('/system/lib/lib_ll_ndk.so'))
    214         self.assertEqual('ll_ndk_indirect',
    215                          d.get_path_tag('/system/lib/lib_ll_ndk_indirect.so'))
    216         self.assertEqual('vndk_sp',
    217                          d.get_path_tag('/system/lib/lib_vndk_sp.so'))
    218         self.assertEqual('vndk_sp_indirect',
    219                          d.get_path_tag('/system/lib/lib_vndk_sp_indirect.so'))
    220         self.assertEqual(
    221                 'vndk_sp_indirect_private',
    222                 d.get_path_tag('/system/lib/lib_vndk_sp_indirect_private.so'))
    223         self.assertEqual('vndk', d.get_path_tag('/system/lib/lib_vndk.so'))
    224         self.assertEqual('fwk_only',
    225                          d.get_path_tag('/system/lib/lib_fwk_only.so'))
    226         self.assertEqual('fwk_only_rs',
    227                          d.get_path_tag('/system/lib/lib_fwk_only_rs.so'))
    228         self.assertEqual('sp_hal',
    229                          d.get_path_tag('/vendor/lib/lib_sp_hal.so'))
    230         self.assertEqual('sp_hal_dep',
    231                          d.get_path_tag('/vendor/lib/lib_sp_hal_dep.so'))
    232         self.assertEqual('vnd_only',
    233                          d.get_path_tag('/vendor/lib/lib_vnd_only.so'))
    234         self.assertEqual('remove',
    235                          d.get_path_tag('/system/lib/lib_remove.so'))
    236 
    237         # Aliases
    238         self.assertEqual('fwk_only',
    239                          d.get_path_tag('/system/lib/lib_hl_ndk.so'))
    240         self.assertEqual('vndk_sp',
    241                          d.get_path_tag('/system/lib/lib_vndk_sp_hal.so'))
    242         self.assertEqual('vndk_sp',
    243                          d.get_path_tag('/system/lib/lib_vndk_sp_both.so'))
    244         self.assertEqual('vndk',
    245                          d.get_path_tag('/system/lib/lib_vndk_indirect.so'))
    246 
    247         # Unmatched paths
    248         self.assertEqual('fwk_only', d.get_path_tag('/system/lib/unknown.so'))
    249         self.assertEqual('fwk_only', d.get_path_tag('/data/lib/unknown.so'))
    250         self.assertEqual('vnd_only', d.get_path_tag('/vendor/lib/unknown.so'))
    251 
    252 
    253     def _check_path_visibility(self, d, all_paths, from_paths, visible_paths):
    254         for from_path in from_paths:
    255             for to_path in all_paths:
    256                 self.assertEqual(d.is_path_visible(from_path, to_path),
    257                                  to_path in visible_paths)
    258 
    259 
    260     def test_is_path_visible(self):
    261         fp = StringIO(_TEST_DATA)
    262         d = TaggedPathDict()
    263         d.load_from_csv(fp)
    264 
    265         # Collect path universe set.
    266         all_paths = set()
    267         for tag in TaggedPathDict.TAGS:
    268             all_paths |= getattr(d, tag)
    269         all_paths -= _TEST_DATA_ALIAS_PATHS
    270 
    271         # LL-NDK
    272         from_paths = {
    273             '/system/lib/lib_ll_ndk.so',
    274             '/system/lib/lib_ll_ndk_indirect.so',
    275         }
    276         visible_paths = {
    277             '/system/lib/lib_ll_ndk.so',
    278             '/system/lib/lib_ll_ndk_indirect.so',
    279         }
    280         self._check_path_visibility(d, all_paths, from_paths, visible_paths)
    281 
    282         # VNDK-SP
    283         from_paths = {
    284             '/system/lib/lib_vndk_sp.so',
    285             '/system/lib/lib_vndk_sp_indirect.so',
    286             '/system/lib/lib_vndk_sp_indirect_private.so',
    287         }
    288         visible_paths = {
    289             '/system/lib/lib_ll_ndk.so',
    290             '/system/lib/lib_vndk_sp.so',
    291             '/system/lib/lib_vndk_sp_indirect.so',
    292             '/system/lib/lib_vndk_sp_indirect_private.so',
    293             '/system/lib/lib_fwk_only_rs.so',
    294         }
    295         self._check_path_visibility(d, all_paths, from_paths, visible_paths)
    296 
    297         # VNDK
    298         from_paths = {
    299             '/system/lib/lib_vndk.so',
    300         }
    301         visible_paths = {
    302             '/system/lib/lib_ll_ndk.so',
    303             '/system/lib/lib_vndk_sp.so',
    304             '/system/lib/lib_vndk_sp_indirect.so',
    305             '/system/lib/lib_vndk.so',
    306         }
    307         self._check_path_visibility(d, all_paths, from_paths, visible_paths)
    308 
    309         # FWK-ONLY
    310         from_paths = {
    311             '/system/lib/lib_fwk_only.so',
    312             '/system/lib/lib_fwk_only_rs.so',
    313         }
    314         visible_paths = {
    315             '/system/lib/lib_ll_ndk.so',
    316             '/system/lib/lib_ll_ndk_indirect.so',
    317             '/system/lib/lib_vndk_sp.so',
    318             '/system/lib/lib_vndk_sp_indirect.so',
    319             '/system/lib/lib_vndk_sp_indirect_private.so',
    320             '/system/lib/lib_vndk.so',
    321             '/system/lib/lib_fwk_only.so',
    322             '/system/lib/lib_fwk_only_rs.so',
    323             '/vendor/lib/lib_sp_hal.so',
    324         }
    325         self._check_path_visibility(d, all_paths, from_paths, visible_paths)
    326 
    327         # SP-HAL
    328         from_paths = {
    329             '/vendor/lib/lib_sp_hal.so',
    330             '/vendor/lib/lib_sp_hal_dep.so',
    331         }
    332         visible_paths = {
    333             '/system/lib/lib_ll_ndk.so',
    334             '/system/lib/lib_vndk_sp.so',
    335             '/vendor/lib/lib_sp_hal.so',
    336             '/vendor/lib/lib_sp_hal_dep.so',
    337         }
    338         self._check_path_visibility(d, all_paths, from_paths, visible_paths)
    339 
    340         # VND-ONLY
    341         from_paths = {
    342             '/vendor/lib/lib_vnd_only.so',
    343         }
    344         visible_paths = {
    345             '/system/lib/lib_ll_ndk.so',
    346             '/system/lib/lib_vndk_sp.so',
    347             '/system/lib/lib_vndk_sp_indirect.so',
    348             '/system/lib/lib_vndk.so',
    349             '/vendor/lib/lib_sp_hal.so',
    350             '/vendor/lib/lib_sp_hal_dep.so',
    351             '/vendor/lib/lib_vnd_only.so',
    352         }
    353         self._check_path_visibility(d, all_paths, from_paths, visible_paths)
    354 
    355 
    356 class MockSPLibResult(object):
    357     def __init__(self, sp_hal, sp_hal_dep):
    358         self.sp_hal = sp_hal
    359         self.sp_hal_dep = sp_hal_dep
    360 
    361 
    362 class MockELFLinkData(object):
    363     def __init__(self, path):
    364         self.path = path
    365 
    366 
    367 class MockELFGraph(object):
    368     def __init__(self):
    369         self.lib_pt = [dict() for i in range(NUM_PARTITIONS)]
    370 
    371     def add(self, path):
    372         partition = PT_VENDOR if path.startswith('/vendor') else PT_SYSTEM
    373         lib = MockELFLinkData(path)
    374         self.lib_pt[partition][path] = lib
    375         return lib
    376 
    377     def compute_sp_lib(self, generic_refs=None):
    378         vendor_libs = self.lib_pt[PT_VENDOR].values()
    379         return MockSPLibResult(
    380                 set(v for v in vendor_libs if 'lib_sp_hal.so' in v.path),
    381                 set(v for v in vendor_libs if 'lib_sp_hal_dep.so' in v.path))
    382 
    383 
    384 class TaggedLibDictTest(unittest.TestCase):
    385     def setUp(self):
    386         self.tagged_paths = TaggedPathDict.create_from_csv(StringIO(_TEST_DATA))
    387 
    388         self.graph = MockELFGraph()
    389 
    390         self.lib_ll_ndk = self.graph.add('/system/lib/lib_ll_ndk.so')
    391         self.lib_ll_ndk_indirect = \
    392                 self.graph.add('/system/lib/lib_ll_ndk_indirect.so')
    393 
    394         self.lib_vndk_sp = self.graph.add('/system/lib/lib_vndk_sp.so')
    395         self.lib_vndk_sp_indirect = \
    396                 self.graph.add('/system/lib/lib_vndk_sp_indirect.so')
    397         self.lib_vndk_sp_indirect_private = \
    398                 self.graph.add('/system/lib/lib_vndk_sp_indirect_private.so')
    399 
    400         self.lib_vndk = self.graph.add('/system/lib/lib_vndk.so')
    401 
    402         self.lib_fwk_only = self.graph.add('/system/lib/lib_fwk_only.so')
    403         self.lib_fwk_only_rs = self.graph.add('/system/lib/lib_fwk_only_rs.so')
    404 
    405         self.lib_sp_hal = self.graph.add('/vendor/lib/lib_sp_hal.so')
    406         self.lib_sp_hal_dep = self.graph.add('/vendor/lib/lib_sp_hal_dep.so')
    407 
    408         self.lib_vnd_only = self.graph.add('/vendor/lib/lib_vnd_only.so')
    409 
    410         self.tagged_libs = TaggedLibDict.create_from_graph(
    411                 self.graph, self.tagged_paths)
    412 
    413 
    414     def test_create_from_graph(self):
    415         self.assertIn(self.lib_ll_ndk, self.tagged_libs.ll_ndk)
    416         self.assertIn(self.lib_ll_ndk_indirect,
    417                       self.tagged_libs.ll_ndk_indirect)
    418         self.assertIn(self.lib_vndk_sp, self.tagged_libs.vndk_sp)
    419         self.assertIn(self.lib_vndk_sp_indirect,
    420                       self.tagged_libs.vndk_sp_indirect)
    421         self.assertIn(self.lib_vndk_sp_indirect_private,
    422                       self.tagged_libs.vndk_sp_indirect_private)
    423 
    424         self.assertIn(self.lib_vndk, self.tagged_libs.vndk)
    425 
    426         self.assertIn(self.lib_fwk_only, self.tagged_libs.fwk_only)
    427         self.assertIn(self.lib_fwk_only_rs, self.tagged_libs.fwk_only_rs)
    428 
    429         self.assertIn(self.lib_sp_hal, self.tagged_libs.sp_hal)
    430         self.assertIn(self.lib_sp_hal_dep, self.tagged_libs.sp_hal_dep)
    431         self.assertIn(self.lib_vnd_only, self.tagged_libs.vnd_only)
    432 
    433 
    434     def test_get_path_tag(self):
    435         d = self.tagged_libs
    436 
    437         self.assertEqual('ll_ndk', d.get_path_tag(self.lib_ll_ndk))
    438         self.assertEqual('ll_ndk_indirect',
    439                          d.get_path_tag(self.lib_ll_ndk_indirect))
    440         self.assertEqual('vndk_sp', d.get_path_tag(self.lib_vndk_sp))
    441         self.assertEqual('vndk_sp_indirect',
    442                          d.get_path_tag(self.lib_vndk_sp_indirect))
    443         self.assertEqual('vndk_sp_indirect_private',
    444                          d.get_path_tag(self.lib_vndk_sp_indirect_private))
    445         self.assertEqual('vndk', d.get_path_tag(self.lib_vndk))
    446         self.assertEqual('fwk_only', d.get_path_tag(self.lib_fwk_only))
    447         self.assertEqual('fwk_only_rs', d.get_path_tag(self.lib_fwk_only_rs))
    448         self.assertEqual('sp_hal', d.get_path_tag(self.lib_sp_hal))
    449         self.assertEqual('sp_hal_dep', d.get_path_tag(self.lib_sp_hal_dep))
    450         self.assertEqual('vnd_only', d.get_path_tag(self.lib_vnd_only))
    451 
    452         # Unmatched paths
    453         tag = d.get_path_tag(MockELFLinkData('/system/lib/unknown.so'))
    454         self.assertEqual('fwk_only', tag)
    455         tag = d.get_path_tag(MockELFLinkData('/data/lib/unknown.so'))
    456         self.assertEqual('fwk_only', tag)
    457         tag = d.get_path_tag(MockELFLinkData('/vendor/lib/unknown.so'))
    458         self.assertEqual('vnd_only', tag)
    459 
    460 
    461 if __name__ == '__main__':
    462     unittest.main()
    463