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