1 //===-- TextStubV3Tests.cpp - TBD V3 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 #include "TextStubHelpers.h" 9 #include "llvm/TextAPI/MachO/InterfaceFile.h" 10 #include "llvm/TextAPI/MachO/TextAPIReader.h" 11 #include "llvm/TextAPI/MachO/TextAPIWriter.h" 12 #include "gtest/gtest.h" 13 #include <string> 14 #include <vector> 15 16 using namespace llvm; 17 using namespace llvm::MachO; 18 19 static ExportedSymbol TBDv3Symbols[] = { 20 {SymbolKind::GlobalSymbol, "$ld$hide$os9.0$_sym1", false, false}, 21 {SymbolKind::GlobalSymbol, "_sym1", false, false}, 22 {SymbolKind::GlobalSymbol, "_sym2", false, false}, 23 {SymbolKind::GlobalSymbol, "_sym3", false, false}, 24 {SymbolKind::GlobalSymbol, "_sym4", false, false}, 25 {SymbolKind::GlobalSymbol, "_sym5", false, false}, 26 {SymbolKind::GlobalSymbol, "_tlv1", false, true}, 27 {SymbolKind::GlobalSymbol, "_tlv3", false, true}, 28 {SymbolKind::GlobalSymbol, "_weak1", true, false}, 29 {SymbolKind::GlobalSymbol, "_weak2", true, false}, 30 {SymbolKind::GlobalSymbol, "_weak3", true, false}, 31 {SymbolKind::ObjectiveCClass, "class1", false, false}, 32 {SymbolKind::ObjectiveCClass, "class2", false, false}, 33 {SymbolKind::ObjectiveCClass, "class3", false, false}, 34 {SymbolKind::ObjectiveCClassEHType, "class1", false, false}, 35 {SymbolKind::ObjectiveCInstanceVariable, "class1._ivar1", false, false}, 36 {SymbolKind::ObjectiveCInstanceVariable, "class1._ivar2", false, false}, 37 {SymbolKind::ObjectiveCInstanceVariable, "class1._ivar3", false, false}, 38 }; 39 40 namespace TBDv3 { 41 42 TEST(TBDv3, ReadFile) { 43 static const char TBDv3File1[] = 44 "--- !tapi-tbd-v3\n" 45 "archs: [ armv7, arm64 ]\n" 46 "uuids: [ 'armv7: 00000000-0000-0000-0000-000000000000',\n" 47 " 'arm64: 11111111-1111-1111-1111-111111111111']\n" 48 "platform: ios\n" 49 "flags: [ installapi ]\n" 50 "install-name: Test.dylib\n" 51 "current-version: 2.3.4\n" 52 "compatibility-version: 1.0\n" 53 "swift-abi-version: 1.1\n" 54 "parent-umbrella: Umbrella.dylib\n" 55 "exports:\n" 56 " - archs: [ armv7, arm64 ]\n" 57 " allowable-clients: [ clientA ]\n" 58 " re-exports: [ /usr/lib/libfoo.dylib ]\n" 59 " symbols: [ _sym1, _sym2, _sym3, _sym4, $ld$hide$os9.0$_sym1 ]\n" 60 " objc-classes: [ class1, class2 ]\n" 61 " objc-eh-types: [ class1 ]\n" 62 " objc-ivars: [ class1._ivar1, class1._ivar2 ]\n" 63 " weak-def-symbols: [ _weak1, _weak2 ]\n" 64 " thread-local-symbols: [ _tlv1, _tlv3 ]\n" 65 " - archs: [ armv7 ]\n" 66 " symbols: [ _sym5 ]\n" 67 " objc-classes: [ class3 ]\n" 68 " objc-ivars: [ class1._ivar3 ]\n" 69 " weak-def-symbols: [ _weak3 ]\n" 70 " thread-local-symbols: [ _tlv3 ]\n" 71 "...\n"; 72 73 Expected<TBDFile> Result = 74 TextAPIReader::get(MemoryBufferRef(TBDv3File1, "Test.tbd")); 75 EXPECT_TRUE(!!Result); 76 TBDFile File = std::move(Result.get()); 77 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 78 auto Archs = AK_armv7 | AK_arm64; 79 auto Platform = PlatformKind::iOS; 80 TargetList Targets; 81 for (auto &&arch : Archs) 82 Targets.emplace_back(Target(arch, Platform)); 83 EXPECT_EQ(Archs, File->getArchitectures()); 84 UUIDs Uuids = {{Target(AK_armv7, PlatformKind::unknown), 85 "00000000-0000-0000-0000-000000000000"}, 86 {Target(AK_arm64, PlatformKind::unknown), 87 "11111111-1111-1111-1111-111111111111"}}; 88 EXPECT_EQ(Uuids, File->uuids()); 89 EXPECT_EQ(File->getPlatforms().size(), 1U); 90 EXPECT_EQ(Platform, *File->getPlatforms().begin()); 91 EXPECT_EQ(std::string("Test.dylib"), File->getInstallName()); 92 EXPECT_EQ(PackedVersion(2, 3, 4), File->getCurrentVersion()); 93 EXPECT_EQ(PackedVersion(1, 0, 0), File->getCompatibilityVersion()); 94 EXPECT_EQ(2U, File->getSwiftABIVersion()); 95 EXPECT_EQ(ObjCConstraintType::Retain_Release, File->getObjCConstraint()); 96 EXPECT_TRUE(File->isTwoLevelNamespace()); 97 EXPECT_TRUE(File->isApplicationExtensionSafe()); 98 EXPECT_TRUE(File->isInstallAPI()); 99 InterfaceFileRef client("clientA", Targets); 100 InterfaceFileRef reexport("/usr/lib/libfoo.dylib", Targets); 101 EXPECT_EQ(1U, File->allowableClients().size()); 102 EXPECT_EQ(client, File->allowableClients().front()); 103 EXPECT_EQ(1U, File->reexportedLibraries().size()); 104 EXPECT_EQ(reexport, File->reexportedLibraries().front()); 105 106 ExportedSymbolSeq Exports; 107 for (const auto *Sym : File->symbols()) { 108 EXPECT_FALSE(Sym->isWeakReferenced()); 109 EXPECT_FALSE(Sym->isUndefined()); 110 Exports.emplace_back( 111 ExportedSymbol{Sym->getKind(), std::string(Sym->getName()), 112 Sym->isWeakDefined(), Sym->isThreadLocalValue()}); 113 } 114 llvm::sort(Exports.begin(), Exports.end()); 115 116 EXPECT_EQ(sizeof(TBDv3Symbols) / sizeof(ExportedSymbol), Exports.size()); 117 EXPECT_TRUE( 118 std::equal(Exports.begin(), Exports.end(), std::begin(TBDv3Symbols))); 119 } 120 121 TEST(TBDv3, ReadMultipleDocuments) { 122 static const char TBDv3Inlines[] = 123 "--- !tapi-tbd-v3\n" 124 "archs: [ armv7, arm64 ]\n" 125 "uuids: [ 'armv7: 00000000-0000-0000-0000-000000000000',\n" 126 " 'arm64: 11111111-1111-1111-1111-111111111111']\n" 127 "platform: ios\n" 128 "install-name: Test.dylib\n" 129 "current-version: 2.3.4\n" 130 "compatibility-version: 1.0\n" 131 "swift-abi-version: 1.1\n" 132 "parent-umbrella: Umbrella.dylib\n" 133 "exports:\n" 134 " - archs: [ armv7, arm64 ]\n" 135 " allowable-clients: [ clientA ]\n" 136 " re-exports: [ /usr/lib/libfoo.dylib,\n" 137 " TestInline.dylib ]\n" 138 " symbols: [ _sym1, _sym2, _sym3, _sym4, $ld$hide$os9.0$_sym1 ]\n" 139 " objc-classes: [ class1, class2 ]\n" 140 " objc-eh-types: [ class1 ]\n" 141 " objc-ivars: [ class1._ivar1, class1._ivar2 ]\n" 142 " weak-def-symbols: [ _weak1, _weak2 ]\n" 143 " thread-local-symbols: [ _tlv1, _tlv3 ]\n" 144 " - archs: [ armv7 ]\n" 145 " symbols: [ _sym5 ]\n" 146 " objc-classes: [ class3 ]\n" 147 " objc-ivars: [ class1._ivar3 ]\n" 148 " weak-def-symbols: [ _weak3 ]\n" 149 " thread-local-symbols: [ _tlv3 ]\n" 150 "--- !tapi-tbd-v3\n" 151 "archs: [ armv7, arm64 ]\n" 152 "uuids: [ 'armv7: 00000000-0000-0000-0000-000000000000',\n" 153 " 'arm64: 11111111-1111-1111-1111-111111111111']\n" 154 "platform: ios\n" 155 "install-name: TestInline.dylib\n" 156 "swift-abi-version: 1.1\n" 157 "exports:\n" 158 " - archs: [ armv7, arm64 ]\n" 159 " symbols: [ _sym5, _sym6 ]\n" 160 "...\n"; 161 162 Expected<TBDFile> Result = 163 TextAPIReader::get(MemoryBufferRef(TBDv3Inlines, "Test.tbd")); 164 EXPECT_TRUE(!!Result); 165 TBDFile File = std::move(Result.get()); 166 EXPECT_EQ(File->documents().size(), 1U); 167 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 168 auto Archs = AK_armv7 | AK_arm64; 169 auto Platform = PlatformKind::iOS; 170 TargetList Targets; 171 for (auto &&arch : Archs) 172 Targets.emplace_back(Target(arch, Platform)); 173 EXPECT_EQ(Archs, File->getArchitectures()); 174 UUIDs Uuids = {{Target(AK_armv7, PlatformKind::unknown), 175 "00000000-0000-0000-0000-000000000000"}, 176 {Target(AK_arm64, PlatformKind::unknown), 177 "11111111-1111-1111-1111-111111111111"}}; 178 EXPECT_EQ(Uuids, File->uuids()); 179 EXPECT_EQ(File->getPlatforms().size(), 1U); 180 EXPECT_EQ(Platform, *File->getPlatforms().begin()); 181 EXPECT_EQ(std::string("Test.dylib"), File->getInstallName()); 182 EXPECT_EQ(PackedVersion(2, 3, 4), File->getCurrentVersion()); 183 EXPECT_EQ(PackedVersion(1, 0, 0), File->getCompatibilityVersion()); 184 EXPECT_EQ(2U, File->getSwiftABIVersion()); 185 EXPECT_EQ(ObjCConstraintType::Retain_Release, File->getObjCConstraint()); 186 EXPECT_TRUE(File->isTwoLevelNamespace()); 187 EXPECT_TRUE(File->isApplicationExtensionSafe()); 188 EXPECT_FALSE(File->isInstallAPI()); 189 InterfaceFileRef Client("clientA", Targets); 190 const std::vector<InterfaceFileRef> Reexports = { 191 InterfaceFileRef("/usr/lib/libfoo.dylib", Targets), 192 InterfaceFileRef("TestInline.dylib", Targets)}; 193 EXPECT_EQ(1U, File->allowableClients().size()); 194 EXPECT_EQ(Client, File->allowableClients().front()); 195 EXPECT_EQ(2U, File->reexportedLibraries().size()); 196 EXPECT_EQ(Reexports, File->reexportedLibraries()); 197 198 ExportedSymbolSeq Exports; 199 for (const auto *Sym : File->symbols()) { 200 EXPECT_FALSE(Sym->isWeakReferenced()); 201 EXPECT_FALSE(Sym->isUndefined()); 202 Exports.emplace_back(ExportedSymbol{Sym->getKind(), Sym->getName().str(), 203 Sym->isWeakDefined(), 204 Sym->isThreadLocalValue()}); 205 } 206 llvm::sort(Exports.begin(), Exports.end()); 207 208 EXPECT_EQ(sizeof(TBDv3Symbols) / sizeof(ExportedSymbol), Exports.size()); 209 EXPECT_TRUE( 210 std::equal(Exports.begin(), Exports.end(), std::begin(TBDv3Symbols))); 211 212 // Check Second Document 213 Exports.clear(); 214 TBDReexportFile Document = File->documents().front(); 215 EXPECT_EQ(FileType::TBD_V3, Document->getFileType()); 216 EXPECT_EQ(Archs, Document->getArchitectures()); 217 EXPECT_EQ(Uuids, Document->uuids()); 218 EXPECT_EQ(Platform, *Document->getPlatforms().begin()); 219 EXPECT_EQ(std::string("TestInline.dylib"), Document->getInstallName()); 220 EXPECT_EQ(PackedVersion(1, 0, 0), Document->getCurrentVersion()); 221 EXPECT_EQ(PackedVersion(1, 0, 0), Document->getCompatibilityVersion()); 222 EXPECT_EQ(2U, Document->getSwiftABIVersion()); 223 224 for (const auto *Sym : Document->symbols()) { 225 EXPECT_FALSE(Sym->isWeakReferenced()); 226 EXPECT_FALSE(Sym->isUndefined()); 227 Exports.emplace_back(ExportedSymbol{Sym->getKind(), Sym->getName().str(), 228 Sym->isWeakDefined(), 229 Sym->isThreadLocalValue()}); 230 } 231 llvm::sort(Exports.begin(), Exports.end()); 232 233 ExportedSymbolSeq DocumentSymbols{ 234 {SymbolKind::GlobalSymbol, "_sym5", false, false}, 235 {SymbolKind::GlobalSymbol, "_sym6", false, false}, 236 }; 237 238 EXPECT_EQ(DocumentSymbols.size(), Exports.size()); 239 EXPECT_TRUE( 240 std::equal(Exports.begin(), Exports.end(), DocumentSymbols.begin())); 241 } 242 243 TEST(TBDv3, WriteFile) { 244 static const char TBDv3File3[] = 245 "--- !tapi-tbd-v3\n" 246 "archs: [ i386, x86_64 ]\n" 247 "platform: macosx\n" 248 "install-name: '/usr/lib/libfoo.dylib'\n" 249 "current-version: 1.2.3\n" 250 "compatibility-version: 0\n" 251 "swift-abi-version: 5\n" 252 "exports:\n" 253 " - archs: [ i386 ]\n" 254 " symbols: [ _sym1 ]\n" 255 " weak-def-symbols: [ _sym2 ]\n" 256 " thread-local-symbols: [ _sym3 ]\n" 257 " - archs: [ x86_64 ]\n" 258 " allowable-clients: [ clientA ]\n" 259 " re-exports: [ '/usr/lib/libfoo.dylib' ]\n" 260 " objc-classes: [ Class1 ]\n" 261 " objc-eh-types: [ Class1 ]\n" 262 " objc-ivars: [ Class1._ivar1 ]\n" 263 "...\n"; 264 265 InterfaceFile File; 266 TargetList Targets; 267 for (auto &&arch : AK_i386 | AK_x86_64) 268 Targets.emplace_back(Target(arch, PlatformKind::macOS)); 269 File.setPath("libfoo.dylib"); 270 File.setInstallName("/usr/lib/libfoo.dylib"); 271 File.setFileType(FileType::TBD_V3); 272 File.addTargets(Targets); 273 File.setCurrentVersion(PackedVersion(1, 2, 3)); 274 File.setTwoLevelNamespace(); 275 File.setApplicationExtensionSafe(); 276 File.setSwiftABIVersion(5); 277 File.setObjCConstraint(ObjCConstraintType::Retain_Release); 278 File.addAllowableClient("clientA", Targets[1]); 279 File.addReexportedLibrary("/usr/lib/libfoo.dylib", Targets[1]); 280 File.addSymbol(SymbolKind::GlobalSymbol, "_sym1", {Targets[0]}); 281 File.addSymbol(SymbolKind::GlobalSymbol, "_sym2", {Targets[0]}, 282 SymbolFlags::WeakDefined); 283 File.addSymbol(SymbolKind::GlobalSymbol, "_sym3", {Targets[0]}, 284 SymbolFlags::ThreadLocalValue); 285 File.addSymbol(SymbolKind::ObjectiveCClass, "Class1", {Targets[1]}); 286 File.addSymbol(SymbolKind::ObjectiveCClassEHType, "Class1", {Targets[1]}); 287 File.addSymbol(SymbolKind::ObjectiveCInstanceVariable, "Class1._ivar1", 288 {Targets[1]}); 289 290 SmallString<4096> Buffer; 291 raw_svector_ostream OS(Buffer); 292 Error Result = TextAPIWriter::writeToStream(OS, File); 293 EXPECT_FALSE(Result); 294 EXPECT_STREQ(TBDv3File3, Buffer.c_str()); 295 } 296 297 TEST(TBDv3, WriteMultipleDocuments) { 298 static const char TBDv3Inlines[] = 299 "--- !tapi-tbd-v3\n" 300 "archs: [ i386, x86_64 ]\n" 301 "platform: zippered\n" 302 "install-name: '/usr/lib/libfoo.dylib'\n" 303 "current-version: 1.2.3\n" 304 "compatibility-version: 0\n" 305 "swift-abi-version: 5\n" 306 "exports:\n" 307 " - archs: [ x86_64 ]\n" 308 " allowable-clients: [ clientA ]\n" 309 " re-exports: [ '/usr/lib/libbar.dylib' ]\n" 310 " - archs: [ i386, x86_64 ]\n" 311 " symbols: [ _sym1 ]\n" 312 " objc-classes: [ Class1 ]\n" 313 " objc-eh-types: [ Class1 ]\n" 314 " objc-ivars: [ Class1._ivar1 ]\n" 315 " weak-def-symbols: [ _sym2 ]\n" 316 " thread-local-symbols: [ _symA ]\n" 317 "--- !tapi-tbd-v3\n" 318 "archs: [ i386 ]\n" 319 "platform: macosx\n" 320 "install-name: '/usr/lib/libbar.dylib'\n" 321 "current-version: 0\n" 322 "compatibility-version: 0\n" 323 "swift-abi-version: 5\n" 324 "objc-constraint: none\n" 325 "exports:\n" 326 " - archs: [ i386 ]\n" 327 " symbols: [ _sym3, _sym4 ]\n" 328 "...\n"; 329 330 InterfaceFile File; 331 TargetList Targets; 332 for (auto &&arch : AK_i386 | AK_x86_64) { 333 Targets.emplace_back(Target(arch, PlatformKind::macOS)); 334 Targets.emplace_back(Target(arch, PlatformKind::macCatalyst)); 335 } 336 File.addTargets(Targets); 337 File.setPath("libfoo.dylib"); 338 File.setInstallName("/usr/lib/libfoo.dylib"); 339 File.setFileType(FileType::TBD_V3); 340 File.setCurrentVersion(PackedVersion(1, 2, 3)); 341 File.setTwoLevelNamespace(); 342 File.setApplicationExtensionSafe(); 343 File.setSwiftABIVersion(5); 344 File.setObjCConstraint(ObjCConstraintType::Retain_Release); 345 File.addAllowableClient("clientA", Targets[2]); 346 File.addReexportedLibrary("/usr/lib/libbar.dylib", Targets[2]); 347 File.addSymbol(SymbolKind::GlobalSymbol, "_sym1", Targets); 348 File.addSymbol(SymbolKind::GlobalSymbol, "_sym2", Targets, 349 SymbolFlags::WeakDefined); 350 File.addSymbol(SymbolKind::GlobalSymbol, "_symA", Targets, 351 SymbolFlags::ThreadLocalValue); 352 File.addSymbol(SymbolKind::ObjectiveCClass, "Class1", Targets); 353 File.addSymbol(SymbolKind::ObjectiveCClassEHType, "Class1", Targets); 354 File.addSymbol(SymbolKind::ObjectiveCInstanceVariable, "Class1._ivar1", 355 Targets); 356 357 // Inline document 358 InterfaceFile Document; 359 Targets = {Target(AK_i386, PlatformKind::macOS)}; 360 Document.addTargets(Targets); 361 Document.setPath("libbar.dylib"); 362 Document.setInstallName("/usr/lib/libbar.dylib"); 363 Document.setFileType(FileType::TBD_V3); 364 Document.setTwoLevelNamespace(); 365 Document.setApplicationExtensionSafe(); 366 Document.setSwiftABIVersion(5); 367 Document.addSymbol(SymbolKind::GlobalSymbol, "_sym3", Targets); 368 Document.addSymbol(SymbolKind::GlobalSymbol, "_sym4", Targets); 369 File.addDocument(std::make_shared<InterfaceFile>(std::move(Document))); 370 371 SmallString<4096> Buffer; 372 raw_svector_ostream OS(Buffer); 373 Error Result = TextAPIWriter::writeToStream(OS, File); 374 EXPECT_FALSE(Result); 375 EXPECT_STREQ(TBDv3Inlines, Buffer.c_str()); 376 } 377 378 TEST(TBDv3, Platform_macOS) { 379 static const char TBDv3PlatformMacOS[] = "--- !tapi-tbd-v3\n" 380 "archs: [ x86_64 ]\n" 381 "platform: macosx\n" 382 "install-name: Test.dylib\n" 383 "...\n"; 384 385 Expected<TBDFile> Result = 386 TextAPIReader::get(MemoryBufferRef(TBDv3PlatformMacOS, "Test.tbd")); 387 EXPECT_TRUE(!!Result); 388 auto Platform = PlatformKind::macOS; 389 TBDFile File = std::move(Result.get()); 390 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 391 EXPECT_EQ(File->getPlatforms().size(), 1U); 392 EXPECT_EQ(Platform, *File->getPlatforms().begin()); 393 394 SmallString<4096> Buffer; 395 raw_svector_ostream OS(Buffer); 396 Error WriteResult = TextAPIWriter::writeToStream(OS, *File); 397 EXPECT_TRUE(!WriteResult); 398 EXPECT_EQ(stripWhitespace(TBDv3PlatformMacOS), 399 stripWhitespace(Buffer.c_str())); 400 } 401 402 TEST(TBDv3, Platform_iOS) { 403 static const char TBDv3PlatformiOS[] = "--- !tapi-tbd-v3\n" 404 "archs: [ arm64 ]\n" 405 "platform: ios\n" 406 "install-name: Test.dylib\n" 407 "...\n"; 408 409 Expected<TBDFile> Result = 410 TextAPIReader::get(MemoryBufferRef(TBDv3PlatformiOS, "Test.tbd")); 411 EXPECT_TRUE(!!Result); 412 auto Platform = PlatformKind::iOS; 413 TBDFile File = std::move(Result.get()); 414 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 415 EXPECT_EQ(File->getPlatforms().size(), 1U); 416 EXPECT_EQ(Platform, *File->getPlatforms().begin()); 417 418 SmallString<4096> Buffer; 419 raw_svector_ostream OS(Buffer); 420 Error WriteResult = TextAPIWriter::writeToStream(OS, *File); 421 EXPECT_TRUE(!WriteResult); 422 EXPECT_EQ(stripWhitespace(TBDv3PlatformiOS), stripWhitespace(Buffer.c_str())); 423 } 424 425 TEST(TBDv3, Platform_watchOS) { 426 static const char TBDv3watchOS[] = "--- !tapi-tbd-v3\n" 427 "archs: [ armv7k ]\n" 428 "platform: watchos\n" 429 "install-name: Test.dylib\n" 430 "...\n"; 431 432 Expected<TBDFile> Result = 433 TextAPIReader::get(MemoryBufferRef(TBDv3watchOS, "Test.tbd")); 434 EXPECT_TRUE(!!Result); 435 auto Platform = PlatformKind::watchOS; 436 TBDFile File = std::move(Result.get()); 437 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 438 EXPECT_EQ(File->getPlatforms().size(), 1U); 439 EXPECT_EQ(Platform, *File->getPlatforms().begin()); 440 441 SmallString<4096> Buffer; 442 raw_svector_ostream OS(Buffer); 443 Error WriteResult = TextAPIWriter::writeToStream(OS, *File); 444 EXPECT_TRUE(!WriteResult); 445 EXPECT_EQ(stripWhitespace(TBDv3watchOS), stripWhitespace(Buffer.c_str())); 446 } 447 448 TEST(TBDv3, Platform_tvOS) { 449 static const char TBDv3PlatformtvOS[] = "--- !tapi-tbd-v3\n" 450 "archs: [ arm64 ]\n" 451 "platform: tvos\n" 452 "install-name: Test.dylib\n" 453 "...\n"; 454 455 Expected<TBDFile> Result = 456 TextAPIReader::get(MemoryBufferRef(TBDv3PlatformtvOS, "Test.tbd")); 457 EXPECT_TRUE(!!Result); 458 TBDFile File = std::move(Result.get()); 459 auto Platform = PlatformKind::tvOS; 460 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 461 EXPECT_EQ(File->getPlatforms().size(), 1U); 462 EXPECT_EQ(Platform, *File->getPlatforms().begin()); 463 464 SmallString<4096> Buffer; 465 raw_svector_ostream OS(Buffer); 466 Error WriteResult = TextAPIWriter::writeToStream(OS, *File); 467 EXPECT_FALSE(WriteResult); 468 EXPECT_EQ(stripWhitespace(TBDv3PlatformtvOS), 469 stripWhitespace(Buffer.c_str())); 470 } 471 472 TEST(TBDv3, Platform_bridgeOS) { 473 static const char TBDv3BridgeOS[] = "--- !tapi-tbd-v3\n" 474 "archs: [ armv7k ]\n" 475 "platform: bridgeos\n" 476 "install-name: Test.dylib\n" 477 "...\n"; 478 479 Expected<TBDFile> Result = 480 TextAPIReader::get(MemoryBufferRef(TBDv3BridgeOS, "Test.tbd")); 481 EXPECT_TRUE(!!Result); 482 auto Platform = PlatformKind::bridgeOS; 483 TBDFile File = std::move(Result.get()); 484 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 485 EXPECT_EQ(File->getPlatforms().size(), 1U); 486 EXPECT_EQ(Platform, *File->getPlatforms().begin()); 487 488 SmallString<4096> Buffer; 489 raw_svector_ostream OS(Buffer); 490 Error WriteResult = TextAPIWriter::writeToStream(OS, *File); 491 EXPECT_TRUE(!WriteResult); 492 EXPECT_EQ(stripWhitespace(TBDv3BridgeOS), stripWhitespace(Buffer.c_str())); 493 } 494 495 TEST(TBDv3, Platform_macCatalyst) { 496 static const char TBDv3PlatformiOSmac[] = "--- !tapi-tbd-v3\n" 497 "archs: [ armv7k ]\n" 498 "platform: iosmac\n" 499 "install-name: Test.dylib\n" 500 "...\n"; 501 502 Expected<TBDFile> Result = 503 TextAPIReader::get(MemoryBufferRef(TBDv3PlatformiOSmac, "Test.tbd")); 504 EXPECT_TRUE(!!Result); 505 auto Platform = PlatformKind::macCatalyst; 506 TBDFile File = std::move(Result.get()); 507 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 508 EXPECT_EQ(Platform, *File->getPlatforms().begin()); 509 510 SmallString<4096> Buffer; 511 raw_svector_ostream OS(Buffer); 512 Error WriteResult = TextAPIWriter::writeToStream(OS, *File); 513 EXPECT_TRUE(!WriteResult); 514 EXPECT_EQ(stripWhitespace(TBDv3PlatformiOSmac), 515 stripWhitespace(Buffer.c_str())); 516 } 517 518 TEST(TBDv3, Platform_zippered) { 519 static const char TBDv3PlatformZippered[] = "--- !tapi-tbd-v3\n" 520 "archs: [ armv7k ]\n" 521 "platform: zippered\n" 522 "install-name: Test.dylib\n" 523 "...\n"; 524 525 Expected<TBDFile> Result = 526 TextAPIReader::get(MemoryBufferRef(TBDv3PlatformZippered, "Test.tbd")); 527 EXPECT_TRUE(!!Result); 528 TBDFile File = std::move(Result.get()); 529 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 530 531 PlatformSet Platforms; 532 Platforms.insert(PlatformKind::macOS); 533 Platforms.insert(PlatformKind::macCatalyst); 534 EXPECT_EQ(Platforms.size(), File->getPlatforms().size()); 535 for (auto Platform : File->getPlatforms()) 536 EXPECT_EQ(Platforms.count(Platform), 1U); 537 538 SmallString<4096> Buffer; 539 raw_svector_ostream OS(Buffer); 540 Error WriteResult = TextAPIWriter::writeToStream(OS, *File); 541 EXPECT_TRUE(!WriteResult); 542 EXPECT_EQ(stripWhitespace(TBDv3PlatformZippered), 543 stripWhitespace(Buffer.c_str())); 544 } 545 546 TEST(TBDv3, Platform_iOSSim) { 547 static const char TBDv3PlatformiOSsim[] = "--- !tapi-tbd-v3\n" 548 "archs: [ x86_64 ]\n" 549 "platform: ios\n" 550 "install-name: Test.dylib\n" 551 "...\n"; 552 553 Expected<TBDFile> Result = 554 TextAPIReader::get(MemoryBufferRef(TBDv3PlatformiOSsim, "Test.tbd")); 555 EXPECT_TRUE(!!Result); 556 auto Platform = PlatformKind::iOSSimulator; 557 TBDFile File = std::move(Result.get()); 558 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 559 EXPECT_EQ(File->getPlatforms().size(), 1U); 560 EXPECT_EQ(Platform, *File->getPlatforms().begin()); 561 562 SmallString<4096> Buffer; 563 raw_svector_ostream OS(Buffer); 564 Error WriteResult = TextAPIWriter::writeToStream(OS, *File); 565 EXPECT_TRUE(!WriteResult); 566 EXPECT_EQ(stripWhitespace(TBDv3PlatformiOSsim), 567 stripWhitespace(Buffer.c_str())); 568 } 569 570 TEST(TBDv3, Platform_watchOSSim) { 571 static const char TBDv3watchOSsim[] = "--- !tapi-tbd-v3\n" 572 "archs: [ x86_64 ]\n" 573 "platform: watchos\n" 574 "install-name: Test.dylib\n" 575 "...\n"; 576 577 Expected<TBDFile> Result = 578 TextAPIReader::get(MemoryBufferRef(TBDv3watchOSsim, "Test.tbd")); 579 EXPECT_TRUE(!!Result); 580 auto Platform = PlatformKind::watchOSSimulator; 581 TBDFile File = std::move(Result.get()); 582 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 583 EXPECT_EQ(File->getPlatforms().size(), 1U); 584 EXPECT_EQ(Platform, *File->getPlatforms().begin()); 585 586 SmallString<4096> Buffer; 587 raw_svector_ostream OS(Buffer); 588 Error WriteResult = TextAPIWriter::writeToStream(OS, *File); 589 EXPECT_TRUE(!WriteResult); 590 EXPECT_EQ(stripWhitespace(TBDv3watchOSsim), stripWhitespace(Buffer.c_str())); 591 } 592 593 TEST(TBDv3, Platform_tvOSSim) { 594 static const char TBDv3PlatformtvOSsim[] = "--- !tapi-tbd-v3\n" 595 "archs: [ x86_64 ]\n" 596 "platform: tvos\n" 597 "install-name: Test.dylib\n" 598 "...\n"; 599 600 Expected<TBDFile> Result = 601 TextAPIReader::get(MemoryBufferRef(TBDv3PlatformtvOSsim, "Test.tbd")); 602 EXPECT_TRUE(!!Result); 603 TBDFile File = std::move(Result.get()); 604 auto Platform = PlatformKind::tvOSSimulator; 605 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 606 EXPECT_EQ(File->getPlatforms().size(), 1U); 607 EXPECT_EQ(Platform, *File->getPlatforms().begin()); 608 609 SmallString<4096> Buffer; 610 raw_svector_ostream OS(Buffer); 611 Error WriteResult = TextAPIWriter::writeToStream(OS, *File); 612 EXPECT_TRUE(!WriteResult); 613 EXPECT_EQ(stripWhitespace(TBDv3PlatformtvOSsim), 614 stripWhitespace(Buffer.c_str())); 615 } 616 617 TEST(TBDv3, Arch_arm64e) { 618 static const char TBDv3ArchArm64e[] = "--- !tapi-tbd-v3\n" 619 "archs: [ arm64, arm64e ]\n" 620 "platform: ios\n" 621 "install-name: Test.dylib\n" 622 "...\n"; 623 624 Expected<TBDFile> Result = 625 TextAPIReader::get(MemoryBufferRef(TBDv3ArchArm64e, "Test.tbd")); 626 EXPECT_TRUE(!!Result); 627 TBDFile File = std::move(Result.get()); 628 auto Platform = PlatformKind::iOS; 629 auto Archs = AK_arm64 | AK_arm64e; 630 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 631 EXPECT_EQ(File->getPlatforms().size(), 1U); 632 EXPECT_EQ(Platform, *File->getPlatforms().begin()); 633 EXPECT_EQ(Archs, File->getArchitectures()); 634 635 SmallString<4096> Buffer; 636 raw_svector_ostream OS(Buffer); 637 Error WriteResult = TextAPIWriter::writeToStream(OS, *File); 638 EXPECT_TRUE(!WriteResult); 639 EXPECT_EQ(stripWhitespace(TBDv3ArchArm64e), stripWhitespace(Buffer.c_str())); 640 } 641 642 TEST(TBDv3, Swift_1_0) { 643 static const char TBDv3Swift1[] = "--- !tapi-tbd-v3\n" 644 "archs: [ arm64 ]\n" 645 "platform: ios\n" 646 "install-name: Test.dylib\n" 647 "swift-abi-version: 1.0\n" 648 "...\n"; 649 650 Expected<TBDFile> Result = 651 TextAPIReader::get(MemoryBufferRef(TBDv3Swift1, "Test.tbd")); 652 EXPECT_TRUE(!!Result); 653 TBDFile File = std::move(Result.get()); 654 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 655 EXPECT_EQ(1U, File->getSwiftABIVersion()); 656 657 SmallString<4096> Buffer; 658 raw_svector_ostream OS(Buffer); 659 Error WriteResult = TextAPIWriter::writeToStream(OS, *File); 660 EXPECT_TRUE(!WriteResult); 661 EXPECT_EQ(stripWhitespace(TBDv3Swift1), stripWhitespace(Buffer.c_str())); 662 } 663 664 TEST(TBDv3, Swift_1_1) { 665 static const char TBDv3Swift1Dot[] = "--- !tapi-tbd-v3\n" 666 "archs: [ arm64 ]\n" 667 "platform: ios\n" 668 "install-name: Test.dylib\n" 669 "swift-abi-version: 1.1\n" 670 "...\n"; 671 672 Expected<TBDFile> Result = 673 TextAPIReader::get(MemoryBufferRef(TBDv3Swift1Dot, "Test.tbd")); 674 EXPECT_TRUE(!!Result); 675 TBDFile File = std::move(Result.get()); 676 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 677 EXPECT_EQ(2U, File->getSwiftABIVersion()); 678 679 SmallString<4096> Buffer; 680 raw_svector_ostream OS(Buffer); 681 Error WriteResult = TextAPIWriter::writeToStream(OS, *File); 682 EXPECT_TRUE(!WriteResult); 683 EXPECT_EQ(stripWhitespace(TBDv3Swift1Dot), stripWhitespace(Buffer.c_str())); 684 } 685 686 TEST(TBDv3, Swift_2_0) { 687 static const char TBDv3Swift2[] = "--- !tapi-tbd-v3\n" 688 "archs: [ arm64 ]\n" 689 "platform: ios\n" 690 "install-name: Test.dylib\n" 691 "swift-abi-version: 2.0\n" 692 "...\n"; 693 694 Expected<TBDFile> Result = 695 TextAPIReader::get(MemoryBufferRef(TBDv3Swift2, "Test.tbd")); 696 EXPECT_TRUE(!!Result); 697 TBDFile File = std::move(Result.get()); 698 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 699 EXPECT_EQ(3U, File->getSwiftABIVersion()); 700 701 SmallString<4096> Buffer; 702 raw_svector_ostream OS(Buffer); 703 Error WriteResult = TextAPIWriter::writeToStream(OS, *File); 704 EXPECT_TRUE(!WriteResult); 705 EXPECT_EQ(stripWhitespace(TBDv3Swift2), stripWhitespace(Buffer.c_str())); 706 } 707 708 TEST(TBDv3, Swift_3_0) { 709 static const char TBDv3Swift3[] = "--- !tapi-tbd-v3\n" 710 "archs: [ arm64 ]\n" 711 "platform: ios\n" 712 "install-name: Test.dylib\n" 713 "swift-abi-version: 3.0\n" 714 "...\n"; 715 716 Expected<TBDFile> Result = 717 TextAPIReader::get(MemoryBufferRef(TBDv3Swift3, "Test.tbd")); 718 EXPECT_TRUE(!!Result); 719 TBDFile File = std::move(Result.get()); 720 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 721 EXPECT_EQ(4U, File->getSwiftABIVersion()); 722 723 SmallString<4096> Buffer; 724 raw_svector_ostream OS(Buffer); 725 Error WriteResult = TextAPIWriter::writeToStream(OS, *File); 726 EXPECT_TRUE(!WriteResult); 727 EXPECT_EQ(stripWhitespace(TBDv3Swift3), stripWhitespace(Buffer.c_str())); 728 } 729 730 TEST(TBDv3, Swift_4_0) { 731 static const char TBDv3Swift4[] = "--- !tapi-tbd-v3\n" 732 "archs: [ arm64 ]\n" 733 "platform: ios\n" 734 "install-name: Test.dylib\n" 735 "swift-abi-version: 4.0\n" 736 "...\n"; 737 738 Expected<TBDFile> Result = 739 TextAPIReader::get(MemoryBufferRef(TBDv3Swift4, "Test.tbd")); 740 EXPECT_FALSE(!!Result); 741 std::string ErrorMessage = toString(Result.takeError()); 742 EXPECT_EQ("malformed file\nTest.tbd:5:20: error: invalid Swift ABI " 743 "version.\nswift-abi-version: 4.0\n ^~~\n", 744 ErrorMessage); 745 } 746 747 TEST(TBDv3, Swift_5) { 748 static const char TBDv3Swift5[] = "--- !tapi-tbd-v3\n" 749 "archs: [ arm64 ]\n" 750 "platform: ios\n" 751 "install-name: Test.dylib\n" 752 "swift-abi-version: 5\n" 753 "...\n"; 754 755 Expected<TBDFile> Result = 756 TextAPIReader::get(MemoryBufferRef(TBDv3Swift5, "Test.tbd")); 757 EXPECT_TRUE(!!Result); 758 TBDFile File = std::move(Result.get()); 759 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 760 EXPECT_EQ(5U, File->getSwiftABIVersion()); 761 } 762 763 TEST(TBDv3, Swift_99) { 764 static const char TBDv3Swift99[] = "--- !tapi-tbd-v3\n" 765 "archs: [ arm64 ]\n" 766 "platform: ios\n" 767 "install-name: Test.dylib\n" 768 "swift-abi-version: 99\n" 769 "...\n"; 770 771 Expected<TBDFile> Result = 772 TextAPIReader::get(MemoryBufferRef(TBDv3Swift99, "Test.tbd")); 773 EXPECT_TRUE(!!Result); 774 TBDFile File = std::move(Result.get()); 775 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 776 EXPECT_EQ(99U, File->getSwiftABIVersion()); 777 } 778 779 TEST(TBDv3, UnknownArchitecture) { 780 static const char TBDv3FileUnknownArch[] = "--- !tapi-tbd-v3\n" 781 "archs: [ foo ]\n" 782 "platform: macosx\n" 783 "install-name: Test.dylib\n" 784 "...\n"; 785 786 Expected<TBDFile> Result = 787 TextAPIReader::get(MemoryBufferRef(TBDv3FileUnknownArch, "Test.tbd")); 788 EXPECT_TRUE(!!Result); 789 } 790 791 TEST(TBDv3, UnknownPlatform) { 792 static const char TBDv3FileUnknownPlatform[] = "--- !tapi-tbd-v3\n" 793 "archs: [ i386 ]\n" 794 "platform: newOS\n" 795 "...\n"; 796 797 Expected<TBDFile> Result = 798 TextAPIReader::get(MemoryBufferRef(TBDv3FileUnknownPlatform, "Test.tbd")); 799 EXPECT_FALSE(!!Result); 800 std::string ErrorMessage = toString(Result.takeError()); 801 EXPECT_EQ("malformed file\nTest.tbd:3:11: error: unknown platform\nplatform: " 802 "newOS\n ^~~~~\n", 803 ErrorMessage); 804 } 805 806 TEST(TBDv3, MalformedFile1) { 807 static const char TBDv3FileMalformed1[] = "--- !tapi-tbd-v3\n" 808 "archs: [ arm64 ]\n" 809 "foobar: \"Unsupported key\"\n" 810 "...\n"; 811 812 Expected<TBDFile> Result = 813 TextAPIReader::get(MemoryBufferRef(TBDv3FileMalformed1, "Test.tbd")); 814 EXPECT_FALSE(!!Result); 815 std::string ErrorMessage = toString(Result.takeError()); 816 ASSERT_EQ("malformed file\nTest.tbd:2:1: error: missing required key " 817 "'platform'\narchs: [ arm64 ]\n^\n", 818 ErrorMessage); 819 } 820 821 TEST(TBDv3, MalformedFile2) { 822 static const char TBDv3FileMalformed2[] = "--- !tapi-tbd-v3\n" 823 "archs: [ arm64 ]\n" 824 "platform: ios\n" 825 "install-name: Test.dylib\n" 826 "foobar: \"Unsupported key\"\n" 827 "...\n"; 828 829 Expected<TBDFile> Result = 830 TextAPIReader::get(MemoryBufferRef(TBDv3FileMalformed2, "Test.tbd")); 831 EXPECT_FALSE(!!Result); 832 std::string ErrorMessage = toString(Result.takeError()); 833 ASSERT_EQ( 834 "malformed file\nTest.tbd:5:9: error: unknown key 'foobar'\nfoobar: " 835 "\"Unsupported key\"\n ^~~~~~~~~~~~~~~~~\n", 836 ErrorMessage); 837 } 838 839 } // namespace TBDv3 840