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 unittest
10
11from compat import StringIO
12from vndk_definition_tool import (BannedLibDict, ELF, ELFLinker, GenericRefs,
13                                  PT_SYSTEM, PT_VENDOR)
14
15
16class GraphBuilder(object):
17    _PARTITION_NAMES = {
18        PT_SYSTEM: 'system',
19        PT_VENDOR: 'vendor',
20    }
21
22    _LIB_DIRS = {
23        ELF.ELFCLASS32: 'lib',
24        ELF.ELFCLASS64: 'lib64',
25    }
26
27    def __init__(self):
28        self.graph = ELFLinker()
29
30    def add_lib(self, partition, klass, name, dt_needed=[],
31                exported_symbols=set(), imported_symbols=set(),
32                extra_dir=None):
33        """Create and add a shared library to ELFLinker."""
34
35        lib_dir = os.path.join('/', self._PARTITION_NAMES[partition],
36                               self._LIB_DIRS[klass])
37        if extra_dir:
38            lib_dir = os.path.join(lib_dir, extra_dir)
39
40        path = os.path.join(lib_dir, name + '.so')
41
42        elf = ELF(klass, ELF.ELFDATA2LSB, dt_needed=dt_needed,
43                  exported_symbols=exported_symbols,
44                  imported_symbols=imported_symbols)
45
46        node = self.graph.add_lib(partition, path, elf)
47        setattr(self, name + '_' + elf.elf_class_name, node)
48        return node
49
50    def add_multilib(self, partition, name, dt_needed=[],
51                     exported_symbols=set(), imported_symbols=set(),
52                     extra_dir=None):
53        """Add 32-bit / 64-bit shared libraries to ELFLinker."""
54        return (
55            self.add_lib(partition, ELF.ELFCLASS32, name, dt_needed,
56                         exported_symbols, imported_symbols, extra_dir),
57            self.add_lib(partition, ELF.ELFCLASS64, name, dt_needed,
58                         exported_symbols, imported_symbols, extra_dir)
59        )
60
61    def resolve(self):
62        self.graph.resolve_deps()
63
64
65class ELFLinkerTest(unittest.TestCase):
66    def _create_normal_graph(self):
67        gb = GraphBuilder()
68
69        gb.add_multilib(PT_SYSTEM, 'libdl',
70                        exported_symbols={'dlclose', 'dlopen', 'dlsym'})
71
72        gb.add_multilib(PT_SYSTEM, 'libm', exported_symbols={'cos', 'sin'})
73
74        gb.add_multilib(PT_SYSTEM, 'libc', dt_needed=['libdl.so', 'libm.so'],
75                        exported_symbols={'fclose', 'fopen', 'fread'},
76                        imported_symbols={'dlclose', 'dlopen', 'cos', 'sin'})
77
78        gb.add_multilib(PT_SYSTEM, 'libRS', dt_needed=['libdl.so'],
79                        exported_symbols={'rsContextCreate'},
80                        imported_symbols={'dlclose', 'dlopen', 'dlsym'})
81
82        gb.add_multilib(PT_SYSTEM, 'libcutils',
83                        dt_needed=['libc.so', 'libdl.so'],
84                        imported_symbols={'dlclose', 'dlopen', 'fclose',
85                                          'fopen'})
86
87        gb.add_multilib(PT_VENDOR, 'libEGL',
88                        dt_needed=['libc.so', 'libcutils.so', 'libdl.so'],
89                        exported_symbols={'eglGetDisplay'},
90                        imported_symbols={'fclose', 'fopen'})
91
92        gb.resolve()
93        return gb
94
95    def _get_paths_from_nodes(self, nodes):
96        return sorted([node.path for node in nodes])
97
98    def test_get_lib(self):
99        gb = self._create_normal_graph()
100        graph = gb.graph
101
102        node = graph.get_lib('/system/lib/libc.so')
103        self.assertEqual(gb.libc_32, node)
104        self.assertEqual('/system/lib/libc.so', node.path)
105
106        node = graph.get_lib('/system/lib64/libdl.so')
107        self.assertEqual(gb.libdl_64, node)
108        self.assertEqual('/system/lib64/libdl.so', node.path)
109
110        node = graph.get_lib('/vendor/lib64/libEGL.so')
111        self.assertEqual(gb.libEGL_64, node)
112        self.assertEqual('/vendor/lib64/libEGL.so', node.path)
113
114        self.assertEqual(None, graph.get_lib('/no/such/path.so'))
115
116    def test_map_paths_to_libs(self):
117        gb = self._create_normal_graph()
118        graph = gb.graph
119
120        bad = []
121        paths = ['/system/lib/libc.so', '/system/lib/libdl.so']
122        nodes = graph.get_libs(paths, bad.append)
123
124        self.assertEqual([], bad)
125        self.assertEqual(2, len(nodes))
126        self.assertEqual(paths, self._get_paths_from_nodes(nodes))
127
128        bad = []
129        paths = ['/no/such/path.so', '/system/lib64/libdl.so']
130        nodes = graph.get_libs(paths, bad.append)
131        self.assertEqual(['/no/such/path.so'], bad)
132        self.assertEqual(['/system/lib64/libdl.so'],
133                         self._get_paths_from_nodes(nodes))
134
135    def test_elf_class_and_partitions(self):
136        gb = self._create_normal_graph()
137        graph = gb.graph
138        self.assertEqual(5, len(graph.lib_pt[PT_SYSTEM].lib32))
139        self.assertEqual(5, len(graph.lib_pt[PT_SYSTEM].lib64))
140        self.assertEqual(1, len(graph.lib_pt[PT_VENDOR].lib32))
141        self.assertEqual(1, len(graph.lib_pt[PT_VENDOR].lib64))
142
143    def test_deps(self):
144        gb = self._create_normal_graph()
145        graph = gb.graph
146
147        # Check the dependencies of libc.so.
148        node = gb.graph.get_lib('/system/lib/libc.so')
149        self.assertEqual(['/system/lib/libdl.so', '/system/lib/libm.so'],
150                         self._get_paths_from_nodes(node.deps))
151
152        # Check the dependencies of libRS.so.
153        node = gb.graph.get_lib('/system/lib64/libRS.so')
154        self.assertEqual(['/system/lib64/libdl.so'],
155                         self._get_paths_from_nodes(node.deps))
156
157        # Check the dependencies of libEGL.so.
158        node = gb.graph.get_lib('/vendor/lib64/libEGL.so')
159        self.assertEqual(['/system/lib64/libc.so', '/system/lib64/libcutils.so',
160                          '/system/lib64/libdl.so'],
161                         self._get_paths_from_nodes(node.deps))
162
163    def test_linked_symbols(self):
164        gb = self._create_normal_graph()
165        graph = gb.graph
166
167        # Check the unresolved symbols.
168        for lib_set in graph.lib_pt:
169            for lib in lib_set.values():
170                self.assertEqual(set(), lib.unresolved_symbols)
171
172        # Check the linked symbols.
173        for lib in ('lib', 'lib64'):
174            libdl = graph.get_lib('/system/' + lib + '/libdl.so')
175            libm = graph.get_lib('/system/' + lib + '/libm.so')
176            libc = graph.get_lib('/system/' + lib + '/libc.so')
177            libRS = graph.get_lib('/system/' + lib + '/libRS.so')
178            libcutils = \
179                    graph.get_lib('/system/' + lib + '/libcutils.so')
180            libEGL = graph.get_lib('/vendor/' + lib + '/libEGL.so')
181
182            # Check the linked symbols for libc.so.
183            self.assertIs(libdl, libc.linked_symbols['dlclose'])
184            self.assertIs(libdl, libc.linked_symbols['dlopen'])
185            self.assertIs(libm, libc.linked_symbols['cos'])
186            self.assertIs(libm, libc.linked_symbols['sin'])
187
188            # Check the linked symbols for libRS.so.
189            self.assertIs(libdl, libRS.linked_symbols['dlclose'])
190            self.assertIs(libdl, libRS.linked_symbols['dlopen'])
191            self.assertIs(libdl, libRS.linked_symbols['dlsym'])
192
193            # Check the linked symbols for libcutils.so.
194            self.assertIs(libdl, libcutils.linked_symbols['dlclose'])
195            self.assertIs(libdl, libcutils.linked_symbols['dlopen'])
196            self.assertIs(libc, libcutils.linked_symbols['fclose'])
197            self.assertIs(libc, libcutils.linked_symbols['fopen'])
198
199            # Check the linked symbols for libEGL.so.
200            self.assertIs(libc, libEGL.linked_symbols['fclose'])
201            self.assertIs(libc, libEGL.linked_symbols['fopen'])
202
203    def test_unresolved_symbols(self):
204        gb = GraphBuilder()
205        gb.add_lib(PT_SYSTEM, ELF.ELFCLASS64, 'libfoo', dt_needed=[],
206                   exported_symbols={'foo', 'bar'},
207                   imported_symbols={'__does_not_exist'})
208        gb.resolve()
209
210        lib = gb.graph.get_lib('/system/lib64/libfoo.so')
211        self.assertEqual({'__does_not_exist'}, lib.unresolved_symbols)
212
213    def test_users(self):
214        gb = self._create_normal_graph()
215        graph = gb.graph
216
217        # Check the users of libc.so.
218        node = graph.get_lib('/system/lib/libc.so')
219        self.assertEqual(['/system/lib/libcutils.so', '/vendor/lib/libEGL.so'],
220                         self._get_paths_from_nodes(node.users))
221
222        # Check the users of libdl.so.
223        node = graph.get_lib('/system/lib/libdl.so')
224        self.assertEqual(['/system/lib/libRS.so', '/system/lib/libc.so',
225                          '/system/lib/libcutils.so', '/vendor/lib/libEGL.so'],
226                         self._get_paths_from_nodes(node.users))
227
228        # Check the users of libRS.so.
229        node = graph.get_lib('/system/lib64/libRS.so')
230        self.assertEqual([], self._get_paths_from_nodes(node.users))
231
232        # Check the users of libEGL.so.
233        node = graph.get_lib('/vendor/lib64/libEGL.so')
234        self.assertEqual([], self._get_paths_from_nodes(node.users))
235
236    def test_compute_predefined_fwk_only_rs(self):
237        lib_names = (
238            'libft2',
239            'libmediandk',
240        )
241
242        # Add VNDK-SP libraries.
243        gb = GraphBuilder()
244        for name in lib_names:
245            gb.add_multilib(PT_SYSTEM, name)
246        gb.resolve()
247
248        # Compute FWK-ONLY-RS and check the result.
249        fwk_only_rs = gb.graph.compute_predefined_fwk_only_rs()
250        fwk_only_rs = set(lib.path for lib in fwk_only_rs)
251
252        for lib_dir_name in ('lib', 'lib64'):
253            lib_dir = '/system/' + lib_dir_name
254            for name in lib_names:
255                self.assertIn(os.path.join(lib_dir, name + '.so'), fwk_only_rs)
256
257    def test_compute_predefined_vndk_sp(self):
258        lib_names = (
259            'android.hardware.graphics.allocator@2.0',
260            'android.hardware.graphics.common@1.0',
261            'android.hardware.graphics.mapper@2.0',
262            'android.hardware.renderscript@1.0',
263            'libRSCpuRef',
264            'libRSDriver',
265            'libRS_internal',
266            'libbase',
267            'libbcinfo',
268            'libc++',
269            'libcompiler_rt',
270            'libcutils',
271            'libhardware',
272            'libhidlbase',
273            'libhidltransport',
274            'libhwbinder',
275            'libutils',
276        )
277
278        # Add VNDK-SP libraries.
279        gb = GraphBuilder()
280        for name in lib_names:
281            gb.add_multilib(PT_SYSTEM, name, extra_dir='vndk-sp')
282
283        # Add some unrelated libraries.
284        gb.add_multilib(PT_SYSTEM, 'libfoo')
285        gb.add_multilib(PT_SYSTEM, 'libbar', extra_dir='vndk-sp')
286
287        gb.resolve()
288
289        # Compute VNDK-SP and check the result.
290        vndk_sp = set(lib.path for lib in gb.graph.compute_predefined_vndk_sp())
291
292        for lib_dir_name in ('lib', 'lib64'):
293            lib_dir = '/system/' + lib_dir_name + '/vndk-sp'
294            for name in lib_names:
295                self.assertIn(os.path.join(lib_dir, name + '.so'), vndk_sp)
296
297        self.assertNotIn('/system/lib/libfoo.so', vndk_sp)
298        self.assertNotIn('/system/lib64/libfoo.so', vndk_sp)
299
300        self.assertNotIn('/system/lib/vndk-sp/libbar.so', vndk_sp)
301        self.assertNotIn('/system/lib64/vndk-sp/libbar.so', vndk_sp)
302
303    def test_compute_predefined_vndk_sp_indirect(self):
304        lib_names = (
305            'libbacktrace',
306            'libblas',
307            'liblzma',
308            'libpng',
309            'libunwind',
310        )
311
312        # Add VNDK-SP-Indirect libraries.
313        gb = GraphBuilder()
314        for name in lib_names:
315            gb.add_multilib(PT_SYSTEM, name, extra_dir='vndk-sp')
316
317        # Add some unrelated libraries.
318        gb.add_multilib(PT_SYSTEM, 'libfoo')
319        gb.add_multilib(PT_SYSTEM, 'libbar', extra_dir='vndk-sp')
320
321        gb.resolve()
322
323        # Compute VNDK-SP-Indirect and check the result.
324        vndk_sp_indirect = gb.graph.compute_predefined_vndk_sp_indirect()
325        vndk_sp_indirect = set(lib.path for lib in vndk_sp_indirect)
326
327        for lib_dir_name in ('lib', 'lib64'):
328            lib_dir = '/system/' + lib_dir_name + '/vndk-sp'
329            for name in lib_names:
330                self.assertIn(os.path.join(lib_dir, name + '.so'),
331                              vndk_sp_indirect)
332
333        self.assertNotIn('/system/lib/libfoo.so', vndk_sp_indirect)
334        self.assertNotIn('/system/lib64/libfoo.so', vndk_sp_indirect)
335
336        self.assertNotIn('/system/lib/vndk-sp/libbar.so', vndk_sp_indirect)
337        self.assertNotIn('/system/lib64/vndk-sp/libbar.so', vndk_sp_indirect)
338
339    def test_compute_predefined_sp_hal(self):
340        gb = GraphBuilder()
341
342        # HIDL SP-HAL implementation.
343        gb.add_multilib(PT_SYSTEM, 'gralloc.default', extra_dir='hw')
344        gb.add_multilib(PT_SYSTEM, 'gralloc.chipset', extra_dir='hw')
345        gb.add_multilib(PT_SYSTEM, 'android.hardware.graphics.mapper@2.0-impl',
346                        extra_dir='hw')
347
348        # NDK loader libraries should not be considered as SP-HALs.
349        gb.add_multilib(PT_SYSTEM, 'libvulkan')
350        gb.add_multilib(PT_SYSTEM, 'libEGL')
351        gb.add_multilib(PT_SYSTEM, 'libGLESv1_CM')
352        gb.add_multilib(PT_SYSTEM, 'libGLESv2')
353        gb.add_multilib(PT_SYSTEM, 'libGLESv3')
354
355        # OpenGL implementation.
356        gb.add_multilib(PT_VENDOR, 'libEGL_chipset', extra_dir='egl')
357        gb.add_multilib(PT_VENDOR, 'libGLES_chipset', extra_dir='egl')
358        gb.add_multilib(PT_VENDOR, 'libGLESv1_CM_chipset', extra_dir='egl')
359        gb.add_multilib(PT_VENDOR, 'libGLESv2_chipset', extra_dir='egl')
360        gb.add_multilib(PT_VENDOR, 'libGLESv3_chipset', extra_dir='egl')
361
362        # Renderscript implementation.
363        gb.add_multilib(PT_VENDOR, 'libRSDriver_chipset')
364        gb.add_multilib(PT_VENDOR, 'libPVRRS')
365
366        # Vulkan implementation.
367        gb.add_multilib(PT_VENDOR, 'vulkan.chipset', extra_dir='hw')
368
369        # Some un-related libraries.
370        gb.add_multilib(PT_SYSTEM, 'libfoo')
371        gb.add_multilib(PT_VENDOR, 'libfoo')
372
373        gb.resolve()
374
375        # Compute SP-HAL.
376        sp_hals = set(lib.path for lib in gb.graph.compute_predefined_sp_hal())
377
378        for lib in ('lib', 'lib64'):
379            # Check HIDL SP-HAL implementation.
380            self.assertIn('/system/' + lib + '/hw/gralloc.default.so', sp_hals)
381            self.assertIn('/system/' + lib + '/hw/gralloc.chipset.so', sp_hals)
382            self.assertIn('/system/' + lib + '/hw/'
383                          'android.hardware.graphics.mapper@2.0-impl.so',
384                          sp_hals)
385
386
387            # Check that NDK loaders are not SP-HALs.
388            self.assertNotIn('/system/' + lib + '/libvulkan.so', sp_hals)
389            self.assertNotIn('/system/' + lib + '/libEGL.so', sp_hals)
390            self.assertNotIn('/system/' + lib + '/libGLESv1_CM.so', sp_hals)
391            self.assertNotIn('/system/' + lib + '/libGLESv2.so', sp_hals)
392            self.assertNotIn('/system/' + lib + '/libGLESv3.so', sp_hals)
393
394            # Check that OpenGL implementations are SP-HALs.
395            self.assertIn('/vendor/' + lib + '/egl/libEGL_chipset.so', sp_hals)
396            self.assertIn('/vendor/' + lib + '/egl/libGLES_chipset.so',
397                          sp_hals)
398            self.assertIn('/vendor/' + lib + '/egl/libGLESv1_CM_chipset.so',
399                          sp_hals)
400            self.assertIn('/vendor/' + lib + '/egl/libGLESv2_chipset.so',
401                          sp_hals)
402            self.assertIn('/vendor/' + lib + '/egl/libGLESv3_chipset.so',
403                          sp_hals)
404
405            # Check that Renderscript implementations are SP-HALs.
406            self.assertIn('/vendor/' + lib + '/libRSDriver_chipset.so', sp_hals)
407            self.assertIn('/vendor/' + lib + '/libPVRRS.so', sp_hals)
408
409            # Check that vulkan implementation are SP-HALs.
410            self.assertIn('/vendor/' + lib + '/libPVRRS.so', sp_hals)
411
412            # Check that un-related libraries are not SP-HALs.
413            self.assertNotIn('/system/' + lib + '/libfoo.so', sp_hals)
414            self.assertNotIn('/vendor/' + lib + '/libfoo.so', sp_hals)
415
416    def test_compute_sp_lib(self):
417        # Create graph.
418        gb = GraphBuilder()
419
420        # LL-NDK (should be excluded from result)
421        gb.add_multilib(PT_SYSTEM, 'libc')
422
423        # SP-Both VNDK-SP
424        gb.add_multilib(PT_SYSTEM, 'libsp_both_vs')
425
426        # SP-NDK VNDK-SP
427        gb.add_multilib(PT_SYSTEM, 'libcutils_dep', dt_needed=['libc.so'])
428        gb.add_multilib(PT_SYSTEM, 'libcutils',
429                        dt_needed=['libc.so', 'libcutils_dep.so',
430                                   'libsp_both_vs.so'])
431
432        # SP-NDK dependencies
433        gb.add_multilib(PT_SYSTEM, 'libutils',
434                        dt_needed=['libc.so', 'libcutils.so'])
435
436        # SP-NDK
437        gb.add_multilib(PT_SYSTEM, 'libEGL',
438                        dt_needed=['libc.so', 'libutils.so'])
439
440        # SP-HAL dependencies
441        gb.add_multilib(PT_VENDOR, 'libllvm_vendor_dep')
442        gb.add_multilib(PT_VENDOR, 'libllvm_vendor',
443                        dt_needed=['libc.so', 'libllvm_vendor_dep.so'])
444
445        # SP-HAL VNDK-SP
446        gb.add_multilib(PT_SYSTEM, 'libhidlbase')
447        gb.add_multilib(PT_SYSTEM, 'libhidlmemory',
448                        dt_needed=['libhidlbase.so', 'libsp_both_vs.so'])
449
450        # SP-HAL
451        gb.add_multilib(PT_VENDOR, 'libEGL_chipset', extra_dir='egl',
452                        dt_needed=['libc.so', 'libllvm_vendor.so',
453                                   'libhidlmemory.so'])
454
455        gb.resolve()
456
457        # Create generic reference.
458        class MockGenericRefs(object):
459            def classify_lib(self, lib):
460                if 'libllvm_vendor' in lib.path:
461                    return GenericRefs.NEW_LIB
462                return GenericRefs.EXPORT_EQUAL
463
464        sp_lib = gb.graph.compute_sp_lib(MockGenericRefs())
465
466        self.assertEqual(2 * 1, len(sp_lib.sp_hal))
467        self.assertEqual(2 * 2, len(sp_lib.sp_hal_dep))
468        self.assertEqual(2 * 2, len(sp_lib.vndk_sp_hal))
469        self.assertEqual(2 * 1, len(sp_lib.sp_ndk))
470        self.assertEqual(2 * 3, len(sp_lib.sp_ndk_indirect))
471        self.assertEqual(2 * 1, len(sp_lib.vndk_sp_both))
472
473        sp_hal = self._get_paths_from_nodes(sp_lib.sp_hal)
474        sp_hal_dep = self._get_paths_from_nodes(sp_lib.sp_hal_dep)
475        vndk_sp_hal = self._get_paths_from_nodes(sp_lib.vndk_sp_hal)
476
477        sp_ndk = self._get_paths_from_nodes(sp_lib.sp_ndk)
478        sp_ndk_indirect = self._get_paths_from_nodes(sp_lib.sp_ndk_indirect)
479
480        vndk_sp_both = self._get_paths_from_nodes(sp_lib.vndk_sp_both)
481
482        for lib_dir in ('lib', 'lib64'):
483            # SP-Both
484            self.assertIn('/system/{}/libsp_both_vs.so'.format(lib_dir),
485                          vndk_sp_both)
486
487            # SP-NDK dependencies
488            self.assertIn('/system/{}/libcutils.so'.format(lib_dir),
489                          sp_ndk_indirect)
490            self.assertIn('/system/{}/libcutils_dep.so'.format(lib_dir),
491                          sp_ndk_indirect)
492            self.assertIn('/system/{}/libutils.so'.format(lib_dir),
493                          sp_ndk_indirect)
494
495            # SP-NDK
496            self.assertIn('/system/{}/libEGL.so'.format(lib_dir), sp_ndk)
497
498            # SP-HAL dependencies
499            self.assertIn('/vendor/{}/libllvm_vendor.so'.format(lib_dir),
500                          sp_hal_dep)
501            self.assertIn('/vendor/{}/libllvm_vendor_dep.so'.format(lib_dir),
502                          sp_hal_dep)
503
504            # SP-HAL VNDK-SP
505            self.assertIn('/system/{}/libhidlbase.so'.format(lib_dir),
506                          vndk_sp_hal)
507            self.assertIn('/system/{}/libhidlmemory.so'.format(lib_dir),
508                          vndk_sp_hal)
509
510            # SP-HAL
511            self.assertIn('/vendor/{}/egl/libEGL_chipset.so'.format(lib_dir),
512                          sp_hal)
513
514            # LL-NDK must be excluded.
515            libc_path = '/system/{}/libc.so'.format(lib_dir)
516            self.assertNotIn(libc_path, sp_hal)
517            self.assertNotIn(libc_path, sp_hal_dep)
518            self.assertNotIn(libc_path, vndk_sp_hal)
519            self.assertNotIn(libc_path, sp_ndk)
520            self.assertNotIn(libc_path, sp_ndk_indirect)
521
522
523    def test_compute_vndk_cap(self):
524        gb = GraphBuilder()
525
526        # Add LL-NDK libraries.
527        gb.add_multilib(PT_SYSTEM, 'libc')
528        gb.add_multilib(PT_SYSTEM, 'libdl')
529        gb.add_multilib(PT_SYSTEM, 'liblog')
530        gb.add_multilib(PT_SYSTEM, 'libm')
531        gb.add_multilib(PT_SYSTEM, 'libstdc++')
532
533        # Add SP-NDK libraries.
534        gb.add_multilib(PT_SYSTEM, 'libEGL')
535        gb.add_multilib(PT_SYSTEM, 'libGLES_v2')
536
537        # Add banned libraries.
538        gb.add_multilib(PT_SYSTEM, 'libbinder')
539        gb.add_multilib(PT_SYSTEM, 'libselinux')
540
541        # Add good examples.
542        gb.add_multilib(PT_SYSTEM, 'libgood_a', dt_needed=['libc.so'])
543        gb.add_multilib(PT_SYSTEM, 'libgood_b', dt_needed=['libEGL.so'])
544        gb.add_multilib(PT_SYSTEM, 'libgood_c', dt_needed=['libGLES_v2.so'])
545
546        # Add bad examples.
547        gb.add_multilib(PT_SYSTEM, 'libbad_a', dt_needed=['libbinder.so'])
548        gb.add_multilib(PT_SYSTEM, 'libbad_b', dt_needed=['libselinux.so'])
549        gb.add_multilib(PT_SYSTEM, 'libbad_c', dt_needed=['libbad_a.so'])
550        gb.add_multilib(PT_SYSTEM, 'libbad_d', dt_needed=['libbad_c.so'])
551        gb.add_multilib(PT_VENDOR, 'libbad_e', dt_needed=['libc.so'])
552
553        gb.resolve()
554
555        # Compute VNDK cap.
556        banned_libs = BannedLibDict.create_default()
557        vndk_cap = gb.graph.compute_vndk_cap(banned_libs)
558        vndk_cap = set(lib.path for lib in vndk_cap)
559
560        # Check the existence of good examples.
561        self.assertIn('/system/lib/libgood_a.so', vndk_cap)
562        self.assertIn('/system/lib/libgood_b.so', vndk_cap)
563        self.assertIn('/system/lib/libgood_c.so', vndk_cap)
564
565        self.assertIn('/system/lib64/libgood_a.so', vndk_cap)
566        self.assertIn('/system/lib64/libgood_b.so', vndk_cap)
567        self.assertIn('/system/lib64/libgood_c.so', vndk_cap)
568
569        # Check the absence of bad examples.
570        self.assertNotIn('/system/lib/libbad_a.so', vndk_cap)
571        self.assertNotIn('/system/lib/libbad_b.so', vndk_cap)
572        self.assertNotIn('/system/lib/libbad_c.so', vndk_cap)
573        self.assertNotIn('/system/lib/libbad_d.so', vndk_cap)
574        self.assertNotIn('/vendor/lib/libbad_e.so', vndk_cap)
575
576        self.assertNotIn('/system/lib64/libbad_a.so', vndk_cap)
577        self.assertNotIn('/system/lib64/libbad_b.so', vndk_cap)
578        self.assertNotIn('/system/lib64/libbad_c.so', vndk_cap)
579        self.assertNotIn('/system/lib64/libbad_d.so', vndk_cap)
580        self.assertNotIn('/vendor/lib64/libbad_e.so', vndk_cap)
581
582        # Check the absence of banned libraries.
583        self.assertNotIn('/system/lib/libbinder.so', vndk_cap)
584        self.assertNotIn('/system/lib/libselinux.so', vndk_cap)
585
586        self.assertNotIn('/system/lib64/libbinder.so', vndk_cap)
587        self.assertNotIn('/system/lib64/libselinux.so', vndk_cap)
588
589        # Check the absence of NDK libraries.  Although LL-NDK and SP-NDK
590        # libraries are not banned, they are not VNDK libraries either.
591        self.assertNotIn('/system/lib/libEGL.so', vndk_cap)
592        self.assertNotIn('/system/lib/libOpenGLES_v2.so', vndk_cap)
593        self.assertNotIn('/system/lib/libc.so', vndk_cap)
594        self.assertNotIn('/system/lib/libdl.so', vndk_cap)
595        self.assertNotIn('/system/lib/liblog.so', vndk_cap)
596        self.assertNotIn('/system/lib/libm.so', vndk_cap)
597        self.assertNotIn('/system/lib/libstdc++.so', vndk_cap)
598
599        self.assertNotIn('/system/lib64/libEGL.so', vndk_cap)
600        self.assertNotIn('/system/lib64/libOpenGLES_v2.so', vndk_cap)
601        self.assertNotIn('/system/lib64/libc.so', vndk_cap)
602        self.assertNotIn('/system/lib64/libdl.so', vndk_cap)
603        self.assertNotIn('/system/lib64/liblog.so', vndk_cap)
604        self.assertNotIn('/system/lib64/libm.so', vndk_cap)
605        self.assertNotIn('/system/lib64/libstdc++.so', vndk_cap)
606
607if __name__ == '__main__':
608    unittest.main()
609