1 //===-- TextStubV5Tests.cpp - TBD V5 File Test ----------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===-----------------------------------------------------------------------===/ 8 9 #include "TextStubHelpers.h" 10 #include "llvm/TextAPI/InterfaceFile.h" 11 #include "llvm/TextAPI/TextAPIReader.h" 12 #include "llvm/TextAPI/TextAPIWriter.h" 13 #include "gtest/gtest.h" 14 #include <string> 15 #include <vector> 16 17 using namespace llvm; 18 using namespace llvm::MachO; 19 20 namespace TBDv5 { 21 22 TEST(TBDv5, ReadFile) { 23 static const char TBDv5File[] = R"({ 24 "tapi_tbd_version": 5, 25 "main_library": { 26 "target_info": [ 27 { 28 "target": "x86_64-macos", 29 "min_deployment": "10.14" 30 }, 31 { 32 "target": "arm64-macos", 33 "min_deployment": "10.14" 34 }, 35 { 36 "target": "arm64-maccatalyst", 37 "min_deployment": "12.1" 38 } 39 ], 40 "flags": [ 41 { 42 "targets": [ 43 "x86_64-macos" 44 ], 45 "attributes": [ 46 "flat_namespace" 47 ] 48 } 49 ], 50 "install_names": [ 51 { 52 "name": "/S/L/F/Foo.framework/Foo" 53 } 54 ], 55 "current_versions": [ 56 { 57 "version": "1.2" 58 } 59 ], 60 "compatibility_versions": [ 61 { "version": "1.1" } 62 ], 63 "rpaths": [ 64 { 65 "targets": [ 66 "x86_64-macos" 67 ], 68 "paths": [ 69 "@executable_path/.../Frameworks" 70 ] 71 } 72 ], 73 "parent_umbrellas": [ 74 { 75 "umbrella": "System" 76 } 77 ], 78 "allowable_clients": [ 79 { 80 "clients": [ 81 "ClientA", 82 "ClientB" 83 ] 84 } 85 ], 86 "reexported_libraries": [ 87 { 88 "names": [ 89 "/u/l/l/libfoo.dylib", 90 "/u/l/l/libbar.dylib" 91 ] 92 } 93 ], 94 "exported_symbols": [ 95 { 96 "targets": [ 97 "x86_64-macos", 98 "arm64-macos" 99 ], 100 "data": { 101 "global": [ 102 "_global" 103 ], 104 "objc_class": [ 105 "ClassA" 106 ], 107 "weak": [], 108 "thread_local": [] 109 }, 110 "text": { 111 "global": [ 112 "_func" 113 ], 114 "weak": [], 115 "thread_local": [] 116 } 117 }, 118 { 119 "targets": [ 120 "x86_64-macos" 121 ], 122 "data": { 123 "global": [ 124 "_globalVar" 125 ], 126 "objc_class": [ 127 "ClassA", 128 "ClassB", 129 "ClassData" 130 ], 131 "objc_eh_type": [ 132 "ClassA", 133 "ClassB" 134 ], 135 "objc_ivar": [ 136 "ClassA.ivar1", 137 "ClassA.ivar2", 138 "ClassC.ivar1" 139 ] 140 }, 141 "text": { 142 "global": [ 143 "_funcFoo" 144 ] 145 } 146 } 147 ], 148 "reexported_symbols": [ 149 { 150 "targets": [ 151 "x86_64-macos", 152 "arm64-macos" 153 ], 154 "data": { 155 "global": [ 156 "_globalRe" 157 ], 158 "objc_class": [ 159 "ClassRexport" 160 ] 161 }, 162 "text": { 163 "global": [ 164 "_funcA" 165 ] 166 } 167 } 168 ], 169 "undefined_symbols": [ 170 { 171 "targets": [ 172 "x86_64-macos" 173 ], 174 "data": { 175 "global": [ 176 "_globalBind" 177 ], 178 "weak": [ 179 "referenced_sym" 180 ] 181 } 182 } 183 ] 184 }, 185 "libraries": [] 186 })"; 187 188 MemoryBufferRef InputBuf = MemoryBufferRef(TBDv5File, "Test.tbd"); 189 Expected<FileType> ExpectedFT = TextAPIReader::canRead(InputBuf); 190 EXPECT_TRUE(!!ExpectedFT); 191 192 Expected<TBDFile> Result = TextAPIReader::get(InputBuf); 193 EXPECT_TRUE(!!Result); 194 TBDFile File = std::move(Result.get()); 195 EXPECT_EQ(FileType::TBD_V5, File->getFileType()); 196 EXPECT_EQ(*ExpectedFT, File->getFileType()); 197 EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"), File->getInstallName()); 198 199 TargetList AllTargets = { 200 Target(AK_x86_64, PLATFORM_MACOS, VersionTuple(10, 14)), 201 Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0, 0)), 202 Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(14, 0)), 203 }; 204 std::set<Target> FileTargets{File->targets().begin(), File->targets().end()}; 205 EXPECT_EQ(mapToPlatformSet(AllTargets), File->getPlatforms()); 206 EXPECT_EQ(mapToArchitectureSet(AllTargets), File->getArchitectures()); 207 EXPECT_EQ(FileTargets.size(), AllTargets.size()); 208 for (const auto &Targ : AllTargets) { 209 auto FileTarg = FileTargets.find(Targ); 210 EXPECT_FALSE(FileTarg == FileTargets.end()); 211 EXPECT_EQ(*FileTarg, Targ); 212 PackedVersion MD = Targ.MinDeployment; 213 PackedVersion FileMD = FileTarg->MinDeployment; 214 EXPECT_EQ(MD, FileMD); 215 } 216 217 EXPECT_EQ(PackedVersion(1, 2, 0), File->getCurrentVersion()); 218 EXPECT_EQ(PackedVersion(1, 1, 0), File->getCompatibilityVersion()); 219 EXPECT_TRUE(File->isApplicationExtensionSafe()); 220 EXPECT_FALSE(File->isTwoLevelNamespace()); 221 EXPECT_FALSE(File->isOSLibNotForSharedCache()); 222 EXPECT_EQ(0U, File->documents().size()); 223 224 InterfaceFileRef ClientA("ClientA", AllTargets); 225 InterfaceFileRef ClientB("ClientB", AllTargets); 226 EXPECT_EQ(2U, File->allowableClients().size()); 227 EXPECT_EQ(ClientA, File->allowableClients().at(0)); 228 EXPECT_EQ(ClientB, File->allowableClients().at(1)); 229 230 InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets); 231 InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets); 232 EXPECT_EQ(2U, File->reexportedLibraries().size()); 233 EXPECT_EQ(ReexportA, File->reexportedLibraries().at(0)); 234 EXPECT_EQ(ReexportB, File->reexportedLibraries().at(1)); 235 236 TargetToAttr RPaths = { 237 {Target(AK_x86_64, PLATFORM_MACOS), "@executable_path/.../Frameworks"}, 238 }; 239 EXPECT_EQ(RPaths, File->rpaths()); 240 241 TargetToAttr Umbrellas = {{Target(AK_x86_64, PLATFORM_MACOS), "System"}, 242 {Target(AK_arm64, PLATFORM_MACOS), "System"}, 243 {Target(AK_arm64, PLATFORM_MACCATALYST), "System"}}; 244 EXPECT_EQ(Umbrellas, File->umbrellas()); 245 246 ExportedSymbolSeq Exports, Reexports, Undefineds; 247 for (const auto *Sym : File->symbols()) { 248 TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()}; 249 ExportedSymbol Temp = 250 ExportedSymbol{Sym->getKind(), 251 std::string(Sym->getName()), 252 Sym->isWeakDefined() || Sym->isWeakReferenced(), 253 Sym->isThreadLocalValue(), 254 Sym->isData(), 255 SymTargets}; 256 if (Sym->isUndefined()) 257 Undefineds.emplace_back(std::move(Temp)); 258 else 259 Sym->isReexported() ? Reexports.emplace_back(std::move(Temp)) 260 : Exports.emplace_back(std::move(Temp)); 261 } 262 llvm::sort(Exports); 263 llvm::sort(Reexports); 264 llvm::sort(Undefineds); 265 266 TargetList MacOSTargets = {Target(AK_x86_64, PLATFORM_MACOS), 267 Target(AK_arm64, PLATFORM_MACOS)}; 268 269 std::vector<ExportedSymbol> ExpectedExportedSymbols = { 270 {EncodeKind::GlobalSymbol, "_func", false, false, false, MacOSTargets}, 271 {EncodeKind::GlobalSymbol, 272 "_funcFoo", 273 false, 274 false, 275 false, 276 {Target(AK_x86_64, PLATFORM_MACOS)}}, 277 {EncodeKind::GlobalSymbol, "_global", false, false, true, MacOSTargets}, 278 {EncodeKind::GlobalSymbol, 279 "_globalVar", 280 false, 281 false, 282 true, 283 {Target(AK_x86_64, PLATFORM_MACOS)}}, 284 {EncodeKind::ObjectiveCClass, 285 "ClassA", 286 false, 287 false, 288 true, 289 {Target(AK_x86_64, PLATFORM_MACOS)}}, 290 {EncodeKind::ObjectiveCClass, 291 "ClassB", 292 false, 293 false, 294 true, 295 {Target(AK_x86_64, PLATFORM_MACOS)}}, 296 {EncodeKind::ObjectiveCClass, 297 "ClassData", 298 false, 299 false, 300 true, 301 {Target(AK_x86_64, PLATFORM_MACOS)}}, 302 {EncodeKind::ObjectiveCClassEHType, 303 "ClassA", 304 false, 305 false, 306 true, 307 {Target(AK_x86_64, PLATFORM_MACOS)}}, 308 {EncodeKind::ObjectiveCClassEHType, 309 "ClassB", 310 false, 311 false, 312 true, 313 {Target(AK_x86_64, PLATFORM_MACOS)}}, 314 {EncodeKind::ObjectiveCInstanceVariable, 315 "ClassA.ivar1", 316 false, 317 false, 318 true, 319 {Target(AK_x86_64, PLATFORM_MACOS)}}, 320 {EncodeKind::ObjectiveCInstanceVariable, 321 "ClassA.ivar2", 322 false, 323 false, 324 true, 325 {Target(AK_x86_64, PLATFORM_MACOS)}}, 326 {EncodeKind::ObjectiveCInstanceVariable, 327 "ClassC.ivar1", 328 false, 329 false, 330 true, 331 {Target(AK_x86_64, PLATFORM_MACOS)}}, 332 }; 333 std::vector<ExportedSymbol> ExpectedReexportedSymbols = { 334 {EncodeKind::GlobalSymbol, "_funcA", false, false, false, MacOSTargets}, 335 {EncodeKind::GlobalSymbol, "_globalRe", false, false, true, MacOSTargets}, 336 {EncodeKind::ObjectiveCClass, "ClassRexport", false, false, true, 337 MacOSTargets}, 338 }; 339 340 std::vector<ExportedSymbol> ExpectedUndefinedSymbols = { 341 {EncodeKind::GlobalSymbol, 342 "_globalBind", 343 false, 344 false, 345 true, 346 {Target(AK_x86_64, PLATFORM_MACOS)}}, 347 {EncodeKind::GlobalSymbol, 348 "referenced_sym", 349 true, 350 false, 351 true, 352 {Target(AK_x86_64, PLATFORM_MACOS)}}, 353 }; 354 355 EXPECT_EQ(ExpectedExportedSymbols.size(), Exports.size()); 356 EXPECT_EQ(ExpectedReexportedSymbols.size(), Reexports.size()); 357 EXPECT_EQ(ExpectedUndefinedSymbols.size(), Undefineds.size()); 358 EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(), 359 std::begin(ExpectedExportedSymbols))); 360 EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(), 361 std::begin(ExpectedReexportedSymbols))); 362 EXPECT_TRUE(std::equal(Undefineds.begin(), Undefineds.end(), 363 std::begin(ExpectedUndefinedSymbols))); 364 365 EXPECT_TRUE( 366 File->getSymbol(EncodeKind::GlobalSymbol, "_globalBind").has_value()); 367 } 368 369 TEST(TBDv5, ReadMultipleTargets) { 370 static const char TBDv5File[] = R"({ 371 "tapi_tbd_version": 5, 372 "main_library": { 373 "target_info": [ 374 { 375 "target": "x86_64-macos", 376 "min_deployment": "10.14" 377 }, 378 { 379 "target": "arm64-macos", 380 "min_deployment": "10.14" 381 }, 382 { 383 "target": "arm64-maccatalyst", 384 "min_deployment": "12.1" 385 } 386 ], 387 "install_names":[ 388 { "name":"/usr/lib/libFoo.dylib" } 389 ], 390 "swift_abi":[ { "abi":8 } ], 391 "reexported_libraries": [ 392 { 393 "targets": [ "x86_64-maccatalyst" ], 394 "names": [ 395 "/u/l/l/libfoo.dylib", 396 "/u/l/l/libbar.dylib" 397 ] 398 }, 399 { 400 "targets": [ "arm64-maccatalyst" ], 401 "names": [ "/u/l/l/libArmOnly.dylib" ] 402 } 403 ] 404 } 405 })"; 406 407 Expected<TBDFile> Result = 408 TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd")); 409 EXPECT_TRUE(!!Result); 410 TBDFile File = std::move(Result.get()); 411 EXPECT_EQ(FileType::TBD_V5, File->getFileType()); 412 EXPECT_EQ(std::string("/usr/lib/libFoo.dylib"), File->getInstallName()); 413 EXPECT_TRUE(File->isApplicationExtensionSafe()); 414 EXPECT_TRUE(File->isTwoLevelNamespace()); 415 EXPECT_EQ(PackedVersion(1, 0, 0), File->getCurrentVersion()); 416 EXPECT_EQ(PackedVersion(1, 0, 0), File->getCompatibilityVersion()); 417 EXPECT_EQ(8U, File->getSwiftABIVersion()); 418 419 TargetList AllTargets = { 420 Target(AK_x86_64, PLATFORM_MACOS, VersionTuple(10, 14)), 421 Target(AK_arm64, PLATFORM_MACOS, VersionTuple(10, 14)), 422 Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(12, 1)), 423 }; 424 EXPECT_EQ(mapToPlatformSet(AllTargets), File->getPlatforms()); 425 EXPECT_EQ(mapToArchitectureSet(AllTargets), File->getArchitectures()); 426 427 InterfaceFileRef ReexportA("/u/l/l/libArmOnly.dylib", 428 {Target(AK_arm64, PLATFORM_MACCATALYST)}); 429 InterfaceFileRef ReexportB("/u/l/l/libbar.dylib", 430 {Target(AK_x86_64, PLATFORM_MACCATALYST)}); 431 InterfaceFileRef ReexportC("/u/l/l/libfoo.dylib", 432 {Target(AK_x86_64, PLATFORM_MACCATALYST)}); 433 EXPECT_EQ(3U, File->reexportedLibraries().size()); 434 EXPECT_EQ(ReexportA, File->reexportedLibraries().at(0)); 435 EXPECT_EQ(ReexportB, File->reexportedLibraries().at(1)); 436 EXPECT_EQ(ReexportC, File->reexportedLibraries().at(2)); 437 } 438 439 TEST(TBDv5, ReadMultipleDocuments) { 440 static const char TBDv5File[] = R"({ 441 "tapi_tbd_version": 5, 442 "main_library": { 443 "target_info": [ 444 { 445 "target": "armv7-ios", 446 "min_deployment": "11.0" 447 } 448 ], 449 "install_names":[ 450 { "name":"/S/L/F/Foo.framework/Foo" } 451 ], 452 "reexported_libraries": [ 453 { "names": ["/u/l/l/libfoo.dylib"] } 454 ] 455 }, 456 "libraries": [ 457 { 458 "target_info": [ 459 { 460 "target": "armv7-ios", 461 "min_deployment": "11.0" 462 } 463 ], 464 "install_names":[ 465 { "name":"/u/l/l/libfoo.dylib" } 466 ], 467 "flags":[ 468 { "attributes": ["not_app_extension_safe"] } 469 ], 470 "exported_symbols": [ 471 { 472 "data": { 473 "thread_local": [ "_globalVar" ], 474 "objc_class": [ "ClassData", "ClassA", "ClassB"], 475 "objc_eh_type": [ "ClassA", "ClassB" ] 476 }, 477 "text": { 478 "global": [ "_funcFoo" ] 479 } 480 } 481 ] 482 } 483 ]})"; 484 485 Expected<TBDFile> Result = 486 TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd")); 487 EXPECT_TRUE(!!Result); 488 TBDFile File = std::move(Result.get()); 489 EXPECT_EQ(FileType::TBD_V5, File->getFileType()); 490 EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"), File->getInstallName()); 491 EXPECT_TRUE(File->isTwoLevelNamespace()); 492 EXPECT_TRUE(File->isApplicationExtensionSafe()); 493 494 TargetList Targets(File->targets().begin(), File->targets().end()); 495 Target iOSTarget(AK_armv7, PLATFORM_IOS, VersionTuple(11, 0)); 496 EXPECT_EQ(TargetList{iOSTarget}, Targets); 497 std::vector<const Symbol *> Symbols(File->symbols().begin(), 498 File->symbols().end()); 499 EXPECT_EQ(0U, Symbols.size()); 500 501 InterfaceFileRef Reexport("/u/l/l/libfoo.dylib", {iOSTarget}); 502 EXPECT_EQ(1U, File->reexportedLibraries().size()); 503 EXPECT_EQ(Reexport, File->reexportedLibraries().at(0)); 504 505 // Check inlined library. 506 EXPECT_EQ(1U, File->documents().size()); 507 TBDReexportFile Document = File->documents().front(); 508 Targets = {Document->targets().begin(), Document->targets().end()}; 509 EXPECT_EQ(TargetList{iOSTarget}, Targets); 510 EXPECT_EQ(std::string("/u/l/l/libfoo.dylib"), Document->getInstallName()); 511 EXPECT_EQ(0U, Document->getSwiftABIVersion()); 512 EXPECT_TRUE(Document->isTwoLevelNamespace()); 513 EXPECT_FALSE(Document->isApplicationExtensionSafe()); 514 515 ExportedSymbolSeq Exports; 516 for (const auto *Sym : Document->symbols()) 517 Exports.emplace_back( 518 ExportedSymbol{Sym->getKind(), 519 std::string(Sym->getName()), 520 Sym->isWeakDefined() || Sym->isWeakReferenced(), 521 Sym->isThreadLocalValue(), 522 Sym->isData(), 523 {iOSTarget}}); 524 525 llvm::sort(Exports); 526 ExportedSymbolSeq ExpectedExports = { 527 {EncodeKind::GlobalSymbol, "_funcFoo", false, false, false, {iOSTarget}}, 528 {EncodeKind::GlobalSymbol, "_globalVar", false, true, true, {iOSTarget}}, 529 {EncodeKind::ObjectiveCClass, "ClassA", false, false, true, {iOSTarget}}, 530 {EncodeKind::ObjectiveCClass, "ClassB", false, false, true, {iOSTarget}}, 531 {EncodeKind::ObjectiveCClass, 532 "ClassData", 533 false, 534 false, 535 true, 536 {iOSTarget}}, 537 {EncodeKind::ObjectiveCClassEHType, 538 "ClassA", 539 false, 540 false, 541 true, 542 {iOSTarget}}, 543 {EncodeKind::ObjectiveCClassEHType, 544 "ClassB", 545 false, 546 false, 547 true, 548 {iOSTarget}}, 549 }; 550 551 EXPECT_EQ(ExpectedExports.size(), Exports.size()); 552 EXPECT_TRUE( 553 std::equal(Exports.begin(), Exports.end(), std::begin(ExpectedExports))); 554 } 555 556 TEST(TBDv5, WriteFile) { 557 static const char TBDv5File[] = R"({ 558 "tapi_tbd_version": 5, 559 "main_library": { 560 "target_info": [ 561 { 562 "target": "x86_64-macos", 563 "min_deployment": "10.14" 564 }, 565 { 566 "target": "arm64-macos", 567 "min_deployment": "10.14" 568 }, 569 { 570 "target": "arm64-maccatalyst", 571 "min_deployment": "12.1" 572 } 573 ], 574 "install_names": [ 575 { 576 "name": "@rpath/S/L/F/Foo.framework/Foo" 577 } 578 ], 579 "current_versions": [ 580 { 581 "version": "1.2" 582 } 583 ], 584 "compatibility_versions": [ 585 { "version": "1.1" } 586 ], 587 "flags": [ 588 { 589 "attributes": [ 590 "flat_namespace" 591 ] 592 } 593 ], 594 "rpaths": [ 595 { 596 "targets": [ 597 "x86_64-macos" 598 ], 599 "paths": [ 600 "@executable_path/.../Frameworks" 601 ] 602 } 603 ], 604 "parent_umbrellas": [ 605 { 606 "umbrella": "System" 607 } 608 ], 609 "allowable_clients": [ 610 { 611 "clients": [ 612 "ClientA", 613 "ClientB" 614 ] 615 } 616 ], 617 "reexported_libraries": [ 618 { 619 "names": [ 620 "/u/l/l/libfoo.dylib", 621 "/u/l/l/libbar.dylib" 622 ] 623 } 624 ], 625 "exported_symbols": [ 626 { 627 "targets": [ 628 "x86_64-macos", 629 "arm64-macos" 630 ], 631 "data": { 632 "global": [ 633 "_global" 634 ], 635 "objc_class": [ 636 "ClassA" 637 ], 638 "weak": [], 639 "thread_local": [] 640 }, 641 "text": { 642 "global": [ 643 "_func" 644 ], 645 "weak": [], 646 "thread_local": [] 647 } 648 }, 649 { 650 "targets": [ 651 "x86_64-macos" 652 ], 653 "data": { 654 "global": [ 655 "_globalVar" 656 ], 657 "objc_class": [ 658 "ClassA", 659 "ClassB", 660 "ClassData" 661 ], 662 "objc_eh_type": [ 663 "ClassA", 664 "ClassB" 665 ], 666 "objc_ivar": [ 667 "ClassA.ivar1", 668 "ClassA.ivar2", 669 "ClassC.ivar1" 670 ] 671 }, 672 "text": { 673 "global": [ 674 "_funcFoo" 675 ] 676 } 677 } 678 ], 679 "reexported_symbols": [ 680 { 681 "data": { 682 "global": [ 683 "_globalRe" 684 ], 685 "objc_class": [ 686 "ClassRexport" 687 ] 688 }, 689 "text": { 690 "global": [ 691 "_funcA" 692 ] 693 } 694 } 695 ], 696 "undefined_symbols": [ 697 { 698 "targets": [ 699 "x86_64-macos" 700 ], 701 "data": { 702 "global": [ 703 "_globalBind" 704 ], 705 "weak": [ 706 "referenced_sym" 707 ] 708 } 709 } 710 ] 711 }})"; 712 713 InterfaceFile File; 714 File.setFileType(FileType::TBD_V5); 715 716 TargetList AllTargets = { 717 Target(AK_x86_64, PLATFORM_MACOS, VersionTuple(10, 14)), 718 Target(AK_arm64, PLATFORM_MACOS, VersionTuple(10, 14)), 719 Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(12, 1)), 720 }; 721 File.addTargets(AllTargets); 722 File.setInstallName("@rpath/S/L/F/Foo.framework/Foo"); 723 File.setCurrentVersion(PackedVersion(1, 2, 0)); 724 File.setCompatibilityVersion(PackedVersion(1, 1, 0)); 725 File.addRPath("@executable_path/.../Frameworks", AllTargets[0]); 726 727 for (const auto &Targ : AllTargets) { 728 File.addParentUmbrella(Targ, "System"); 729 File.addAllowableClient("ClientA", Targ); 730 File.addAllowableClient("ClientB", Targ); 731 File.addReexportedLibrary("/u/l/l/libfoo.dylib", Targ); 732 File.addReexportedLibrary("/u/l/l/libbar.dylib", Targ); 733 } 734 735 SymbolFlags Flags = SymbolFlags::None; 736 // Exports. 737 File.addSymbol(EncodeKind::GlobalSymbol, "_global", 738 {AllTargets[0], AllTargets[1]}, Flags | SymbolFlags::Data); 739 File.addSymbol(EncodeKind::GlobalSymbol, "_func", 740 {AllTargets[0], AllTargets[1]}, Flags | SymbolFlags::Text); 741 File.addSymbol(EncodeKind::ObjectiveCClass, "ClassA", 742 {AllTargets[0], AllTargets[1]}, Flags | SymbolFlags::Data); 743 File.addSymbol(EncodeKind::GlobalSymbol, "_funcFoo", {AllTargets[0]}, 744 Flags | SymbolFlags::Text); 745 File.addSymbol(EncodeKind::GlobalSymbol, "_globalVar", {AllTargets[0]}, 746 Flags | SymbolFlags::Data); 747 File.addSymbol(EncodeKind::ObjectiveCClass, "ClassData", {AllTargets[0]}, 748 Flags | SymbolFlags::Data); 749 File.addSymbol(EncodeKind::ObjectiveCClassEHType, "ClassA", {AllTargets[0]}, 750 Flags | SymbolFlags::Data); 751 File.addSymbol(EncodeKind::ObjectiveCClassEHType, "ClassB", {AllTargets[0]}, 752 Flags | SymbolFlags::Data); 753 File.addSymbol(EncodeKind::ObjectiveCInstanceVariable, "ClassA.ivar1", 754 {AllTargets[0]}, Flags | SymbolFlags::Data); 755 File.addSymbol(EncodeKind::ObjectiveCInstanceVariable, "ClassA.ivar2", 756 {AllTargets[0]}, Flags | SymbolFlags::Data); 757 File.addSymbol(EncodeKind::ObjectiveCInstanceVariable, "ClassC.ivar1", 758 {AllTargets[0]}, Flags | SymbolFlags::Data); 759 760 // Reexports. 761 Flags = SymbolFlags::Rexported; 762 File.addSymbol(EncodeKind::GlobalSymbol, "_globalRe", AllTargets, 763 Flags | SymbolFlags::Data); 764 File.addSymbol(EncodeKind::GlobalSymbol, "_funcA", AllTargets, 765 Flags | SymbolFlags::Text); 766 File.addSymbol(EncodeKind::ObjectiveCClass, "ClassRexport", AllTargets, 767 Flags | SymbolFlags::Data); 768 769 // Undefineds. 770 Flags = SymbolFlags::Undefined; 771 File.addSymbol(EncodeKind::GlobalSymbol, "_globalBind", {AllTargets[0]}, 772 Flags | SymbolFlags::Data); 773 File.addSymbol(EncodeKind::GlobalSymbol, "referenced_sym", {AllTargets[0]}, 774 Flags | SymbolFlags::Data | SymbolFlags::WeakReferenced); 775 776 File.setTwoLevelNamespace(false); 777 File.setApplicationExtensionSafe(true); 778 779 // Write out file then process it back into IF and compare equality 780 // against TBDv5File. 781 SmallString<4096> Buffer; 782 raw_svector_ostream OS(Buffer); 783 Error Result = TextAPIWriter::writeToStream(OS, File); 784 EXPECT_FALSE(Result); 785 786 Expected<TBDFile> Input = 787 TextAPIReader::get(MemoryBufferRef(TBDv5File, "Input.tbd")); 788 EXPECT_TRUE(!!Input); 789 TBDFile InputFile = std::move(Input.get()); 790 791 Expected<TBDFile> Output = 792 TextAPIReader::get(MemoryBufferRef(Buffer, "Output.tbd")); 793 EXPECT_TRUE(!!Output); 794 TBDFile OutputFile = std::move(Output.get()); 795 EXPECT_EQ(*InputFile, *OutputFile); 796 } 797 798 TEST(TBDv5, WriteMultipleDocuments) { 799 static const char TBDv5File[] = R"({ 800 "tapi_tbd_version": 5, 801 "main_library": { 802 "target_info": [ 803 { 804 "target": "armv7-ios", 805 "min_deployment": "11.0" 806 } 807 ], 808 "install_names":[ 809 { "name":"/S/L/F/Foo.framework/Foo" } 810 ], 811 "reexported_libraries": [ 812 { "names": ["/u/l/l/libfoo.dylib"] 813 } 814 ] 815 }, 816 "libraries": [ 817 { 818 "target_info": [ 819 { 820 "target": "armv7-ios", 821 "min_deployment": "11.0" 822 }, 823 { 824 "target": "armv7s-ios", 825 "min_deployment": "11.0" 826 } 827 ], 828 "install_names":[ 829 { "name":"/u/l/l/libfoo.dylib" } 830 ], 831 "current_versions": [ 832 { 833 "version": "2.1.1" 834 } 835 ], 836 "rpaths": [ 837 { 838 "targets": [ 839 "armv7-ios" 840 ], 841 "paths": [ 842 "@executable_path/.../Frameworks" 843 ] 844 }], 845 "reexported_libraries": [ { "names": ["@rpath/libfoo.dylib"] } ], 846 "flags":[ 847 { "attributes": ["not_app_extension_safe"] } 848 ], 849 "exported_symbols": [ 850 { 851 "text": { 852 "global": [ "_funcFoo" ] 853 } 854 } 855 ] 856 }, 857 { 858 "target_info": [ 859 { 860 "target": "armv7-ios", 861 "min_deployment": "11.0" 862 } 863 ], 864 "install_names":[ 865 { "name":"@rpath/libfoo.dylib" } 866 ], 867 "exported_symbols": [ 868 { 869 "data": { 870 "global": [ "_varFooBaz" ] 871 } 872 } 873 ] 874 } 875 ]})"; 876 877 InterfaceFile File; 878 File.setFileType(FileType::TBD_V5); 879 880 TargetList AllTargets = { 881 Target(AK_armv7, PLATFORM_IOS, VersionTuple(11, 0)), 882 Target(AK_armv7s, PLATFORM_IOS, VersionTuple(11, 0)), 883 }; 884 File.setInstallName("/S/L/F/Foo.framework/Foo"); 885 File.addTarget(AllTargets[0]); 886 File.setCurrentVersion(PackedVersion(1, 0, 0)); 887 File.setCompatibilityVersion(PackedVersion(1, 0, 0)); 888 File.addReexportedLibrary("/u/l/l/libfoo.dylib", AllTargets[0]); 889 File.setTwoLevelNamespace(); 890 File.setApplicationExtensionSafe(true); 891 892 InterfaceFile NestedFile; 893 NestedFile.setFileType(FileType::TBD_V5); 894 NestedFile.setInstallName("/u/l/l/libfoo.dylib"); 895 NestedFile.addTargets(AllTargets); 896 NestedFile.setCompatibilityVersion(PackedVersion(1, 0, 0)); 897 NestedFile.setTwoLevelNamespace(); 898 NestedFile.setApplicationExtensionSafe(false); 899 NestedFile.setCurrentVersion(PackedVersion(2, 1, 1)); 900 NestedFile.addRPath("@executable_path/.../Frameworks", AllTargets[0]); 901 for (const auto &Targ : AllTargets) 902 NestedFile.addReexportedLibrary("@rpath/libfoo.dylib", Targ); 903 NestedFile.addSymbol(EncodeKind::GlobalSymbol, "_funcFoo", AllTargets, 904 SymbolFlags::Text); 905 File.addDocument(std::make_shared<InterfaceFile>(std::move(NestedFile))); 906 907 InterfaceFile NestedFileB; 908 NestedFileB.setFileType(FileType::TBD_V5); 909 NestedFileB.setInstallName("@rpath/libfoo.dylib"); 910 NestedFileB.addTarget(AllTargets[0]); 911 NestedFileB.setCompatibilityVersion(PackedVersion(1, 0, 0)); 912 NestedFileB.setCurrentVersion(PackedVersion(1, 0, 0)); 913 NestedFileB.setTwoLevelNamespace(); 914 NestedFileB.setApplicationExtensionSafe(true); 915 NestedFileB.addSymbol(EncodeKind::GlobalSymbol, "_varFooBaz", {AllTargets[0]}, 916 SymbolFlags::Data); 917 File.addDocument(std::make_shared<InterfaceFile>(std::move(NestedFileB))); 918 919 // Write out file then process it back into IF and compare equality 920 // against TBDv5File. 921 SmallString<4096> Buffer; 922 raw_svector_ostream OS(Buffer); 923 Error Result = TextAPIWriter::writeToStream(OS, File, FileType::Invalid, 924 /*Compact=*/true); 925 EXPECT_FALSE(Result); 926 927 Expected<TBDFile> Input = 928 TextAPIReader::get(MemoryBufferRef(TBDv5File, "Input.tbd")); 929 EXPECT_TRUE(!!Input); 930 TBDFile InputFile = std::move(Input.get()); 931 932 Expected<TBDFile> Output = 933 TextAPIReader::get(MemoryBufferRef(Buffer, "Output.tbd")); 934 EXPECT_TRUE(!!Output); 935 TBDFile OutputFile = std::move(Output.get()); 936 EXPECT_EQ(*InputFile, *OutputFile); 937 } 938 939 TEST(TBDv5, Target_Simulator) { 940 static const char TBDv5File[] = R"({ 941 "tapi_tbd_version": 5, 942 "main_library": { 943 "target_info": [ 944 { 945 "target": "arm64-ios-simulator", 946 "min_deployment": "11.0" 947 }, 948 { 949 "target": "x86_64-ios-simulator", 950 "min_deployment": "11.3" 951 } 952 ], 953 "install_names":[ 954 { "name":"/S/L/F/Foo.framework/Foo" } 955 ] 956 }})"; 957 958 Expected<TBDFile> Result = 959 TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd")); 960 EXPECT_TRUE(!!Result); 961 TBDFile File = std::move(Result.get()); 962 EXPECT_EQ(FileType::TBD_V5, File->getFileType()); 963 TargetList ExpectedTargets = { 964 Target(AK_x86_64, PLATFORM_IOSSIMULATOR, VersionTuple(11, 3)), 965 Target(AK_arm64, PLATFORM_IOSSIMULATOR, VersionTuple(14, 0)), 966 }; 967 TargetList Targets{File->targets().begin(), File->targets().end()}; 968 llvm::sort(Targets); 969 EXPECT_EQ(Targets, ExpectedTargets); 970 971 SmallString<4096> Buffer; 972 raw_svector_ostream OS(Buffer); 973 Error WriteResult = TextAPIWriter::writeToStream(OS, *File); 974 EXPECT_TRUE(!WriteResult); 975 976 Expected<TBDFile> Output = 977 TextAPIReader::get(MemoryBufferRef(Buffer, "Output.tbd")); 978 EXPECT_TRUE(!!Output); 979 TBDFile WriteResultFile = std::move(Output.get()); 980 EXPECT_EQ(*File, *WriteResultFile); 981 } 982 983 TEST(TBDv5, Target_UnsupportedMinOS) { 984 static const char TBDv5File[] = R"({ 985 "tapi_tbd_version": 5, 986 "main_library": { 987 "target_info": [ 988 { 989 "target": "arm64-macos", 990 "min_deployment": "10.14" 991 }, 992 { 993 "target": "x86_64-macos", 994 "min_deployment": "10.14" 995 } 996 ], 997 "install_names":[ 998 { "name":"/S/L/F/Foo.framework/Foo" } 999 ] 1000 }})"; 1001 1002 Expected<TBDFile> Result = 1003 TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd")); 1004 EXPECT_TRUE(!!Result); 1005 TBDFile File = std::move(Result.get()); 1006 EXPECT_EQ(FileType::TBD_V5, File->getFileType()); 1007 TargetList ExpectedTargets = { 1008 Target(AK_x86_64, PLATFORM_MACOS, VersionTuple(10, 14)), 1009 Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0)), 1010 }; 1011 TargetList Targets{File->targets().begin(), File->targets().end()}; 1012 llvm::sort(Targets); 1013 EXPECT_EQ(Targets, ExpectedTargets); 1014 1015 SmallString<4096> Buffer; 1016 raw_svector_ostream OS(Buffer); 1017 Error WriteResult = TextAPIWriter::writeToStream(OS, *File); 1018 EXPECT_TRUE(!WriteResult); 1019 1020 Expected<TBDFile> Output = 1021 TextAPIReader::get(MemoryBufferRef(Buffer, "Output.tbd")); 1022 EXPECT_TRUE(!!Output); 1023 TBDFile WriteResultFile = std::move(Output.get()); 1024 EXPECT_EQ(*File, *WriteResultFile); 1025 } 1026 1027 TEST(TBDv5, MisspelledKey) { 1028 static const char TBDv5File[] = R"({ 1029 "tapi_tbd_version": 5, 1030 "main_library": { 1031 "target_info": [ 1032 { 1033 "target": "arm64-ios-simulator", 1034 "min_deployment": "11.0" 1035 } 1036 ], 1037 "intall_names":[ 1038 { "name":"/S/L/F/Foo.framework/Foo" } 1039 ] 1040 }})"; 1041 1042 Expected<TBDFile> Result = 1043 TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd")); 1044 EXPECT_FALSE(!!Result); 1045 std::string ErrorMessage = toString(Result.takeError()); 1046 EXPECT_EQ("invalid install_names section\n", ErrorMessage); 1047 } 1048 1049 TEST(TBDv5, InvalidVersion) { 1050 static const char TBDv5File[] = R"({ 1051 "tapi_tbd_version": 11, 1052 "main_library": { 1053 "target_info": [ 1054 { 1055 "target": "arm64-ios-simulator", 1056 "min_deployment": "11.0" 1057 } 1058 ], 1059 "install_names":[ 1060 { "name":"/S/L/F/Foo.framework/Foo" } 1061 ] 1062 }})"; 1063 1064 Expected<TBDFile> Result = 1065 TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd")); 1066 EXPECT_FALSE(!!Result); 1067 std::string ErrorMessage = toString(Result.takeError()); 1068 EXPECT_EQ("invalid tapi_tbd_version section\n", ErrorMessage); 1069 } 1070 1071 TEST(TBDv5, MissingRequiredKey) { 1072 static const char TBDv5File[] = R"({ 1073 "main_library": { 1074 "target_info": [ 1075 { 1076 "target": "arm64-ios-simulator", 1077 "min_deployment": "11.0" 1078 } 1079 ], 1080 "install_names":[ 1081 { "name":"/S/L/F/Foo.framework/Foo" } 1082 ] 1083 }})"; 1084 1085 Expected<TBDFile> Result = 1086 TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd")); 1087 EXPECT_FALSE(!!Result); 1088 std::string ErrorMessage = toString(Result.takeError()); 1089 EXPECT_EQ("invalid tapi_tbd_version section\n", ErrorMessage); 1090 } 1091 1092 TEST(TBDv5, InvalidSymbols) { 1093 static const char TBDv5File[] = R"({ 1094 "tapi_tbd_version": 5, 1095 "main_library": { 1096 "target_info": [ 1097 { 1098 "target": "arm64-driverkit", 1099 "min_deployment": "11.0" 1100 } 1101 ], 1102 "install_names":[ 1103 { "name":"/S/L/F/Foo.framework/Foo" } 1104 ], 1105 "exported_symbols": [ 1106 { 1107 "daa": { 1108 "global": { 1109 "weak": [] 1110 } 1111 } 1112 } 1113 ] 1114 }})"; 1115 1116 Expected<TBDFile> Result = 1117 TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd")); 1118 EXPECT_FALSE(!!Result); 1119 std::string ErrorMessage = toString(Result.takeError()); 1120 EXPECT_EQ("invalid exported_symbols section\n", ErrorMessage); 1121 } 1122 1123 TEST(TBDv5, DefaultMinOS) { 1124 static const char TBDv5File[] = R"({ 1125 "tapi_tbd_version": 5, 1126 "main_library": { 1127 "target_info": [ 1128 { 1129 "target": "arm64-ios-simulator" 1130 } 1131 ], 1132 "install_names":[ 1133 { "name":"/S/L/F/Foo.framework/Foo" } 1134 ] 1135 }})"; 1136 1137 Expected<TBDFile> Result = 1138 TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd")); 1139 EXPECT_TRUE(!!Result); 1140 TBDFile File = std::move(Result.get()); 1141 EXPECT_EQ(FileType::TBD_V5, File->getFileType()); 1142 EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"), File->getInstallName()); 1143 EXPECT_TRUE(File->targets().begin() != File->targets().end()); 1144 EXPECT_EQ(*File->targets().begin(), 1145 Target(AK_arm64, PLATFORM_IOSSIMULATOR, VersionTuple(0, 0))); 1146 } 1147 1148 TEST(TBDv5, InvalidMinOS) { 1149 static const char TBDv5File[] = R"({ 1150 "tapi_tbd_version": 5, 1151 "main_library": { 1152 "target_info": [ 1153 { 1154 "target": "arm64-ios-simulator", 1155 "min_deployment": "swift-abi" 1156 } 1157 ], 1158 "install_names":[ 1159 { "name":"/S/L/F/Foo.framework/Foo" } 1160 ] 1161 }})"; 1162 1163 Expected<TBDFile> Result = 1164 TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd")); 1165 EXPECT_FALSE(!!Result); 1166 std::string ErrorMessage = toString(Result.takeError()); 1167 EXPECT_EQ("invalid min_deployment section\n", ErrorMessage); 1168 } 1169 1170 TEST(TBDv5, SimSupport) { 1171 static const char TBDv5File[] = R"({ 1172 "tapi_tbd_version": 5, 1173 "main_library": { 1174 "target_info": [ 1175 { 1176 "target": "arm64-macos", 1177 "min_deployment": "11.1" 1178 } 1179 ], 1180 "install_names":[ 1181 { "name":"/S/L/F/Foo.framework/Foo" } 1182 ], 1183 "flags":[ 1184 { "attributes": ["sim_support"] } 1185 ] 1186 }})"; 1187 1188 Expected<TBDFile> Result = 1189 TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd")); 1190 EXPECT_TRUE(!!Result); 1191 Target ExpectedTarget = Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 1)); 1192 TBDFile ReadFile = std::move(Result.get()); 1193 EXPECT_EQ(FileType::TBD_V5, ReadFile->getFileType()); 1194 EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"), 1195 ReadFile->getInstallName()); 1196 EXPECT_TRUE(ReadFile->targets().begin() != ReadFile->targets().end()); 1197 EXPECT_EQ(*ReadFile->targets().begin(), ExpectedTarget); 1198 EXPECT_TRUE(ReadFile->hasSimulatorSupport()); 1199 } 1200 1201 TEST(TBDv5, NotForSharedCache) { 1202 static const char TBDv5File[] = R"({ 1203 "tapi_tbd_version": 5, 1204 "main_library": { 1205 "target_info": [ 1206 { 1207 "target": "arm64-macos", 1208 "min_deployment": "11.1" 1209 } 1210 ], 1211 "install_names":[ 1212 { "name":"/S/L/F/Foo.framework/Foo" } 1213 ], 1214 "flags":[ 1215 { "attributes": ["not_for_dyld_shared_cache"] } 1216 ] 1217 }})"; 1218 1219 Expected<TBDFile> Result = 1220 TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd")); 1221 EXPECT_TRUE(!!Result); 1222 Target ExpectedTarget = Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 1)); 1223 TBDFile ReadFile = std::move(Result.get()); 1224 EXPECT_EQ(FileType::TBD_V5, ReadFile->getFileType()); 1225 EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"), 1226 ReadFile->getInstallName()); 1227 EXPECT_TRUE(ReadFile->targets().begin() != ReadFile->targets().end()); 1228 EXPECT_EQ(*ReadFile->targets().begin(), ExpectedTarget); 1229 EXPECT_FALSE(ReadFile->hasSimulatorSupport()); 1230 EXPECT_TRUE(ReadFile->isOSLibNotForSharedCache()); 1231 } 1232 1233 TEST(TBDv5, ObjCInterfaces) { 1234 static const char TBDv5File[] = R"({ 1235 "tapi_tbd_version": 5, 1236 "main_library": { 1237 "target_info": [ 1238 { 1239 "target": "arm64-ios-simulator", 1240 "min_deployment": "14.0" 1241 } 1242 ], 1243 "install_names":[ 1244 { "name":"/S/L/F/Foo.framework/Foo" } 1245 ], 1246 "exported_symbols": [ 1247 { 1248 "data": { 1249 "global": [ 1250 "_global", 1251 "_OBJC_METACLASS_$_Standalone", 1252 "_OBJC_CLASS_$_Standalone2" 1253 ], 1254 "weak": ["_OBJC_EHTYPE_$_NSObject"], 1255 "objc_class": [ 1256 "ClassA", 1257 "ClassB" 1258 ], 1259 "objc_eh_type": ["ClassA"] 1260 } 1261 }] 1262 }})"; 1263 1264 Expected<TBDFile> Result = 1265 TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd")); 1266 EXPECT_TRUE(!!Result); 1267 TBDFile File = std::move(Result.get()); 1268 EXPECT_EQ(FileType::TBD_V5, File->getFileType()); 1269 Target ExpectedTarget = 1270 Target(AK_arm64, PLATFORM_IOSSIMULATOR, VersionTuple(14, 0)); 1271 EXPECT_EQ(*File->targets().begin(), ExpectedTarget); 1272 1273 // Check Symbols. 1274 ExportedSymbolSeq Exports; 1275 for (const auto *Sym : File->symbols()) { 1276 ExportedSymbol Temp = 1277 ExportedSymbol{Sym->getKind(), std::string(Sym->getName()), 1278 Sym->isWeakDefined() || Sym->isWeakReferenced(), 1279 Sym->isThreadLocalValue(), Sym->isData()}; 1280 Exports.emplace_back(std::move(Temp)); 1281 } 1282 llvm::sort(Exports); 1283 1284 std::vector<ExportedSymbol> ExpectedExports = { 1285 {EncodeKind::GlobalSymbol, "_OBJC_CLASS_$_Standalone2", false, false, 1286 true}, 1287 {EncodeKind::GlobalSymbol, "_OBJC_EHTYPE_$_NSObject", true, false, true}, 1288 {EncodeKind::GlobalSymbol, "_OBJC_METACLASS_$_Standalone", false, false, 1289 true}, 1290 {EncodeKind::GlobalSymbol, "_global", false, false, true}, 1291 {EncodeKind::ObjectiveCClass, "ClassA", false, false, true}, 1292 {EncodeKind::ObjectiveCClass, "ClassB", false, false, true}, 1293 {EncodeKind::ObjectiveCClassEHType, "ClassA", false, false, true}}; 1294 1295 EXPECT_EQ(ExpectedExports.size(), Exports.size()); 1296 EXPECT_TRUE( 1297 std::equal(Exports.begin(), Exports.end(), std::begin(ExpectedExports))); 1298 1299 SmallString<4096> Buffer; 1300 raw_svector_ostream OS(Buffer); 1301 Error WriteResult = TextAPIWriter::writeToStream(OS, *File); 1302 EXPECT_TRUE(!WriteResult); 1303 1304 Expected<TBDFile> Output = 1305 TextAPIReader::get(MemoryBufferRef(Buffer, "Output.tbd")); 1306 EXPECT_TRUE(!!Output); 1307 TBDFile WriteResultFile = std::move(Output.get()); 1308 EXPECT_EQ(*File, *WriteResultFile); 1309 } 1310 1311 TEST(TBDv5, MergeIF) { 1312 static const char TBDv5FileA[] = R"({ 1313 "tapi_tbd_version": 5, 1314 "main_library": { 1315 "target_info": [ 1316 { 1317 "target": "x86_64-macos", 1318 "min_deployment": "10.14" 1319 }, 1320 { 1321 "target": "arm64-macos", 1322 "min_deployment": "10.14" 1323 }, 1324 { 1325 "target": "arm64-maccatalyst", 1326 "min_deployment": "12.1" 1327 } 1328 ], 1329 "flags": [ 1330 { 1331 "targets": [ 1332 "x86_64-macos" 1333 ], 1334 "attributes": [ 1335 "flat_namespace" 1336 ] 1337 } 1338 ], 1339 "install_names": [ 1340 { 1341 "name": "/S/L/F/Foo.framework/Foo" 1342 } 1343 ], 1344 "current_versions": [ 1345 { 1346 "version": "1.2" 1347 } 1348 ], 1349 "compatibility_versions": [ 1350 { "version": "1.1" } 1351 ], 1352 "rpaths": [ 1353 { 1354 "targets": [ 1355 "x86_64-macos" 1356 ], 1357 "paths": [ 1358 "@executable_path/.../Frameworks" 1359 ] 1360 } 1361 ], 1362 "parent_umbrellas": [ 1363 { 1364 "umbrella": "System" 1365 } 1366 ], 1367 "allowable_clients": [ 1368 { 1369 "clients": [ 1370 "ClientA", 1371 "ClientB" 1372 ] 1373 } 1374 ], 1375 "reexported_libraries": [ 1376 { 1377 "names": [ 1378 "/u/l/l/libfoo.dylib", 1379 "/u/l/l/libbar.dylib" 1380 ] 1381 } 1382 ], 1383 "exported_symbols": [ 1384 { 1385 "targets": [ 1386 "x86_64-macos", 1387 "arm64-macos" 1388 ], 1389 "data": { 1390 "global": [ 1391 "_global" 1392 ], 1393 "objc_class": [ 1394 "ClassA" 1395 ], 1396 "weak": [], 1397 "thread_local": [] 1398 }, 1399 "text": { 1400 "global": [ 1401 "_func" 1402 ], 1403 "weak": [], 1404 "thread_local": [] 1405 } 1406 }, 1407 { 1408 "targets": [ 1409 "x86_64-macos" 1410 ], 1411 "data": { 1412 "global": [ 1413 "_globalVar" 1414 ], 1415 "objc_class": [ 1416 "ClassA", 1417 "ClassB", 1418 "ClassData" 1419 ], 1420 "objc_eh_type": [ 1421 "ClassA", 1422 "ClassB" 1423 ], 1424 "objc_ivar": [ 1425 "ClassA.ivar1", 1426 "ClassA.ivar2", 1427 "ClassC.ivar1" 1428 ] 1429 }, 1430 "text": { 1431 "global": [ 1432 "_funcFoo" 1433 ] 1434 } 1435 } 1436 ], 1437 "reexported_symbols": [ 1438 { 1439 "targets": [ 1440 "x86_64-macos", 1441 "arm64-macos" 1442 ], 1443 "data": { 1444 "global": [ 1445 "_globalRe" 1446 ], 1447 "objc_class": [ 1448 "ClassRexport" 1449 ] 1450 }, 1451 "text": { 1452 "global": [ 1453 "_funcA" 1454 ] 1455 } 1456 } 1457 ], 1458 "undefined_symbols": [ 1459 { 1460 "targets": [ 1461 "x86_64-macos" 1462 ], 1463 "data": { 1464 "global": [ 1465 "_globalBind" 1466 ], 1467 "weak": [ 1468 "referenced_sym" 1469 ] 1470 } 1471 } 1472 ] 1473 }, 1474 "libraries": [] 1475 })"; 1476 1477 static const char TBDv5FileB[] = R"({ 1478 "tapi_tbd_version": 5, 1479 "main_library": { 1480 "target_info": [ 1481 { 1482 "target": "x86_64-macos", 1483 "min_deployment": "10.14" 1484 }, 1485 { 1486 "target": "arm64-macos", 1487 "min_deployment": "10.14" 1488 }, 1489 { 1490 "target": "arm64-maccatalyst", 1491 "min_deployment": "12.1" 1492 } 1493 ], 1494 "flags": [ 1495 { 1496 "targets": [ 1497 "x86_64-macos" 1498 ], 1499 "attributes": [ 1500 "flat_namespace" 1501 ] 1502 } 1503 ], 1504 "install_names": [ 1505 { 1506 "name": "/S/L/F/Foo.framework/Foo" 1507 } 1508 ], 1509 "current_versions": [ 1510 { 1511 "version": "1.2" 1512 } 1513 ], 1514 "compatibility_versions": [ 1515 { "version": "1.1" } 1516 ], 1517 "exported_symbols": [ 1518 { 1519 "targets": [ 1520 "x86_64-macos", 1521 "arm64-macos" 1522 ], 1523 "data": { 1524 "global": [ 1525 "_globalZ" 1526 ], 1527 "objc_class": [ 1528 "ClassZ" 1529 ], 1530 "weak": [], 1531 "thread_local": [] 1532 }, 1533 "text": { 1534 "global": [ 1535 "_funcZ" 1536 ], 1537 "weak": [], 1538 "thread_local": [] 1539 } 1540 }, 1541 { 1542 "targets": [ 1543 "x86_64-macos" 1544 ], 1545 "data": { 1546 "global": [ 1547 "_globalVarZ" 1548 ], 1549 "objc_class": [ 1550 "ClassZ", 1551 "ClassF" 1552 ], 1553 "objc_eh_type": [ 1554 "ClassZ", 1555 "ClassF" 1556 ], 1557 "objc_ivar": [ 1558 "ClassZ.ivar1", 1559 "ClassZ.ivar2", 1560 "ClassF.ivar1" 1561 ] 1562 }, 1563 "text": { 1564 "global": [ 1565 "_funcFooZ" 1566 ] 1567 } 1568 } 1569 ] 1570 }, 1571 "libraries": [] 1572 })"; 1573 1574 Expected<TBDFile> ResultA = 1575 TextAPIReader::get(MemoryBufferRef(TBDv5FileA, "Test.tbd")); 1576 EXPECT_TRUE(!!ResultA); 1577 TBDFile FileA = std::move(ResultA.get()); 1578 1579 Expected<TBDFile> ResultB = 1580 TextAPIReader::get(MemoryBufferRef(TBDv5FileB, "Test.tbd")); 1581 EXPECT_TRUE(!!ResultB); 1582 TBDFile FileB = std::move(ResultB.get()); 1583 1584 Expected<TBDFile> MergedResult = FileA->merge(FileB.get()); 1585 EXPECT_TRUE(!!MergedResult); 1586 TBDFile MergedFile = std::move(MergedResult.get()); 1587 1588 EXPECT_EQ(FileType::TBD_V5, MergedFile->getFileType()); 1589 EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"), 1590 MergedFile->getInstallName()); 1591 TargetList AllTargets = { 1592 Target(AK_x86_64, PLATFORM_MACOS, VersionTuple(10, 14)), 1593 Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0, 0)), 1594 Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(14, 0)), 1595 }; 1596 EXPECT_EQ(mapToPlatformSet(AllTargets), MergedFile->getPlatforms()); 1597 EXPECT_EQ(mapToArchitectureSet(AllTargets), MergedFile->getArchitectures()); 1598 EXPECT_EQ(PackedVersion(1, 2, 0), MergedFile->getCurrentVersion()); 1599 EXPECT_EQ(PackedVersion(1, 1, 0), MergedFile->getCompatibilityVersion()); 1600 EXPECT_TRUE(MergedFile->isApplicationExtensionSafe()); 1601 EXPECT_FALSE(MergedFile->isTwoLevelNamespace()); 1602 EXPECT_EQ(0U, MergedFile->documents().size()); 1603 InterfaceFileRef ClientA("ClientA", AllTargets); 1604 InterfaceFileRef ClientB("ClientB", AllTargets); 1605 EXPECT_EQ(2U, MergedFile->allowableClients().size()); 1606 EXPECT_EQ(ClientA, MergedFile->allowableClients().at(0)); 1607 EXPECT_EQ(ClientB, MergedFile->allowableClients().at(1)); 1608 1609 InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets); 1610 InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets); 1611 EXPECT_EQ(2U, MergedFile->reexportedLibraries().size()); 1612 EXPECT_EQ(ReexportA, MergedFile->reexportedLibraries().at(0)); 1613 EXPECT_EQ(ReexportB, MergedFile->reexportedLibraries().at(1)); 1614 1615 TargetToAttr RPaths = { 1616 {Target(AK_x86_64, PLATFORM_MACOS), "@executable_path/.../Frameworks"}, 1617 }; 1618 EXPECT_EQ(RPaths, MergedFile->rpaths()); 1619 1620 TargetToAttr Umbrellas = {{Target(AK_x86_64, PLATFORM_MACOS), "System"}, 1621 {Target(AK_arm64, PLATFORM_MACOS), "System"}, 1622 {Target(AK_arm64, PLATFORM_MACCATALYST), "System"}}; 1623 EXPECT_EQ(Umbrellas, MergedFile->umbrellas()); 1624 1625 ExportedSymbolSeq Exports, Reexports, Undefineds; 1626 for (const auto *Sym : MergedFile->symbols()) { 1627 TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()}; 1628 ExportedSymbol Temp = 1629 ExportedSymbol{Sym->getKind(), 1630 std::string(Sym->getName()), 1631 Sym->isWeakDefined() || Sym->isWeakReferenced(), 1632 Sym->isThreadLocalValue(), 1633 Sym->isData(), 1634 SymTargets}; 1635 if (Sym->isUndefined()) 1636 Undefineds.emplace_back(std::move(Temp)); 1637 else 1638 Sym->isReexported() ? Reexports.emplace_back(std::move(Temp)) 1639 : Exports.emplace_back(std::move(Temp)); 1640 } 1641 llvm::sort(Exports); 1642 llvm::sort(Reexports); 1643 llvm::sort(Undefineds); 1644 1645 TargetList MacOSTargets = {Target(AK_x86_64, PLATFORM_MACOS), 1646 Target(AK_arm64, PLATFORM_MACOS)}; 1647 1648 std::vector<ExportedSymbol> ExpectedExportedSymbols = { 1649 {EncodeKind::GlobalSymbol, "_func", false, false, false, MacOSTargets}, 1650 {EncodeKind::GlobalSymbol, 1651 "_funcFoo", 1652 false, 1653 false, 1654 false, 1655 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1656 {EncodeKind::GlobalSymbol, 1657 "_funcFooZ", 1658 false, 1659 false, 1660 false, 1661 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1662 {EncodeKind::GlobalSymbol, "_funcZ", false, false, false, MacOSTargets}, 1663 {EncodeKind::GlobalSymbol, "_global", false, false, true, MacOSTargets}, 1664 {EncodeKind::GlobalSymbol, 1665 "_globalVar", 1666 false, 1667 false, 1668 true, 1669 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1670 {EncodeKind::GlobalSymbol, 1671 "_globalVarZ", 1672 false, 1673 false, 1674 true, 1675 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1676 {EncodeKind::GlobalSymbol, "_globalZ", false, false, true, MacOSTargets}, 1677 {EncodeKind::ObjectiveCClass, 1678 "ClassA", 1679 false, 1680 false, 1681 true, 1682 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1683 {EncodeKind::ObjectiveCClass, 1684 "ClassB", 1685 false, 1686 false, 1687 true, 1688 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1689 {EncodeKind::ObjectiveCClass, 1690 "ClassData", 1691 false, 1692 false, 1693 true, 1694 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1695 {EncodeKind::ObjectiveCClass, 1696 "ClassF", 1697 false, 1698 false, 1699 true, 1700 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1701 {EncodeKind::ObjectiveCClass, 1702 "ClassZ", 1703 false, 1704 false, 1705 true, 1706 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1707 {EncodeKind::ObjectiveCClassEHType, 1708 "ClassA", 1709 false, 1710 false, 1711 true, 1712 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1713 {EncodeKind::ObjectiveCClassEHType, 1714 "ClassB", 1715 false, 1716 false, 1717 true, 1718 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1719 {EncodeKind::ObjectiveCClassEHType, 1720 "ClassF", 1721 false, 1722 false, 1723 true, 1724 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1725 {EncodeKind::ObjectiveCClassEHType, 1726 "ClassZ", 1727 false, 1728 false, 1729 true, 1730 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1731 {EncodeKind::ObjectiveCInstanceVariable, 1732 "ClassA.ivar1", 1733 false, 1734 false, 1735 true, 1736 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1737 {EncodeKind::ObjectiveCInstanceVariable, 1738 "ClassA.ivar2", 1739 false, 1740 false, 1741 true, 1742 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1743 {EncodeKind::ObjectiveCInstanceVariable, 1744 "ClassC.ivar1", 1745 false, 1746 false, 1747 true, 1748 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1749 {EncodeKind::ObjectiveCInstanceVariable, 1750 "ClassF.ivar1", 1751 false, 1752 false, 1753 true, 1754 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1755 {EncodeKind::ObjectiveCInstanceVariable, 1756 "ClassZ.ivar1", 1757 false, 1758 false, 1759 true, 1760 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1761 {EncodeKind::ObjectiveCInstanceVariable, 1762 "ClassZ.ivar2", 1763 false, 1764 false, 1765 true, 1766 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1767 }; 1768 1769 std::vector<ExportedSymbol> ExpectedReexportedSymbols = { 1770 {EncodeKind::GlobalSymbol, "_funcA", false, false, false, MacOSTargets}, 1771 {EncodeKind::GlobalSymbol, "_globalRe", false, false, true, MacOSTargets}, 1772 {EncodeKind::ObjectiveCClass, "ClassRexport", false, false, true, 1773 MacOSTargets}, 1774 }; 1775 1776 std::vector<ExportedSymbol> ExpectedUndefinedSymbols = { 1777 {EncodeKind::GlobalSymbol, 1778 "_globalBind", 1779 false, 1780 false, 1781 true, 1782 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1783 {EncodeKind::GlobalSymbol, 1784 "referenced_sym", 1785 true, 1786 false, 1787 true, 1788 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1789 }; 1790 1791 EXPECT_EQ(ExpectedExportedSymbols.size(), Exports.size()); 1792 EXPECT_EQ(ExpectedReexportedSymbols.size(), Reexports.size()); 1793 EXPECT_EQ(ExpectedUndefinedSymbols.size(), Undefineds.size()); 1794 EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(), 1795 std::begin(ExpectedExportedSymbols))); 1796 EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(), 1797 std::begin(ExpectedReexportedSymbols))); 1798 EXPECT_TRUE(std::equal(Undefineds.begin(), Undefineds.end(), 1799 std::begin(ExpectedUndefinedSymbols))); 1800 } 1801 1802 TEST(TBDv5, ExtractIF) { 1803 static const char TBDv5File[] = R"({ 1804 "tapi_tbd_version": 5, 1805 "main_library": { 1806 "target_info": [ 1807 { 1808 "target": "x86_64-macos", 1809 "min_deployment": "10.14" 1810 }, 1811 { 1812 "target": "arm64-macos", 1813 "min_deployment": "10.14" 1814 }, 1815 { 1816 "target": "arm64-maccatalyst", 1817 "min_deployment": "12.1" 1818 } 1819 ], 1820 "flags": [ 1821 { 1822 "targets": [ 1823 "x86_64-macos" 1824 ], 1825 "attributes": [ 1826 "flat_namespace" 1827 ] 1828 } 1829 ], 1830 "install_names": [ 1831 { 1832 "name": "/S/L/F/Foo.framework/Foo" 1833 } 1834 ], 1835 "current_versions": [ 1836 { 1837 "version": "1.2" 1838 } 1839 ], 1840 "compatibility_versions": [ 1841 { "version": "1.1" } 1842 ], 1843 "rpaths": [ 1844 { 1845 "targets": [ 1846 "x86_64-macos" 1847 ], 1848 "paths": [ 1849 "@executable_path/.../Frameworks" 1850 ] 1851 } 1852 ], 1853 "parent_umbrellas": [ 1854 { 1855 "umbrella": "System" 1856 } 1857 ], 1858 "allowable_clients": [ 1859 { 1860 "clients": [ 1861 "ClientA", 1862 "ClientB" 1863 ] 1864 } 1865 ], 1866 "reexported_libraries": [ 1867 { 1868 "names": [ 1869 "/u/l/l/libfoo.dylib", 1870 "/u/l/l/libbar.dylib" 1871 ] 1872 } 1873 ], 1874 "exported_symbols": [ 1875 { 1876 "targets": [ 1877 "x86_64-macos", 1878 "arm64-macos" 1879 ], 1880 "data": { 1881 "global": [ 1882 "_global" 1883 ], 1884 "objc_class": [ 1885 "ClassA" 1886 ], 1887 "weak": [], 1888 "thread_local": [] 1889 }, 1890 "text": { 1891 "global": [ 1892 "_func" 1893 ], 1894 "weak": [], 1895 "thread_local": [] 1896 } 1897 }, 1898 { 1899 "targets": [ 1900 "x86_64-macos" 1901 ], 1902 "data": { 1903 "global": [ 1904 "_globalVar" 1905 ], 1906 "objc_class": [ 1907 "ClassA", 1908 "ClassB", 1909 "ClassData" 1910 ], 1911 "objc_eh_type": [ 1912 "ClassA", 1913 "ClassB" 1914 ], 1915 "objc_ivar": [ 1916 "ClassA.ivar1", 1917 "ClassA.ivar2", 1918 "ClassC.ivar1" 1919 ] 1920 }, 1921 "text": { 1922 "global": [ 1923 "_funcFoo" 1924 ] 1925 } 1926 } 1927 ], 1928 "reexported_symbols": [ 1929 { 1930 "targets": [ 1931 "x86_64-macos", 1932 "arm64-macos" 1933 ], 1934 "data": { 1935 "global": [ 1936 "_globalRe" 1937 ], 1938 "objc_class": [ 1939 "ClassRexport" 1940 ] 1941 }, 1942 "text": { 1943 "global": [ 1944 "_funcA" 1945 ] 1946 } 1947 } 1948 ], 1949 "undefined_symbols": [ 1950 { 1951 "targets": [ 1952 "x86_64-macos" 1953 ], 1954 "data": { 1955 "global": [ 1956 "_globalBind" 1957 ], 1958 "weak": [ 1959 "referenced_sym" 1960 ] 1961 } 1962 } 1963 ] 1964 }, 1965 "libraries": [] 1966 })"; 1967 1968 Expected<TBDFile> Result = 1969 TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd")); 1970 EXPECT_TRUE(!!Result); 1971 TBDFile File = std::move(Result.get()); 1972 1973 Expected<TBDFile> ExtractedResult = File->extract(AK_arm64); 1974 EXPECT_TRUE(!!ExtractedResult); 1975 TBDFile ExtractedFile = std::move(ExtractedResult.get()); 1976 1977 EXPECT_EQ(FileType::TBD_V5, ExtractedFile->getFileType()); 1978 EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"), 1979 ExtractedFile->getInstallName()); 1980 1981 TargetList AllTargets = { 1982 Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0, 0)), 1983 Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(14, 0)), 1984 }; 1985 EXPECT_EQ(mapToPlatformSet(AllTargets), ExtractedFile->getPlatforms()); 1986 EXPECT_EQ(mapToArchitectureSet(AllTargets), 1987 ExtractedFile->getArchitectures()); 1988 1989 EXPECT_EQ(PackedVersion(1, 2, 0), ExtractedFile->getCurrentVersion()); 1990 EXPECT_EQ(PackedVersion(1, 1, 0), ExtractedFile->getCompatibilityVersion()); 1991 EXPECT_TRUE(ExtractedFile->isApplicationExtensionSafe()); 1992 EXPECT_FALSE(ExtractedFile->isTwoLevelNamespace()); 1993 EXPECT_EQ(0U, ExtractedFile->documents().size()); 1994 1995 InterfaceFileRef ClientA("ClientA", AllTargets); 1996 InterfaceFileRef ClientB("ClientB", AllTargets); 1997 EXPECT_EQ(2U, ExtractedFile->allowableClients().size()); 1998 EXPECT_EQ(ClientA, ExtractedFile->allowableClients().at(0)); 1999 EXPECT_EQ(ClientB, ExtractedFile->allowableClients().at(1)); 2000 2001 InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets); 2002 InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets); 2003 EXPECT_EQ(2U, ExtractedFile->reexportedLibraries().size()); 2004 EXPECT_EQ(ReexportA, ExtractedFile->reexportedLibraries().at(0)); 2005 EXPECT_EQ(ReexportB, ExtractedFile->reexportedLibraries().at(1)); 2006 2007 EXPECT_EQ(0u, ExtractedFile->rpaths().size()); 2008 2009 TargetToAttr Umbrellas = {{Target(AK_arm64, PLATFORM_MACOS), "System"}, 2010 {Target(AK_arm64, PLATFORM_MACCATALYST), "System"}}; 2011 EXPECT_EQ(Umbrellas, ExtractedFile->umbrellas()); 2012 2013 ExportedSymbolSeq Exports, Reexports, Undefineds; 2014 for (const auto *Sym : ExtractedFile->symbols()) { 2015 TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()}; 2016 ExportedSymbol Temp = 2017 ExportedSymbol{Sym->getKind(), 2018 std::string(Sym->getName()), 2019 Sym->isWeakDefined() || Sym->isWeakReferenced(), 2020 Sym->isThreadLocalValue(), 2021 Sym->isData(), 2022 SymTargets}; 2023 if (Sym->isUndefined()) 2024 Undefineds.emplace_back(std::move(Temp)); 2025 else 2026 Sym->isReexported() ? Reexports.emplace_back(std::move(Temp)) 2027 : Exports.emplace_back(std::move(Temp)); 2028 } 2029 llvm::sort(Exports); 2030 llvm::sort(Reexports); 2031 llvm::sort(Undefineds); 2032 2033 TargetList MacOSTargets = {Target(AK_arm64, PLATFORM_MACOS)}; 2034 2035 std::vector<ExportedSymbol> ExpectedExportedSymbols = { 2036 {EncodeKind::GlobalSymbol, "_func", false, false, false, MacOSTargets}, 2037 {EncodeKind::GlobalSymbol, "_global", false, false, true, MacOSTargets}, 2038 {EncodeKind::ObjectiveCClass, "ClassA", false, false, true, MacOSTargets}, 2039 }; 2040 std::vector<ExportedSymbol> ExpectedReexportedSymbols = { 2041 {EncodeKind::GlobalSymbol, "_funcA", false, false, false, MacOSTargets}, 2042 {EncodeKind::GlobalSymbol, "_globalRe", false, false, true, MacOSTargets}, 2043 {EncodeKind::ObjectiveCClass, "ClassRexport", false, false, true, 2044 MacOSTargets}, 2045 }; 2046 2047 EXPECT_EQ(ExpectedExportedSymbols.size(), Exports.size()); 2048 EXPECT_EQ(ExpectedReexportedSymbols.size(), Reexports.size()); 2049 EXPECT_EQ(0U, Undefineds.size()); 2050 EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(), 2051 std::begin(ExpectedExportedSymbols))); 2052 EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(), 2053 std::begin(ExpectedReexportedSymbols))); 2054 } 2055 2056 TEST(TBDv5, RemoveIF) { 2057 static const char TBDv5File[] = R"({ 2058 "tapi_tbd_version": 5, 2059 "main_library": { 2060 "target_info": [ 2061 { 2062 "target": "x86_64-macos", 2063 "min_deployment": "10.14" 2064 }, 2065 { 2066 "target": "arm64-macos", 2067 "min_deployment": "10.14" 2068 }, 2069 { 2070 "target": "arm64-maccatalyst", 2071 "min_deployment": "12.1" 2072 } 2073 ], 2074 "flags": [ 2075 { 2076 "targets": [ 2077 "x86_64-macos" 2078 ], 2079 "attributes": [ 2080 "flat_namespace", 2081 "not_for_dyld_shared_cache" 2082 ] 2083 } 2084 ], 2085 "install_names": [ 2086 { 2087 "name": "/S/L/F/Foo.framework/Foo" 2088 } 2089 ], 2090 "current_versions": [ 2091 { 2092 "version": "1.2" 2093 } 2094 ], 2095 "compatibility_versions": [ 2096 { "version": "1.1" } 2097 ], 2098 "rpaths": [ 2099 { 2100 "targets": [ 2101 "x86_64-macos" 2102 ], 2103 "paths": [ 2104 "@executable_path/.../Frameworks" 2105 ] 2106 } 2107 ], 2108 "parent_umbrellas": [ 2109 { 2110 "umbrella": "System" 2111 } 2112 ], 2113 "allowable_clients": [ 2114 { 2115 "clients": [ 2116 "ClientA", 2117 "ClientB" 2118 ] 2119 } 2120 ], 2121 "reexported_libraries": [ 2122 { 2123 "names": [ 2124 "/u/l/l/libfoo.dylib", 2125 "/u/l/l/libbar.dylib" 2126 ] 2127 } 2128 ], 2129 "exported_symbols": [ 2130 { 2131 "targets": [ 2132 "x86_64-macos", 2133 "arm64-macos" 2134 ], 2135 "data": { 2136 "global": [ 2137 "_global" 2138 ], 2139 "objc_class": [ 2140 "ClassA" 2141 ], 2142 "weak": [], 2143 "thread_local": [] 2144 }, 2145 "text": { 2146 "global": [ 2147 "_func" 2148 ], 2149 "weak": [], 2150 "thread_local": [] 2151 } 2152 }, 2153 { 2154 "targets": [ 2155 "x86_64-macos" 2156 ], 2157 "data": { 2158 "global": [ 2159 "_globalVar" 2160 ], 2161 "objc_class": [ 2162 "ClassA", 2163 "ClassB", 2164 "ClassData" 2165 ], 2166 "objc_eh_type": [ 2167 "ClassA", 2168 "ClassB" 2169 ], 2170 "objc_ivar": [ 2171 "ClassA.ivar1", 2172 "ClassA.ivar2", 2173 "ClassC.ivar1" 2174 ] 2175 }, 2176 "text": { 2177 "global": [ 2178 "_funcFoo" 2179 ] 2180 } 2181 } 2182 ], 2183 "reexported_symbols": [ 2184 { 2185 "targets": [ 2186 "x86_64-macos", 2187 "arm64-macos" 2188 ], 2189 "data": { 2190 "global": [ 2191 "_globalRe" 2192 ], 2193 "objc_class": [ 2194 "ClassRexport" 2195 ] 2196 }, 2197 "text": { 2198 "global": [ 2199 "_funcA" 2200 ] 2201 } 2202 } 2203 ], 2204 "undefined_symbols": [ 2205 { 2206 "targets": [ 2207 "x86_64-macos" 2208 ], 2209 "data": { 2210 "global": [ 2211 "_globalBind" 2212 ], 2213 "weak": [ 2214 "referenced_sym" 2215 ] 2216 } 2217 } 2218 ] 2219 }, 2220 "libraries": [] 2221 })"; 2222 2223 Expected<TBDFile> Result = 2224 TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd")); 2225 EXPECT_TRUE(!!Result); 2226 TBDFile File = std::move(Result.get()); 2227 2228 Expected<TBDFile> RemovedResult = File->remove(AK_x86_64); 2229 EXPECT_TRUE(!!RemovedResult); 2230 TBDFile RemovedFile = std::move(RemovedResult.get()); 2231 2232 EXPECT_EQ(FileType::TBD_V5, RemovedFile->getFileType()); 2233 EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"), 2234 RemovedFile->getInstallName()); 2235 2236 TargetList AllTargets = { 2237 Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0, 0)), 2238 Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(14, 0)), 2239 }; 2240 EXPECT_EQ(mapToPlatformSet(AllTargets), RemovedFile->getPlatforms()); 2241 EXPECT_EQ(mapToArchitectureSet(AllTargets), RemovedFile->getArchitectures()); 2242 2243 EXPECT_EQ(PackedVersion(1, 2, 0), RemovedFile->getCurrentVersion()); 2244 EXPECT_EQ(PackedVersion(1, 1, 0), RemovedFile->getCompatibilityVersion()); 2245 EXPECT_TRUE(RemovedFile->isApplicationExtensionSafe()); 2246 EXPECT_TRUE(RemovedFile->isOSLibNotForSharedCache()); 2247 EXPECT_FALSE(RemovedFile->isTwoLevelNamespace()); 2248 EXPECT_EQ(0U, RemovedFile->documents().size()); 2249 2250 InterfaceFileRef ClientA("ClientA", AllTargets); 2251 InterfaceFileRef ClientB("ClientB", AllTargets); 2252 EXPECT_EQ(2U, RemovedFile->allowableClients().size()); 2253 EXPECT_EQ(ClientA, RemovedFile->allowableClients().at(0)); 2254 EXPECT_EQ(ClientB, RemovedFile->allowableClients().at(1)); 2255 2256 InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets); 2257 InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets); 2258 EXPECT_EQ(2U, RemovedFile->reexportedLibraries().size()); 2259 EXPECT_EQ(ReexportA, RemovedFile->reexportedLibraries().at(0)); 2260 EXPECT_EQ(ReexportB, RemovedFile->reexportedLibraries().at(1)); 2261 2262 EXPECT_EQ(0u, RemovedFile->rpaths().size()); 2263 2264 TargetToAttr Umbrellas = {{Target(AK_arm64, PLATFORM_MACOS), "System"}, 2265 {Target(AK_arm64, PLATFORM_MACCATALYST), "System"}}; 2266 EXPECT_EQ(Umbrellas, RemovedFile->umbrellas()); 2267 2268 ExportedSymbolSeq Exports, Reexports, Undefineds; 2269 for (const auto *Sym : RemovedFile->symbols()) { 2270 TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()}; 2271 ExportedSymbol Temp = 2272 ExportedSymbol{Sym->getKind(), 2273 std::string(Sym->getName()), 2274 Sym->isWeakDefined() || Sym->isWeakReferenced(), 2275 Sym->isThreadLocalValue(), 2276 Sym->isData(), 2277 SymTargets}; 2278 if (Sym->isUndefined()) 2279 Undefineds.emplace_back(std::move(Temp)); 2280 else 2281 Sym->isReexported() ? Reexports.emplace_back(std::move(Temp)) 2282 : Exports.emplace_back(std::move(Temp)); 2283 } 2284 llvm::sort(Exports); 2285 llvm::sort(Reexports); 2286 llvm::sort(Undefineds); 2287 2288 TargetList MacOSTargets = {Target(AK_arm64, PLATFORM_MACOS)}; 2289 2290 std::vector<ExportedSymbol> ExpectedExportedSymbols = { 2291 {EncodeKind::GlobalSymbol, "_func", false, false, false, MacOSTargets}, 2292 {EncodeKind::GlobalSymbol, "_global", false, false, true, MacOSTargets}, 2293 {EncodeKind::ObjectiveCClass, "ClassA", false, false, true, MacOSTargets}, 2294 }; 2295 std::vector<ExportedSymbol> ExpectedReexportedSymbols = { 2296 {EncodeKind::GlobalSymbol, "_funcA", false, false, false, MacOSTargets}, 2297 {EncodeKind::GlobalSymbol, "_globalRe", false, false, true, MacOSTargets}, 2298 {EncodeKind::ObjectiveCClass, "ClassRexport", false, false, true, 2299 MacOSTargets}, 2300 }; 2301 2302 EXPECT_EQ(ExpectedExportedSymbols.size(), Exports.size()); 2303 EXPECT_EQ(ExpectedReexportedSymbols.size(), Reexports.size()); 2304 EXPECT_EQ(0U, Undefineds.size()); 2305 EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(), 2306 std::begin(ExpectedExportedSymbols))); 2307 EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(), 2308 std::begin(ExpectedReexportedSymbols))); 2309 } 2310 2311 TEST(TBDv5, InlineIF) { 2312 static const char UmbrellaFile[] = R"({ 2313 "tapi_tbd_version": 5, 2314 "main_library": { 2315 "target_info": [ 2316 { 2317 "target": "x86_64-macos", 2318 "min_deployment": "10.14" 2319 }, 2320 { 2321 "target": "arm64-macos", 2322 "min_deployment": "10.14" 2323 } 2324 ], 2325 "install_names": [ 2326 { 2327 "name": "/S/L/F/Foo.framework/Foo" 2328 } 2329 ], 2330 "current_versions": [ 2331 { 2332 "version": "1.2" 2333 } 2334 ], 2335 "reexported_libraries": [ 2336 { 2337 "names": [ 2338 "/u/l/l/libfoo.dylib", 2339 "/u/l/l/libbar.dylib" 2340 ] 2341 } 2342 ] 2343 }})"; 2344 2345 static const char ReexportFile[] = R"({ 2346 "tapi_tbd_version": 5, 2347 "main_library": { 2348 "target_info": [ 2349 { 2350 "target": "x86_64-macos", 2351 "min_deployment": "10.14" 2352 }, 2353 { 2354 "target": "arm64-macos", 2355 "min_deployment": "10.14" 2356 } 2357 ], 2358 "install_names": [ 2359 { 2360 "name" : "/u/l/l/libfoo.dylib" 2361 } 2362 ], 2363 "current_versions": [ 2364 { 2365 "version": "1" 2366 } 2367 ], 2368 "rpaths": [ 2369 { 2370 "targets": [ 2371 "x86_64-macos" 2372 ], 2373 "paths": [ 2374 "@executable_path/.../Frameworks" 2375 ] 2376 } 2377 ], 2378 "exported_symbols": [ 2379 { 2380 "targets": [ 2381 "x86_64-macos", 2382 "arm64-macos" 2383 ], 2384 "data": { 2385 "global": [ 2386 "_global" 2387 ], 2388 "objc_class": [ 2389 "ClassA" 2390 ], 2391 "weak": [], 2392 "thread_local": [] 2393 } 2394 } 2395 ]}})"; 2396 2397 Expected<TBDFile> UmbrellaResult = 2398 TextAPIReader::get(MemoryBufferRef(UmbrellaFile, "Test.tbd")); 2399 EXPECT_TRUE(!!UmbrellaResult); 2400 TBDFile Umbrella = std::move(UmbrellaResult.get()); 2401 2402 Expected<TBDFile> ReexportResult = 2403 TextAPIReader::get(MemoryBufferRef(ReexportFile, "Test.tbd")); 2404 EXPECT_TRUE(!!ReexportResult); 2405 TBDReexportFile Reexport = std::move(ReexportResult.get()); 2406 Umbrella->inlineLibrary(Reexport); 2407 2408 EXPECT_EQ(FileType::TBD_V5, Umbrella->getFileType()); 2409 EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"), 2410 Umbrella->getInstallName()); 2411 2412 TargetList AllTargets = { 2413 Target(AK_x86_64, PLATFORM_MACOS, VersionTuple(10, 14)), 2414 Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0, 0)), 2415 }; 2416 EXPECT_EQ(mapToPlatformSet(AllTargets), Umbrella->getPlatforms()); 2417 EXPECT_EQ(mapToArchitectureSet(AllTargets), Umbrella->getArchitectures()); 2418 2419 EXPECT_EQ(PackedVersion(1, 2, 0), Umbrella->getCurrentVersion()); 2420 EXPECT_EQ(PackedVersion(1, 0, 0), Umbrella->getCompatibilityVersion()); 2421 InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets); 2422 InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets); 2423 EXPECT_EQ(2U, Umbrella->reexportedLibraries().size()); 2424 EXPECT_EQ(ReexportA, Umbrella->reexportedLibraries().at(0)); 2425 EXPECT_EQ(ReexportB, Umbrella->reexportedLibraries().at(1)); 2426 EXPECT_EQ(1U, Umbrella->documents().size()); 2427 2428 TBDReexportFile Document = Umbrella->documents().front(); 2429 EXPECT_EQ(std::string("/u/l/l/libfoo.dylib"), Document->getInstallName()); 2430 EXPECT_EQ(0U, Document->getSwiftABIVersion()); 2431 EXPECT_TRUE(Document->isTwoLevelNamespace()); 2432 EXPECT_TRUE(Document->isApplicationExtensionSafe()); 2433 EXPECT_EQ(PackedVersion(1, 0, 0), Document->getCurrentVersion()); 2434 EXPECT_EQ(PackedVersion(1, 0, 0), Document->getCompatibilityVersion()); 2435 2436 ExportedSymbolSeq Exports; 2437 for (const auto *Sym : Document->symbols()) { 2438 TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()}; 2439 Exports.emplace_back( 2440 ExportedSymbol{Sym->getKind(), std::string(Sym->getName()), 2441 Sym->isWeakDefined() || Sym->isWeakReferenced(), 2442 Sym->isThreadLocalValue(), Sym->isData(), SymTargets}); 2443 } 2444 llvm::sort(Exports); 2445 2446 ExportedSymbolSeq ExpectedExports = { 2447 {EncodeKind::GlobalSymbol, "_global", false, false, true, AllTargets}, 2448 {EncodeKind::ObjectiveCClass, "ClassA", false, false, true, AllTargets}, 2449 }; 2450 EXPECT_EQ(ExpectedExports.size(), Exports.size()); 2451 EXPECT_TRUE( 2452 std::equal(Exports.begin(), Exports.end(), std::begin(ExpectedExports))); 2453 } 2454 } // end namespace TBDv5 2455