1 //===-- TextStubV4Tests.cpp - TBD V4 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/MachO/InterfaceFile.h" 11 #include "llvm/TextAPI/MachO/TextAPIReader.h" 12 #include "llvm/TextAPI/MachO/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 21 namespace TBDv4 { 22 23 TEST(TBDv4, ReadFile) { 24 static const char TBDv4File[] = 25 "--- !tapi-tbd\n" 26 "tbd-version: 4\n" 27 "targets: [ i386-macos, x86_64-macos, x86_64-ios ]\n" 28 "uuids:\n" 29 " - target: i386-macos\n" 30 " value: 00000000-0000-0000-0000-000000000000\n" 31 " - target: x86_64-macos\n" 32 " value: 11111111-1111-1111-1111-111111111111\n" 33 " - target: x86_64-ios\n" 34 " value: 11111111-1111-1111-1111-111111111111\n" 35 "flags: [ flat_namespace, installapi ]\n" 36 "install-name: Umbrella.framework/Umbrella\n" 37 "current-version: 1.2.3\n" 38 "compatibility-version: 1.2\n" 39 "swift-abi-version: 5\n" 40 "parent-umbrella:\n" 41 " - targets: [ i386-macos, x86_64-macos, x86_64-ios ]\n" 42 " umbrella: System\n" 43 "allowable-clients:\n" 44 " - targets: [ i386-macos, x86_64-macos, x86_64-ios ]\n" 45 " clients: [ ClientA ]\n" 46 "reexported-libraries:\n" 47 " - targets: [ i386-macos ]\n" 48 " libraries: [ /System/Library/Frameworks/A.framework/A ]\n" 49 "exports:\n" 50 " - targets: [ i386-macos ]\n" 51 " symbols: [ _symA ]\n" 52 " objc-classes: []\n" 53 " objc-eh-types: []\n" 54 " objc-ivars: []\n" 55 " weak-symbols: []\n" 56 " thread-local-symbols: []\n" 57 " - targets: [ x86_64-ios ]\n" 58 " symbols: [_symB]\n" 59 " - targets: [ x86_64-macos, x86_64-ios ]\n" 60 " symbols: [_symAB]\n" 61 "reexports:\n" 62 " - targets: [ i386-macos ]\n" 63 " symbols: [_symC]\n" 64 " objc-classes: []\n" 65 " objc-eh-types: []\n" 66 " objc-ivars: []\n" 67 " weak-symbols: []\n" 68 " thread-local-symbols: []\n" 69 "undefineds:\n" 70 " - targets: [ i386-macos ]\n" 71 " symbols: [ _symD ]\n" 72 " objc-classes: []\n" 73 " objc-eh-types: []\n" 74 " objc-ivars: []\n" 75 " weak-symbols: []\n" 76 " thread-local-symbols: []\n" 77 "...\n"; 78 79 Expected<TBDFile> Result = 80 TextAPIReader::get(MemoryBufferRef(TBDv4File, "Test.tbd")); 81 EXPECT_TRUE(!!Result); 82 TBDFile File = std::move(Result.get()); 83 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 84 PlatformSet Platforms; 85 Platforms.insert(PlatformKind::macOS); 86 Platforms.insert(PlatformKind::iOS); 87 auto Archs = AK_i386 | AK_x86_64; 88 TargetList Targets = { 89 Target(AK_i386, PlatformKind::macOS), 90 Target(AK_x86_64, PlatformKind::macOS), 91 Target(AK_x86_64, PlatformKind::iOS), 92 }; 93 UUIDs uuids = {{Targets[0], "00000000-0000-0000-0000-000000000000"}, 94 {Targets[1], "11111111-1111-1111-1111-111111111111"}, 95 {Targets[2], "11111111-1111-1111-1111-111111111111"}}; 96 EXPECT_EQ(Archs, File->getArchitectures()); 97 EXPECT_EQ(uuids, File->uuids()); 98 EXPECT_EQ(Platforms.size(), File->getPlatforms().size()); 99 for (auto Platform : File->getPlatforms()) 100 EXPECT_EQ(Platforms.count(Platform), 1U); 101 EXPECT_EQ(std::string("Umbrella.framework/Umbrella"), File->getInstallName()); 102 EXPECT_EQ(PackedVersion(1, 2, 3), File->getCurrentVersion()); 103 EXPECT_EQ(PackedVersion(1, 2, 0), File->getCompatibilityVersion()); 104 EXPECT_EQ(5U, File->getSwiftABIVersion()); 105 EXPECT_FALSE(File->isTwoLevelNamespace()); 106 EXPECT_TRUE(File->isApplicationExtensionSafe()); 107 EXPECT_TRUE(File->isInstallAPI()); 108 InterfaceFileRef client("ClientA", Targets); 109 InterfaceFileRef reexport("/System/Library/Frameworks/A.framework/A", 110 {Targets[0]}); 111 EXPECT_EQ(1U, File->allowableClients().size()); 112 EXPECT_EQ(client, File->allowableClients().front()); 113 EXPECT_EQ(1U, File->reexportedLibraries().size()); 114 EXPECT_EQ(reexport, File->reexportedLibraries().front()); 115 116 ExportedSymbolSeq Exports, Reexports, Undefineds; 117 ExportedSymbol temp; 118 for (const auto *Sym : File->symbols()) { 119 temp = ExportedSymbol{Sym->getKind(), std::string(Sym->getName()), 120 Sym->isWeakDefined(), Sym->isThreadLocalValue()}; 121 EXPECT_FALSE(Sym->isWeakReferenced()); 122 if (Sym->isUndefined()) 123 Undefineds.emplace_back(std::move(temp)); 124 else 125 Sym->isReexported() ? Reexports.emplace_back(std::move(temp)) 126 : Exports.emplace_back(std::move(temp)); 127 } 128 llvm::sort(Exports.begin(), Exports.end()); 129 llvm::sort(Reexports.begin(), Reexports.end()); 130 llvm::sort(Undefineds.begin(), Undefineds.end()); 131 132 static ExportedSymbol ExpectedExportedSymbols[] = { 133 {SymbolKind::GlobalSymbol, "_symA", false, false}, 134 {SymbolKind::GlobalSymbol, "_symAB", false, false}, 135 {SymbolKind::GlobalSymbol, "_symB", false, false}, 136 }; 137 138 static ExportedSymbol ExpectedReexportedSymbols[] = { 139 {SymbolKind::GlobalSymbol, "_symC", false, false}, 140 }; 141 142 static ExportedSymbol ExpectedUndefinedSymbols[] = { 143 {SymbolKind::GlobalSymbol, "_symD", false, false}, 144 }; 145 146 EXPECT_EQ(sizeof(ExpectedExportedSymbols) / sizeof(ExportedSymbol), 147 Exports.size()); 148 EXPECT_EQ(sizeof(ExpectedReexportedSymbols) / sizeof(ExportedSymbol), 149 Reexports.size()); 150 EXPECT_EQ(sizeof(ExpectedUndefinedSymbols) / sizeof(ExportedSymbol), 151 Undefineds.size()); 152 EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(), 153 std::begin(ExpectedExportedSymbols))); 154 EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(), 155 std::begin(ExpectedReexportedSymbols))); 156 EXPECT_TRUE(std::equal(Undefineds.begin(), Undefineds.end(), 157 std::begin(ExpectedUndefinedSymbols))); 158 } 159 160 TEST(TBDv4, ReadMultipleDocuments) { 161 static const char TBDv4Inlines[] = 162 "--- !tapi-tbd\n" 163 "tbd-version: 4\n" 164 "targets: [ i386-macos, i386-maccatalyst, x86_64-macos, " 165 "x86_64-maccatalyst ]\n" 166 "uuids:\n" 167 " - target: i386-macos\n" 168 " value: 00000000-0000-0000-0000-000000000000\n" 169 " - target: i386-maccatalyst\n" 170 " value: 00000000-0000-0000-0000-000000000002\n" 171 " - target: x86_64-macos\n" 172 " value: 11111111-1111-1111-1111-111111111111\n" 173 " - target: x86_64-maccatalyst\n" 174 " value: 11111111-1111-1111-1111-111111111112\n" 175 "install-name: /System/Library/Frameworks/Umbrella.framework/Umbrella\n" 176 "parent-umbrella:\n" 177 " - targets: [ i386-macos, x86_64-macos ]\n" 178 " umbrella: System\n" 179 "reexported-libraries:\n" 180 " - targets: [ i386-macos, x86_64-macos ]\n" 181 " libraries: [ /System/Library/Frameworks/A.framework/A ]\n" 182 "--- !tapi-tbd\n" 183 "tbd-version: 4\n" 184 "targets: [ i386-macos, x86_64-macos ]\n" 185 "uuids:\n" 186 " - target: i386-macos\n" 187 " value: 20000000-0000-0000-0000-000000000000\n" 188 " - target: x86_64-macos\n" 189 " value: 21111111-1111-1111-1111-111111111111\n" 190 "flags: [ flat_namespace ]\n" 191 "install-name: /System/Library/Frameworks/A.framework/A\n" 192 "current-version: 1.2.3\n" 193 "compatibility-version: 1.2\n" 194 "swift-abi-version: 5\n" 195 "exports:\n" 196 " - targets: [ i386-macos ]\n" 197 " symbols: [ _symA ]\n" 198 " objc-classes: []\n" 199 " objc-eh-types: []\n" 200 " objc-ivars: []\n" 201 " weak-symbols: []\n" 202 " thread-local-symbols: []\n" 203 " - targets: [ x86_64-macos ]\n" 204 " symbols: [_symAB]\n" 205 "reexports:\n" 206 " - targets: [ i386-macos ]\n" 207 " symbols: [_symC]\n" 208 " objc-classes: []\n" 209 " objc-eh-types: []\n" 210 " objc-ivars: []\n" 211 " weak-symbols: []\n" 212 " thread-local-symbols: []\n" 213 "undefineds:\n" 214 " - targets: [ i386-macos ]\n" 215 " symbols: [ _symD ]\n" 216 " objc-classes: []\n" 217 " objc-eh-types: []\n" 218 " objc-ivars: []\n" 219 " weak-symbols: []\n" 220 " thread-local-symbols: []\n" 221 "...\n"; 222 223 PlatformSet Platforms; 224 Platforms.insert(PlatformKind::macOS); 225 Platforms.insert(PlatformKind::macCatalyst); 226 ArchitectureSet Archs = AK_i386 | AK_x86_64; 227 TargetList Targets; 228 for (auto &&Arch : Archs) 229 for (auto &&Platform : Platforms) 230 Targets.emplace_back(Target(Arch, Platform)); 231 UUIDs Uuids = { 232 {Targets[0], "00000000-0000-0000-0000-000000000000"}, 233 {Targets[1], "00000000-0000-0000-0000-000000000002"}, 234 {Targets[2], "11111111-1111-1111-1111-111111111111"}, 235 {Targets[3], "11111111-1111-1111-1111-111111111112"}, 236 }; 237 238 Expected<TBDFile> Result = 239 TextAPIReader::get(MemoryBufferRef(TBDv4Inlines, "Test.tbd")); 240 EXPECT_TRUE(!!Result); 241 TBDFile File = std::move(Result.get()); 242 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 243 EXPECT_EQ(Archs, File->getArchitectures()); 244 EXPECT_EQ(Uuids, File->uuids()); 245 EXPECT_EQ(Platforms, File->getPlatforms()); 246 EXPECT_EQ( 247 std::string("/System/Library/Frameworks/Umbrella.framework/Umbrella"), 248 File->getInstallName()); 249 EXPECT_TRUE(File->isTwoLevelNamespace()); 250 EXPECT_TRUE(File->isApplicationExtensionSafe()); 251 EXPECT_FALSE(File->isInstallAPI()); 252 EXPECT_EQ(PackedVersion(1, 0, 0), File->getCurrentVersion()); 253 EXPECT_EQ(PackedVersion(1, 0, 0), File->getCompatibilityVersion()); 254 InterfaceFileRef reexport("/System/Library/Frameworks/A.framework/A", 255 {Targets[0], Targets[2]}); 256 EXPECT_EQ(1U, File->reexportedLibraries().size()); 257 EXPECT_EQ(reexport, File->reexportedLibraries().front()); 258 ExportedSymbolSeq Exports; 259 for (const auto *Sym : File->symbols()) { 260 EXPECT_FALSE(Sym->isWeakReferenced()); 261 EXPECT_FALSE(Sym->isUndefined()); 262 Exports.emplace_back(ExportedSymbol{Sym->getKind(), Sym->getName().str(), 263 Sym->isWeakDefined(), 264 Sym->isThreadLocalValue()}); 265 } 266 EXPECT_EQ(0U, Exports.size()); 267 268 // Check Inlined Document 269 Exports.clear(); 270 Targets.clear(); 271 Uuids.clear(); 272 PlatformKind Platform = PlatformKind::macOS; 273 for (auto &&Arch : Archs) 274 Targets.emplace_back(Target(Arch, Platform)); 275 Uuids = { 276 {Targets[0], "20000000-0000-0000-0000-000000000000"}, 277 {Targets[1], "21111111-1111-1111-1111-111111111111"}, 278 }; 279 280 auto Document = File->documents().front(); 281 EXPECT_EQ(FileType::TBD_V4, Document->getFileType()); 282 EXPECT_EQ(Archs, Document->getArchitectures()); 283 EXPECT_EQ(Uuids, Document->uuids()); 284 EXPECT_EQ(1U, Document->getPlatforms().size()); 285 EXPECT_EQ(Platform, *(Document->getPlatforms().begin())); 286 EXPECT_EQ(std::string("/System/Library/Frameworks/A.framework/A"), 287 Document->getInstallName()); 288 EXPECT_EQ(PackedVersion(1, 2, 3), Document->getCurrentVersion()); 289 EXPECT_EQ(PackedVersion(1, 2, 0), Document->getCompatibilityVersion()); 290 EXPECT_EQ(5U, Document->getSwiftABIVersion()); 291 EXPECT_FALSE(Document->isTwoLevelNamespace()); 292 EXPECT_TRUE(Document->isApplicationExtensionSafe()); 293 EXPECT_FALSE(Document->isInstallAPI()); 294 295 ExportedSymbolSeq Reexports, Undefineds; 296 for (const auto *Sym : Document->symbols()) { 297 ExportedSymbol Temp = 298 ExportedSymbol{Sym->getKind(), std::string(Sym->getName()), 299 Sym->isWeakDefined(), Sym->isThreadLocalValue()}; 300 EXPECT_FALSE(Sym->isWeakReferenced()); 301 if (Sym->isUndefined()) 302 Undefineds.emplace_back(std::move(Temp)); 303 else 304 Sym->isReexported() ? Reexports.emplace_back(std::move(Temp)) 305 : Exports.emplace_back(std::move(Temp)); 306 } 307 llvm::sort(Exports.begin(), Exports.end()); 308 llvm::sort(Reexports.begin(), Reexports.end()); 309 llvm::sort(Undefineds.begin(), Undefineds.end()); 310 311 static ExportedSymbol ExpectedExportedSymbols[] = { 312 {SymbolKind::GlobalSymbol, "_symA", false, false}, 313 {SymbolKind::GlobalSymbol, "_symAB", false, false}, 314 }; 315 316 static ExportedSymbol ExpectedReexportedSymbols[] = { 317 {SymbolKind::GlobalSymbol, "_symC", false, false}, 318 }; 319 320 static ExportedSymbol ExpectedUndefinedSymbols[] = { 321 {SymbolKind::GlobalSymbol, "_symD", false, false}, 322 }; 323 324 EXPECT_EQ(sizeof(ExpectedExportedSymbols) / sizeof(ExportedSymbol), 325 Exports.size()); 326 EXPECT_EQ(sizeof(ExpectedReexportedSymbols) / sizeof(ExportedSymbol), 327 Reexports.size()); 328 EXPECT_EQ(sizeof(ExpectedUndefinedSymbols) / sizeof(ExportedSymbol), 329 Undefineds.size()); 330 EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(), 331 std::begin(ExpectedExportedSymbols))); 332 EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(), 333 std::begin(ExpectedReexportedSymbols))); 334 EXPECT_TRUE(std::equal(Undefineds.begin(), Undefineds.end(), 335 std::begin(ExpectedUndefinedSymbols))); 336 } 337 338 TEST(TBDv4, WriteFile) { 339 static const char TBDv4File[] = 340 "--- !tapi-tbd\n" 341 "tbd-version: 4\n" 342 "targets: [ i386-macos, x86_64-ios-simulator ]\n" 343 "uuids:\n" 344 " - target: i386-macos\n" 345 " value: 00000000-0000-0000-0000-000000000000\n" 346 " - target: x86_64-ios-simulator\n" 347 " value: 11111111-1111-1111-1111-111111111111\n" 348 "flags: [ installapi ]\n" 349 "install-name: 'Umbrella.framework/Umbrella'\n" 350 "current-version: 1.2.3\n" 351 "compatibility-version: 0\n" 352 "swift-abi-version: 5\n" 353 "parent-umbrella:\n" 354 " - targets: [ i386-macos, x86_64-ios-simulator ]\n" 355 " umbrella: System\n" 356 "allowable-clients:\n" 357 " - targets: [ i386-macos ]\n" 358 " clients: [ ClientA ]\n" 359 "exports:\n" 360 " - targets: [ i386-macos ]\n" 361 " symbols: [ _symA ]\n" 362 " objc-classes: [ Class1 ]\n" 363 " weak-symbols: [ _symC ]\n" 364 " - targets: [ x86_64-ios-simulator ]\n" 365 " symbols: [ _symB ]\n" 366 "...\n"; 367 368 InterfaceFile File; 369 TargetList Targets = { 370 Target(AK_i386, PlatformKind::macOS), 371 Target(AK_x86_64, PlatformKind::iOSSimulator), 372 }; 373 UUIDs uuids = {{Targets[0], "00000000-0000-0000-0000-000000000000"}, 374 {Targets[1], "11111111-1111-1111-1111-111111111111"}}; 375 File.setInstallName("Umbrella.framework/Umbrella"); 376 File.setFileType(FileType::TBD_V4); 377 File.addTargets(Targets); 378 File.addUUID(uuids[0].first, uuids[0].second); 379 File.addUUID(uuids[1].first, uuids[1].second); 380 File.setCurrentVersion(PackedVersion(1, 2, 3)); 381 File.setTwoLevelNamespace(); 382 File.setInstallAPI(true); 383 File.setApplicationExtensionSafe(true); 384 File.setSwiftABIVersion(5); 385 File.addAllowableClient("ClientA", Targets[0]); 386 File.addParentUmbrella(Targets[0], "System"); 387 File.addParentUmbrella(Targets[1], "System"); 388 File.addSymbol(SymbolKind::GlobalSymbol, "_symA", {Targets[0]}); 389 File.addSymbol(SymbolKind::GlobalSymbol, "_symB", {Targets[1]}); 390 File.addSymbol(SymbolKind::GlobalSymbol, "_symC", {Targets[0]}, 391 SymbolFlags::WeakDefined); 392 File.addSymbol(SymbolKind::ObjectiveCClass, "Class1", {Targets[0]}); 393 394 SmallString<4096> Buffer; 395 raw_svector_ostream OS(Buffer); 396 Error Result = TextAPIWriter::writeToStream(OS, File); 397 EXPECT_FALSE(Result); 398 EXPECT_STREQ(TBDv4File, Buffer.c_str()); 399 } 400 401 TEST(TBDv4, WriteMultipleDocuments) { 402 static const char TBDv4Inlines[] = 403 "--- !tapi-tbd\n" 404 "tbd-version: 4\n" 405 "targets: [ i386-maccatalyst, x86_64-maccatalyst ]\n" 406 "uuids:\n" 407 " - target: i386-maccatalyst\n" 408 " value: 00000000-0000-0000-0000-000000000002\n" 409 " - target: x86_64-maccatalyst\n" 410 " value: 11111111-1111-1111-1111-111111111112\n" 411 "install-name: " 412 "'/System/Library/Frameworks/Umbrella.framework/Umbrella'\n" 413 "reexported-libraries:\n" 414 " - targets: [ i386-maccatalyst, x86_64-maccatalyst ]\n" 415 " libraries: [ '/System/Library/Frameworks/A.framework/A' ]\n" 416 "--- !tapi-tbd\n" 417 "tbd-version: 4\n" 418 "targets: [ i386-maccatalyst, x86_64-maccatalyst ]\n" 419 "uuids:\n" 420 " - target: i386-maccatalyst\n" 421 " value: 00000000-0000-0000-0000-000000000000\n" 422 " - target: x86_64-maccatalyst\n" 423 " value: 11111111-1111-1111-1111-111111111111\n" 424 "install-name: '/System/Library/Frameworks/A.framework/A'\n" 425 "exports:\n" 426 " - targets: [ i386-maccatalyst ]\n" 427 " weak-symbols: [ _symC ]\n" 428 " - targets: [ i386-maccatalyst, x86_64-maccatalyst ]\n" 429 " symbols: [ _symA ]\n" 430 " objc-classes: [ Class1 ]\n" 431 " - targets: [ x86_64-maccatalyst ]\n" 432 " symbols: [ _symAB ]\n" 433 "...\n"; 434 435 InterfaceFile File; 436 PlatformKind Platform = PlatformKind::macCatalyst; 437 TargetList Targets = { 438 Target(AK_i386, Platform), 439 Target(AK_x86_64, Platform), 440 }; 441 UUIDs Uuids = {{Targets[0], "00000000-0000-0000-0000-000000000002"}, 442 {Targets[1], "11111111-1111-1111-1111-111111111112"}}; 443 File.setInstallName("/System/Library/Frameworks/Umbrella.framework/Umbrella"); 444 File.setFileType(FileType::TBD_V4); 445 File.addTargets(Targets); 446 File.addUUID(Uuids[0].first, Uuids[0].second); 447 File.addUUID(Uuids[1].first, Uuids[1].second); 448 File.setCompatibilityVersion(PackedVersion(1, 0, 0)); 449 File.setCurrentVersion(PackedVersion(1, 0, 0)); 450 File.setTwoLevelNamespace(); 451 File.setApplicationExtensionSafe(true); 452 File.addReexportedLibrary("/System/Library/Frameworks/A.framework/A", 453 Targets[0]); 454 File.addReexportedLibrary("/System/Library/Frameworks/A.framework/A", 455 Targets[1]); 456 457 // Write Second Document 458 Uuids = {{Targets[0], "00000000-0000-0000-0000-000000000000"}, 459 {Targets[1], "11111111-1111-1111-1111-111111111111"}}; 460 InterfaceFile Document; 461 Document.setInstallName("/System/Library/Frameworks/A.framework/A"); 462 Document.setFileType(FileType::TBD_V4); 463 Document.addTargets(Targets); 464 Document.addUUID(Uuids[0].first, Uuids[0].second); 465 Document.addUUID(Uuids[1].first, Uuids[1].second); 466 Document.setCompatibilityVersion(PackedVersion(1, 0, 0)); 467 Document.setCurrentVersion(PackedVersion(1, 0, 0)); 468 Document.setTwoLevelNamespace(); 469 Document.setApplicationExtensionSafe(true); 470 Document.addSymbol(SymbolKind::GlobalSymbol, "_symA", Targets); 471 Document.addSymbol(SymbolKind::GlobalSymbol, "_symAB", {Targets[1]}); 472 Document.addSymbol(SymbolKind::GlobalSymbol, "_symC", {Targets[0]}, 473 SymbolFlags::WeakDefined); 474 Document.addSymbol(SymbolKind::ObjectiveCClass, "Class1", Targets); 475 File.addDocument(std::make_shared<InterfaceFile>(std::move(Document))); 476 477 SmallString<4096> Buffer; 478 raw_svector_ostream OS(Buffer); 479 Error Result = TextAPIWriter::writeToStream(OS, File); 480 EXPECT_FALSE(Result); 481 EXPECT_STREQ(TBDv4Inlines, Buffer.c_str()); 482 } 483 484 TEST(TBDv4, MultipleTargets) { 485 static const char TBDv4MultipleTargets[] = 486 "--- !tapi-tbd\n" 487 "tbd-version: 4\n" 488 "targets: [ i386-maccatalyst, x86_64-tvos, arm64-ios ]\n" 489 "install-name: Test.dylib\n" 490 "...\n"; 491 492 Expected<TBDFile> Result = 493 TextAPIReader::get(MemoryBufferRef(TBDv4MultipleTargets, "Test.tbd")); 494 EXPECT_TRUE(!!Result); 495 PlatformSet Platforms; 496 Platforms.insert(PlatformKind::macCatalyst); 497 Platforms.insert(PlatformKind::tvOS); 498 Platforms.insert(PlatformKind::iOS); 499 TBDFile File = std::move(Result.get()); 500 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 501 EXPECT_EQ(AK_x86_64 | AK_arm64 | AK_i386, File->getArchitectures()); 502 EXPECT_EQ(Platforms.size(), File->getPlatforms().size()); 503 for (auto Platform : File->getPlatforms()) 504 EXPECT_EQ(Platforms.count(Platform), 1U); 505 506 SmallString<4096> Buffer; 507 raw_svector_ostream OS(Buffer); 508 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 509 EXPECT_TRUE(!WriteResult); 510 EXPECT_EQ(stripWhitespace(TBDv4MultipleTargets), 511 stripWhitespace(Buffer.c_str())); 512 } 513 514 TEST(TBDv4, MultipleTargetsSameArch) { 515 static const char TBDv4TargetsSameArch[] = 516 "--- !tapi-tbd\n" 517 "tbd-version: 4\n" 518 "targets: [ x86_64-tvos , x86_64-maccatalyst ]\n" 519 "install-name: Test.dylib\n" 520 "...\n"; 521 522 Expected<TBDFile> Result = 523 TextAPIReader::get(MemoryBufferRef(TBDv4TargetsSameArch, "Test.tbd")); 524 EXPECT_TRUE(!!Result); 525 PlatformSet Platforms; 526 Platforms.insert(PlatformKind::tvOS); 527 Platforms.insert(PlatformKind::macCatalyst); 528 TBDFile File = std::move(Result.get()); 529 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 530 EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures()); 531 EXPECT_EQ(Platforms.size(), File->getPlatforms().size()); 532 for (auto Platform : File->getPlatforms()) 533 EXPECT_EQ(Platforms.count(Platform), 1U); 534 535 SmallString<4096> Buffer; 536 raw_svector_ostream OS(Buffer); 537 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 538 EXPECT_TRUE(!WriteResult); 539 EXPECT_EQ(stripWhitespace(TBDv4TargetsSameArch), 540 stripWhitespace(Buffer.c_str())); 541 } 542 543 TEST(TBDv4, MultipleTargetsSamePlatform) { 544 static const char TBDv4MultipleTargetsSamePlatform[] = 545 "--- !tapi-tbd\n" 546 "tbd-version: 4\n" 547 "targets: [ armv7k-ios , arm64-ios]\n" 548 "install-name: Test.dylib\n" 549 "...\n"; 550 551 Expected<TBDFile> Result = TextAPIReader::get( 552 MemoryBufferRef(TBDv4MultipleTargetsSamePlatform, "Test.tbd")); 553 EXPECT_TRUE(!!Result); 554 TBDFile File = std::move(Result.get()); 555 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 556 EXPECT_EQ(AK_arm64 | AK_armv7k, File->getArchitectures()); 557 EXPECT_EQ(File->getPlatforms().size(), 1U); 558 EXPECT_EQ(PlatformKind::iOS, *File->getPlatforms().begin()); 559 560 SmallString<4096> Buffer; 561 raw_svector_ostream OS(Buffer); 562 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 563 EXPECT_TRUE(!WriteResult); 564 EXPECT_EQ(stripWhitespace(TBDv4MultipleTargetsSamePlatform), 565 stripWhitespace(Buffer.c_str())); 566 } 567 568 TEST(TBDv4, Target_maccatalyst) { 569 static const char TBDv4TargetMacCatalyst[] = 570 "--- !tapi-tbd\n" 571 "tbd-version: 4\n" 572 "targets: [ x86_64-maccatalyst ]\n" 573 "install-name: Test.dylib\n" 574 "...\n"; 575 576 Expected<TBDFile> Result = 577 TextAPIReader::get(MemoryBufferRef(TBDv4TargetMacCatalyst, "Test.tbd")); 578 EXPECT_TRUE(!!Result); 579 TBDFile File = std::move(Result.get()); 580 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 581 EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures()); 582 EXPECT_EQ(File->getPlatforms().size(), 1U); 583 EXPECT_EQ(PlatformKind::macCatalyst, *File->getPlatforms().begin()); 584 585 SmallString<4096> Buffer; 586 raw_svector_ostream OS(Buffer); 587 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 588 EXPECT_TRUE(!WriteResult); 589 EXPECT_EQ(stripWhitespace(TBDv4TargetMacCatalyst), 590 stripWhitespace(Buffer.c_str())); 591 } 592 593 TEST(TBDv4, Target_x86_ios) { 594 static const char TBDv4Targetx86iOS[] = "--- !tapi-tbd\n" 595 "tbd-version: 4\n" 596 "targets: [ x86_64-ios ]\n" 597 "install-name: Test.dylib\n" 598 "...\n"; 599 600 Expected<TBDFile> Result = 601 TextAPIReader::get(MemoryBufferRef(TBDv4Targetx86iOS, "Test.tbd")); 602 EXPECT_TRUE(!!Result); 603 TBDFile File = std::move(Result.get()); 604 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 605 EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures()); 606 EXPECT_EQ(File->getPlatforms().size(), 1U); 607 EXPECT_EQ(PlatformKind::iOS, *File->getPlatforms().begin()); 608 609 SmallString<4096> Buffer; 610 raw_svector_ostream OS(Buffer); 611 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 612 EXPECT_TRUE(!WriteResult); 613 EXPECT_EQ(stripWhitespace(TBDv4Targetx86iOS), 614 stripWhitespace(Buffer.c_str())); 615 } 616 617 TEST(TBDv4, Target_arm_bridgeOS) { 618 static const char TBDv4PlatformBridgeOS[] = "--- !tapi-tbd\n" 619 "tbd-version: 4\n" 620 "targets: [ armv7k-bridgeos ]\n" 621 "install-name: Test.dylib\n" 622 "...\n"; 623 624 Expected<TBDFile> Result = 625 TextAPIReader::get(MemoryBufferRef(TBDv4PlatformBridgeOS, "Test.tbd")); 626 EXPECT_TRUE(!!Result); 627 TBDFile File = std::move(Result.get()); 628 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 629 EXPECT_EQ(File->getPlatforms().size(), 1U); 630 EXPECT_EQ(PlatformKind::bridgeOS, *File->getPlatforms().begin()); 631 EXPECT_EQ(ArchitectureSet(AK_armv7k), File->getArchitectures()); 632 633 SmallString<4096> Buffer; 634 raw_svector_ostream OS(Buffer); 635 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 636 EXPECT_TRUE(!WriteResult); 637 EXPECT_EQ(stripWhitespace(TBDv4PlatformBridgeOS), 638 stripWhitespace(Buffer.c_str())); 639 } 640 641 TEST(TBDv4, Target_arm_iOS) { 642 static const char TBDv4ArchArm64e[] = "--- !tapi-tbd\n" 643 "tbd-version: 4\n" 644 "targets: [ arm64e-ios ]\n" 645 "install-name: Test.dylib\n" 646 "...\n"; 647 648 Expected<TBDFile> Result = 649 TextAPIReader::get(MemoryBufferRef(TBDv4ArchArm64e, "Test.tbd")); 650 EXPECT_TRUE(!!Result); 651 TBDFile File = std::move(Result.get()); 652 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 653 EXPECT_EQ(File->getPlatforms().size(), 1U); 654 EXPECT_EQ(PlatformKind::iOS, *File->getPlatforms().begin()); 655 EXPECT_EQ(ArchitectureSet(AK_arm64e), File->getArchitectures()); 656 657 SmallString<4096> Buffer; 658 raw_svector_ostream OS(Buffer); 659 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 660 EXPECT_TRUE(!WriteResult); 661 EXPECT_EQ(stripWhitespace(TBDv4ArchArm64e), stripWhitespace(Buffer.c_str())); 662 } 663 664 TEST(TBDv4, Target_x86_macos) { 665 static const char TBDv4Targetx86MacOS[] = "--- !tapi-tbd\n" 666 "tbd-version: 4\n" 667 "targets: [ x86_64-macos ]\n" 668 "install-name: Test.dylib\n" 669 "...\n"; 670 671 Expected<TBDFile> Result = 672 TextAPIReader::get(MemoryBufferRef(TBDv4Targetx86MacOS, "Test.tbd")); 673 EXPECT_TRUE(!!Result); 674 TBDFile File = std::move(Result.get()); 675 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 676 EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures()); 677 EXPECT_EQ(File->getPlatforms().size(), 1U); 678 EXPECT_EQ(PlatformKind::macOS, *File->getPlatforms().begin()); 679 680 SmallString<4096> Buffer; 681 raw_svector_ostream OS(Buffer); 682 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 683 EXPECT_TRUE(!WriteResult); 684 EXPECT_EQ(stripWhitespace(TBDv4Targetx86MacOS), 685 stripWhitespace(Buffer.c_str())); 686 } 687 688 TEST(TBDv4, Target_x86_ios_simulator) { 689 static const char TBDv4Targetx86iOSSim[] = 690 "--- !tapi-tbd\n" 691 "tbd-version: 4\n" 692 "targets: [ x86_64-ios-simulator ]\n" 693 "install-name: Test.dylib\n" 694 "...\n"; 695 696 Expected<TBDFile> Result = 697 TextAPIReader::get(MemoryBufferRef(TBDv4Targetx86iOSSim, "Test.tbd")); 698 EXPECT_TRUE(!!Result); 699 TBDFile File = std::move(Result.get()); 700 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 701 EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures()); 702 EXPECT_EQ(File->getPlatforms().size(), 1U); 703 EXPECT_EQ(PlatformKind::iOSSimulator, *File->getPlatforms().begin()); 704 705 SmallString<4096> Buffer; 706 raw_svector_ostream OS(Buffer); 707 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 708 EXPECT_TRUE(!WriteResult); 709 EXPECT_EQ(stripWhitespace(TBDv4Targetx86iOSSim), 710 stripWhitespace(Buffer.c_str())); 711 } 712 713 TEST(TBDv4, Target_x86_tvos_simulator) { 714 static const char TBDv4x86tvOSSim[] = "--- !tapi-tbd\n" 715 "tbd-version: 4\n" 716 "targets: [ x86_64-tvos-simulator ]\n" 717 "install-name: Test.dylib\n" 718 "...\n"; 719 720 Expected<TBDFile> Result = 721 TextAPIReader::get(MemoryBufferRef(TBDv4x86tvOSSim, "Test.tbd")); 722 EXPECT_TRUE(!!Result); 723 TBDFile File = std::move(Result.get()); 724 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 725 EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures()); 726 EXPECT_EQ(File->getPlatforms().size(), 1U); 727 EXPECT_EQ(PlatformKind::tvOSSimulator, *File->getPlatforms().begin()); 728 729 SmallString<4096> Buffer; 730 raw_svector_ostream OS(Buffer); 731 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 732 EXPECT_TRUE(!WriteResult); 733 EXPECT_EQ(stripWhitespace(TBDv4x86tvOSSim), stripWhitespace(Buffer.c_str())); 734 } 735 736 TEST(TBDv4, Target_i386_watchos_simulator) { 737 static const char TBDv4i386watchOSSim[] = 738 "--- !tapi-tbd\n" 739 "tbd-version: 4\n" 740 "targets: [ i386-watchos-simulator ]\n" 741 "install-name: Test.dylib\n" 742 "...\n"; 743 744 Expected<TBDFile> Result = 745 TextAPIReader::get(MemoryBufferRef(TBDv4i386watchOSSim, "Test.tbd")); 746 EXPECT_TRUE(!!Result); 747 TBDFile File = std::move(Result.get()); 748 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 749 EXPECT_EQ(ArchitectureSet(AK_i386), File->getArchitectures()); 750 EXPECT_EQ(File->getPlatforms().size(), 1U); 751 EXPECT_EQ(PlatformKind::watchOSSimulator, *File->getPlatforms().begin()); 752 753 SmallString<4096> Buffer; 754 raw_svector_ostream OS(Buffer); 755 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 756 EXPECT_TRUE(!WriteResult); 757 EXPECT_EQ(stripWhitespace(TBDv4i386watchOSSim), 758 stripWhitespace(Buffer.c_str())); 759 } 760 761 TEST(TBDv4, Swift_1) { 762 static const char TBDv4SwiftVersion1[] = "--- !tapi-tbd\n" 763 "tbd-version: 4\n" 764 "targets: [ x86_64-macos ]\n" 765 "install-name: Test.dylib\n" 766 "swift-abi-version: 1\n" 767 "...\n"; 768 769 Expected<TBDFile> Result = 770 TextAPIReader::get(MemoryBufferRef(TBDv4SwiftVersion1, "Test.tbd")); 771 EXPECT_TRUE(!!Result); 772 TBDFile File = std::move(Result.get()); 773 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 774 EXPECT_EQ(1U, File->getSwiftABIVersion()); 775 776 // No writer test because we emit "swift-abi-version:1.0". 777 } 778 779 TEST(TBDv4, Swift_2) { 780 static const char TBDv4Swift2[] = "--- !tapi-tbd\n" 781 "tbd-version: 4\n" 782 "targets: [ x86_64-macos ]\n" 783 "install-name: Test.dylib\n" 784 "swift-abi-version: 2\n" 785 "...\n"; 786 787 Expected<TBDFile> Result = 788 TextAPIReader::get(MemoryBufferRef(TBDv4Swift2, "Test.tbd")); 789 EXPECT_TRUE(!!Result); 790 TBDFile File = std::move(Result.get()); 791 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 792 EXPECT_EQ(2U, File->getSwiftABIVersion()); 793 794 // No writer test because we emit "swift-abi-version:2.0". 795 } 796 797 TEST(TBDv4, Swift_5) { 798 static const char TBDv4SwiftVersion5[] = "--- !tapi-tbd\n" 799 "tbd-version: 4\n" 800 "targets: [ x86_64-macos ]\n" 801 "install-name: Test.dylib\n" 802 "swift-abi-version: 5\n" 803 "...\n"; 804 805 Expected<TBDFile> Result = 806 TextAPIReader::get(MemoryBufferRef(TBDv4SwiftVersion5, "Test.tbd")); 807 EXPECT_TRUE(!!Result); 808 TBDFile File = std::move(Result.get()); 809 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 810 EXPECT_EQ(5U, File->getSwiftABIVersion()); 811 812 SmallString<4096> Buffer; 813 raw_svector_ostream OS(Buffer); 814 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 815 EXPECT_TRUE(!WriteResult); 816 EXPECT_EQ(stripWhitespace(TBDv4SwiftVersion5), 817 stripWhitespace(Buffer.c_str())); 818 } 819 820 TEST(TBDv4, Swift_99) { 821 static const char TBDv4SwiftVersion99[] = "--- !tapi-tbd\n" 822 "tbd-version: 4\n" 823 "targets: [ x86_64-macos ]\n" 824 "install-name: Test.dylib\n" 825 "swift-abi-version: 99\n" 826 "...\n"; 827 828 Expected<TBDFile> Result = 829 TextAPIReader::get(MemoryBufferRef(TBDv4SwiftVersion99, "Test.tbd")); 830 EXPECT_TRUE(!!Result); 831 TBDFile File = std::move(Result.get()); 832 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 833 EXPECT_EQ(99U, File->getSwiftABIVersion()); 834 835 SmallString<4096> Buffer; 836 raw_svector_ostream OS(Buffer); 837 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 838 EXPECT_TRUE(!WriteResult); 839 EXPECT_EQ(stripWhitespace(TBDv4SwiftVersion99), 840 stripWhitespace(Buffer.c_str())); 841 } 842 843 TEST(TBDv4, InvalidArchitecture) { 844 static const char TBDv4UnknownArch[] = "--- !tapi-tbd\n" 845 "tbd-version: 4\n" 846 "targets: [ foo-macos ]\n" 847 "install-name: Test.dylib\n" 848 "...\n"; 849 850 Expected<TBDFile> Result = 851 TextAPIReader::get(MemoryBufferRef(TBDv4UnknownArch, "Test.tbd")); 852 EXPECT_FALSE(!!Result); 853 std::string ErrorMessage = toString(Result.takeError()); 854 EXPECT_EQ("malformed file\nTest.tbd:3:12: error: unknown " 855 "architecture\ntargets: [ foo-macos ]\n" 856 " ^~~~~~~~~~\n", 857 ErrorMessage); 858 } 859 860 TEST(TBDv4, InvalidPlatform) { 861 static const char TBDv4FInvalidPlatform[] = "--- !tapi-tbd\n" 862 "tbd-version: 4\n" 863 "targets: [ x86_64-maos ]\n" 864 "install-name: Test.dylib\n" 865 "...\n"; 866 867 Expected<TBDFile> Result = 868 TextAPIReader::get(MemoryBufferRef(TBDv4FInvalidPlatform, "Test.tbd")); 869 EXPECT_FALSE(!!Result); 870 std::string ErrorMessage = toString(Result.takeError()); 871 EXPECT_EQ("malformed file\nTest.tbd:3:12: error: unknown platform\ntargets: " 872 "[ x86_64-maos ]\n" 873 " ^~~~~~~~~~~~\n", 874 ErrorMessage); 875 } 876 877 TEST(TBDv4, MalformedFile1) { 878 static const char TBDv4MalformedFile1[] = "--- !tapi-tbd\n" 879 "tbd-version: 4\n" 880 "...\n"; 881 882 Expected<TBDFile> Result = 883 TextAPIReader::get(MemoryBufferRef(TBDv4MalformedFile1, "Test.tbd")); 884 EXPECT_FALSE(!!Result); 885 std::string ErrorMessage = toString(Result.takeError()); 886 ASSERT_EQ("malformed file\nTest.tbd:2:1: error: missing required key " 887 "'targets'\ntbd-version: 4\n^\n", 888 ErrorMessage); 889 } 890 891 TEST(TBDv4, MalformedFile2) { 892 static const char TBDv4MalformedFile2[] = "--- !tapi-tbd\n" 893 "tbd-version: 4\n" 894 "targets: [ x86_64-macos ]\n" 895 "install-name: Test.dylib\n" 896 "foobar: \"unsupported key\"\n"; 897 898 Expected<TBDFile> Result = 899 TextAPIReader::get(MemoryBufferRef(TBDv4MalformedFile2, "Test.tbd")); 900 EXPECT_FALSE(!!Result); 901 std::string ErrorMessage = toString(Result.takeError()); 902 ASSERT_EQ( 903 "malformed file\nTest.tbd:5:9: error: unknown key 'foobar'\nfoobar: " 904 "\"unsupported key\"\n ^~~~~~~~~~~~~~~~~\n", 905 ErrorMessage); 906 } 907 908 TEST(TBDv4, MalformedFile3) { 909 static const char TBDv4MalformedSwift[] = "--- !tapi-tbd\n" 910 "tbd-version: 4\n" 911 "targets: [ x86_64-macos ]\n" 912 "install-name: Test.dylib\n" 913 "swift-abi-version: 1.1\n" 914 "...\n"; 915 916 Expected<TBDFile> Result = 917 TextAPIReader::get(MemoryBufferRef(TBDv4MalformedSwift, "Test.tbd")); 918 EXPECT_FALSE(!!Result); 919 std::string ErrorMessage = toString(Result.takeError()); 920 EXPECT_EQ("malformed file\nTest.tbd:5:20: error: invalid Swift ABI " 921 "version.\nswift-abi-version: 1.1\n ^~~\n", 922 ErrorMessage); 923 } 924 925 } // end namespace TBDv4 926