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, Platform_iOSSim) { 368 static const char tbd_v3_platform_iossim[] = "--- !tapi-tbd-v3\n" 369 "archs: [ x86_64 ]\n" 370 "platform: ios\n" 371 "install-name: Test.dylib\n" 372 "...\n"; 373 374 auto Result = 375 TextAPIReader::get(MemoryBufferRef(tbd_v3_platform_iossim, "Test.tbd")); 376 EXPECT_TRUE(!!Result); 377 auto Platform = PlatformKind::iOSSimulator; 378 auto File = std::move(Result.get()); 379 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 380 EXPECT_EQ(File->getPlatforms().size(), 1U); 381 EXPECT_EQ(Platform, *File->getPlatforms().begin()); 382 383 SmallString<4096> Buffer; 384 raw_svector_ostream OS(Buffer); 385 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 386 EXPECT_TRUE(!WriteResult); 387 EXPECT_EQ(stripWhitespace(tbd_v3_platform_iossim), 388 stripWhitespace(Buffer.c_str())); 389 } 390 391 TEST(TBDv3, Platform_watchOSSim) { 392 static const char tbd_v3_platform_watchossim[] = "--- !tapi-tbd-v3\n" 393 "archs: [ x86_64 ]\n" 394 "platform: watchos\n" 395 "install-name: Test.dylib\n" 396 "...\n"; 397 398 auto Result = TextAPIReader::get( 399 MemoryBufferRef(tbd_v3_platform_watchossim, "Test.tbd")); 400 EXPECT_TRUE(!!Result); 401 auto Platform = PlatformKind::watchOSSimulator; 402 auto File = std::move(Result.get()); 403 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 404 EXPECT_EQ(File->getPlatforms().size(), 1U); 405 EXPECT_EQ(Platform, *File->getPlatforms().begin()); 406 407 SmallString<4096> Buffer; 408 raw_svector_ostream OS(Buffer); 409 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 410 EXPECT_TRUE(!WriteResult); 411 EXPECT_EQ(stripWhitespace(tbd_v3_platform_watchossim), 412 stripWhitespace(Buffer.c_str())); 413 } 414 415 TEST(TBDv3, Platform_tvOSSim) { 416 static const char tbd_v3_platform_tvossim[] = "--- !tapi-tbd-v3\n" 417 "archs: [ x86_64 ]\n" 418 "platform: tvos\n" 419 "install-name: Test.dylib\n" 420 "...\n"; 421 422 auto Result = 423 TextAPIReader::get(MemoryBufferRef(tbd_v3_platform_tvossim, "Test.tbd")); 424 EXPECT_TRUE(!!Result); 425 auto File = std::move(Result.get()); 426 auto Platform = PlatformKind::tvOSSimulator; 427 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 428 EXPECT_EQ(File->getPlatforms().size(), 1U); 429 EXPECT_EQ(Platform, *File->getPlatforms().begin()); 430 431 SmallString<4096> Buffer; 432 raw_svector_ostream OS(Buffer); 433 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 434 EXPECT_TRUE(!WriteResult); 435 EXPECT_EQ(stripWhitespace(tbd_v3_platform_tvossim), 436 stripWhitespace(Buffer.c_str())); 437 } 438 439 TEST(TBDv3, Swift_1_0) { 440 static const char tbd_v3_swift_1_0[] = "--- !tapi-tbd-v3\n" 441 "archs: [ arm64 ]\n" 442 "platform: ios\n" 443 "install-name: Test.dylib\n" 444 "swift-abi-version: 1.0\n" 445 "...\n"; 446 447 auto Result = 448 TextAPIReader::get(MemoryBufferRef(tbd_v3_swift_1_0, "Test.tbd")); 449 EXPECT_TRUE(!!Result); 450 auto File = std::move(Result.get()); 451 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 452 EXPECT_EQ(1U, File->getSwiftABIVersion()); 453 454 SmallString<4096> Buffer; 455 raw_svector_ostream OS(Buffer); 456 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 457 EXPECT_TRUE(!WriteResult); 458 EXPECT_EQ(stripWhitespace(tbd_v3_swift_1_0), stripWhitespace(Buffer.c_str())); 459 } 460 461 TEST(TBDv3, Swift_1_1) { 462 static const char tbd_v3_swift_1_1[] = "--- !tapi-tbd-v3\n" 463 "archs: [ arm64 ]\n" 464 "platform: ios\n" 465 "install-name: Test.dylib\n" 466 "swift-abi-version: 1.1\n" 467 "...\n"; 468 469 auto Result = 470 TextAPIReader::get(MemoryBufferRef(tbd_v3_swift_1_1, "Test.tbd")); 471 EXPECT_TRUE(!!Result); 472 auto File = std::move(Result.get()); 473 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 474 EXPECT_EQ(2U, File->getSwiftABIVersion()); 475 476 SmallString<4096> Buffer; 477 raw_svector_ostream OS(Buffer); 478 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 479 EXPECT_TRUE(!WriteResult); 480 EXPECT_EQ(stripWhitespace(tbd_v3_swift_1_1), stripWhitespace(Buffer.c_str())); 481 } 482 483 TEST(TBDv3, Swift_2_0) { 484 static const char tbd_v3_swift_2_0[] = "--- !tapi-tbd-v3\n" 485 "archs: [ arm64 ]\n" 486 "platform: ios\n" 487 "install-name: Test.dylib\n" 488 "swift-abi-version: 2.0\n" 489 "...\n"; 490 491 auto Result = 492 TextAPIReader::get(MemoryBufferRef(tbd_v3_swift_2_0, "Test.tbd")); 493 EXPECT_TRUE(!!Result); 494 auto File = std::move(Result.get()); 495 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 496 EXPECT_EQ(3U, File->getSwiftABIVersion()); 497 498 SmallString<4096> Buffer; 499 raw_svector_ostream OS(Buffer); 500 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 501 EXPECT_TRUE(!WriteResult); 502 EXPECT_EQ(stripWhitespace(tbd_v3_swift_2_0), stripWhitespace(Buffer.c_str())); 503 } 504 505 TEST(TBDv3, Swift_3_0) { 506 static const char tbd_v3_swift_3_0[] = "--- !tapi-tbd-v3\n" 507 "archs: [ arm64 ]\n" 508 "platform: ios\n" 509 "install-name: Test.dylib\n" 510 "swift-abi-version: 3.0\n" 511 "...\n"; 512 513 auto Result = 514 TextAPIReader::get(MemoryBufferRef(tbd_v3_swift_3_0, "Test.tbd")); 515 EXPECT_TRUE(!!Result); 516 auto File = std::move(Result.get()); 517 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 518 EXPECT_EQ(4U, File->getSwiftABIVersion()); 519 520 SmallString<4096> Buffer; 521 raw_svector_ostream OS(Buffer); 522 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 523 EXPECT_TRUE(!WriteResult); 524 EXPECT_EQ(stripWhitespace(tbd_v3_swift_3_0), stripWhitespace(Buffer.c_str())); 525 } 526 527 TEST(TBDv3, Swift_4_0) { 528 static const char tbd_v3_swift_4_0[] = "--- !tapi-tbd-v3\n" 529 "archs: [ arm64 ]\n" 530 "platform: ios\n" 531 "install-name: Test.dylib\n" 532 "swift-abi-version: 4.0\n" 533 "...\n"; 534 535 auto Result = 536 TextAPIReader::get(MemoryBufferRef(tbd_v3_swift_4_0, "Test.tbd")); 537 EXPECT_FALSE(!!Result); 538 auto errorMessage = toString(Result.takeError()); 539 EXPECT_EQ("malformed file\nTest.tbd:5:20: error: invalid Swift ABI " 540 "version.\nswift-abi-version: 4.0\n ^~~\n", 541 errorMessage); 542 } 543 544 TEST(TBDv3, Swift_5) { 545 static const char tbd_v3_swift_5[] = "--- !tapi-tbd-v3\n" 546 "archs: [ arm64 ]\n" 547 "platform: ios\n" 548 "install-name: Test.dylib\n" 549 "swift-abi-version: 5\n" 550 "...\n"; 551 552 auto Result = TextAPIReader::get(MemoryBufferRef(tbd_v3_swift_5, "Test.tbd")); 553 EXPECT_TRUE(!!Result); 554 auto File = std::move(Result.get()); 555 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 556 EXPECT_EQ(5U, File->getSwiftABIVersion()); 557 } 558 559 TEST(TBDv3, Swift_99) { 560 static const char tbd_v3_swift_99[] = "--- !tapi-tbd-v3\n" 561 "archs: [ arm64 ]\n" 562 "platform: ios\n" 563 "install-name: Test.dylib\n" 564 "swift-abi-version: 99\n" 565 "...\n"; 566 567 auto Result = 568 TextAPIReader::get(MemoryBufferRef(tbd_v3_swift_99, "Test.tbd")); 569 EXPECT_TRUE(!!Result); 570 auto File = std::move(Result.get()); 571 EXPECT_EQ(FileType::TBD_V3, File->getFileType()); 572 EXPECT_EQ(99U, File->getSwiftABIVersion()); 573 } 574 575 TEST(TBDv3, UnknownArchitecture) { 576 static const char tbd_v3_file_unknown_architecture[] = 577 "--- !tapi-tbd-v3\n" 578 "archs: [ foo ]\n" 579 "platform: macosx\n" 580 "install-name: Test.dylib\n" 581 "...\n"; 582 583 auto Result = TextAPIReader::get( 584 MemoryBufferRef(tbd_v3_file_unknown_architecture, "Test.tbd")); 585 EXPECT_TRUE(!!Result); 586 } 587 588 TEST(TBDv3, UnknownPlatform) { 589 static const char tbd_v3_file_unknown_platform[] = "--- !tapi-tbd-v3\n" 590 "archs: [ i386 ]\n" 591 "platform: newOS\n" 592 "...\n"; 593 594 auto Result = TextAPIReader::get( 595 MemoryBufferRef(tbd_v3_file_unknown_platform, "Test.tbd")); 596 EXPECT_FALSE(!!Result); 597 auto errorMessage = toString(Result.takeError()); 598 EXPECT_EQ("malformed file\nTest.tbd:3:11: error: unknown platform\nplatform: " 599 "newOS\n ^~~~~\n", 600 errorMessage); 601 } 602 603 TEST(TBDv3, MalformedFile1) { 604 static const char malformed_file1[] = "--- !tapi-tbd-v3\n" 605 "archs: [ arm64 ]\n" 606 "foobar: \"Unsupported key\"\n" 607 "...\n"; 608 609 auto Result = 610 TextAPIReader::get(MemoryBufferRef(malformed_file1, "Test.tbd")); 611 EXPECT_FALSE(!!Result); 612 auto errorMessage = toString(Result.takeError()); 613 ASSERT_EQ("malformed file\nTest.tbd:2:1: error: missing required key " 614 "'platform'\narchs: [ arm64 ]\n^\n", 615 errorMessage); 616 } 617 618 TEST(TBDv3, MalformedFile2) { 619 static const char malformed_file2[] = "--- !tapi-tbd-v3\n" 620 "archs: [ arm64 ]\n" 621 "platform: ios\n" 622 "install-name: Test.dylib\n" 623 "foobar: \"Unsupported key\"\n" 624 "...\n"; 625 626 auto Result = 627 TextAPIReader::get(MemoryBufferRef(malformed_file2, "Test.tbd")); 628 EXPECT_FALSE(!!Result); 629 auto errorMessage = toString(Result.takeError()); 630 ASSERT_EQ( 631 "malformed file\nTest.tbd:5:9: error: unknown key 'foobar'\nfoobar: " 632 "\"Unsupported key\"\n ^~~~~~~~~~~~~~~~~\n", 633 errorMessage); 634 } 635 636 } // namespace TBDv3 637