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