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