1 //===-- TextStubV4Tests.cpp - TBD V4 File Test ----------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===-----------------------------------------------------------------------===/ 8 #include "llvm/TextAPI/MachO/InterfaceFile.h" 9 #include "llvm/TextAPI/MachO/TextAPIReader.h" 10 #include "llvm/TextAPI/MachO/TextAPIWriter.h" 11 #include "gtest/gtest.h" 12 #include <string> 13 #include <vector> 14 15 using namespace llvm; 16 using namespace llvm::MachO; 17 18 struct ExampleSymbol { 19 SymbolKind Kind; 20 std::string Name; 21 bool WeakDefined; 22 bool ThreadLocalValue; 23 }; 24 using ExampleSymbolSeq = std::vector<ExampleSymbol>; 25 using UUIDs = std::vector<std::pair<Target, std::string>>; 26 27 inline bool operator<(const ExampleSymbol &LHS, const ExampleSymbol &RHS) { 28 return std::tie(LHS.Kind, LHS.Name) < std::tie(RHS.Kind, RHS.Name); 29 } 30 31 inline bool operator==(const ExampleSymbol &LHS, const ExampleSymbol &RHS) { 32 return std::tie(LHS.Kind, LHS.Name, LHS.WeakDefined, LHS.ThreadLocalValue) == 33 std::tie(RHS.Kind, RHS.Name, RHS.WeakDefined, RHS.ThreadLocalValue); 34 } 35 36 inline std::string stripWhitespace(std::string s) { 37 s.erase(std::remove_if(s.begin(), s.end(), ::isspace), s.end()); 38 return s; 39 } 40 41 static ExampleSymbol TBDv4ExportedSymbols[] = { 42 {SymbolKind::GlobalSymbol, "_symA", false, false}, 43 {SymbolKind::GlobalSymbol, "_symAB", false, false}, 44 {SymbolKind::GlobalSymbol, "_symB", false, false}, 45 }; 46 47 static ExampleSymbol TBDv4ReexportedSymbols[] = { 48 {SymbolKind::GlobalSymbol, "_symC", false, false}, 49 }; 50 51 static ExampleSymbol TBDv4UndefinedSymbols[] = { 52 {SymbolKind::GlobalSymbol, "_symD", false, false}, 53 }; 54 55 namespace TBDv4 { 56 57 TEST(TBDv4, ReadFile) { 58 static const char tbd_v4_file[] = 59 "--- !tapi-tbd\n" 60 "tbd-version: 4\n" 61 "targets: [ i386-macos, x86_64-macos, x86_64-ios ]\n" 62 "uuids:\n" 63 " - target: i386-macos\n" 64 " value: 00000000-0000-0000-0000-000000000000\n" 65 " - target: x86_64-macos\n" 66 " value: 11111111-1111-1111-1111-111111111111\n" 67 " - target: x86_64-ios\n" 68 " value: 11111111-1111-1111-1111-111111111111\n" 69 "flags: [ flat_namespace, installapi ]\n" 70 "install-name: Umbrella.framework/Umbrella\n" 71 "current-version: 1.2.3\n" 72 "compatibility-version: 1.2\n" 73 "swift-abi-version: 5\n" 74 "parent-umbrella:\n" 75 " - targets: [ i386-macos, x86_64-macos, x86_64-ios ]\n" 76 " umbrella: System\n" 77 "allowable-clients:\n" 78 " - targets: [ i386-macos, x86_64-macos, x86_64-ios ]\n" 79 " clients: [ ClientA ]\n" 80 "reexported-libraries:\n" 81 " - targets: [ i386-macos ]\n" 82 " libraries: [ /System/Library/Frameworks/A.framework/A ]\n" 83 "exports:\n" 84 " - targets: [ i386-macos ]\n" 85 " symbols: [ _symA ]\n" 86 " objc-classes: []\n" 87 " objc-eh-types: []\n" 88 " objc-ivars: []\n" 89 " weak-symbols: []\n" 90 " thread-local-symbols: []\n" 91 " - targets: [ x86_64-ios ]\n" 92 " symbols: [_symB]\n" 93 " - targets: [ x86_64-macos, x86_64-ios ]\n" 94 " symbols: [_symAB]\n" 95 "reexports:\n" 96 " - targets: [ i386-macos ]\n" 97 " symbols: [_symC]\n" 98 " objc-classes: []\n" 99 " objc-eh-types: []\n" 100 " objc-ivars: []\n" 101 " weak-symbols: []\n" 102 " thread-local-symbols: []\n" 103 "undefineds:\n" 104 " - targets: [ i386-macos ]\n" 105 " symbols: [ _symD ]\n" 106 " objc-classes: []\n" 107 " objc-eh-types: []\n" 108 " objc-ivars: []\n" 109 " weak-symbols: []\n" 110 " thread-local-symbols: []\n" 111 "...\n"; 112 113 auto Result = TextAPIReader::get(MemoryBufferRef(tbd_v4_file, "Test.tbd")); 114 EXPECT_TRUE(!!Result); 115 auto File = std::move(Result.get()); 116 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 117 PlatformSet Platforms; 118 Platforms.insert(PlatformKind::macOS); 119 Platforms.insert(PlatformKind::iOS); 120 auto Archs = AK_i386 | AK_x86_64; 121 TargetList Targets = { 122 Target(AK_i386, PlatformKind::macOS), 123 Target(AK_x86_64, PlatformKind::macOS), 124 Target(AK_x86_64, PlatformKind::iOS), 125 }; 126 UUIDs uuids = {{Targets[0], "00000000-0000-0000-0000-000000000000"}, 127 {Targets[1], "11111111-1111-1111-1111-111111111111"}, 128 {Targets[2], "11111111-1111-1111-1111-111111111111"}}; 129 EXPECT_EQ(Archs, File->getArchitectures()); 130 EXPECT_EQ(uuids, File->uuids()); 131 EXPECT_EQ(Platforms.size(), File->getPlatforms().size()); 132 for (auto Platform : File->getPlatforms()) 133 EXPECT_EQ(Platforms.count(Platform), 1U); 134 EXPECT_EQ(std::string("Umbrella.framework/Umbrella"), File->getInstallName()); 135 EXPECT_EQ(PackedVersion(1, 2, 3), File->getCurrentVersion()); 136 EXPECT_EQ(PackedVersion(1, 2, 0), File->getCompatibilityVersion()); 137 EXPECT_EQ(5U, File->getSwiftABIVersion()); 138 EXPECT_FALSE(File->isTwoLevelNamespace()); 139 EXPECT_TRUE(File->isApplicationExtensionSafe()); 140 EXPECT_TRUE(File->isInstallAPI()); 141 InterfaceFileRef client("ClientA", Targets); 142 InterfaceFileRef reexport("/System/Library/Frameworks/A.framework/A", 143 {Targets[0]}); 144 EXPECT_EQ(1U, File->allowableClients().size()); 145 EXPECT_EQ(client, File->allowableClients().front()); 146 EXPECT_EQ(1U, File->reexportedLibraries().size()); 147 EXPECT_EQ(reexport, File->reexportedLibraries().front()); 148 149 ExampleSymbolSeq Exports, Reexports, Undefineds; 150 ExampleSymbol temp; 151 for (const auto *Sym : File->symbols()) { 152 temp = ExampleSymbol{Sym->getKind(), std::string(Sym->getName()), 153 Sym->isWeakDefined(), Sym->isThreadLocalValue()}; 154 EXPECT_FALSE(Sym->isWeakReferenced()); 155 if (Sym->isUndefined()) 156 Undefineds.emplace_back(std::move(temp)); 157 else 158 Sym->isReexported() ? Reexports.emplace_back(std::move(temp)) 159 : Exports.emplace_back(std::move(temp)); 160 } 161 llvm::sort(Exports.begin(), Exports.end()); 162 llvm::sort(Reexports.begin(), Reexports.end()); 163 llvm::sort(Undefineds.begin(), Undefineds.end()); 164 165 EXPECT_EQ(sizeof(TBDv4ExportedSymbols) / sizeof(ExampleSymbol), 166 Exports.size()); 167 EXPECT_EQ(sizeof(TBDv4ReexportedSymbols) / sizeof(ExampleSymbol), 168 Reexports.size()); 169 EXPECT_EQ(sizeof(TBDv4UndefinedSymbols) / sizeof(ExampleSymbol), 170 Undefineds.size()); 171 EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(), 172 std::begin(TBDv4ExportedSymbols))); 173 EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(), 174 std::begin(TBDv4ReexportedSymbols))); 175 EXPECT_TRUE(std::equal(Undefineds.begin(), Undefineds.end(), 176 std::begin(TBDv4UndefinedSymbols))); 177 } 178 179 TEST(TBDv4, WriteFile) { 180 static const char tbd_v4_file[] = 181 "--- !tapi-tbd\n" 182 "tbd-version: 4\n" 183 "targets: [ i386-macos, x86_64-ios-simulator ]\n" 184 "uuids:\n" 185 " - target: i386-macos\n" 186 " value: 00000000-0000-0000-0000-000000000000\n" 187 " - target: x86_64-ios-simulator\n" 188 " value: 11111111-1111-1111-1111-111111111111\n" 189 "flags: [ installapi ]\n" 190 "install-name: 'Umbrella.framework/Umbrella'\n" 191 "current-version: 1.2.3\n" 192 "compatibility-version: 0\n" 193 "swift-abi-version: 5\n" 194 "parent-umbrella:\n" 195 " - targets: [ i386-macos, x86_64-ios-simulator ]\n" 196 " umbrella: System\n" 197 "allowable-clients:\n" 198 " - targets: [ i386-macos ]\n" 199 " clients: [ ClientA ]\n" 200 "exports:\n" 201 " - targets: [ i386-macos ]\n" 202 " symbols: [ _symA ]\n" 203 " objc-classes: [ Class1 ]\n" 204 " weak-symbols: [ _symC ]\n" 205 " - targets: [ x86_64-ios-simulator ]\n" 206 " symbols: [ _symB ]\n" 207 "...\n"; 208 209 InterfaceFile File; 210 TargetList Targets = { 211 Target(AK_i386, PlatformKind::macOS), 212 Target(AK_x86_64, PlatformKind::iOSSimulator), 213 }; 214 UUIDs uuids = {{Targets[0], "00000000-0000-0000-0000-000000000000"}, 215 {Targets[1], "11111111-1111-1111-1111-111111111111"}}; 216 File.setInstallName("Umbrella.framework/Umbrella"); 217 File.setFileType(FileType::TBD_V4); 218 File.addTargets(Targets); 219 File.addUUID(uuids[0].first, uuids[0].second); 220 File.addUUID(uuids[1].first, uuids[1].second); 221 File.setCurrentVersion(PackedVersion(1, 2, 3)); 222 File.setTwoLevelNamespace(); 223 File.setInstallAPI(true); 224 File.setApplicationExtensionSafe(true); 225 File.setSwiftABIVersion(5); 226 File.addAllowableClient("ClientA", Targets[0]); 227 File.addParentUmbrella(Targets[0], "System"); 228 File.addParentUmbrella(Targets[1], "System"); 229 File.addSymbol(SymbolKind::GlobalSymbol, "_symA", {Targets[0]}); 230 File.addSymbol(SymbolKind::GlobalSymbol, "_symB", {Targets[1]}); 231 File.addSymbol(SymbolKind::GlobalSymbol, "_symC", {Targets[0]}, 232 SymbolFlags::WeakDefined); 233 File.addSymbol(SymbolKind::ObjectiveCClass, "Class1", {Targets[0]}); 234 235 SmallString<4096> Buffer; 236 raw_svector_ostream OS(Buffer); 237 auto Result = TextAPIWriter::writeToStream(OS, File); 238 EXPECT_FALSE(Result); 239 EXPECT_STREQ(tbd_v4_file, Buffer.c_str()); 240 } 241 242 TEST(TBDv4, MultipleTargets) { 243 static const char tbd_multiple_targets[] = 244 "--- !tapi-tbd\n" 245 "tbd-version: 4\n" 246 "targets: [ i386-maccatalyst, x86_64-tvos, arm64-ios ]\n" 247 "install-name: Test.dylib\n" 248 "...\n"; 249 250 auto Result = 251 TextAPIReader::get(MemoryBufferRef(tbd_multiple_targets, "Test.tbd")); 252 EXPECT_TRUE(!!Result); 253 PlatformSet Platforms; 254 Platforms.insert(PlatformKind::macCatalyst); 255 Platforms.insert(PlatformKind::tvOS); 256 Platforms.insert(PlatformKind::iOS); 257 auto File = std::move(Result.get()); 258 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 259 EXPECT_EQ(AK_x86_64 | AK_arm64 | AK_i386, File->getArchitectures()); 260 EXPECT_EQ(Platforms.size(), File->getPlatforms().size()); 261 for (auto Platform : File->getPlatforms()) 262 EXPECT_EQ(Platforms.count(Platform), 1U); 263 264 SmallString<4096> Buffer; 265 raw_svector_ostream OS(Buffer); 266 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 267 EXPECT_TRUE(!WriteResult); 268 EXPECT_EQ(stripWhitespace(tbd_multiple_targets), 269 stripWhitespace(Buffer.c_str())); 270 } 271 272 TEST(TBDv4, MultipleTargetsSameArch) { 273 static const char tbd_targets_same_arch[] = 274 "--- !tapi-tbd\n" 275 "tbd-version: 4\n" 276 "targets: [ x86_64-tvos , x86_64-maccatalyst ]\n" 277 "install-name: Test.dylib\n" 278 "...\n"; 279 280 auto Result = 281 TextAPIReader::get(MemoryBufferRef(tbd_targets_same_arch, "Test.tbd")); 282 EXPECT_TRUE(!!Result); 283 PlatformSet Platforms; 284 Platforms.insert(PlatformKind::tvOS); 285 Platforms.insert(PlatformKind::macCatalyst); 286 auto File = std::move(Result.get()); 287 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 288 EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures()); 289 EXPECT_EQ(Platforms.size(), File->getPlatforms().size()); 290 for (auto Platform : File->getPlatforms()) 291 EXPECT_EQ(Platforms.count(Platform), 1U); 292 293 SmallString<4096> Buffer; 294 raw_svector_ostream OS(Buffer); 295 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 296 EXPECT_TRUE(!WriteResult); 297 EXPECT_EQ(stripWhitespace(tbd_targets_same_arch), 298 stripWhitespace(Buffer.c_str())); 299 } 300 301 TEST(TBDv4, MultipleTargetsSamePlatform) { 302 static const char tbd_multiple_targets_same_platform[] = 303 "--- !tapi-tbd\n" 304 "tbd-version: 4\n" 305 "targets: [ armv7k-ios , arm64-ios]\n" 306 "install-name: Test.dylib\n" 307 "...\n"; 308 309 auto Result = TextAPIReader::get( 310 MemoryBufferRef(tbd_multiple_targets_same_platform, "Test.tbd")); 311 EXPECT_TRUE(!!Result); 312 auto File = std::move(Result.get()); 313 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 314 EXPECT_EQ(AK_arm64 | AK_armv7k, File->getArchitectures()); 315 EXPECT_EQ(File->getPlatforms().size(), 1U); 316 EXPECT_EQ(PlatformKind::iOS, *File->getPlatforms().begin()); 317 318 SmallString<4096> Buffer; 319 raw_svector_ostream OS(Buffer); 320 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 321 EXPECT_TRUE(!WriteResult); 322 EXPECT_EQ(stripWhitespace(tbd_multiple_targets_same_platform), 323 stripWhitespace(Buffer.c_str())); 324 } 325 326 TEST(TBDv4, Target_maccatalyst) { 327 static const char tbd_target_maccatalyst[] = 328 "--- !tapi-tbd\n" 329 "tbd-version: 4\n" 330 "targets: [ x86_64-maccatalyst ]\n" 331 "install-name: Test.dylib\n" 332 "...\n"; 333 334 auto Result = 335 TextAPIReader::get(MemoryBufferRef(tbd_target_maccatalyst, "Test.tbd")); 336 EXPECT_TRUE(!!Result); 337 auto File = std::move(Result.get()); 338 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 339 EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures()); 340 EXPECT_EQ(File->getPlatforms().size(), 1U); 341 EXPECT_EQ(PlatformKind::macCatalyst, *File->getPlatforms().begin()); 342 343 SmallString<4096> Buffer; 344 raw_svector_ostream OS(Buffer); 345 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 346 EXPECT_TRUE(!WriteResult); 347 EXPECT_EQ(stripWhitespace(tbd_target_maccatalyst), 348 stripWhitespace(Buffer.c_str())); 349 } 350 351 TEST(TBDv4, Target_x86_ios) { 352 static const char tbd_target_x86_ios[] = "--- !tapi-tbd\n" 353 "tbd-version: 4\n" 354 "targets: [ x86_64-ios ]\n" 355 "install-name: Test.dylib\n" 356 "...\n"; 357 358 auto Result = 359 TextAPIReader::get(MemoryBufferRef(tbd_target_x86_ios, "Test.tbd")); 360 EXPECT_TRUE(!!Result); 361 auto File = std::move(Result.get()); 362 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 363 EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures()); 364 EXPECT_EQ(File->getPlatforms().size(), 1U); 365 EXPECT_EQ(PlatformKind::iOS, *File->getPlatforms().begin()); 366 367 SmallString<4096> Buffer; 368 raw_svector_ostream OS(Buffer); 369 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 370 EXPECT_TRUE(!WriteResult); 371 EXPECT_EQ(stripWhitespace(tbd_target_x86_ios), 372 stripWhitespace(Buffer.c_str())); 373 } 374 375 TEST(TBDv4, Target_arm_bridgeOS) { 376 static const char tbd_platform_bridgeos[] = "--- !tapi-tbd\n" 377 "tbd-version: 4\n" 378 "targets: [ armv7k-bridgeos ]\n" 379 "install-name: Test.dylib\n" 380 "...\n"; 381 382 auto Result = 383 TextAPIReader::get(MemoryBufferRef(tbd_platform_bridgeos, "Test.tbd")); 384 EXPECT_TRUE(!!Result); 385 auto File = std::move(Result.get()); 386 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 387 EXPECT_EQ(File->getPlatforms().size(), 1U); 388 EXPECT_EQ(PlatformKind::bridgeOS, *File->getPlatforms().begin()); 389 EXPECT_EQ(ArchitectureSet(AK_armv7k), File->getArchitectures()); 390 391 SmallString<4096> Buffer; 392 raw_svector_ostream OS(Buffer); 393 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 394 EXPECT_TRUE(!WriteResult); 395 EXPECT_EQ(stripWhitespace(tbd_platform_bridgeos), 396 stripWhitespace(Buffer.c_str())); 397 } 398 399 TEST(TBDv4, Target_x86_macos) { 400 static const char tbd_x86_macos[] = "--- !tapi-tbd\n" 401 "tbd-version: 4\n" 402 "targets: [ x86_64-macos ]\n" 403 "install-name: Test.dylib\n" 404 "...\n"; 405 406 auto Result = TextAPIReader::get(MemoryBufferRef(tbd_x86_macos, "Test.tbd")); 407 EXPECT_TRUE(!!Result); 408 auto File = std::move(Result.get()); 409 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 410 EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures()); 411 EXPECT_EQ(File->getPlatforms().size(), 1U); 412 EXPECT_EQ(PlatformKind::macOS, *File->getPlatforms().begin()); 413 414 SmallString<4096> Buffer; 415 raw_svector_ostream OS(Buffer); 416 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 417 EXPECT_TRUE(!WriteResult); 418 EXPECT_EQ(stripWhitespace(tbd_x86_macos), stripWhitespace(Buffer.c_str())); 419 } 420 421 TEST(TBDv4, Target_x86_ios_simulator) { 422 static const char tbd_x86_ios_sim[] = "--- !tapi-tbd\n" 423 "tbd-version: 4\n" 424 "targets: [ x86_64-ios-simulator ]\n" 425 "install-name: Test.dylib\n" 426 "...\n"; 427 428 auto Result = 429 TextAPIReader::get(MemoryBufferRef(tbd_x86_ios_sim, "Test.tbd")); 430 EXPECT_TRUE(!!Result); 431 auto File = std::move(Result.get()); 432 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 433 EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures()); 434 EXPECT_EQ(File->getPlatforms().size(), 1U); 435 EXPECT_EQ(PlatformKind::iOSSimulator, *File->getPlatforms().begin()); 436 437 SmallString<4096> Buffer; 438 raw_svector_ostream OS(Buffer); 439 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 440 EXPECT_TRUE(!WriteResult); 441 EXPECT_EQ(stripWhitespace(tbd_x86_ios_sim), stripWhitespace(Buffer.c_str())); 442 } 443 444 TEST(TBDv4, Target_x86_tvos_simulator) { 445 static const char tbd_x86_tvos_sim[] = 446 "--- !tapi-tbd\n" 447 "tbd-version: 4\n" 448 "targets: [ x86_64-tvos-simulator ]\n" 449 "install-name: Test.dylib\n" 450 "...\n"; 451 452 auto Result = 453 TextAPIReader::get(MemoryBufferRef(tbd_x86_tvos_sim, "Test.tbd")); 454 EXPECT_TRUE(!!Result); 455 auto File = std::move(Result.get()); 456 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 457 EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures()); 458 EXPECT_EQ(File->getPlatforms().size(), 1U); 459 EXPECT_EQ(PlatformKind::tvOSSimulator, *File->getPlatforms().begin()); 460 461 SmallString<4096> Buffer; 462 raw_svector_ostream OS(Buffer); 463 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 464 EXPECT_TRUE(!WriteResult); 465 EXPECT_EQ(stripWhitespace(tbd_x86_tvos_sim), stripWhitespace(Buffer.c_str())); 466 } 467 468 TEST(TBDv4, Target_i386_watchos_simulator) { 469 static const char tbd_i386_watchos_sim[] = 470 "--- !tapi-tbd\n" 471 "tbd-version: 4\n" 472 "targets: [ i386-watchos-simulator ]\n" 473 "install-name: Test.dylib\n" 474 "...\n"; 475 476 auto Result = 477 TextAPIReader::get(MemoryBufferRef(tbd_i386_watchos_sim, "Test.tbd")); 478 EXPECT_TRUE(!!Result); 479 auto File = std::move(Result.get()); 480 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 481 EXPECT_EQ(ArchitectureSet(AK_i386), File->getArchitectures()); 482 EXPECT_EQ(File->getPlatforms().size(), 1U); 483 EXPECT_EQ(PlatformKind::watchOSSimulator, *File->getPlatforms().begin()); 484 485 SmallString<4096> Buffer; 486 raw_svector_ostream OS(Buffer); 487 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 488 EXPECT_TRUE(!WriteResult); 489 EXPECT_EQ(stripWhitespace(tbd_i386_watchos_sim), 490 stripWhitespace(Buffer.c_str())); 491 } 492 493 TEST(TBDv4, Swift_1) { 494 static const char tbd_swift_1[] = "--- !tapi-tbd\n" 495 "tbd-version: 4\n" 496 "targets: [ x86_64-macos ]\n" 497 "install-name: Test.dylib\n" 498 "swift-abi-version: 1\n" 499 "...\n"; 500 501 auto Result = TextAPIReader::get(MemoryBufferRef(tbd_swift_1, "Test.tbd")); 502 EXPECT_TRUE(!!Result); 503 auto File = std::move(Result.get()); 504 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 505 EXPECT_EQ(1U, File->getSwiftABIVersion()); 506 507 // No writer test because we emit "swift-abi-version:1.0". 508 } 509 510 TEST(TBDv4, Swift_2) { 511 static const char tbd_v4_swift_2[] = "--- !tapi-tbd\n" 512 "tbd-version: 4\n" 513 "targets: [ x86_64-macos ]\n" 514 "install-name: Test.dylib\n" 515 "swift-abi-version: 2\n" 516 "...\n"; 517 518 auto Result = TextAPIReader::get(MemoryBufferRef(tbd_v4_swift_2, "Test.tbd")); 519 EXPECT_TRUE(!!Result); 520 auto File = std::move(Result.get()); 521 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 522 EXPECT_EQ(2U, File->getSwiftABIVersion()); 523 524 // No writer test because we emit "swift-abi-version:2.0". 525 } 526 527 TEST(TBDv4, Swift_5) { 528 static const char tbd_swift_5[] = "--- !tapi-tbd\n" 529 "tbd-version: 4\n" 530 "targets: [ x86_64-macos ]\n" 531 "install-name: Test.dylib\n" 532 "swift-abi-version: 5\n" 533 "...\n"; 534 535 auto Result = TextAPIReader::get(MemoryBufferRef(tbd_swift_5, "Test.tbd")); 536 EXPECT_TRUE(!!Result); 537 auto File = std::move(Result.get()); 538 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 539 EXPECT_EQ(5U, File->getSwiftABIVersion()); 540 541 SmallString<4096> Buffer; 542 raw_svector_ostream OS(Buffer); 543 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 544 EXPECT_TRUE(!WriteResult); 545 EXPECT_EQ(stripWhitespace(tbd_swift_5), stripWhitespace(Buffer.c_str())); 546 } 547 548 TEST(TBDv4, Swift_99) { 549 static const char tbd_swift_99[] = "--- !tapi-tbd\n" 550 "tbd-version: 4\n" 551 "targets: [ x86_64-macos ]\n" 552 "install-name: Test.dylib\n" 553 "swift-abi-version: 99\n" 554 "...\n"; 555 556 auto Result = TextAPIReader::get(MemoryBufferRef(tbd_swift_99, "Test.tbd")); 557 EXPECT_TRUE(!!Result); 558 auto File = std::move(Result.get()); 559 EXPECT_EQ(FileType::TBD_V4, File->getFileType()); 560 EXPECT_EQ(99U, File->getSwiftABIVersion()); 561 562 SmallString<4096> Buffer; 563 raw_svector_ostream OS(Buffer); 564 auto WriteResult = TextAPIWriter::writeToStream(OS, *File); 565 EXPECT_TRUE(!WriteResult); 566 EXPECT_EQ(stripWhitespace(tbd_swift_99), stripWhitespace(Buffer.c_str())); 567 } 568 569 TEST(TBDv4, InvalidArchitecture) { 570 static const char tbd_file_unknown_architecture[] = 571 "--- !tapi-tbd\n" 572 "tbd-version: 4\n" 573 "targets: [ foo-macos ]\n" 574 "install-name: Test.dylib\n" 575 "...\n"; 576 577 auto Result = TextAPIReader::get( 578 MemoryBufferRef(tbd_file_unknown_architecture, "Test.tbd")); 579 EXPECT_FALSE(!!Result); 580 auto errorMessage = toString(Result.takeError()); 581 EXPECT_EQ("malformed file\nTest.tbd:3:12: error: unknown " 582 "architecture\ntargets: [ foo-macos ]\n" 583 " ^~~~~~~~~~\n", 584 errorMessage); 585 } 586 587 TEST(TBDv4, InvalidPlatform) { 588 static const char tbd_file_invalid_platform[] = "--- !tapi-tbd\n" 589 "tbd-version: 4\n" 590 "targets: [ x86_64-maos ]\n" 591 "install-name: Test.dylib\n" 592 "...\n"; 593 594 auto Result = TextAPIReader::get( 595 MemoryBufferRef(tbd_file_invalid_platform, "Test.tbd")); 596 EXPECT_FALSE(!!Result); 597 auto errorMessage = toString(Result.takeError()); 598 EXPECT_EQ("malformed file\nTest.tbd:3:12: error: unknown platform\ntargets: " 599 "[ x86_64-maos ]\n" 600 " ^~~~~~~~~~~~\n", 601 errorMessage); 602 } 603 604 TEST(TBDv4, MalformedFile1) { 605 static const char malformed_file1[] = "--- !tapi-tbd\n" 606 "tbd-version: 4\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 "'targets'\ntbd-version: 4\n^\n", 615 errorMessage); 616 } 617 618 TEST(TBDv4, MalformedFile2) { 619 static const char malformed_file2[] = "--- !tapi-tbd\n" 620 "tbd-version: 4\n" 621 "targets: [ x86_64-macos ]\n" 622 "install-name: Test.dylib\n" 623 "foobar: \"unsupported key\"\n"; 624 625 auto Result = 626 TextAPIReader::get(MemoryBufferRef(malformed_file2, "Test.tbd")); 627 EXPECT_FALSE(!!Result); 628 auto errorMessage = toString(Result.takeError()); 629 ASSERT_EQ( 630 "malformed file\nTest.tbd:5:9: error: unknown key 'foobar'\nfoobar: " 631 "\"unsupported key\"\n ^~~~~~~~~~~~~~~~~\n", 632 errorMessage); 633 } 634 635 TEST(TBDv4, MalformedFile3) { 636 static const char tbd_v4_swift_1_1[] = "--- !tapi-tbd\n" 637 "tbd-version: 4\n" 638 "targets: [ x86_64-macos ]\n" 639 "install-name: Test.dylib\n" 640 "swift-abi-version: 1.1\n" 641 "...\n"; 642 643 auto Result = 644 TextAPIReader::get(MemoryBufferRef(tbd_v4_swift_1_1, "Test.tbd")); 645 EXPECT_FALSE(!!Result); 646 auto errorMessage = toString(Result.takeError()); 647 EXPECT_EQ("malformed file\nTest.tbd:5:20: error: invalid Swift ABI " 648 "version.\nswift-abi-version: 1.1\n ^~~\n", 649 errorMessage); 650 } 651 652 } // end namespace TBDv4 653