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 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 struct ExportedSymbol { 20 SymbolKind Kind; 21 std::string Name; 22 bool WeakDefined; 23 bool ThreadLocalValue; 24 }; 25 using ExportedSymbolSeq = std::vector<ExportedSymbol>; 26 using UUIDs = std::vector<std::pair<Target, std::string>>; 27 28 inline bool operator<(const ExportedSymbol &lhs, const ExportedSymbol &rhs) { 29 return std::tie(lhs.Kind, lhs.Name) < std::tie(rhs.Kind, rhs.Name); 30 } 31 32 inline bool operator==(const ExportedSymbol &lhs, const ExportedSymbol &rhs) { 33 return std::tie(lhs.Kind, lhs.Name, lhs.WeakDefined, lhs.ThreadLocalValue) == 34 std::tie(rhs.Kind, rhs.Name, rhs.WeakDefined, rhs.ThreadLocalValue); 35 } 36 37 inline std::string stripWhitespace(std::string s) { 38 s.erase(std::remove_if(s.begin(), s.end(), ::isspace), s.end()); 39 return s; 40 } 41 42 static ExportedSymbol TBDv3Symbols[] = { 43 {SymbolKind::GlobalSymbol, "$ld$hide$os9.0$_sym1", false, false}, 44 {SymbolKind::GlobalSymbol, "_sym1", false, false}, 45 {SymbolKind::GlobalSymbol, "_sym2", false, false}, 46 {SymbolKind::GlobalSymbol, "_sym3", false, false}, 47 {SymbolKind::GlobalSymbol, "_sym4", false, false}, 48 {SymbolKind::GlobalSymbol, "_sym5", false, false}, 49 {SymbolKind::GlobalSymbol, "_tlv1", false, true}, 50 {SymbolKind::GlobalSymbol, "_tlv3", false, true}, 51 {SymbolKind::GlobalSymbol, "_weak1", true, false}, 52 {SymbolKind::GlobalSymbol, "_weak2", true, false}, 53 {SymbolKind::GlobalSymbol, "_weak3", true, false}, 54 {SymbolKind::ObjectiveCClass, "class1", false, false}, 55 {SymbolKind::ObjectiveCClass, "class2", false, false}, 56 {SymbolKind::ObjectiveCClass, "class3", false, false}, 57 {SymbolKind::ObjectiveCClassEHType, "class1", false, false}, 58 {SymbolKind::ObjectiveCInstanceVariable, "class1._ivar1", false, false}, 59 {SymbolKind::ObjectiveCInstanceVariable, "class1._ivar2", false, false}, 60 {SymbolKind::ObjectiveCInstanceVariable, "class1._ivar3", false, false}, 61 }; 62 63 namespace TBDv3 { 64 65 TEST(TBDv3, ReadFile) { 66 static const char tbd_v3_file1[] = 67 "--- !tapi-tbd-v3\n" 68 "archs: [ armv7, arm64 ]\n" 69 "uuids: [ 'armv7: 00000000-0000-0000-0000-000000000000',\n" 70 " 'arm64: 11111111-1111-1111-1111-111111111111']\n" 71 "platform: ios\n" 72 "flags: [ installapi ]\n" 73 "install-name: Test.dylib\n" 74 "current-version: 2.3.4\n" 75 "compatibility-version: 1.0\n" 76 "swift-abi-version: 1.1\n" 77 "parent-umbrella: Umbrella.dylib\n" 78 "exports:\n" 79 " - archs: [ armv7, arm64 ]\n" 80 " allowable-clients: [ clientA ]\n" 81 " re-exports: [ /usr/lib/libfoo.dylib ]\n" 82 " symbols: [ _sym1, _sym2, _sym3, _sym4, $ld$hide$os9.0$_sym1 ]\n" 83 " objc-classes: [ class1, class2 ]\n" 84 " objc-eh-types: [ class1 ]\n" 85 " objc-ivars: [ class1._ivar1, class1._ivar2 ]\n" 86 " weak-def-symbols: [ _weak1, _weak2 ]\n" 87 " thread-local-symbols: [ _tlv1, _tlv3 ]\n" 88 " - archs: [ armv7 ]\n" 89 " symbols: [ _sym5 ]\n" 90 " objc-classes: [ class3 ]\n" 91 " objc-ivars: [ class1._ivar3 ]\n" 92 " weak-def-symbols: [ _weak3 ]\n" 93 " thread-local-symbols: [ _tlv3 ]\n" 94 "...\n"; 95 96 auto Result = TextAPIReader::get(MemoryBufferRef(tbd_v3_file1, "Test.tbd")); 97 EXPECT_TRUE(!!Result); 98 auto File = std::move(Result.get()); 99 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 100 auto Archs = AK_armv7 | AK_arm64; 101 auto Platform = PlatformKind::iOS; 102 TargetList Targets; 103 for (auto &&arch : Archs) 104 Targets.emplace_back(Target(arch, Platform)); 105 EXPECT_EQ(Archs, File->getArchitectures()); 106 UUIDs Uuids = {{Target(AK_armv7, PlatformKind::unknown), 107 "00000000-0000-0000-0000-000000000000"}, 108 {Target(AK_arm64, PlatformKind::unknown), 109 "11111111-1111-1111-1111-111111111111"}}; 110 EXPECT_EQ(Uuids, File->uuids()); 111 EXPECT_EQ(File->getPlatforms().size(), 1U); 112 EXPECT_EQ(Platform, *File->getPlatforms().begin()); 113 EXPECT_EQ(std::string("Test.dylib"), File->getInstallName()); 114 EXPECT_EQ(PackedVersion(2, 3, 4), File->getCurrentVersion()); 115 EXPECT_EQ(PackedVersion(1, 0, 0), File->getCompatibilityVersion()); 116 EXPECT_EQ(2U, File->getSwiftABIVersion()); 117 EXPECT_EQ(ObjCConstraintType::Retain_Release, File->getObjCConstraint()); 118 EXPECT_TRUE(File->isTwoLevelNamespace()); 119 EXPECT_TRUE(File->isApplicationExtensionSafe()); 120 EXPECT_TRUE(File->isInstallAPI()); 121 InterfaceFileRef client("clientA", Targets); 122 InterfaceFileRef reexport("/usr/lib/libfoo.dylib", Targets); 123 EXPECT_EQ(1U, File->allowableClients().size()); 124 EXPECT_EQ(client, File->allowableClients().front()); 125 EXPECT_EQ(1U, File->reexportedLibraries().size()); 126 EXPECT_EQ(reexport, File->reexportedLibraries().front()); 127 128 ExportedSymbolSeq Exports; 129 for (const auto *Sym : File->symbols()) { 130 EXPECT_FALSE(Sym->isWeakReferenced()); 131 EXPECT_FALSE(Sym->isUndefined()); 132 Exports.emplace_back( 133 ExportedSymbol{Sym->getKind(), std::string(Sym->getName()), 134 Sym->isWeakDefined(), Sym->isThreadLocalValue()}); 135 } 136 llvm::sort(Exports.begin(), Exports.end()); 137 138 EXPECT_EQ(sizeof(TBDv3Symbols) / sizeof(ExportedSymbol), Exports.size()); 139 EXPECT_TRUE( 140 std::equal(Exports.begin(), Exports.end(), std::begin(TBDv3Symbols))); 141 } 142 143 TEST(TBDv3, WriteFile) { 144 static const char tbd_v3_file3[] = 145 "--- !tapi-tbd-v3\n" 146 "archs: [ i386, x86_64 ]\n" 147 "platform: macosx\n" 148 "install-name: '/usr/lib/libfoo.dylib'\n" 149 "current-version: 1.2.3\n" 150 "compatibility-version: 0\n" 151 "swift-abi-version: 5\n" 152 "exports:\n" 153 " - archs: [ i386 ]\n" 154 " symbols: [ _sym1 ]\n" 155 " weak-def-symbols: [ _sym2 ]\n" 156 " thread-local-symbols: [ _sym3 ]\n" 157 " - archs: [ x86_64 ]\n" 158 " allowable-clients: [ clientA ]\n" 159 " re-exports: [ '/usr/lib/libfoo.dylib' ]\n" 160 " objc-classes: [ Class1 ]\n" 161 " objc-eh-types: [ Class1 ]\n" 162 " objc-ivars: [ Class1._ivar1 ]\n" 163 "...\n"; 164 165 InterfaceFile File; 166 TargetList Targets; 167 for (auto &&arch : AK_i386 | AK_x86_64) 168 Targets.emplace_back(Target(arch, PlatformKind::macOS)); 169 File.setPath("libfoo.dylib"); 170 File.setInstallName("/usr/lib/libfoo.dylib"); 171 File.setFileType(FileType::TBD_V3); 172 File.addTargets(Targets); 173 File.setCurrentVersion(PackedVersion(1, 2, 3)); 174 File.setTwoLevelNamespace(); 175 File.setApplicationExtensionSafe(); 176 File.setSwiftABIVersion(5); 177 File.setObjCConstraint(ObjCConstraintType::Retain_Release); 178 File.addAllowableClient("clientA", Targets[1]); 179 File.addReexportedLibrary("/usr/lib/libfoo.dylib", Targets[1]); 180 File.addSymbol(SymbolKind::GlobalSymbol, "_sym1", {Targets[0]}); 181 File.addSymbol(SymbolKind::GlobalSymbol, "_sym2", {Targets[0]}, 182 SymbolFlags::WeakDefined); 183 File.addSymbol(SymbolKind::GlobalSymbol, "_sym3", {Targets[0]}, 184 SymbolFlags::ThreadLocalValue); 185 File.addSymbol(SymbolKind::ObjectiveCClass, "Class1", {Targets[1]}); 186 File.addSymbol(SymbolKind::ObjectiveCClassEHType, "Class1", {Targets[1]}); 187 File.addSymbol(SymbolKind::ObjectiveCInstanceVariable, "Class1._ivar1", 188 {Targets[1]}); 189 190 SmallString<4096> Buffer; 191 raw_svector_ostream OS(Buffer); 192 auto Result = TextAPIWriter::writeToStream(OS, File); 193 EXPECT_FALSE(Result); 194 EXPECT_STREQ(tbd_v3_file3, Buffer.c_str()); 195 } 196 197 TEST(TBDv3, Platform_macOS) { 198 static const char tbd_v3_platform_macos[] = "--- !tapi-tbd-v3\n" 199 "archs: [ x86_64 ]\n" 200 "platform: macosx\n" 201 "install-name: Test.dylib\n" 202 "...\n"; 203 204 auto Result = 205 TextAPIReader::get(MemoryBufferRef(tbd_v3_platform_macos, "Test.tbd")); 206 EXPECT_TRUE(!!Result); 207 auto Platform = PlatformKind::macOS; 208 auto File = std::move(Result.get()); 209 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 210 EXPECT_EQ(File->getPlatforms().size(), 1U); 211 EXPECT_EQ(Platform, *File->getPlatforms().begin()); 212 213 SmallString<4096> Buffer; 214 raw_svector_ostream OS(Buffer); 215 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 216 EXPECT_TRUE(!WriteResult); 217 EXPECT_EQ(stripWhitespace(tbd_v3_platform_macos), 218 stripWhitespace(Buffer.c_str())); 219 } 220 221 TEST(TBDv3, Platform_iOS) { 222 static const char tbd_v3_platform_ios[] = "--- !tapi-tbd-v3\n" 223 "archs: [ arm64 ]\n" 224 "platform: ios\n" 225 "install-name: Test.dylib\n" 226 "...\n"; 227 228 auto Result = 229 TextAPIReader::get(MemoryBufferRef(tbd_v3_platform_ios, "Test.tbd")); 230 EXPECT_TRUE(!!Result); 231 auto Platform = PlatformKind::iOS; 232 auto File = std::move(Result.get()); 233 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 234 EXPECT_EQ(File->getPlatforms().size(), 1U); 235 EXPECT_EQ(Platform, *File->getPlatforms().begin()); 236 237 SmallString<4096> Buffer; 238 raw_svector_ostream OS(Buffer); 239 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 240 EXPECT_TRUE(!WriteResult); 241 EXPECT_EQ(stripWhitespace(tbd_v3_platform_ios), 242 stripWhitespace(Buffer.c_str())); 243 } 244 245 TEST(TBDv3, Platform_watchOS) { 246 static const char tbd_v3_platform_watchos[] = "--- !tapi-tbd-v3\n" 247 "archs: [ armv7k ]\n" 248 "platform: watchos\n" 249 "install-name: Test.dylib\n" 250 "...\n"; 251 252 auto Result = 253 TextAPIReader::get(MemoryBufferRef(tbd_v3_platform_watchos, "Test.tbd")); 254 EXPECT_TRUE(!!Result); 255 auto Platform = PlatformKind::watchOS; 256 auto File = std::move(Result.get()); 257 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 258 EXPECT_EQ(File->getPlatforms().size(), 1U); 259 EXPECT_EQ(Platform, *File->getPlatforms().begin()); 260 261 SmallString<4096> Buffer; 262 raw_svector_ostream OS(Buffer); 263 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 264 EXPECT_TRUE(!WriteResult); 265 EXPECT_EQ(stripWhitespace(tbd_v3_platform_watchos), 266 stripWhitespace(Buffer.c_str())); 267 } 268 269 TEST(TBDv3, Platform_tvOS) { 270 static const char tbd_v3_platform_tvos[] = "--- !tapi-tbd-v3\n" 271 "archs: [ arm64 ]\n" 272 "platform: tvos\n" 273 "install-name: Test.dylib\n" 274 "...\n"; 275 276 auto Result = 277 TextAPIReader::get(MemoryBufferRef(tbd_v3_platform_tvos, "Test.tbd")); 278 EXPECT_TRUE(!!Result); 279 auto File = std::move(Result.get()); 280 auto Platform = PlatformKind::tvOS; 281 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 282 EXPECT_EQ(File->getPlatforms().size(), 1U); 283 EXPECT_EQ(Platform, *File->getPlatforms().begin()); 284 285 SmallString<4096> Buffer; 286 raw_svector_ostream OS(Buffer); 287 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 288 EXPECT_TRUE(!WriteResult); 289 EXPECT_EQ(stripWhitespace(tbd_v3_platform_tvos), 290 stripWhitespace(Buffer.c_str())); 291 } 292 293 TEST(TBDv3, Platform_bridgeOS) { 294 static const char tbd_v3_platform_bridgeos[] = "--- !tapi-tbd-v3\n" 295 "archs: [ armv7k ]\n" 296 "platform: bridgeos\n" 297 "install-name: Test.dylib\n" 298 "...\n"; 299 300 auto Result = 301 TextAPIReader::get(MemoryBufferRef(tbd_v3_platform_bridgeos, "Test.tbd")); 302 EXPECT_TRUE(!!Result); 303 auto Platform = PlatformKind::bridgeOS; 304 auto File = std::move(Result.get()); 305 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 306 EXPECT_EQ(File->getPlatforms().size(), 1U); 307 EXPECT_EQ(Platform, *File->getPlatforms().begin()); 308 309 SmallString<4096> Buffer; 310 raw_svector_ostream OS(Buffer); 311 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 312 EXPECT_TRUE(!WriteResult); 313 EXPECT_EQ(stripWhitespace(tbd_v3_platform_bridgeos), 314 stripWhitespace(Buffer.c_str())); 315 } 316 317 TEST(TBDv3, Platform_macCatalyst) { 318 static const char tbd_v3_platform_iosmac[] = "--- !tapi-tbd-v3\n" 319 "archs: [ armv7k ]\n" 320 "platform: iosmac\n" 321 "install-name: Test.dylib\n" 322 "...\n"; 323 324 auto Result = 325 TextAPIReader::get(MemoryBufferRef(tbd_v3_platform_iosmac, "Test.tbd")); 326 EXPECT_TRUE(!!Result); 327 auto Platform = PlatformKind::macCatalyst; 328 auto File = std::move(Result.get()); 329 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 330 EXPECT_EQ(Platform, *File->getPlatforms().begin()); 331 332 SmallString<4096> Buffer; 333 raw_svector_ostream OS(Buffer); 334 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 335 EXPECT_TRUE(!WriteResult); 336 EXPECT_EQ(stripWhitespace(tbd_v3_platform_iosmac), stripWhitespace(Buffer.c_str())); 337 } 338 339 TEST(TBDv3, Platform_zippered) { 340 static const char tbd_v3_platform_zip[] = "--- !tapi-tbd-v3\n" 341 "archs: [ armv7k ]\n" 342 "platform: zippered\n" 343 "install-name: Test.dylib\n" 344 "...\n"; 345 346 auto Result = 347 TextAPIReader::get(MemoryBufferRef(tbd_v3_platform_zip, "Test.tbd")); 348 EXPECT_TRUE(!!Result); 349 auto File = std::move(Result.get()); 350 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 351 352 PlatformSet Platforms; 353 Platforms.insert(PlatformKind::macOS); 354 Platforms.insert(PlatformKind::macCatalyst); 355 EXPECT_EQ(Platforms.size(), File->getPlatforms().size()); 356 for (auto Platform : File->getPlatforms()) 357 EXPECT_EQ(Platforms.count(Platform), 1U); 358 359 SmallString<4096> Buffer; 360 raw_svector_ostream OS(Buffer); 361 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 362 EXPECT_TRUE(!WriteResult); 363 EXPECT_EQ(stripWhitespace(tbd_v3_platform_zip), 364 stripWhitespace(Buffer.c_str())); 365 } 366 367 TEST(TBDv3, Swift_1_0) { 368 static const char tbd_v3_swift_1_0[] = "--- !tapi-tbd-v3\n" 369 "archs: [ arm64 ]\n" 370 "platform: ios\n" 371 "install-name: Test.dylib\n" 372 "swift-abi-version: 1.0\n" 373 "...\n"; 374 375 auto Result = 376 TextAPIReader::get(MemoryBufferRef(tbd_v3_swift_1_0, "Test.tbd")); 377 EXPECT_TRUE(!!Result); 378 auto File = std::move(Result.get()); 379 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 380 EXPECT_EQ(1U, File->getSwiftABIVersion()); 381 382 SmallString<4096> Buffer; 383 raw_svector_ostream OS(Buffer); 384 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 385 EXPECT_TRUE(!WriteResult); 386 EXPECT_EQ(stripWhitespace(tbd_v3_swift_1_0), stripWhitespace(Buffer.c_str())); 387 } 388 389 TEST(TBDv3, Swift_1_1) { 390 static const char tbd_v3_swift_1_1[] = "--- !tapi-tbd-v3\n" 391 "archs: [ arm64 ]\n" 392 "platform: ios\n" 393 "install-name: Test.dylib\n" 394 "swift-abi-version: 1.1\n" 395 "...\n"; 396 397 auto Result = 398 TextAPIReader::get(MemoryBufferRef(tbd_v3_swift_1_1, "Test.tbd")); 399 EXPECT_TRUE(!!Result); 400 auto File = std::move(Result.get()); 401 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 402 EXPECT_EQ(2U, File->getSwiftABIVersion()); 403 404 SmallString<4096> Buffer; 405 raw_svector_ostream OS(Buffer); 406 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 407 EXPECT_TRUE(!WriteResult); 408 EXPECT_EQ(stripWhitespace(tbd_v3_swift_1_1), stripWhitespace(Buffer.c_str())); 409 } 410 411 TEST(TBDv3, Swift_2_0) { 412 static const char tbd_v3_swift_2_0[] = "--- !tapi-tbd-v3\n" 413 "archs: [ arm64 ]\n" 414 "platform: ios\n" 415 "install-name: Test.dylib\n" 416 "swift-abi-version: 2.0\n" 417 "...\n"; 418 419 auto Result = 420 TextAPIReader::get(MemoryBufferRef(tbd_v3_swift_2_0, "Test.tbd")); 421 EXPECT_TRUE(!!Result); 422 auto File = std::move(Result.get()); 423 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 424 EXPECT_EQ(3U, File->getSwiftABIVersion()); 425 426 SmallString<4096> Buffer; 427 raw_svector_ostream OS(Buffer); 428 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 429 EXPECT_TRUE(!WriteResult); 430 EXPECT_EQ(stripWhitespace(tbd_v3_swift_2_0), stripWhitespace(Buffer.c_str())); 431 } 432 433 TEST(TBDv3, Swift_3_0) { 434 static const char tbd_v3_swift_3_0[] = "--- !tapi-tbd-v3\n" 435 "archs: [ arm64 ]\n" 436 "platform: ios\n" 437 "install-name: Test.dylib\n" 438 "swift-abi-version: 3.0\n" 439 "...\n"; 440 441 auto Result = 442 TextAPIReader::get(MemoryBufferRef(tbd_v3_swift_3_0, "Test.tbd")); 443 EXPECT_TRUE(!!Result); 444 auto File = std::move(Result.get()); 445 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 446 EXPECT_EQ(4U, File->getSwiftABIVersion()); 447 448 SmallString<4096> Buffer; 449 raw_svector_ostream OS(Buffer); 450 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 451 EXPECT_TRUE(!WriteResult); 452 EXPECT_EQ(stripWhitespace(tbd_v3_swift_3_0), stripWhitespace(Buffer.c_str())); 453 } 454 455 TEST(TBDv3, Swift_4_0) { 456 static const char tbd_v3_swift_4_0[] = "--- !tapi-tbd-v3\n" 457 "archs: [ arm64 ]\n" 458 "platform: ios\n" 459 "install-name: Test.dylib\n" 460 "swift-abi-version: 4.0\n" 461 "...\n"; 462 463 auto Result = 464 TextAPIReader::get(MemoryBufferRef(tbd_v3_swift_4_0, "Test.tbd")); 465 EXPECT_FALSE(!!Result); 466 auto errorMessage = toString(Result.takeError()); 467 EXPECT_EQ("malformed file\nTest.tbd:5:20: error: invalid Swift ABI " 468 "version.\nswift-abi-version: 4.0\n ^~~\n", 469 errorMessage); 470 } 471 472 TEST(TBDv3, Swift_5) { 473 static const char tbd_v3_swift_5[] = "--- !tapi-tbd-v3\n" 474 "archs: [ arm64 ]\n" 475 "platform: ios\n" 476 "install-name: Test.dylib\n" 477 "swift-abi-version: 5\n" 478 "...\n"; 479 480 auto Result = TextAPIReader::get(MemoryBufferRef(tbd_v3_swift_5, "Test.tbd")); 481 EXPECT_TRUE(!!Result); 482 auto File = std::move(Result.get()); 483 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 484 EXPECT_EQ(5U, File->getSwiftABIVersion()); 485 } 486 487 TEST(TBDv3, Swift_99) { 488 static const char tbd_v3_swift_99[] = "--- !tapi-tbd-v3\n" 489 "archs: [ arm64 ]\n" 490 "platform: ios\n" 491 "install-name: Test.dylib\n" 492 "swift-abi-version: 99\n" 493 "...\n"; 494 495 auto Result = 496 TextAPIReader::get(MemoryBufferRef(tbd_v3_swift_99, "Test.tbd")); 497 EXPECT_TRUE(!!Result); 498 auto File = std::move(Result.get()); 499 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 500 EXPECT_EQ(99U, File->getSwiftABIVersion()); 501 } 502 503 TEST(TBDv3, UnknownArchitecture) { 504 static const char tbd_v3_file_unknown_architecture[] = 505 "--- !tapi-tbd-v3\n" 506 "archs: [ foo ]\n" 507 "platform: macosx\n" 508 "install-name: Test.dylib\n" 509 "...\n"; 510 511 auto Result = TextAPIReader::get( 512 MemoryBufferRef(tbd_v3_file_unknown_architecture, "Test.tbd")); 513 EXPECT_TRUE(!!Result); 514 } 515 516 TEST(TBDv3, UnknownPlatform) { 517 static const char tbd_v3_file_unknown_platform[] = "--- !tapi-tbd-v3\n" 518 "archs: [ i386 ]\n" 519 "platform: newOS\n" 520 "...\n"; 521 522 auto Result = TextAPIReader::get( 523 MemoryBufferRef(tbd_v3_file_unknown_platform, "Test.tbd")); 524 EXPECT_FALSE(!!Result); 525 auto errorMessage = toString(Result.takeError()); 526 EXPECT_EQ("malformed file\nTest.tbd:3:11: error: unknown platform\nplatform: " 527 "newOS\n ^~~~~\n", 528 errorMessage); 529 } 530 531 TEST(TBDv3, MalformedFile1) { 532 static const char malformed_file1[] = "--- !tapi-tbd-v3\n" 533 "archs: [ arm64 ]\n" 534 "foobar: \"Unsupported key\"\n" 535 "...\n"; 536 537 auto Result = 538 TextAPIReader::get(MemoryBufferRef(malformed_file1, "Test.tbd")); 539 EXPECT_FALSE(!!Result); 540 auto errorMessage = toString(Result.takeError()); 541 ASSERT_EQ("malformed file\nTest.tbd:2:1: error: missing required key " 542 "'platform'\narchs: [ arm64 ]\n^\n", 543 errorMessage); 544 } 545 546 TEST(TBDv3, MalformedFile2) { 547 static const char malformed_file2[] = "--- !tapi-tbd-v3\n" 548 "archs: [ arm64 ]\n" 549 "platform: ios\n" 550 "install-name: Test.dylib\n" 551 "foobar: \"Unsupported key\"\n" 552 "...\n"; 553 554 auto Result = 555 TextAPIReader::get(MemoryBufferRef(malformed_file2, "Test.tbd")); 556 EXPECT_FALSE(!!Result); 557 auto errorMessage = toString(Result.takeError()); 558 ASSERT_EQ( 559 "malformed file\nTest.tbd:5:9: error: unknown key 'foobar'\nfoobar: " 560 "\"Unsupported key\"\n ^~~~~~~~~~~~~~~~~\n", 561 errorMessage); 562 } 563 564 } // namespace TBDv3 565