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 {SymbolKind::GlobalSymbol, "_func", false, false, false, MacOSTargets}, 271 {SymbolKind::GlobalSymbol, 272 "_funcFoo", 273 false, 274 false, 275 false, 276 {Target(AK_x86_64, PLATFORM_MACOS)}}, 277 {SymbolKind::GlobalSymbol, "_global", false, false, true, MacOSTargets}, 278 {SymbolKind::GlobalSymbol, 279 "_globalVar", 280 false, 281 false, 282 true, 283 {Target(AK_x86_64, PLATFORM_MACOS)}}, 284 {SymbolKind::ObjectiveCClass, 285 "ClassA", 286 false, 287 false, 288 true, 289 {Target(AK_x86_64, PLATFORM_MACOS)}}, 290 {SymbolKind::ObjectiveCClass, 291 "ClassB", 292 false, 293 false, 294 true, 295 {Target(AK_x86_64, PLATFORM_MACOS)}}, 296 {SymbolKind::ObjectiveCClass, 297 "ClassData", 298 false, 299 false, 300 true, 301 {Target(AK_x86_64, PLATFORM_MACOS)}}, 302 {SymbolKind::ObjectiveCClassEHType, 303 "ClassA", 304 false, 305 false, 306 true, 307 {Target(AK_x86_64, PLATFORM_MACOS)}}, 308 {SymbolKind::ObjectiveCClassEHType, 309 "ClassB", 310 false, 311 false, 312 true, 313 {Target(AK_x86_64, PLATFORM_MACOS)}}, 314 {SymbolKind::ObjectiveCInstanceVariable, 315 "ClassA.ivar1", 316 false, 317 false, 318 true, 319 {Target(AK_x86_64, PLATFORM_MACOS)}}, 320 {SymbolKind::ObjectiveCInstanceVariable, 321 "ClassA.ivar2", 322 false, 323 false, 324 true, 325 {Target(AK_x86_64, PLATFORM_MACOS)}}, 326 {SymbolKind::ObjectiveCInstanceVariable, 327 "ClassC.ivar1", 328 false, 329 false, 330 true, 331 {Target(AK_x86_64, PLATFORM_MACOS)}}, 332 }; 333 std::vector<ExportedSymbol> ExpectedReexportedSymbols = { 334 {SymbolKind::GlobalSymbol, "_funcA", false, false, false, MacOSTargets}, 335 {SymbolKind::GlobalSymbol, "_globalRe", false, false, true, MacOSTargets}, 336 {SymbolKind::ObjectiveCClass, "ClassRexport", false, false, true, 337 MacOSTargets}, 338 }; 339 340 std::vector<ExportedSymbol> ExpectedUndefinedSymbols = { 341 {SymbolKind::GlobalSymbol, 342 "_globalBind", 343 false, 344 false, 345 true, 346 {Target(AK_x86_64, PLATFORM_MACOS)}}, 347 {SymbolKind::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(SymbolKind::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 {SymbolKind::GlobalSymbol, "_funcFoo", false, false, false, {iOSTarget}}, 528 {SymbolKind::GlobalSymbol, "_globalVar", false, true, true, {iOSTarget}}, 529 {SymbolKind::ObjectiveCClass, "ClassA", false, false, true, {iOSTarget}}, 530 {SymbolKind::ObjectiveCClass, "ClassB", false, false, true, {iOSTarget}}, 531 {SymbolKind::ObjectiveCClass, 532 "ClassData", 533 false, 534 false, 535 true, 536 {iOSTarget}}, 537 {SymbolKind::ObjectiveCClassEHType, 538 "ClassA", 539 false, 540 false, 541 true, 542 {iOSTarget}}, 543 {SymbolKind::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(AllTargets[0], "@executable_path/.../Frameworks"); 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(SymbolKind::GlobalSymbol, "_global", 738 {AllTargets[0], AllTargets[1]}, Flags | SymbolFlags::Data); 739 File.addSymbol(SymbolKind::GlobalSymbol, "_func", 740 {AllTargets[0], AllTargets[1]}, Flags | SymbolFlags::Text); 741 File.addSymbol(SymbolKind::ObjectiveCClass, "ClassA", 742 {AllTargets[0], AllTargets[1]}, Flags | SymbolFlags::Data); 743 File.addSymbol(SymbolKind::GlobalSymbol, "_funcFoo", {AllTargets[0]}, 744 Flags | SymbolFlags::Text); 745 File.addSymbol(SymbolKind::GlobalSymbol, "_globalVar", {AllTargets[0]}, 746 Flags | SymbolFlags::Data); 747 File.addSymbol(SymbolKind::ObjectiveCClass, "ClassData", {AllTargets[0]}, 748 Flags | SymbolFlags::Data); 749 File.addSymbol(SymbolKind::ObjectiveCClassEHType, "ClassA", {AllTargets[0]}, 750 Flags | SymbolFlags::Data); 751 File.addSymbol(SymbolKind::ObjectiveCClassEHType, "ClassB", {AllTargets[0]}, 752 Flags | SymbolFlags::Data); 753 File.addSymbol(SymbolKind::ObjectiveCInstanceVariable, "ClassA.ivar1", 754 {AllTargets[0]}, Flags | SymbolFlags::Data); 755 File.addSymbol(SymbolKind::ObjectiveCInstanceVariable, "ClassA.ivar2", 756 {AllTargets[0]}, Flags | SymbolFlags::Data); 757 File.addSymbol(SymbolKind::ObjectiveCInstanceVariable, "ClassC.ivar1", 758 {AllTargets[0]}, Flags | SymbolFlags::Data); 759 760 // Reexports. 761 Flags = SymbolFlags::Rexported; 762 File.addSymbol(SymbolKind::GlobalSymbol, "_globalRe", AllTargets, 763 Flags | SymbolFlags::Data); 764 File.addSymbol(SymbolKind::GlobalSymbol, "_funcA", AllTargets, 765 Flags | SymbolFlags::Text); 766 File.addSymbol(SymbolKind::ObjectiveCClass, "ClassRexport", AllTargets, 767 Flags | SymbolFlags::Data); 768 769 // Undefineds. 770 Flags = SymbolFlags::Undefined; 771 File.addSymbol(SymbolKind::GlobalSymbol, "_globalBind", {AllTargets[0]}, 772 Flags | SymbolFlags::Data); 773 File.addSymbol(SymbolKind::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(AllTargets[0], "@executable_path/.../Frameworks"); 901 for (const auto &Targ : AllTargets) 902 NestedFile.addReexportedLibrary("@rpath/libfoo.dylib", Targ); 903 NestedFile.addSymbol(SymbolKind::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(SymbolKind::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, MergeIF) { 1234 static const char TBDv5FileA[] = R"({ 1235 "tapi_tbd_version": 5, 1236 "main_library": { 1237 "target_info": [ 1238 { 1239 "target": "x86_64-macos", 1240 "min_deployment": "10.14" 1241 }, 1242 { 1243 "target": "arm64-macos", 1244 "min_deployment": "10.14" 1245 }, 1246 { 1247 "target": "arm64-maccatalyst", 1248 "min_deployment": "12.1" 1249 } 1250 ], 1251 "flags": [ 1252 { 1253 "targets": [ 1254 "x86_64-macos" 1255 ], 1256 "attributes": [ 1257 "flat_namespace" 1258 ] 1259 } 1260 ], 1261 "install_names": [ 1262 { 1263 "name": "/S/L/F/Foo.framework/Foo" 1264 } 1265 ], 1266 "current_versions": [ 1267 { 1268 "version": "1.2" 1269 } 1270 ], 1271 "compatibility_versions": [ 1272 { "version": "1.1" } 1273 ], 1274 "rpaths": [ 1275 { 1276 "targets": [ 1277 "x86_64-macos" 1278 ], 1279 "paths": [ 1280 "@executable_path/.../Frameworks" 1281 ] 1282 } 1283 ], 1284 "parent_umbrellas": [ 1285 { 1286 "umbrella": "System" 1287 } 1288 ], 1289 "allowable_clients": [ 1290 { 1291 "clients": [ 1292 "ClientA", 1293 "ClientB" 1294 ] 1295 } 1296 ], 1297 "reexported_libraries": [ 1298 { 1299 "names": [ 1300 "/u/l/l/libfoo.dylib", 1301 "/u/l/l/libbar.dylib" 1302 ] 1303 } 1304 ], 1305 "exported_symbols": [ 1306 { 1307 "targets": [ 1308 "x86_64-macos", 1309 "arm64-macos" 1310 ], 1311 "data": { 1312 "global": [ 1313 "_global" 1314 ], 1315 "objc_class": [ 1316 "ClassA" 1317 ], 1318 "weak": [], 1319 "thread_local": [] 1320 }, 1321 "text": { 1322 "global": [ 1323 "_func" 1324 ], 1325 "weak": [], 1326 "thread_local": [] 1327 } 1328 }, 1329 { 1330 "targets": [ 1331 "x86_64-macos" 1332 ], 1333 "data": { 1334 "global": [ 1335 "_globalVar" 1336 ], 1337 "objc_class": [ 1338 "ClassA", 1339 "ClassB", 1340 "ClassData" 1341 ], 1342 "objc_eh_type": [ 1343 "ClassA", 1344 "ClassB" 1345 ], 1346 "objc_ivar": [ 1347 "ClassA.ivar1", 1348 "ClassA.ivar2", 1349 "ClassC.ivar1" 1350 ] 1351 }, 1352 "text": { 1353 "global": [ 1354 "_funcFoo" 1355 ] 1356 } 1357 } 1358 ], 1359 "reexported_symbols": [ 1360 { 1361 "targets": [ 1362 "x86_64-macos", 1363 "arm64-macos" 1364 ], 1365 "data": { 1366 "global": [ 1367 "_globalRe" 1368 ], 1369 "objc_class": [ 1370 "ClassRexport" 1371 ] 1372 }, 1373 "text": { 1374 "global": [ 1375 "_funcA" 1376 ] 1377 } 1378 } 1379 ], 1380 "undefined_symbols": [ 1381 { 1382 "targets": [ 1383 "x86_64-macos" 1384 ], 1385 "data": { 1386 "global": [ 1387 "_globalBind" 1388 ], 1389 "weak": [ 1390 "referenced_sym" 1391 ] 1392 } 1393 } 1394 ] 1395 }, 1396 "libraries": [] 1397 })"; 1398 1399 static const char TBDv5FileB[] = R"({ 1400 "tapi_tbd_version": 5, 1401 "main_library": { 1402 "target_info": [ 1403 { 1404 "target": "x86_64-macos", 1405 "min_deployment": "10.14" 1406 }, 1407 { 1408 "target": "arm64-macos", 1409 "min_deployment": "10.14" 1410 }, 1411 { 1412 "target": "arm64-maccatalyst", 1413 "min_deployment": "12.1" 1414 } 1415 ], 1416 "flags": [ 1417 { 1418 "targets": [ 1419 "x86_64-macos" 1420 ], 1421 "attributes": [ 1422 "flat_namespace" 1423 ] 1424 } 1425 ], 1426 "install_names": [ 1427 { 1428 "name": "/S/L/F/Foo.framework/Foo" 1429 } 1430 ], 1431 "current_versions": [ 1432 { 1433 "version": "1.2" 1434 } 1435 ], 1436 "compatibility_versions": [ 1437 { "version": "1.1" } 1438 ], 1439 "exported_symbols": [ 1440 { 1441 "targets": [ 1442 "x86_64-macos", 1443 "arm64-macos" 1444 ], 1445 "data": { 1446 "global": [ 1447 "_globalZ" 1448 ], 1449 "objc_class": [ 1450 "ClassZ" 1451 ], 1452 "weak": [], 1453 "thread_local": [] 1454 }, 1455 "text": { 1456 "global": [ 1457 "_funcZ" 1458 ], 1459 "weak": [], 1460 "thread_local": [] 1461 } 1462 }, 1463 { 1464 "targets": [ 1465 "x86_64-macos" 1466 ], 1467 "data": { 1468 "global": [ 1469 "_globalVarZ" 1470 ], 1471 "objc_class": [ 1472 "ClassZ", 1473 "ClassF" 1474 ], 1475 "objc_eh_type": [ 1476 "ClassZ", 1477 "ClassF" 1478 ], 1479 "objc_ivar": [ 1480 "ClassZ.ivar1", 1481 "ClassZ.ivar2", 1482 "ClassF.ivar1" 1483 ] 1484 }, 1485 "text": { 1486 "global": [ 1487 "_funcFooZ" 1488 ] 1489 } 1490 } 1491 ] 1492 }, 1493 "libraries": [] 1494 })"; 1495 1496 Expected<TBDFile> ResultA = 1497 TextAPIReader::get(MemoryBufferRef(TBDv5FileA, "Test.tbd")); 1498 EXPECT_TRUE(!!ResultA); 1499 TBDFile FileA = std::move(ResultA.get()); 1500 1501 Expected<TBDFile> ResultB = 1502 TextAPIReader::get(MemoryBufferRef(TBDv5FileB, "Test.tbd")); 1503 EXPECT_TRUE(!!ResultB); 1504 TBDFile FileB = std::move(ResultB.get()); 1505 1506 Expected<TBDFile> MergedResult = FileA->merge(FileB.get()); 1507 EXPECT_TRUE(!!MergedResult); 1508 TBDFile MergedFile = std::move(MergedResult.get()); 1509 1510 EXPECT_EQ(FileType::TBD_V5, MergedFile->getFileType()); 1511 EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"), 1512 MergedFile->getInstallName()); 1513 TargetList AllTargets = { 1514 Target(AK_x86_64, PLATFORM_MACOS, VersionTuple(10, 14)), 1515 Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0, 0)), 1516 Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(14, 0)), 1517 }; 1518 EXPECT_EQ(mapToPlatformSet(AllTargets), MergedFile->getPlatforms()); 1519 EXPECT_EQ(mapToArchitectureSet(AllTargets), MergedFile->getArchitectures()); 1520 EXPECT_EQ(PackedVersion(1, 2, 0), MergedFile->getCurrentVersion()); 1521 EXPECT_EQ(PackedVersion(1, 1, 0), MergedFile->getCompatibilityVersion()); 1522 EXPECT_TRUE(MergedFile->isApplicationExtensionSafe()); 1523 EXPECT_FALSE(MergedFile->isTwoLevelNamespace()); 1524 EXPECT_EQ(0U, MergedFile->documents().size()); 1525 InterfaceFileRef ClientA("ClientA", AllTargets); 1526 InterfaceFileRef ClientB("ClientB", AllTargets); 1527 EXPECT_EQ(2U, MergedFile->allowableClients().size()); 1528 EXPECT_EQ(ClientA, MergedFile->allowableClients().at(0)); 1529 EXPECT_EQ(ClientB, MergedFile->allowableClients().at(1)); 1530 1531 InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets); 1532 InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets); 1533 EXPECT_EQ(2U, MergedFile->reexportedLibraries().size()); 1534 EXPECT_EQ(ReexportA, MergedFile->reexportedLibraries().at(0)); 1535 EXPECT_EQ(ReexportB, MergedFile->reexportedLibraries().at(1)); 1536 1537 TargetToAttr RPaths = { 1538 {Target(AK_x86_64, PLATFORM_MACOS), "@executable_path/.../Frameworks"}, 1539 }; 1540 EXPECT_EQ(RPaths, MergedFile->rpaths()); 1541 1542 TargetToAttr Umbrellas = {{Target(AK_x86_64, PLATFORM_MACOS), "System"}, 1543 {Target(AK_arm64, PLATFORM_MACOS), "System"}, 1544 {Target(AK_arm64, PLATFORM_MACCATALYST), "System"}}; 1545 EXPECT_EQ(Umbrellas, MergedFile->umbrellas()); 1546 1547 ExportedSymbolSeq Exports, Reexports, Undefineds; 1548 for (const auto *Sym : MergedFile->symbols()) { 1549 TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()}; 1550 ExportedSymbol Temp = 1551 ExportedSymbol{Sym->getKind(), 1552 std::string(Sym->getName()), 1553 Sym->isWeakDefined() || Sym->isWeakReferenced(), 1554 Sym->isThreadLocalValue(), 1555 Sym->isData(), 1556 SymTargets}; 1557 if (Sym->isUndefined()) 1558 Undefineds.emplace_back(std::move(Temp)); 1559 else 1560 Sym->isReexported() ? Reexports.emplace_back(std::move(Temp)) 1561 : Exports.emplace_back(std::move(Temp)); 1562 } 1563 llvm::sort(Exports); 1564 llvm::sort(Reexports); 1565 llvm::sort(Undefineds); 1566 1567 TargetList MacOSTargets = {Target(AK_x86_64, PLATFORM_MACOS), 1568 Target(AK_arm64, PLATFORM_MACOS)}; 1569 1570 std::vector<ExportedSymbol> ExpectedExportedSymbols = { 1571 {SymbolKind::GlobalSymbol, "_func", false, false, false, MacOSTargets}, 1572 {SymbolKind::GlobalSymbol, 1573 "_funcFoo", 1574 false, 1575 false, 1576 false, 1577 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1578 {SymbolKind::GlobalSymbol, 1579 "_funcFooZ", 1580 false, 1581 false, 1582 false, 1583 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1584 {SymbolKind::GlobalSymbol, "_funcZ", false, false, false, MacOSTargets}, 1585 {SymbolKind::GlobalSymbol, "_global", false, false, true, MacOSTargets}, 1586 {SymbolKind::GlobalSymbol, 1587 "_globalVar", 1588 false, 1589 false, 1590 true, 1591 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1592 {SymbolKind::GlobalSymbol, 1593 "_globalVarZ", 1594 false, 1595 false, 1596 true, 1597 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1598 {SymbolKind::GlobalSymbol, "_globalZ", false, false, true, MacOSTargets}, 1599 {SymbolKind::ObjectiveCClass, 1600 "ClassA", 1601 false, 1602 false, 1603 true, 1604 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1605 {SymbolKind::ObjectiveCClass, 1606 "ClassB", 1607 false, 1608 false, 1609 true, 1610 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1611 {SymbolKind::ObjectiveCClass, 1612 "ClassData", 1613 false, 1614 false, 1615 true, 1616 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1617 {SymbolKind::ObjectiveCClass, 1618 "ClassF", 1619 false, 1620 false, 1621 true, 1622 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1623 {SymbolKind::ObjectiveCClass, 1624 "ClassZ", 1625 false, 1626 false, 1627 true, 1628 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1629 {SymbolKind::ObjectiveCClassEHType, 1630 "ClassA", 1631 false, 1632 false, 1633 true, 1634 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1635 {SymbolKind::ObjectiveCClassEHType, 1636 "ClassB", 1637 false, 1638 false, 1639 true, 1640 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1641 {SymbolKind::ObjectiveCClassEHType, 1642 "ClassF", 1643 false, 1644 false, 1645 true, 1646 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1647 {SymbolKind::ObjectiveCClassEHType, 1648 "ClassZ", 1649 false, 1650 false, 1651 true, 1652 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1653 {SymbolKind::ObjectiveCInstanceVariable, 1654 "ClassA.ivar1", 1655 false, 1656 false, 1657 true, 1658 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1659 {SymbolKind::ObjectiveCInstanceVariable, 1660 "ClassA.ivar2", 1661 false, 1662 false, 1663 true, 1664 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1665 {SymbolKind::ObjectiveCInstanceVariable, 1666 "ClassC.ivar1", 1667 false, 1668 false, 1669 true, 1670 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1671 {SymbolKind::ObjectiveCInstanceVariable, 1672 "ClassF.ivar1", 1673 false, 1674 false, 1675 true, 1676 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1677 {SymbolKind::ObjectiveCInstanceVariable, 1678 "ClassZ.ivar1", 1679 false, 1680 false, 1681 true, 1682 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1683 {SymbolKind::ObjectiveCInstanceVariable, 1684 "ClassZ.ivar2", 1685 false, 1686 false, 1687 true, 1688 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1689 }; 1690 1691 std::vector<ExportedSymbol> ExpectedReexportedSymbols = { 1692 {SymbolKind::GlobalSymbol, "_funcA", false, false, false, MacOSTargets}, 1693 {SymbolKind::GlobalSymbol, "_globalRe", false, false, true, MacOSTargets}, 1694 {SymbolKind::ObjectiveCClass, "ClassRexport", false, false, true, 1695 MacOSTargets}, 1696 }; 1697 1698 std::vector<ExportedSymbol> ExpectedUndefinedSymbols = { 1699 {SymbolKind::GlobalSymbol, 1700 "_globalBind", 1701 false, 1702 false, 1703 true, 1704 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1705 {SymbolKind::GlobalSymbol, 1706 "referenced_sym", 1707 true, 1708 false, 1709 true, 1710 {Target(AK_x86_64, PLATFORM_MACOS)}}, 1711 }; 1712 1713 EXPECT_EQ(ExpectedExportedSymbols.size(), Exports.size()); 1714 EXPECT_EQ(ExpectedReexportedSymbols.size(), Reexports.size()); 1715 EXPECT_EQ(ExpectedUndefinedSymbols.size(), Undefineds.size()); 1716 EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(), 1717 std::begin(ExpectedExportedSymbols))); 1718 EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(), 1719 std::begin(ExpectedReexportedSymbols))); 1720 EXPECT_TRUE(std::equal(Undefineds.begin(), Undefineds.end(), 1721 std::begin(ExpectedUndefinedSymbols))); 1722 } 1723 1724 TEST(TBDv5, ExtractIF) { 1725 static const char TBDv5File[] = R"({ 1726 "tapi_tbd_version": 5, 1727 "main_library": { 1728 "target_info": [ 1729 { 1730 "target": "x86_64-macos", 1731 "min_deployment": "10.14" 1732 }, 1733 { 1734 "target": "arm64-macos", 1735 "min_deployment": "10.14" 1736 }, 1737 { 1738 "target": "arm64-maccatalyst", 1739 "min_deployment": "12.1" 1740 } 1741 ], 1742 "flags": [ 1743 { 1744 "targets": [ 1745 "x86_64-macos" 1746 ], 1747 "attributes": [ 1748 "flat_namespace" 1749 ] 1750 } 1751 ], 1752 "install_names": [ 1753 { 1754 "name": "/S/L/F/Foo.framework/Foo" 1755 } 1756 ], 1757 "current_versions": [ 1758 { 1759 "version": "1.2" 1760 } 1761 ], 1762 "compatibility_versions": [ 1763 { "version": "1.1" } 1764 ], 1765 "rpaths": [ 1766 { 1767 "targets": [ 1768 "x86_64-macos" 1769 ], 1770 "paths": [ 1771 "@executable_path/.../Frameworks" 1772 ] 1773 } 1774 ], 1775 "parent_umbrellas": [ 1776 { 1777 "umbrella": "System" 1778 } 1779 ], 1780 "allowable_clients": [ 1781 { 1782 "clients": [ 1783 "ClientA", 1784 "ClientB" 1785 ] 1786 } 1787 ], 1788 "reexported_libraries": [ 1789 { 1790 "names": [ 1791 "/u/l/l/libfoo.dylib", 1792 "/u/l/l/libbar.dylib" 1793 ] 1794 } 1795 ], 1796 "exported_symbols": [ 1797 { 1798 "targets": [ 1799 "x86_64-macos", 1800 "arm64-macos" 1801 ], 1802 "data": { 1803 "global": [ 1804 "_global" 1805 ], 1806 "objc_class": [ 1807 "ClassA" 1808 ], 1809 "weak": [], 1810 "thread_local": [] 1811 }, 1812 "text": { 1813 "global": [ 1814 "_func" 1815 ], 1816 "weak": [], 1817 "thread_local": [] 1818 } 1819 }, 1820 { 1821 "targets": [ 1822 "x86_64-macos" 1823 ], 1824 "data": { 1825 "global": [ 1826 "_globalVar" 1827 ], 1828 "objc_class": [ 1829 "ClassA", 1830 "ClassB", 1831 "ClassData" 1832 ], 1833 "objc_eh_type": [ 1834 "ClassA", 1835 "ClassB" 1836 ], 1837 "objc_ivar": [ 1838 "ClassA.ivar1", 1839 "ClassA.ivar2", 1840 "ClassC.ivar1" 1841 ] 1842 }, 1843 "text": { 1844 "global": [ 1845 "_funcFoo" 1846 ] 1847 } 1848 } 1849 ], 1850 "reexported_symbols": [ 1851 { 1852 "targets": [ 1853 "x86_64-macos", 1854 "arm64-macos" 1855 ], 1856 "data": { 1857 "global": [ 1858 "_globalRe" 1859 ], 1860 "objc_class": [ 1861 "ClassRexport" 1862 ] 1863 }, 1864 "text": { 1865 "global": [ 1866 "_funcA" 1867 ] 1868 } 1869 } 1870 ], 1871 "undefined_symbols": [ 1872 { 1873 "targets": [ 1874 "x86_64-macos" 1875 ], 1876 "data": { 1877 "global": [ 1878 "_globalBind" 1879 ], 1880 "weak": [ 1881 "referenced_sym" 1882 ] 1883 } 1884 } 1885 ] 1886 }, 1887 "libraries": [] 1888 })"; 1889 1890 Expected<TBDFile> Result = 1891 TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd")); 1892 EXPECT_TRUE(!!Result); 1893 TBDFile File = std::move(Result.get()); 1894 1895 Expected<TBDFile> ExtractedResult = File->extract(AK_arm64); 1896 EXPECT_TRUE(!!ExtractedResult); 1897 TBDFile ExtractedFile = std::move(ExtractedResult.get()); 1898 1899 EXPECT_EQ(FileType::TBD_V5, ExtractedFile->getFileType()); 1900 EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"), 1901 ExtractedFile->getInstallName()); 1902 1903 TargetList AllTargets = { 1904 Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0, 0)), 1905 Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(14, 0)), 1906 }; 1907 EXPECT_EQ(mapToPlatformSet(AllTargets), ExtractedFile->getPlatforms()); 1908 EXPECT_EQ(mapToArchitectureSet(AllTargets), 1909 ExtractedFile->getArchitectures()); 1910 1911 EXPECT_EQ(PackedVersion(1, 2, 0), ExtractedFile->getCurrentVersion()); 1912 EXPECT_EQ(PackedVersion(1, 1, 0), ExtractedFile->getCompatibilityVersion()); 1913 EXPECT_TRUE(ExtractedFile->isApplicationExtensionSafe()); 1914 EXPECT_FALSE(ExtractedFile->isTwoLevelNamespace()); 1915 EXPECT_EQ(0U, ExtractedFile->documents().size()); 1916 1917 InterfaceFileRef ClientA("ClientA", AllTargets); 1918 InterfaceFileRef ClientB("ClientB", AllTargets); 1919 EXPECT_EQ(2U, ExtractedFile->allowableClients().size()); 1920 EXPECT_EQ(ClientA, ExtractedFile->allowableClients().at(0)); 1921 EXPECT_EQ(ClientB, ExtractedFile->allowableClients().at(1)); 1922 1923 InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets); 1924 InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets); 1925 EXPECT_EQ(2U, ExtractedFile->reexportedLibraries().size()); 1926 EXPECT_EQ(ReexportA, ExtractedFile->reexportedLibraries().at(0)); 1927 EXPECT_EQ(ReexportB, ExtractedFile->reexportedLibraries().at(1)); 1928 1929 EXPECT_EQ(0u, ExtractedFile->rpaths().size()); 1930 1931 TargetToAttr Umbrellas = {{Target(AK_arm64, PLATFORM_MACOS), "System"}, 1932 {Target(AK_arm64, PLATFORM_MACCATALYST), "System"}}; 1933 EXPECT_EQ(Umbrellas, ExtractedFile->umbrellas()); 1934 1935 ExportedSymbolSeq Exports, Reexports, Undefineds; 1936 for (const auto *Sym : ExtractedFile->symbols()) { 1937 TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()}; 1938 ExportedSymbol Temp = 1939 ExportedSymbol{Sym->getKind(), 1940 std::string(Sym->getName()), 1941 Sym->isWeakDefined() || Sym->isWeakReferenced(), 1942 Sym->isThreadLocalValue(), 1943 Sym->isData(), 1944 SymTargets}; 1945 if (Sym->isUndefined()) 1946 Undefineds.emplace_back(std::move(Temp)); 1947 else 1948 Sym->isReexported() ? Reexports.emplace_back(std::move(Temp)) 1949 : Exports.emplace_back(std::move(Temp)); 1950 } 1951 llvm::sort(Exports); 1952 llvm::sort(Reexports); 1953 llvm::sort(Undefineds); 1954 1955 TargetList MacOSTargets = {Target(AK_arm64, PLATFORM_MACOS)}; 1956 1957 std::vector<ExportedSymbol> ExpectedExportedSymbols = { 1958 {SymbolKind::GlobalSymbol, "_func", false, false, false, MacOSTargets}, 1959 {SymbolKind::GlobalSymbol, "_global", false, false, true, MacOSTargets}, 1960 {SymbolKind::ObjectiveCClass, "ClassA", false, false, true, MacOSTargets}, 1961 }; 1962 std::vector<ExportedSymbol> ExpectedReexportedSymbols = { 1963 {SymbolKind::GlobalSymbol, "_funcA", false, false, false, MacOSTargets}, 1964 {SymbolKind::GlobalSymbol, "_globalRe", false, false, true, MacOSTargets}, 1965 {SymbolKind::ObjectiveCClass, "ClassRexport", false, false, true, 1966 MacOSTargets}, 1967 }; 1968 1969 EXPECT_EQ(ExpectedExportedSymbols.size(), Exports.size()); 1970 EXPECT_EQ(ExpectedReexportedSymbols.size(), Reexports.size()); 1971 EXPECT_EQ(0U, Undefineds.size()); 1972 EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(), 1973 std::begin(ExpectedExportedSymbols))); 1974 EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(), 1975 std::begin(ExpectedReexportedSymbols))); 1976 } 1977 1978 TEST(TBDv5, RemoveIF) { 1979 static const char TBDv5File[] = R"({ 1980 "tapi_tbd_version": 5, 1981 "main_library": { 1982 "target_info": [ 1983 { 1984 "target": "x86_64-macos", 1985 "min_deployment": "10.14" 1986 }, 1987 { 1988 "target": "arm64-macos", 1989 "min_deployment": "10.14" 1990 }, 1991 { 1992 "target": "arm64-maccatalyst", 1993 "min_deployment": "12.1" 1994 } 1995 ], 1996 "flags": [ 1997 { 1998 "targets": [ 1999 "x86_64-macos" 2000 ], 2001 "attributes": [ 2002 "flat_namespace" 2003 ] 2004 } 2005 ], 2006 "install_names": [ 2007 { 2008 "name": "/S/L/F/Foo.framework/Foo" 2009 } 2010 ], 2011 "current_versions": [ 2012 { 2013 "version": "1.2" 2014 } 2015 ], 2016 "compatibility_versions": [ 2017 { "version": "1.1" } 2018 ], 2019 "rpaths": [ 2020 { 2021 "targets": [ 2022 "x86_64-macos" 2023 ], 2024 "paths": [ 2025 "@executable_path/.../Frameworks" 2026 ] 2027 } 2028 ], 2029 "parent_umbrellas": [ 2030 { 2031 "umbrella": "System" 2032 } 2033 ], 2034 "allowable_clients": [ 2035 { 2036 "clients": [ 2037 "ClientA", 2038 "ClientB" 2039 ] 2040 } 2041 ], 2042 "reexported_libraries": [ 2043 { 2044 "names": [ 2045 "/u/l/l/libfoo.dylib", 2046 "/u/l/l/libbar.dylib" 2047 ] 2048 } 2049 ], 2050 "exported_symbols": [ 2051 { 2052 "targets": [ 2053 "x86_64-macos", 2054 "arm64-macos" 2055 ], 2056 "data": { 2057 "global": [ 2058 "_global" 2059 ], 2060 "objc_class": [ 2061 "ClassA" 2062 ], 2063 "weak": [], 2064 "thread_local": [] 2065 }, 2066 "text": { 2067 "global": [ 2068 "_func" 2069 ], 2070 "weak": [], 2071 "thread_local": [] 2072 } 2073 }, 2074 { 2075 "targets": [ 2076 "x86_64-macos" 2077 ], 2078 "data": { 2079 "global": [ 2080 "_globalVar" 2081 ], 2082 "objc_class": [ 2083 "ClassA", 2084 "ClassB", 2085 "ClassData" 2086 ], 2087 "objc_eh_type": [ 2088 "ClassA", 2089 "ClassB" 2090 ], 2091 "objc_ivar": [ 2092 "ClassA.ivar1", 2093 "ClassA.ivar2", 2094 "ClassC.ivar1" 2095 ] 2096 }, 2097 "text": { 2098 "global": [ 2099 "_funcFoo" 2100 ] 2101 } 2102 } 2103 ], 2104 "reexported_symbols": [ 2105 { 2106 "targets": [ 2107 "x86_64-macos", 2108 "arm64-macos" 2109 ], 2110 "data": { 2111 "global": [ 2112 "_globalRe" 2113 ], 2114 "objc_class": [ 2115 "ClassRexport" 2116 ] 2117 }, 2118 "text": { 2119 "global": [ 2120 "_funcA" 2121 ] 2122 } 2123 } 2124 ], 2125 "undefined_symbols": [ 2126 { 2127 "targets": [ 2128 "x86_64-macos" 2129 ], 2130 "data": { 2131 "global": [ 2132 "_globalBind" 2133 ], 2134 "weak": [ 2135 "referenced_sym" 2136 ] 2137 } 2138 } 2139 ] 2140 }, 2141 "libraries": [] 2142 })"; 2143 2144 Expected<TBDFile> Result = 2145 TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd")); 2146 EXPECT_TRUE(!!Result); 2147 TBDFile File = std::move(Result.get()); 2148 2149 Expected<TBDFile> RemovedResult = File->remove(AK_x86_64); 2150 EXPECT_TRUE(!!RemovedResult); 2151 TBDFile RemovedFile = std::move(RemovedResult.get()); 2152 2153 EXPECT_EQ(FileType::TBD_V5, RemovedFile->getFileType()); 2154 EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"), 2155 RemovedFile->getInstallName()); 2156 2157 TargetList AllTargets = { 2158 Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0, 0)), 2159 Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(14, 0)), 2160 }; 2161 EXPECT_EQ(mapToPlatformSet(AllTargets), RemovedFile->getPlatforms()); 2162 EXPECT_EQ(mapToArchitectureSet(AllTargets), RemovedFile->getArchitectures()); 2163 2164 EXPECT_EQ(PackedVersion(1, 2, 0), RemovedFile->getCurrentVersion()); 2165 EXPECT_EQ(PackedVersion(1, 1, 0), RemovedFile->getCompatibilityVersion()); 2166 EXPECT_TRUE(RemovedFile->isApplicationExtensionSafe()); 2167 EXPECT_FALSE(RemovedFile->isTwoLevelNamespace()); 2168 EXPECT_EQ(0U, RemovedFile->documents().size()); 2169 2170 InterfaceFileRef ClientA("ClientA", AllTargets); 2171 InterfaceFileRef ClientB("ClientB", AllTargets); 2172 EXPECT_EQ(2U, RemovedFile->allowableClients().size()); 2173 EXPECT_EQ(ClientA, RemovedFile->allowableClients().at(0)); 2174 EXPECT_EQ(ClientB, RemovedFile->allowableClients().at(1)); 2175 2176 InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets); 2177 InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets); 2178 EXPECT_EQ(2U, RemovedFile->reexportedLibraries().size()); 2179 EXPECT_EQ(ReexportA, RemovedFile->reexportedLibraries().at(0)); 2180 EXPECT_EQ(ReexportB, RemovedFile->reexportedLibraries().at(1)); 2181 2182 EXPECT_EQ(0u, RemovedFile->rpaths().size()); 2183 2184 TargetToAttr Umbrellas = {{Target(AK_arm64, PLATFORM_MACOS), "System"}, 2185 {Target(AK_arm64, PLATFORM_MACCATALYST), "System"}}; 2186 EXPECT_EQ(Umbrellas, RemovedFile->umbrellas()); 2187 2188 ExportedSymbolSeq Exports, Reexports, Undefineds; 2189 for (const auto *Sym : RemovedFile->symbols()) { 2190 TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()}; 2191 ExportedSymbol Temp = 2192 ExportedSymbol{Sym->getKind(), 2193 std::string(Sym->getName()), 2194 Sym->isWeakDefined() || Sym->isWeakReferenced(), 2195 Sym->isThreadLocalValue(), 2196 Sym->isData(), 2197 SymTargets}; 2198 if (Sym->isUndefined()) 2199 Undefineds.emplace_back(std::move(Temp)); 2200 else 2201 Sym->isReexported() ? Reexports.emplace_back(std::move(Temp)) 2202 : Exports.emplace_back(std::move(Temp)); 2203 } 2204 llvm::sort(Exports); 2205 llvm::sort(Reexports); 2206 llvm::sort(Undefineds); 2207 2208 TargetList MacOSTargets = {Target(AK_arm64, PLATFORM_MACOS)}; 2209 2210 std::vector<ExportedSymbol> ExpectedExportedSymbols = { 2211 {SymbolKind::GlobalSymbol, "_func", false, false, false, MacOSTargets}, 2212 {SymbolKind::GlobalSymbol, "_global", false, false, true, MacOSTargets}, 2213 {SymbolKind::ObjectiveCClass, "ClassA", false, false, true, MacOSTargets}, 2214 }; 2215 std::vector<ExportedSymbol> ExpectedReexportedSymbols = { 2216 {SymbolKind::GlobalSymbol, "_funcA", false, false, false, MacOSTargets}, 2217 {SymbolKind::GlobalSymbol, "_globalRe", false, false, true, MacOSTargets}, 2218 {SymbolKind::ObjectiveCClass, "ClassRexport", false, false, true, 2219 MacOSTargets}, 2220 }; 2221 2222 EXPECT_EQ(ExpectedExportedSymbols.size(), Exports.size()); 2223 EXPECT_EQ(ExpectedReexportedSymbols.size(), Reexports.size()); 2224 EXPECT_EQ(0U, Undefineds.size()); 2225 EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(), 2226 std::begin(ExpectedExportedSymbols))); 2227 EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(), 2228 std::begin(ExpectedReexportedSymbols))); 2229 } 2230 2231 TEST(TBDv5, InlineIF) { 2232 static const char UmbrellaFile[] = R"({ 2233 "tapi_tbd_version": 5, 2234 "main_library": { 2235 "target_info": [ 2236 { 2237 "target": "x86_64-macos", 2238 "min_deployment": "10.14" 2239 }, 2240 { 2241 "target": "arm64-macos", 2242 "min_deployment": "10.14" 2243 } 2244 ], 2245 "install_names": [ 2246 { 2247 "name": "/S/L/F/Foo.framework/Foo" 2248 } 2249 ], 2250 "current_versions": [ 2251 { 2252 "version": "1.2" 2253 } 2254 ], 2255 "reexported_libraries": [ 2256 { 2257 "names": [ 2258 "/u/l/l/libfoo.dylib", 2259 "/u/l/l/libbar.dylib" 2260 ] 2261 } 2262 ] 2263 }})"; 2264 2265 static const char ReexportFile[] = R"({ 2266 "tapi_tbd_version": 5, 2267 "main_library": { 2268 "target_info": [ 2269 { 2270 "target": "x86_64-macos", 2271 "min_deployment": "10.14" 2272 }, 2273 { 2274 "target": "arm64-macos", 2275 "min_deployment": "10.14" 2276 } 2277 ], 2278 "install_names": [ 2279 { 2280 "name" : "/u/l/l/libfoo.dylib" 2281 } 2282 ], 2283 "current_versions": [ 2284 { 2285 "version": "1" 2286 } 2287 ], 2288 "rpaths": [ 2289 { 2290 "targets": [ 2291 "x86_64-macos" 2292 ], 2293 "paths": [ 2294 "@executable_path/.../Frameworks" 2295 ] 2296 } 2297 ], 2298 "exported_symbols": [ 2299 { 2300 "targets": [ 2301 "x86_64-macos", 2302 "arm64-macos" 2303 ], 2304 "data": { 2305 "global": [ 2306 "_global" 2307 ], 2308 "objc_class": [ 2309 "ClassA" 2310 ], 2311 "weak": [], 2312 "thread_local": [] 2313 } 2314 } 2315 ]}})"; 2316 2317 Expected<TBDFile> UmbrellaResult = 2318 TextAPIReader::get(MemoryBufferRef(UmbrellaFile, "Test.tbd")); 2319 EXPECT_TRUE(!!UmbrellaResult); 2320 TBDFile Umbrella = std::move(UmbrellaResult.get()); 2321 2322 Expected<TBDFile> ReexportResult = 2323 TextAPIReader::get(MemoryBufferRef(ReexportFile, "Test.tbd")); 2324 EXPECT_TRUE(!!ReexportResult); 2325 TBDReexportFile Reexport = std::move(ReexportResult.get()); 2326 Umbrella->inlineLibrary(Reexport); 2327 2328 EXPECT_EQ(FileType::TBD_V5, Umbrella->getFileType()); 2329 EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"), 2330 Umbrella->getInstallName()); 2331 2332 TargetList AllTargets = { 2333 Target(AK_x86_64, PLATFORM_MACOS, VersionTuple(10, 14)), 2334 Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0, 0)), 2335 }; 2336 EXPECT_EQ(mapToPlatformSet(AllTargets), Umbrella->getPlatforms()); 2337 EXPECT_EQ(mapToArchitectureSet(AllTargets), Umbrella->getArchitectures()); 2338 2339 EXPECT_EQ(PackedVersion(1, 2, 0), Umbrella->getCurrentVersion()); 2340 EXPECT_EQ(PackedVersion(1, 0, 0), Umbrella->getCompatibilityVersion()); 2341 InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets); 2342 InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets); 2343 EXPECT_EQ(2U, Umbrella->reexportedLibraries().size()); 2344 EXPECT_EQ(ReexportA, Umbrella->reexportedLibraries().at(0)); 2345 EXPECT_EQ(ReexportB, Umbrella->reexportedLibraries().at(1)); 2346 EXPECT_EQ(1U, Umbrella->documents().size()); 2347 2348 TBDReexportFile Document = Umbrella->documents().front(); 2349 EXPECT_EQ(std::string("/u/l/l/libfoo.dylib"), Document->getInstallName()); 2350 EXPECT_EQ(0U, Document->getSwiftABIVersion()); 2351 EXPECT_TRUE(Document->isTwoLevelNamespace()); 2352 EXPECT_TRUE(Document->isApplicationExtensionSafe()); 2353 EXPECT_EQ(PackedVersion(1, 0, 0), Document->getCurrentVersion()); 2354 EXPECT_EQ(PackedVersion(1, 0, 0), Document->getCompatibilityVersion()); 2355 2356 ExportedSymbolSeq Exports; 2357 for (const auto *Sym : Document->symbols()) { 2358 TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()}; 2359 Exports.emplace_back( 2360 ExportedSymbol{Sym->getKind(), std::string(Sym->getName()), 2361 Sym->isWeakDefined() || Sym->isWeakReferenced(), 2362 Sym->isThreadLocalValue(), Sym->isData(), SymTargets}); 2363 } 2364 llvm::sort(Exports); 2365 2366 ExportedSymbolSeq ExpectedExports = { 2367 {SymbolKind::GlobalSymbol, "_global", false, false, true, AllTargets}, 2368 {SymbolKind::ObjectiveCClass, "ClassA", false, false, true, AllTargets}, 2369 }; 2370 EXPECT_EQ(ExpectedExports.size(), Exports.size()); 2371 EXPECT_TRUE( 2372 std::equal(Exports.begin(), Exports.end(), std::begin(ExpectedExports))); 2373 } 2374 } // end namespace TBDv5 2375