• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2
3from __future__ import print_function
4
5import os
6import sys
7sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
8
9import tempfile
10import unittest
11
12from compat import StringIO
13from 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
44class 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
101class 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
356class 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
362class MockELFLinkData(object):
363    def __init__(self, path):
364        self.path = path
365
366
367class 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
384class 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
461if __name__ == '__main__':
462    unittest.main()
463