1 #!/usr/bin/env python3 2 3 import os 4 import re 5 import sys 6 import tempfile 7 import unittest 8 9 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) 10 11 from compat import StringIO, patch 12 from utils import GraphBuilder 13 from vndk_definition_tool import ( 14 ELF, ELFLinker, GenericRefs, PT_SYSTEM, PT_VENDOR, VNDKLibDir) 15 16 17 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) 18 19 20 class ELFLinkerTest(unittest.TestCase): 21 def _create_normal_graph(self): 22 gb = GraphBuilder() 23 24 gb.add_multilib(PT_SYSTEM, 'libdl', 25 exported_symbols={'dlclose', 'dlopen', 'dlsym'}) 26 27 gb.add_multilib(PT_SYSTEM, 'libm', exported_symbols={'cos', 'sin'}) 28 29 gb.add_multilib(PT_SYSTEM, 'libc', dt_needed=['libdl.so', 'libm.so'], 30 exported_symbols={'fclose', 'fopen', 'fread'}, 31 imported_symbols={'dlclose', 'dlopen', 'cos', 'sin'}) 32 33 gb.add_multilib(PT_SYSTEM, 'libRS', dt_needed=['libdl.so'], 34 exported_symbols={'rsContextCreate'}, 35 imported_symbols={'dlclose', 'dlopen', 'dlsym'}) 36 37 gb.add_multilib(PT_SYSTEM, 'libcutils', 38 dt_needed=['libc.so', 'libdl.so'], 39 imported_symbols={'dlclose', 'dlopen', 'fclose', 40 'fopen'}) 41 42 gb.add_multilib(PT_VENDOR, 'libEGL', 43 dt_needed=['libc.so', 'libcutils.so', 'libdl.so'], 44 exported_symbols={'eglGetDisplay'}, 45 imported_symbols={'fclose', 'fopen'}) 46 47 gb.resolve() 48 return gb 49 50 51 def _get_paths_from_nodes(self, nodes): 52 return sorted([node.path for node in nodes]) 53 54 55 def test_get_lib(self): 56 gb = self._create_normal_graph() 57 graph = gb.graph 58 59 node = graph.get_lib('/system/lib/libc.so') 60 self.assertEqual(gb.libc_32, node) 61 self.assertEqual('/system/lib/libc.so', node.path) 62 63 node = graph.get_lib('/system/lib64/libdl.so') 64 self.assertEqual(gb.libdl_64, node) 65 self.assertEqual('/system/lib64/libdl.so', node.path) 66 67 node = graph.get_lib('/vendor/lib64/libEGL.so') 68 self.assertEqual(gb.libEGL_64, node) 69 self.assertEqual('/vendor/lib64/libEGL.so', node.path) 70 71 self.assertEqual(None, graph.get_lib('/no/such/path.so')) 72 73 74 def test_map_paths_to_libs(self): 75 gb = self._create_normal_graph() 76 graph = gb.graph 77 78 bad = [] 79 paths = ['/system/lib/libc.so', '/system/lib/libdl.so'] 80 nodes = graph.get_libs(paths, bad.append) 81 82 self.assertEqual([], bad) 83 self.assertEqual(2, len(nodes)) 84 self.assertEqual(paths, self._get_paths_from_nodes(nodes)) 85 86 bad = [] 87 paths = ['/no/such/path.so', '/system/lib64/libdl.so'] 88 nodes = graph.get_libs(paths, bad.append) 89 self.assertEqual(['/no/such/path.so'], bad) 90 self.assertEqual(['/system/lib64/libdl.so'], 91 self._get_paths_from_nodes(nodes)) 92 93 94 def test_elf_class_and_partitions(self): 95 gb = self._create_normal_graph() 96 graph = gb.graph 97 self.assertEqual(5, len(graph.lib_pt[PT_SYSTEM].lib32)) 98 self.assertEqual(5, len(graph.lib_pt[PT_SYSTEM].lib64)) 99 self.assertEqual(1, len(graph.lib_pt[PT_VENDOR].lib32)) 100 self.assertEqual(1, len(graph.lib_pt[PT_VENDOR].lib64)) 101 102 103 def test_deps(self): 104 gb = self._create_normal_graph() 105 graph = gb.graph 106 107 # Check the dependencies of libc.so. 108 node = gb.graph.get_lib('/system/lib/libc.so') 109 self.assertEqual(['/system/lib/libdl.so', '/system/lib/libm.so'], 110 self._get_paths_from_nodes(node.deps_all)) 111 112 # Check the dependencies of libRS.so. 113 node = gb.graph.get_lib('/system/lib64/libRS.so') 114 self.assertEqual(['/system/lib64/libdl.so'], 115 self._get_paths_from_nodes(node.deps_all)) 116 117 # Check the dependencies of libEGL.so. 118 node = gb.graph.get_lib('/vendor/lib64/libEGL.so') 119 self.assertEqual(['/system/lib64/libc.so', '/system/lib64/libcutils.so', 120 '/system/lib64/libdl.so'], 121 self._get_paths_from_nodes(node.deps_all)) 122 123 124 def test_linked_symbols(self): 125 gb = self._create_normal_graph() 126 graph = gb.graph 127 128 # Check the unresolved symbols. 129 for lib_set in graph.lib_pt: 130 for lib in lib_set.values(): 131 self.assertEqual(set(), lib.unresolved_symbols) 132 133 # Check the linked symbols. 134 for lib in ('lib', 'lib64'): 135 libdl = graph.get_lib('/system/' + lib + '/libdl.so') 136 libm = graph.get_lib('/system/' + lib + '/libm.so') 137 libc = graph.get_lib('/system/' + lib + '/libc.so') 138 libRS = graph.get_lib('/system/' + lib + '/libRS.so') 139 libcutils = \ 140 graph.get_lib('/system/' + lib + '/libcutils.so') 141 libEGL = graph.get_lib('/vendor/' + lib + '/libEGL.so') 142 143 # Check the linked symbols for libc.so. 144 self.assertIs(libdl, libc.linked_symbols['dlclose']) 145 self.assertIs(libdl, libc.linked_symbols['dlopen']) 146 self.assertIs(libm, libc.linked_symbols['cos']) 147 self.assertIs(libm, libc.linked_symbols['sin']) 148 149 # Check the linked symbols for libRS.so. 150 self.assertIs(libdl, libRS.linked_symbols['dlclose']) 151 self.assertIs(libdl, libRS.linked_symbols['dlopen']) 152 self.assertIs(libdl, libRS.linked_symbols['dlsym']) 153 154 # Check the linked symbols for libcutils.so. 155 self.assertIs(libdl, libcutils.linked_symbols['dlclose']) 156 self.assertIs(libdl, libcutils.linked_symbols['dlopen']) 157 self.assertIs(libc, libcutils.linked_symbols['fclose']) 158 self.assertIs(libc, libcutils.linked_symbols['fopen']) 159 160 # Check the linked symbols for libEGL.so. 161 self.assertIs(libc, libEGL.linked_symbols['fclose']) 162 self.assertIs(libc, libEGL.linked_symbols['fopen']) 163 164 165 def test_unresolved_symbols(self): 166 gb = GraphBuilder() 167 gb.add_lib(PT_SYSTEM, ELF.ELFCLASS64, 'libfoo', dt_needed=[], 168 exported_symbols={'foo', 'bar'}, 169 imported_symbols={'__does_not_exist'}) 170 gb.resolve() 171 172 lib = gb.graph.get_lib('/system/lib64/libfoo.so') 173 self.assertEqual({'__does_not_exist'}, lib.unresolved_symbols) 174 175 176 def test_users(self): 177 gb = self._create_normal_graph() 178 graph = gb.graph 179 180 # Check the users of libc.so. 181 node = graph.get_lib('/system/lib/libc.so') 182 self.assertEqual(['/system/lib/libcutils.so', '/vendor/lib/libEGL.so'], 183 self._get_paths_from_nodes(node.users_all)) 184 185 # Check the users of libdl.so. 186 node = graph.get_lib('/system/lib/libdl.so') 187 self.assertEqual(['/system/lib/libRS.so', '/system/lib/libc.so', 188 '/system/lib/libcutils.so', '/vendor/lib/libEGL.so'], 189 self._get_paths_from_nodes(node.users_all)) 190 191 # Check the users of libRS.so. 192 node = graph.get_lib('/system/lib64/libRS.so') 193 self.assertEqual([], self._get_paths_from_nodes(node.users_all)) 194 195 # Check the users of libEGL.so. 196 node = graph.get_lib('/vendor/lib64/libEGL.so') 197 self.assertEqual([], self._get_paths_from_nodes(node.users_all)) 198 199 200 def test_compute_predefined_sp_hal(self): 201 gb = GraphBuilder() 202 203 # HIDL SP-HAL implementation. 204 gb.add_multilib(PT_SYSTEM, 'gralloc.default', extra_dir='hw') 205 gb.add_multilib(PT_SYSTEM, 'gralloc.chipset', extra_dir='hw') 206 gb.add_multilib(PT_SYSTEM, 'android.hardware.graphics.mapper (at] 2.0-impl', 207 extra_dir='hw') 208 209 # NDK loader libraries should not be considered as SP-HALs. 210 gb.add_multilib(PT_SYSTEM, 'libvulkan') 211 gb.add_multilib(PT_SYSTEM, 'libEGL') 212 gb.add_multilib(PT_SYSTEM, 'libGLESv1_CM') 213 gb.add_multilib(PT_SYSTEM, 'libGLESv2') 214 gb.add_multilib(PT_SYSTEM, 'libGLESv3') 215 216 # OpenGL implementation. 217 gb.add_multilib(PT_VENDOR, 'libEGL_chipset', extra_dir='egl') 218 gb.add_multilib(PT_VENDOR, 'libGLES_chipset', extra_dir='egl') 219 gb.add_multilib(PT_VENDOR, 'libGLESv1_CM_chipset', extra_dir='egl') 220 gb.add_multilib(PT_VENDOR, 'libGLESv2_chipset', extra_dir='egl') 221 gb.add_multilib(PT_VENDOR, 'libGLESv3_chipset', extra_dir='egl') 222 223 # Renderscript implementation. 224 gb.add_multilib(PT_VENDOR, 'libRSDriver_chipset') 225 gb.add_multilib(PT_VENDOR, 'libPVRRS') 226 227 # Vulkan implementation. 228 gb.add_multilib(PT_VENDOR, 'vulkan.chipset', extra_dir='hw') 229 230 # Some un-related libraries. 231 gb.add_multilib(PT_SYSTEM, 'libfoo') 232 gb.add_multilib(PT_VENDOR, 'libfoo') 233 234 gb.resolve() 235 236 # Compute SP-HAL. 237 sp_hals = set(lib.path for lib in gb.graph.compute_predefined_sp_hal()) 238 239 for lib in ('lib', 'lib64'): 240 # Check HIDL SP-HAL implementation. 241 self.assertIn('/system/' + lib + '/hw/gralloc.default.so', sp_hals) 242 self.assertIn('/system/' + lib + '/hw/gralloc.chipset.so', sp_hals) 243 self.assertIn('/system/' + lib + '/hw/' 244 'android.hardware.graphics.mapper (at] 2.0-impl.so', 245 sp_hals) 246 247 248 # Check that NDK loaders are not SP-HALs. 249 self.assertNotIn('/system/' + lib + '/libvulkan.so', sp_hals) 250 self.assertNotIn('/system/' + lib + '/libEGL.so', sp_hals) 251 self.assertNotIn('/system/' + lib + '/libGLESv1_CM.so', sp_hals) 252 self.assertNotIn('/system/' + lib + '/libGLESv2.so', sp_hals) 253 self.assertNotIn('/system/' + lib + '/libGLESv3.so', sp_hals) 254 255 # Check that OpenGL implementations are SP-HALs. 256 self.assertIn('/vendor/' + lib + '/egl/libEGL_chipset.so', sp_hals) 257 self.assertIn('/vendor/' + lib + '/egl/libGLES_chipset.so', 258 sp_hals) 259 self.assertIn('/vendor/' + lib + '/egl/libGLESv1_CM_chipset.so', 260 sp_hals) 261 self.assertIn('/vendor/' + lib + '/egl/libGLESv2_chipset.so', 262 sp_hals) 263 self.assertIn('/vendor/' + lib + '/egl/libGLESv3_chipset.so', 264 sp_hals) 265 266 # Check that Renderscript implementations are SP-HALs. 267 self.assertIn('/vendor/' + lib + '/libRSDriver_chipset.so', sp_hals) 268 self.assertIn('/vendor/' + lib + '/libPVRRS.so', sp_hals) 269 270 # Check that vulkan implementation are SP-HALs. 271 self.assertIn('/vendor/' + lib + '/libPVRRS.so', sp_hals) 272 273 # Check that un-related libraries are not SP-HALs. 274 self.assertNotIn('/system/' + lib + '/libfoo.so', sp_hals) 275 self.assertNotIn('/vendor/' + lib + '/libfoo.so', sp_hals) 276 277 278 def test_compute_sp_lib(self): 279 # Create graph. 280 gb = GraphBuilder() 281 282 # LL-NDK (should be excluded from result) 283 gb.add_multilib(PT_SYSTEM, 'libc') 284 285 libEGL_32, libEGL_64 = \ 286 gb.add_multilib(PT_SYSTEM, 'libEGL', 287 dt_needed=['libc.so', 'libutils.so']) 288 289 # LL-NDK dependencies 290 gb.add_multilib(PT_SYSTEM, 'libutils', 291 dt_needed=['libc.so', 'libcutils.so']) 292 293 # VNDK-SP used by both LL-NDK and SP-HAL 294 gb.add_multilib(PT_SYSTEM, 'libsp_both_vs') 295 296 # VNDK-SP used by LL-NDK 297 gb.add_multilib(PT_SYSTEM, 'libcutils_dep', dt_needed=['libc.so']) 298 gb.add_multilib(PT_SYSTEM, 'libcutils', 299 dt_needed=['libc.so', 'libcutils_dep.so', 300 'libsp_both_vs.so']) 301 302 # VNDK-SP used by SP-HAL 303 gb.add_multilib(PT_SYSTEM, 'libhidlbase') 304 gb.add_multilib(PT_SYSTEM, 'libhidlmemory', 305 dt_needed=['libhidlbase.so', 'libsp_both_vs.so']) 306 307 # SP-HAL dependencies 308 gb.add_multilib(PT_VENDOR, 'libllvm_vendor_dep') 309 gb.add_multilib(PT_VENDOR, 'libllvm_vendor', 310 dt_needed=['libc.so', 'libllvm_vendor_dep.so']) 311 312 # SP-HAL 313 libEGL_chipset_32, libEGL_chipset_64 = \ 314 gb.add_multilib(PT_VENDOR, 'libEGL_chipset', extra_dir='egl', 315 dt_needed=['libc.so', 'libllvm_vendor.so', 316 'libhidlmemory.so']) 317 318 gb.resolve() 319 320 # Add dlopen() dependencies from libEGL to libEGL_chipset. 321 libEGL_32.add_dlopen_dep(libEGL_chipset_32) 322 libEGL_64.add_dlopen_dep(libEGL_chipset_64) 323 324 # Create generic reference. 325 class MockGenericRefs(object): 326 def classify_lib(self, lib): 327 if 'libllvm_vendor' in lib.path: 328 return GenericRefs.NEW_LIB 329 return GenericRefs.EXPORT_EQUAL 330 331 sp_lib = gb.graph.compute_sp_lib(MockGenericRefs()) 332 333 self.assertEqual(2 * 1, len(sp_lib.sp_hal)) 334 self.assertEqual(2 * 2, len(sp_lib.sp_hal_dep)) 335 self.assertEqual(2 * 2, len(sp_lib.vndk_sp_hal)) 336 self.assertEqual(2 * 2, len(sp_lib.ll_ndk)) 337 self.assertEqual(2 * 3, len(sp_lib.ll_ndk_indirect)) 338 self.assertEqual(2 * 1, len(sp_lib.vndk_sp_both)) 339 340 sp_hal = self._get_paths_from_nodes(sp_lib.sp_hal) 341 sp_hal_dep = self._get_paths_from_nodes(sp_lib.sp_hal_dep) 342 vndk_sp_hal = self._get_paths_from_nodes(sp_lib.vndk_sp_hal) 343 344 ll_ndk = self._get_paths_from_nodes(sp_lib.ll_ndk) 345 ll_ndk_indirect = self._get_paths_from_nodes(sp_lib.ll_ndk_indirect) 346 347 vndk_sp_both = self._get_paths_from_nodes(sp_lib.vndk_sp_both) 348 349 for lib_dir in ('lib', 'lib64'): 350 # VNDK-SP used by both LL-NDK and SP-HAL 351 self.assertIn('/system/{}/libsp_both_vs.so'.format(lib_dir), 352 vndk_sp_both) 353 354 # VNDK-SP used by LL-NDK 355 self.assertIn('/system/{}/libcutils.so'.format(lib_dir), 356 ll_ndk_indirect) 357 self.assertIn('/system/{}/libcutils_dep.so'.format(lib_dir), 358 ll_ndk_indirect) 359 self.assertIn('/system/{}/libutils.so'.format(lib_dir), 360 ll_ndk_indirect) 361 362 # VNDK-SP used by SP-HAL 363 self.assertIn('/system/{}/libhidlbase.so'.format(lib_dir), 364 vndk_sp_hal) 365 self.assertIn('/system/{}/libhidlmemory.so'.format(lib_dir), 366 vndk_sp_hal) 367 368 # SP-HAL dependencies 369 self.assertIn('/vendor/{}/libllvm_vendor.so'.format(lib_dir), 370 sp_hal_dep) 371 self.assertIn('/vendor/{}/libllvm_vendor_dep.so'.format(lib_dir), 372 sp_hal_dep) 373 374 # SP-HAL 375 self.assertIn('/vendor/{}/egl/libEGL_chipset.so'.format(lib_dir), 376 sp_hal) 377 378 # LL-NDK 379 self.assertIn('/system/{}/libEGL.so'.format(lib_dir), ll_ndk) 380 self.assertIn('/system/{}/libc.so'.format(lib_dir), ll_ndk) 381 382 # LL-NDK must not in sp_hal, sp_hal_dep, and vndk_sp_hal. 383 libc_path = '/system/{}/libc.so'.format(lib_dir) 384 self.assertNotIn(libc_path, sp_hal) 385 self.assertNotIn(libc_path, sp_hal_dep) 386 self.assertNotIn(libc_path, vndk_sp_hal) 387 self.assertNotIn(libc_path, ll_ndk_indirect) 388 389 390 def test_link_vndk_ver_dirs(self): 391 gb = GraphBuilder() 392 393 libc_32, libc_64 = gb.add_multilib(PT_SYSTEM, 'libc') 394 395 libvndk_a_32, libvndk_a_64 = gb.add_multilib( 396 PT_SYSTEM, 'libvndk_a', extra_dir='vndk-28', 397 dt_needed=['libc.so', 'libvndk_b.so', 'libvndk_sp_b.so']) 398 399 libvndk_b_32, libvndk_b_64 = gb.add_multilib( 400 PT_SYSTEM, 'libvndk_b', extra_dir='vndk-28', 401 dt_needed=['libc.so', 'libvndk_sp_b.so']) 402 403 libvndk_c_32, libvndk_c_64 = gb.add_multilib( 404 PT_VENDOR, 'libvndk_c', extra_dir='vndk-28', 405 dt_needed=['libc.so', 'libvndk_d.so', 'libvndk_sp_d.so']) 406 407 libvndk_d_32, libvndk_d_64 = gb.add_multilib( 408 PT_VENDOR, 'libvndk_d', extra_dir='vndk-28', 409 dt_needed=['libc.so', 'libvndk_sp_d.so']) 410 411 libvndk_sp_a_32, libvndk_sp_a_64 = gb.add_multilib( 412 PT_SYSTEM, 'libvndk_sp_a', extra_dir='vndk-sp-28', 413 dt_needed=['libc.so', 'libvndk_sp_b.so']) 414 415 libvndk_sp_b_32, libvndk_sp_b_64 = gb.add_multilib( 416 PT_SYSTEM, 'libvndk_sp_b', extra_dir='vndk-sp-28', 417 dt_needed=['libc.so']) 418 419 libvndk_sp_c_32, libvndk_sp_c_64 = gb.add_multilib( 420 PT_VENDOR, 'libvndk_sp_c', extra_dir='vndk-sp-28', 421 dt_needed=['libc.so', 'libvndk_sp_d.so']) 422 423 libvndk_sp_d_32, libvndk_sp_d_64 = gb.add_multilib( 424 PT_VENDOR, 'libvndk_sp_d', extra_dir='vndk-sp-28', 425 dt_needed=['libc.so']) 426 427 gb.resolve(VNDKLibDir.create_from_version('28'), '28') 428 429 # 32-bit shared libraries 430 self.assertIn(libc_32, libvndk_a_32.deps_all) 431 self.assertIn(libc_32, libvndk_b_32.deps_all) 432 self.assertIn(libc_32, libvndk_c_32.deps_all) 433 self.assertIn(libc_32, libvndk_d_32.deps_all) 434 self.assertIn(libc_32, libvndk_sp_a_32.deps_all) 435 self.assertIn(libc_32, libvndk_sp_b_32.deps_all) 436 self.assertIn(libc_32, libvndk_sp_c_32.deps_all) 437 self.assertIn(libc_32, libvndk_sp_d_32.deps_all) 438 439 self.assertIn(libvndk_b_32, libvndk_a_32.deps_all) 440 self.assertIn(libvndk_sp_b_32, libvndk_a_32.deps_all) 441 self.assertIn(libvndk_sp_b_32, libvndk_b_32.deps_all) 442 self.assertIn(libvndk_sp_b_32, libvndk_sp_a_32.deps_all) 443 444 self.assertIn(libvndk_d_32, libvndk_c_32.deps_all) 445 self.assertIn(libvndk_sp_d_32, libvndk_c_32.deps_all) 446 self.assertIn(libvndk_sp_d_32, libvndk_d_32.deps_all) 447 self.assertIn(libvndk_sp_d_32, libvndk_sp_c_32.deps_all) 448 449 # 64-bit shared libraries 450 self.assertIn(libc_64, libvndk_a_64.deps_all) 451 self.assertIn(libc_64, libvndk_b_64.deps_all) 452 self.assertIn(libc_64, libvndk_c_64.deps_all) 453 self.assertIn(libc_64, libvndk_d_64.deps_all) 454 self.assertIn(libc_64, libvndk_sp_a_64.deps_all) 455 self.assertIn(libc_64, libvndk_sp_b_64.deps_all) 456 self.assertIn(libc_64, libvndk_sp_c_64.deps_all) 457 self.assertIn(libc_64, libvndk_sp_d_64.deps_all) 458 459 self.assertIn(libvndk_b_64, libvndk_a_64.deps_all) 460 self.assertIn(libvndk_sp_b_64, libvndk_a_64.deps_all) 461 self.assertIn(libvndk_sp_b_64, libvndk_b_64.deps_all) 462 self.assertIn(libvndk_sp_b_64, libvndk_sp_a_64.deps_all) 463 464 self.assertIn(libvndk_d_64, libvndk_c_64.deps_all) 465 self.assertIn(libvndk_sp_d_64, libvndk_c_64.deps_all) 466 self.assertIn(libvndk_sp_d_64, libvndk_d_64.deps_all) 467 self.assertIn(libvndk_sp_d_64, libvndk_sp_c_64.deps_all) 468 469 470 class ELFLinkerDlopenDepsTest(unittest.TestCase): 471 def test_add_dlopen_deps(self): 472 gb = GraphBuilder() 473 liba = gb.add_lib32(PT_SYSTEM, 'liba') 474 libb = gb.add_lib32(PT_SYSTEM, 'libb') 475 gb.resolve() 476 477 with tempfile.NamedTemporaryFile(mode='w') as tmp_file: 478 tmp_file.write('/system/lib/liba.so: /system/lib/libb.so') 479 tmp_file.seek(0) 480 gb.graph.add_dlopen_deps(tmp_file.name) 481 482 self.assertIn(libb, liba.deps_dlopen) 483 self.assertIn(liba, libb.users_dlopen) 484 485 self.assertNotIn(libb, liba.deps_needed) 486 self.assertNotIn(liba, libb.users_needed) 487 488 489 def test_add_dlopen_deps_lib_subst(self): 490 gb = GraphBuilder() 491 liba_32, liba_64 = gb.add_multilib(PT_SYSTEM, 'liba') 492 libb_32, libb_64 = gb.add_multilib(PT_SYSTEM, 'libb') 493 gb.resolve() 494 495 with tempfile.NamedTemporaryFile(mode='w') as tmp_file: 496 tmp_file.write('/system/${LIB}/liba.so: /system/${LIB}/libb.so') 497 tmp_file.seek(0) 498 gb.graph.add_dlopen_deps(tmp_file.name) 499 500 self.assertIn(libb_32, liba_32.deps_dlopen) 501 self.assertIn(liba_32, libb_32.users_dlopen) 502 503 self.assertIn(libb_64, liba_64.deps_dlopen) 504 self.assertIn(liba_64, libb_64.users_dlopen) 505 506 507 def test_add_dlopen_deps_lib_subset_single_bitness(self): 508 gb = GraphBuilder() 509 liba_32, liba_64 = gb.add_multilib(PT_SYSTEM, 'liba') 510 libb_32 = gb.add_lib32(PT_SYSTEM, 'libb') 511 gb.resolve() 512 513 with tempfile.NamedTemporaryFile(mode='w') as tmp_file: 514 tmp_file.write('/system/${LIB}/libb.so: /system/${LIB}/liba.so') 515 tmp_file.seek(0) 516 517 stderr = StringIO() 518 with patch('sys.stderr', stderr): 519 gb.graph.add_dlopen_deps(tmp_file.name) 520 521 self.assertEqual('', stderr.getvalue()) 522 523 self.assertIn(liba_32, libb_32.deps_dlopen) 524 self.assertIn(libb_32, liba_32.users_dlopen) 525 526 self.assertEqual(0, len(liba_64.users_dlopen)) 527 528 529 def test_add_dlopen_deps_regex(self): 530 gb = GraphBuilder() 531 liba = gb.add_lib32(PT_SYSTEM, 'liba') 532 libb = gb.add_lib32(PT_SYSTEM, 'libb') 533 gb.resolve() 534 535 with tempfile.NamedTemporaryFile(mode='w') as tmp_file: 536 tmp_file.write('[regex].*libb\\.so: [regex].*/${LIB}/liba\\.so') 537 tmp_file.seek(0) 538 539 stderr = StringIO() 540 with patch('sys.stderr', stderr): 541 gb.graph.add_dlopen_deps(tmp_file.name) 542 543 self.assertEqual('', stderr.getvalue()) 544 545 self.assertIn(liba, libb.deps_dlopen) 546 self.assertIn(libb, liba.users_dlopen) 547 548 549 def test_add_dlopen_deps_error(self): 550 gb = GraphBuilder() 551 liba = gb.add_lib32(PT_SYSTEM, 'liba') 552 libb = gb.add_lib32(PT_SYSTEM, 'libb') 553 gb.resolve() 554 555 with tempfile.NamedTemporaryFile(mode='w') as tmp_file: 556 tmp_file.write('/system/lib/libc.so: /system/lib/libd.so') 557 tmp_file.seek(0) 558 559 stderr = StringIO() 560 with patch('sys.stderr', stderr): 561 gb.graph.add_dlopen_deps(tmp_file.name) 562 563 self.assertRegexpMatches( 564 stderr.getvalue(), 565 'error:' + re.escape(tmp_file.name) + ':1: ' + 566 'Failed to add dlopen dependency from .* to .*\\.\n') 567 568 569 if __name__ == '__main__': 570 unittest.main() 571