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