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(ExportedSymbol{Sym->getKind(), Sym->getName(), 133 Sym->isWeakDefined(), 134 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 // It's not currently possible to emit the iomac platform. Enable this once 333 // that's fixed. 334 #if 0 335 SmallString<4096> Buffer; 336 raw_svector_ostream OS(Buffer); 337 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 338 EXPECT_TRUE(!WriteResult); 339 EXPECT_EQ(stripWhitespace(tbd_v3_platform_iosmac), stripWhitespace(Buffer.c_str())); 340 #endif 341 } 342 343 TEST(TBDv3, Platform_zippered) { 344 static const char tbd_v3_platform_zip[] = "--- !tapi-tbd-v3\n" 345 "archs: [ armv7k ]\n" 346 "platform: zippered\n" 347 "install-name: Test.dylib\n" 348 "...\n"; 349 350 auto Result = 351 TextAPIReader::get(MemoryBufferRef(tbd_v3_platform_zip, "Test.tbd")); 352 EXPECT_TRUE(!!Result); 353 auto File = std::move(Result.get()); 354 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 355 356 PlatformSet Platforms; 357 Platforms.insert(PlatformKind::macOS); 358 Platforms.insert(PlatformKind::macCatalyst); 359 EXPECT_EQ(Platforms.size(), File->getPlatforms().size()); 360 for (auto Platform : File->getPlatforms()) 361 EXPECT_EQ(Platforms.count(Platform), 1U); 362 363 SmallString<4096> Buffer; 364 raw_svector_ostream OS(Buffer); 365 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 366 EXPECT_TRUE(!WriteResult); 367 EXPECT_EQ(stripWhitespace(tbd_v3_platform_zip), 368 stripWhitespace(Buffer.c_str())); 369 } 370 371 TEST(TBDv3, Swift_1_0) { 372 static const char tbd_v3_swift_1_0[] = "--- !tapi-tbd-v3\n" 373 "archs: [ arm64 ]\n" 374 "platform: ios\n" 375 "install-name: Test.dylib\n" 376 "swift-abi-version: 1.0\n" 377 "...\n"; 378 379 auto Result = 380 TextAPIReader::get(MemoryBufferRef(tbd_v3_swift_1_0, "Test.tbd")); 381 EXPECT_TRUE(!!Result); 382 auto File = std::move(Result.get()); 383 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 384 EXPECT_EQ(1U, File->getSwiftABIVersion()); 385 386 SmallString<4096> Buffer; 387 raw_svector_ostream OS(Buffer); 388 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 389 EXPECT_TRUE(!WriteResult); 390 EXPECT_EQ(stripWhitespace(tbd_v3_swift_1_0), stripWhitespace(Buffer.c_str())); 391 } 392 393 TEST(TBDv3, Swift_1_1) { 394 static const char tbd_v3_swift_1_1[] = "--- !tapi-tbd-v3\n" 395 "archs: [ arm64 ]\n" 396 "platform: ios\n" 397 "install-name: Test.dylib\n" 398 "swift-abi-version: 1.1\n" 399 "...\n"; 400 401 auto Result = 402 TextAPIReader::get(MemoryBufferRef(tbd_v3_swift_1_1, "Test.tbd")); 403 EXPECT_TRUE(!!Result); 404 auto File = std::move(Result.get()); 405 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 406 EXPECT_EQ(2U, File->getSwiftABIVersion()); 407 408 SmallString<4096> Buffer; 409 raw_svector_ostream OS(Buffer); 410 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 411 EXPECT_TRUE(!WriteResult); 412 EXPECT_EQ(stripWhitespace(tbd_v3_swift_1_1), stripWhitespace(Buffer.c_str())); 413 } 414 415 TEST(TBDv3, Swift_2_0) { 416 static const char tbd_v3_swift_2_0[] = "--- !tapi-tbd-v3\n" 417 "archs: [ arm64 ]\n" 418 "platform: ios\n" 419 "install-name: Test.dylib\n" 420 "swift-abi-version: 2.0\n" 421 "...\n"; 422 423 auto Result = 424 TextAPIReader::get(MemoryBufferRef(tbd_v3_swift_2_0, "Test.tbd")); 425 EXPECT_TRUE(!!Result); 426 auto File = std::move(Result.get()); 427 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 428 EXPECT_EQ(3U, File->getSwiftABIVersion()); 429 430 SmallString<4096> Buffer; 431 raw_svector_ostream OS(Buffer); 432 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 433 EXPECT_TRUE(!WriteResult); 434 EXPECT_EQ(stripWhitespace(tbd_v3_swift_2_0), stripWhitespace(Buffer.c_str())); 435 } 436 437 TEST(TBDv3, Swift_3_0) { 438 static const char tbd_v3_swift_3_0[] = "--- !tapi-tbd-v3\n" 439 "archs: [ arm64 ]\n" 440 "platform: ios\n" 441 "install-name: Test.dylib\n" 442 "swift-abi-version: 3.0\n" 443 "...\n"; 444 445 auto Result = 446 TextAPIReader::get(MemoryBufferRef(tbd_v3_swift_3_0, "Test.tbd")); 447 EXPECT_TRUE(!!Result); 448 auto File = std::move(Result.get()); 449 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 450 EXPECT_EQ(4U, File->getSwiftABIVersion()); 451 452 SmallString<4096> Buffer; 453 raw_svector_ostream OS(Buffer); 454 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 455 EXPECT_TRUE(!WriteResult); 456 EXPECT_EQ(stripWhitespace(tbd_v3_swift_3_0), stripWhitespace(Buffer.c_str())); 457 } 458 459 TEST(TBDv3, Swift_4_0) { 460 static const char tbd_v3_swift_4_0[] = "--- !tapi-tbd-v3\n" 461 "archs: [ arm64 ]\n" 462 "platform: ios\n" 463 "install-name: Test.dylib\n" 464 "swift-abi-version: 4.0\n" 465 "...\n"; 466 467 auto Result = 468 TextAPIReader::get(MemoryBufferRef(tbd_v3_swift_4_0, "Test.tbd")); 469 EXPECT_FALSE(!!Result); 470 auto errorMessage = toString(Result.takeError()); 471 EXPECT_EQ("malformed file\nTest.tbd:5:20: error: invalid Swift ABI " 472 "version.\nswift-abi-version: 4.0\n ^~~\n", 473 errorMessage); 474 } 475 476 TEST(TBDv3, Swift_5) { 477 static const char tbd_v3_swift_5[] = "--- !tapi-tbd-v3\n" 478 "archs: [ arm64 ]\n" 479 "platform: ios\n" 480 "install-name: Test.dylib\n" 481 "swift-abi-version: 5\n" 482 "...\n"; 483 484 auto Result = TextAPIReader::get(MemoryBufferRef(tbd_v3_swift_5, "Test.tbd")); 485 EXPECT_TRUE(!!Result); 486 auto File = std::move(Result.get()); 487 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 488 EXPECT_EQ(5U, File->getSwiftABIVersion()); 489 } 490 491 TEST(TBDv3, Swift_99) { 492 static const char tbd_v3_swift_99[] = "--- !tapi-tbd-v3\n" 493 "archs: [ arm64 ]\n" 494 "platform: ios\n" 495 "install-name: Test.dylib\n" 496 "swift-abi-version: 99\n" 497 "...\n"; 498 499 auto Result = 500 TextAPIReader::get(MemoryBufferRef(tbd_v3_swift_99, "Test.tbd")); 501 EXPECT_TRUE(!!Result); 502 auto File = std::move(Result.get()); 503 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 504 EXPECT_EQ(99U, File->getSwiftABIVersion()); 505 } 506 507 TEST(TBDv3, UnknownArchitecture) { 508 static const char tbd_v3_file_unknown_architecture[] = 509 "--- !tapi-tbd-v3\n" 510 "archs: [ foo ]\n" 511 "platform: macosx\n" 512 "install-name: Test.dylib\n" 513 "...\n"; 514 515 auto Result = TextAPIReader::get( 516 MemoryBufferRef(tbd_v3_file_unknown_architecture, "Test.tbd")); 517 EXPECT_TRUE(!!Result); 518 } 519 520 TEST(TBDv3, UnknownPlatform) { 521 static const char tbd_v3_file_unknown_platform[] = "--- !tapi-tbd-v3\n" 522 "archs: [ i386 ]\n" 523 "platform: newOS\n" 524 "...\n"; 525 526 auto Result = TextAPIReader::get( 527 MemoryBufferRef(tbd_v3_file_unknown_platform, "Test.tbd")); 528 EXPECT_FALSE(!!Result); 529 auto errorMessage = toString(Result.takeError()); 530 EXPECT_EQ("malformed file\nTest.tbd:3:11: error: unknown platform\nplatform: " 531 "newOS\n ^~~~~\n", 532 errorMessage); 533 } 534 535 TEST(TBDv3, MalformedFile1) { 536 static const char malformed_file1[] = "--- !tapi-tbd-v3\n" 537 "archs: [ arm64 ]\n" 538 "foobar: \"Unsupported key\"\n" 539 "...\n"; 540 541 auto Result = 542 TextAPIReader::get(MemoryBufferRef(malformed_file1, "Test.tbd")); 543 EXPECT_FALSE(!!Result); 544 auto errorMessage = toString(Result.takeError()); 545 ASSERT_EQ("malformed file\nTest.tbd:2:1: error: missing required key " 546 "'platform'\narchs: [ arm64 ]\n^\n", 547 errorMessage); 548 } 549 550 TEST(TBDv3, MalformedFile2) { 551 static const char malformed_file2[] = "--- !tapi-tbd-v3\n" 552 "archs: [ arm64 ]\n" 553 "platform: ios\n" 554 "install-name: Test.dylib\n" 555 "foobar: \"Unsupported key\"\n" 556 "...\n"; 557 558 auto Result = 559 TextAPIReader::get(MemoryBufferRef(malformed_file2, "Test.tbd")); 560 EXPECT_FALSE(!!Result); 561 auto errorMessage = toString(Result.takeError()); 562 ASSERT_EQ( 563 "malformed file\nTest.tbd:5:9: error: unknown key 'foobar'\nfoobar: " 564 "\"Unsupported key\"\n ^~~~~~~~~~~~~~~~~\n", 565 errorMessage); 566 } 567 568 } // namespace TBDv3 569