|  | //===-- TextStubV4Tests.cpp - TBD V4 File Test ----------------------------===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===-----------------------------------------------------------------------===/ | 
|  |  | 
|  | #include "TextStubHelpers.h" | 
|  | #include "llvm/TextAPI/InterfaceFile.h" | 
|  | #include "llvm/TextAPI/TextAPIReader.h" | 
|  | #include "llvm/TextAPI/TextAPIWriter.h" | 
|  | #include "gtest/gtest.h" | 
|  | #include <string> | 
|  | #include <vector> | 
|  |  | 
|  | using namespace llvm; | 
|  | using namespace llvm::MachO; | 
|  |  | 
|  |  | 
|  | namespace TBDv4 { | 
|  |  | 
|  | TEST(TBDv4, ReadFile) { | 
|  | static const char TBDv4File[] = | 
|  | "--- !tapi-tbd\n" | 
|  | "tbd-version: 4\n" | 
|  | "targets:  [ i386-macos, x86_64-macos, x86_64-ios ]\n" | 
|  | "uuids:\n" | 
|  | "  - target: i386-macos\n" | 
|  | "    value: 00000000-0000-0000-0000-000000000000\n" | 
|  | "  - target: x86_64-macos\n" | 
|  | "    value: 11111111-1111-1111-1111-111111111111\n" | 
|  | "  - target: x86_64-ios\n" | 
|  | "    value: 11111111-1111-1111-1111-111111111111\n" | 
|  | "flags: [ flat_namespace, installapi ]\n" | 
|  | "install-name: Umbrella.framework/Umbrella\n" | 
|  | "current-version: 1.2.3\n" | 
|  | "compatibility-version: 1.2\n" | 
|  | "swift-abi-version: 5\n" | 
|  | "parent-umbrella:\n" | 
|  | "  - targets: [ i386-macos, x86_64-macos, x86_64-ios ]\n" | 
|  | "    umbrella: System\n" | 
|  | "allowable-clients:\n" | 
|  | "  - targets: [ i386-macos, x86_64-macos, x86_64-ios ]\n" | 
|  | "    clients: [ ClientA ]\n" | 
|  | "reexported-libraries:\n" | 
|  | "  - targets: [ i386-macos ]\n" | 
|  | "    libraries: [ /System/Library/Frameworks/A.framework/A ]\n" | 
|  | "exports:\n" | 
|  | "  - targets: [ i386-macos ]\n" | 
|  | "    symbols: [ _symA ]\n" | 
|  | "    objc-classes: []\n" | 
|  | "    objc-eh-types: []\n" | 
|  | "    objc-ivars: []\n" | 
|  | "    weak-symbols: []\n" | 
|  | "    thread-local-symbols: []\n" | 
|  | "  - targets: [ x86_64-ios ]\n" | 
|  | "    symbols: [_symB]\n" | 
|  | "  - targets: [ x86_64-macos, x86_64-ios ]\n" | 
|  | "    symbols: [_symAB]\n" | 
|  | "reexports:\n" | 
|  | "  - targets: [ i386-macos ]\n" | 
|  | "    symbols: [_symC]\n" | 
|  | "    objc-classes: []\n" | 
|  | "    objc-eh-types: []\n" | 
|  | "    objc-ivars: []\n" | 
|  | "    weak-symbols: [weakReexport]\n" | 
|  | "    thread-local-symbols: []\n" | 
|  | "undefineds:\n" | 
|  | "  - targets: [ i386-macos ]\n" | 
|  | "    symbols: [ _symD ]\n" | 
|  | "    objc-classes: []\n" | 
|  | "    objc-eh-types: []\n" | 
|  | "    objc-ivars: []\n" | 
|  | "    weak-symbols: [weakReference]\n" | 
|  | "    thread-local-symbols: []\n" | 
|  | "...\n"; | 
|  |  | 
|  | Expected<TBDFile> Result = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv4File, "Test.tbd")); | 
|  | EXPECT_TRUE(!!Result); | 
|  | TBDFile File = std::move(Result.get()); | 
|  | EXPECT_EQ(FileType::TBD_V4, File->getFileType()); | 
|  | PlatformSet Platforms; | 
|  | Platforms.insert(getPlatformFromName("macos")); | 
|  | Platforms.insert(getPlatformFromName("ios")); | 
|  | auto Archs = AK_i386 | AK_x86_64; | 
|  | TargetList Targets = { | 
|  | Target(AK_i386, PLATFORM_MACOS), | 
|  | Target(AK_x86_64, PLATFORM_MACOS), | 
|  | Target(AK_x86_64, PLATFORM_IOS), | 
|  | }; | 
|  | EXPECT_EQ(Archs, File->getArchitectures()); | 
|  | EXPECT_EQ(Platforms.size(), File->getPlatforms().size()); | 
|  | for (auto Platform : File->getPlatforms()) | 
|  | EXPECT_EQ(Platforms.count(Platform), 1U); | 
|  | EXPECT_EQ(std::string("Umbrella.framework/Umbrella"), File->getInstallName()); | 
|  | EXPECT_EQ(PackedVersion(1, 2, 3), File->getCurrentVersion()); | 
|  | EXPECT_EQ(PackedVersion(1, 2, 0), File->getCompatibilityVersion()); | 
|  | EXPECT_EQ(5U, File->getSwiftABIVersion()); | 
|  | EXPECT_FALSE(File->isTwoLevelNamespace()); | 
|  | EXPECT_TRUE(File->isApplicationExtensionSafe()); | 
|  | EXPECT_FALSE(File->isOSLibNotForSharedCache()); | 
|  | InterfaceFileRef client("ClientA", Targets); | 
|  | InterfaceFileRef reexport("/System/Library/Frameworks/A.framework/A", | 
|  | {Targets[0]}); | 
|  | EXPECT_EQ(1U, File->allowableClients().size()); | 
|  | EXPECT_EQ(client, File->allowableClients().front()); | 
|  | EXPECT_EQ(1U, File->reexportedLibraries().size()); | 
|  | EXPECT_EQ(reexport, File->reexportedLibraries().front()); | 
|  |  | 
|  | ExportedSymbolSeq Exports, Reexports, Undefineds; | 
|  | for (const auto *Sym : File->symbols()) { | 
|  | ExportedSymbol Temp = | 
|  | ExportedSymbol{Sym->getKind(), std::string(Sym->getName()), | 
|  | Sym->isWeakDefined() || Sym->isWeakReferenced(), | 
|  | Sym->isThreadLocalValue()}; | 
|  | if (Sym->isUndefined()) { | 
|  | EXPECT_FALSE(Sym->isWeakDefined()); | 
|  | Undefineds.emplace_back(std::move(Temp)); | 
|  | } | 
|  | // Check that defined symbols cannot be set as weak referenced. | 
|  | else if (Sym->isReexported()) { | 
|  | EXPECT_FALSE(Sym->isWeakReferenced()); | 
|  | Reexports.emplace_back(std::move(Temp)); | 
|  | } else { | 
|  | EXPECT_FALSE(Sym->isWeakReferenced()); | 
|  | Exports.emplace_back(std::move(Temp)); | 
|  | } | 
|  | } | 
|  | llvm::sort(Exports); | 
|  | llvm::sort(Reexports); | 
|  | llvm::sort(Undefineds); | 
|  |  | 
|  | static ExportedSymbol ExpectedExportedSymbols[] = { | 
|  | {EncodeKind::GlobalSymbol, "_symA", false, false}, | 
|  | {EncodeKind::GlobalSymbol, "_symAB", false, false}, | 
|  | {EncodeKind::GlobalSymbol, "_symB", false, false}, | 
|  | }; | 
|  |  | 
|  | static ExportedSymbol ExpectedReexportedSymbols[] = { | 
|  | {EncodeKind::GlobalSymbol, "_symC", false, false}, | 
|  | {EncodeKind::GlobalSymbol, "weakReexport", true, false}, | 
|  | }; | 
|  |  | 
|  | static ExportedSymbol ExpectedUndefinedSymbols[] = { | 
|  | {EncodeKind::GlobalSymbol, "_symD", false, false}, | 
|  | {EncodeKind::GlobalSymbol, "weakReference", true, false}, | 
|  | }; | 
|  |  | 
|  | EXPECT_EQ(std::size(ExpectedExportedSymbols), Exports.size()); | 
|  | EXPECT_EQ(std::size(ExpectedReexportedSymbols), Reexports.size()); | 
|  | EXPECT_EQ(std::size(ExpectedUndefinedSymbols), Undefineds.size()); | 
|  | EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(), | 
|  | std::begin(ExpectedExportedSymbols))); | 
|  | EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(), | 
|  | std::begin(ExpectedReexportedSymbols))); | 
|  | EXPECT_TRUE(std::equal(Undefineds.begin(), Undefineds.end(), | 
|  | std::begin(ExpectedUndefinedSymbols))); | 
|  | } | 
|  |  | 
|  | TEST(TBDv4, ReadMultipleDocuments) { | 
|  | static const char TBDv4Inlines[] = | 
|  | "--- !tapi-tbd\n" | 
|  | "tbd-version: 4\n" | 
|  | "targets: [ i386-macos, i386-maccatalyst, x86_64-macos, " | 
|  | "x86_64-maccatalyst ]\n" | 
|  | "install-name: /System/Library/Frameworks/Umbrella.framework/Umbrella\n" | 
|  | "parent-umbrella:\n" | 
|  | "  - targets: [ i386-macos, x86_64-macos ]\n" | 
|  | "    umbrella: System\n" | 
|  | "reexported-libraries:\n" | 
|  | "  - targets: [ i386-macos, x86_64-macos ]\n" | 
|  | "    libraries: [ /System/Library/Frameworks/A.framework/A ]\n" | 
|  | "--- !tapi-tbd\n" | 
|  | "tbd-version: 4\n" | 
|  | "targets:  [ i386-macos, x86_64-macos ]\n" | 
|  | "uuids:\n" | 
|  | "  - target: i386-macos\n" | 
|  | "    value: 20000000-0000-0000-0000-000000000000\n" | 
|  | "  - target: x86_64-macos\n" | 
|  | "    value: 21111111-1111-1111-1111-111111111111\n" | 
|  | "flags: [ flat_namespace ]\n" | 
|  | "install-name: /System/Library/Frameworks/A.framework/A\n" | 
|  | "current-version: 1.2.3\n" | 
|  | "compatibility-version: 1.2\n" | 
|  | "swift-abi-version: 5\n" | 
|  | "exports:\n" | 
|  | "  - targets: [ i386-macos ]\n" | 
|  | "    symbols: [ _symA ]\n" | 
|  | "    objc-classes: []\n" | 
|  | "    objc-eh-types: []\n" | 
|  | "    objc-ivars: []\n" | 
|  | "    weak-symbols: []\n" | 
|  | "    thread-local-symbols: []\n" | 
|  | "  - targets: [ x86_64-macos ]\n" | 
|  | "    symbols: [_symAB]\n" | 
|  | "reexports:\n" | 
|  | "  - targets: [ i386-macos ]\n" | 
|  | "    symbols: [_symC]\n" | 
|  | "    objc-classes: []\n" | 
|  | "    objc-eh-types: []\n" | 
|  | "    objc-ivars: []\n" | 
|  | "    weak-symbols: []\n" | 
|  | "    thread-local-symbols: []\n" | 
|  | "undefineds:\n" | 
|  | "  - targets: [ i386-macos ]\n" | 
|  | "    symbols: [ _symD ]\n" | 
|  | "    objc-classes: []\n" | 
|  | "    objc-eh-types: []\n" | 
|  | "    objc-ivars: []\n" | 
|  | "    weak-symbols: []\n" | 
|  | "    thread-local-symbols: []\n" | 
|  | "...\n"; | 
|  |  | 
|  | PlatformSet Platforms; | 
|  | Platforms.insert(PLATFORM_MACOS); | 
|  | Platforms.insert(PLATFORM_MACCATALYST); | 
|  | ArchitectureSet Archs = AK_i386 | AK_x86_64; | 
|  | TargetList Targets; | 
|  | for (auto &&Arch : Archs) | 
|  | for (auto &&Platform : Platforms) | 
|  | Targets.emplace_back(Target(Arch, Platform)); | 
|  | TargetToAttr Uuids = { | 
|  | {Targets[0], "00000000-0000-0000-0000-000000000000"}, | 
|  | {Targets[1], "00000000-0000-0000-0000-000000000002"}, | 
|  | {Targets[2], "11111111-1111-1111-1111-111111111111"}, | 
|  | {Targets[3], "11111111-1111-1111-1111-111111111112"}, | 
|  | }; | 
|  |  | 
|  | Expected<TBDFile> Result = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv4Inlines, "Test.tbd")); | 
|  | EXPECT_TRUE(!!Result); | 
|  | TBDFile File = std::move(Result.get()); | 
|  | EXPECT_EQ(FileType::TBD_V4, File->getFileType()); | 
|  | EXPECT_EQ(Archs, File->getArchitectures()); | 
|  | EXPECT_EQ(Platforms, File->getPlatforms()); | 
|  | EXPECT_EQ( | 
|  | std::string("/System/Library/Frameworks/Umbrella.framework/Umbrella"), | 
|  | File->getInstallName()); | 
|  | EXPECT_TRUE(File->isTwoLevelNamespace()); | 
|  | EXPECT_TRUE(File->isApplicationExtensionSafe()); | 
|  | EXPECT_EQ(PackedVersion(1, 0, 0), File->getCurrentVersion()); | 
|  | EXPECT_EQ(PackedVersion(1, 0, 0), File->getCompatibilityVersion()); | 
|  | InterfaceFileRef reexport("/System/Library/Frameworks/A.framework/A", | 
|  | {Targets[0], Targets[2]}); | 
|  | EXPECT_EQ(1U, File->reexportedLibraries().size()); | 
|  | EXPECT_EQ(reexport, File->reexportedLibraries().front()); | 
|  | EXPECT_TRUE(File->symbols().empty()); | 
|  |  | 
|  | // Check Inlined Document | 
|  | Targets.clear(); | 
|  | Uuids.clear(); | 
|  | PlatformType Platform = PLATFORM_MACOS; | 
|  | for (auto &&Arch : Archs) | 
|  | Targets.emplace_back(Target(Arch, Platform)); | 
|  | Uuids = { | 
|  | {Targets[0], "20000000-0000-0000-0000-000000000000"}, | 
|  | {Targets[1], "21111111-1111-1111-1111-111111111111"}, | 
|  | }; | 
|  |  | 
|  | TBDReexportFile Document = File->documents().front(); | 
|  | EXPECT_EQ(FileType::TBD_V4, Document->getFileType()); | 
|  | EXPECT_EQ(Archs, Document->getArchitectures()); | 
|  | EXPECT_EQ(1U, Document->getPlatforms().size()); | 
|  | EXPECT_EQ(Platform, *(Document->getPlatforms().begin())); | 
|  | EXPECT_EQ(std::string("/System/Library/Frameworks/A.framework/A"), | 
|  | Document->getInstallName()); | 
|  | EXPECT_EQ(PackedVersion(1, 2, 3), Document->getCurrentVersion()); | 
|  | EXPECT_EQ(PackedVersion(1, 2, 0), Document->getCompatibilityVersion()); | 
|  | EXPECT_EQ(5U, Document->getSwiftABIVersion()); | 
|  | EXPECT_FALSE(Document->isTwoLevelNamespace()); | 
|  | EXPECT_TRUE(Document->isApplicationExtensionSafe()); | 
|  |  | 
|  | ExportedSymbolSeq Exports; | 
|  | ExportedSymbolSeq Reexports, Undefineds; | 
|  | for (const auto *Sym : Document->symbols()) { | 
|  | ExportedSymbol Temp = | 
|  | ExportedSymbol{Sym->getKind(), std::string(Sym->getName()), | 
|  | Sym->isWeakDefined(), Sym->isThreadLocalValue()}; | 
|  | EXPECT_FALSE(Sym->isWeakReferenced()); | 
|  | if (Sym->isUndefined()) | 
|  | Undefineds.emplace_back(std::move(Temp)); | 
|  | else | 
|  | Sym->isReexported() ? Reexports.emplace_back(std::move(Temp)) | 
|  | : Exports.emplace_back(std::move(Temp)); | 
|  | } | 
|  | llvm::sort(Exports); | 
|  | llvm::sort(Reexports); | 
|  | llvm::sort(Undefineds); | 
|  |  | 
|  | static ExportedSymbol ExpectedExportedSymbols[] = { | 
|  | {EncodeKind::GlobalSymbol, "_symA", false, false}, | 
|  | {EncodeKind::GlobalSymbol, "_symAB", false, false}, | 
|  | }; | 
|  |  | 
|  | static ExportedSymbol ExpectedReexportedSymbols[] = { | 
|  | {EncodeKind::GlobalSymbol, "_symC", false, false}, | 
|  | }; | 
|  |  | 
|  | static ExportedSymbol ExpectedUndefinedSymbols[] = { | 
|  | {EncodeKind::GlobalSymbol, "_symD", false, false}, | 
|  | }; | 
|  |  | 
|  | EXPECT_EQ(std::size(ExpectedExportedSymbols), Exports.size()); | 
|  | EXPECT_EQ(std::size(ExpectedReexportedSymbols), Reexports.size()); | 
|  | EXPECT_EQ(std::size(ExpectedUndefinedSymbols), Undefineds.size()); | 
|  | EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(), | 
|  | std::begin(ExpectedExportedSymbols))); | 
|  | EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(), | 
|  | std::begin(ExpectedReexportedSymbols))); | 
|  | EXPECT_TRUE(std::equal(Undefineds.begin(), Undefineds.end(), | 
|  | std::begin(ExpectedUndefinedSymbols))); | 
|  | } | 
|  |  | 
|  | TEST(TBDv4, WriteFile) { | 
|  | static const char TBDv4File[] = | 
|  | "--- !tapi-tbd\n" | 
|  | "tbd-version:     4\n" | 
|  | "targets:         [ i386-macos, x86_64-ios-simulator ]\n" | 
|  | "install-name:    'Umbrella.framework/Umbrella'\n" | 
|  | "current-version: 1.2.3\n" | 
|  | "compatibility-version: 0\n" | 
|  | "swift-abi-version: 5\n" | 
|  | "parent-umbrella:\n" | 
|  | "  - targets:         [ i386-macos, x86_64-ios-simulator ]\n" | 
|  | "    umbrella:        System\n" | 
|  | "allowable-clients:\n" | 
|  | "  - targets:         [ i386-macos ]\n" | 
|  | "    clients:         [ ClientA ]\n" | 
|  | "exports:\n" | 
|  | "  - targets:         [ i386-macos ]\n" | 
|  | "    symbols:         [ _symA ]\n" | 
|  | "    objc-classes:    [ Class1 ]\n" | 
|  | "    weak-symbols:    [ _symC ]\n" | 
|  | "  - targets:         [ x86_64-ios-simulator ]\n" | 
|  | "    symbols:         [ _symB ]\n" | 
|  | "...\n"; | 
|  |  | 
|  | InterfaceFile File; | 
|  | TargetList Targets = { | 
|  | Target(AK_i386, PLATFORM_MACOS), | 
|  | Target(AK_x86_64, PLATFORM_IOSSIMULATOR), | 
|  | }; | 
|  | File.setInstallName("Umbrella.framework/Umbrella"); | 
|  | File.setFileType(FileType::TBD_V4); | 
|  | File.addTargets(Targets); | 
|  | File.setCurrentVersion(PackedVersion(1, 2, 3)); | 
|  | File.setTwoLevelNamespace(); | 
|  | File.setApplicationExtensionSafe(true); | 
|  | File.setSwiftABIVersion(5); | 
|  | File.addAllowableClient("ClientA", Targets[0]); | 
|  | File.addParentUmbrella(Targets[0], "System"); | 
|  | File.addParentUmbrella(Targets[1], "System"); | 
|  | File.addSymbol(EncodeKind::GlobalSymbol, "_symA", {Targets[0]}); | 
|  | File.addSymbol(EncodeKind::GlobalSymbol, "_symB", {Targets[1]}); | 
|  | File.addSymbol(EncodeKind::GlobalSymbol, "_symC", {Targets[0]}, | 
|  | SymbolFlags::WeakDefined); | 
|  | File.addSymbol(EncodeKind::ObjectiveCClass, "Class1", {Targets[0]}); | 
|  |  | 
|  | SmallString<4096> Buffer; | 
|  | raw_svector_ostream OS(Buffer); | 
|  | Error Result = TextAPIWriter::writeToStream(OS, File); | 
|  | EXPECT_FALSE(Result); | 
|  | EXPECT_STREQ(TBDv4File, Buffer.c_str()); | 
|  | } | 
|  |  | 
|  | TEST(TBDv4, WriteMultipleDocuments) { | 
|  | static const char TBDv4Inlines[] = | 
|  | "--- !tapi-tbd\n" | 
|  | "tbd-version:     4\n" | 
|  | "targets:         [ i386-maccatalyst, x86_64-maccatalyst ]\n" | 
|  | "install-name:    " | 
|  | "'/System/Library/Frameworks/Umbrella.framework/Umbrella'\n" | 
|  | "reexported-libraries:\n" | 
|  | "  - targets:         [ i386-maccatalyst, x86_64-maccatalyst ]\n" | 
|  | "    libraries:       [ '/System/Library/Frameworks/A.framework/A' ]\n" | 
|  | "--- !tapi-tbd\n" | 
|  | "tbd-version:     4\n" | 
|  | "targets:         [ i386-maccatalyst, x86_64-maccatalyst ]\n" | 
|  | "install-name:    '/System/Library/Frameworks/A.framework/A'\n" | 
|  | "exports:\n" | 
|  | "  - targets:         [ i386-maccatalyst ]\n" | 
|  | "    weak-symbols:    [ _symC ]\n" | 
|  | "  - targets:         [ i386-maccatalyst, x86_64-maccatalyst ]\n" | 
|  | "    symbols:         [ _symA ]\n" | 
|  | "    objc-classes:    [ Class1 ]\n" | 
|  | "  - targets:         [ x86_64-maccatalyst ]\n" | 
|  | "    symbols:         [ _symAB ]\n" | 
|  | "...\n"; | 
|  |  | 
|  | InterfaceFile File; | 
|  | PlatformType Platform = PLATFORM_MACCATALYST; | 
|  | TargetList Targets = { | 
|  | Target(AK_i386, Platform), | 
|  | Target(AK_x86_64, Platform), | 
|  | }; | 
|  | TargetToAttr Uuids = {{Targets[0], "00000000-0000-0000-0000-000000000002"}, | 
|  | {Targets[1], "11111111-1111-1111-1111-111111111112"}}; | 
|  | File.setInstallName("/System/Library/Frameworks/Umbrella.framework/Umbrella"); | 
|  | File.setFileType(FileType::TBD_V4); | 
|  | File.addTargets(Targets); | 
|  | File.setCompatibilityVersion(PackedVersion(1, 0, 0)); | 
|  | File.setCurrentVersion(PackedVersion(1, 0, 0)); | 
|  | File.setTwoLevelNamespace(); | 
|  | File.setApplicationExtensionSafe(true); | 
|  | File.addReexportedLibrary("/System/Library/Frameworks/A.framework/A", | 
|  | Targets[0]); | 
|  | File.addReexportedLibrary("/System/Library/Frameworks/A.framework/A", | 
|  | Targets[1]); | 
|  |  | 
|  | // Write Second Document | 
|  | Uuids = {{Targets[0], "00000000-0000-0000-0000-000000000000"}, | 
|  | {Targets[1], "11111111-1111-1111-1111-111111111111"}}; | 
|  | InterfaceFile Document; | 
|  | Document.setInstallName("/System/Library/Frameworks/A.framework/A"); | 
|  | Document.setFileType(FileType::TBD_V4); | 
|  | Document.addTargets(Targets); | 
|  | Document.setCompatibilityVersion(PackedVersion(1, 0, 0)); | 
|  | Document.setCurrentVersion(PackedVersion(1, 0, 0)); | 
|  | Document.setTwoLevelNamespace(); | 
|  | Document.setApplicationExtensionSafe(true); | 
|  | Document.addSymbol(EncodeKind::GlobalSymbol, "_symA", Targets); | 
|  | Document.addSymbol(EncodeKind::GlobalSymbol, "_symAB", {Targets[1]}); | 
|  | Document.addSymbol(EncodeKind::GlobalSymbol, "_symC", {Targets[0]}, | 
|  | SymbolFlags::WeakDefined); | 
|  | Document.addSymbol(EncodeKind::ObjectiveCClass, "Class1", Targets); | 
|  | File.addDocument(std::make_shared<InterfaceFile>(std::move(Document))); | 
|  |  | 
|  | SmallString<4096> Buffer; | 
|  | raw_svector_ostream OS(Buffer); | 
|  | Error Result = TextAPIWriter::writeToStream(OS, File); | 
|  | EXPECT_FALSE(Result); | 
|  | EXPECT_STREQ(TBDv4Inlines, Buffer.c_str()); | 
|  | } | 
|  |  | 
|  | TEST(TBDv4, MultipleTargets) { | 
|  | static const char TBDv4MultipleTargets[] = | 
|  | "--- !tapi-tbd\n" | 
|  | "tbd-version: 4\n" | 
|  | "targets: [ i386-maccatalyst, x86_64-tvos, arm64-ios ]\n" | 
|  | "install-name: Test.dylib\n" | 
|  | "...\n"; | 
|  |  | 
|  | Expected<TBDFile> Result = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv4MultipleTargets, "Test.tbd")); | 
|  | EXPECT_TRUE(!!Result); | 
|  | PlatformSet Platforms; | 
|  | Platforms.insert(PLATFORM_MACCATALYST); | 
|  | Platforms.insert(PLATFORM_TVOS); | 
|  | Platforms.insert(PLATFORM_IOS); | 
|  | TBDFile File = std::move(Result.get()); | 
|  | EXPECT_EQ(FileType::TBD_V4, File->getFileType()); | 
|  | EXPECT_EQ(AK_x86_64 | AK_arm64 | AK_i386, File->getArchitectures()); | 
|  | EXPECT_EQ(Platforms.size(), File->getPlatforms().size()); | 
|  | for (auto Platform : File->getPlatforms()) | 
|  | EXPECT_EQ(Platforms.count(Platform), 1U); | 
|  |  | 
|  | SmallString<4096> Buffer; | 
|  | raw_svector_ostream OS(Buffer); | 
|  | Error WriteResult = TextAPIWriter::writeToStream(OS, *File); | 
|  | EXPECT_TRUE(!WriteResult); | 
|  | EXPECT_EQ(stripWhitespace(TBDv4MultipleTargets), | 
|  | stripWhitespace(Buffer.c_str())); | 
|  | } | 
|  |  | 
|  | TEST(TBDv4, MultipleTargetsSameArch) { | 
|  | static const char TBDv4TargetsSameArch[] = | 
|  | "--- !tapi-tbd\n" | 
|  | "tbd-version: 4\n" | 
|  | "targets: [ x86_64-tvos , x86_64-maccatalyst ]\n" | 
|  | "install-name: Test.dylib\n" | 
|  | "...\n"; | 
|  |  | 
|  | Expected<TBDFile> Result = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv4TargetsSameArch, "Test.tbd")); | 
|  | EXPECT_TRUE(!!Result); | 
|  | PlatformSet Platforms; | 
|  | Platforms.insert(PLATFORM_TVOS); | 
|  | Platforms.insert(PLATFORM_MACCATALYST); | 
|  | TBDFile File = std::move(Result.get()); | 
|  | EXPECT_EQ(FileType::TBD_V4, File->getFileType()); | 
|  | EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures()); | 
|  | EXPECT_EQ(Platforms.size(), File->getPlatforms().size()); | 
|  | for (auto Platform : File->getPlatforms()) | 
|  | EXPECT_EQ(Platforms.count(Platform), 1U); | 
|  |  | 
|  | SmallString<4096> Buffer; | 
|  | raw_svector_ostream OS(Buffer); | 
|  | Error WriteResult = TextAPIWriter::writeToStream(OS, *File); | 
|  | EXPECT_TRUE(!WriteResult); | 
|  | EXPECT_EQ(stripWhitespace(TBDv4TargetsSameArch), | 
|  | stripWhitespace(Buffer.c_str())); | 
|  | } | 
|  |  | 
|  | TEST(TBDv4, MultipleTargetsSamePlatform) { | 
|  | static const char TBDv4MultipleTargetsSamePlatform[] = | 
|  | "--- !tapi-tbd\n" | 
|  | "tbd-version: 4\n" | 
|  | "targets: [ armv7k-ios , arm64-ios]\n" | 
|  | "install-name: Test.dylib\n" | 
|  | "...\n"; | 
|  |  | 
|  | Expected<TBDFile> Result = TextAPIReader::get( | 
|  | MemoryBufferRef(TBDv4MultipleTargetsSamePlatform, "Test.tbd")); | 
|  | EXPECT_TRUE(!!Result); | 
|  | TBDFile File = std::move(Result.get()); | 
|  | EXPECT_EQ(FileType::TBD_V4, File->getFileType()); | 
|  | EXPECT_EQ(AK_arm64 | AK_armv7k, File->getArchitectures()); | 
|  | EXPECT_EQ(File->getPlatforms().size(), 1U); | 
|  | EXPECT_EQ(PLATFORM_IOS, *File->getPlatforms().begin()); | 
|  |  | 
|  | SmallString<4096> Buffer; | 
|  | raw_svector_ostream OS(Buffer); | 
|  | Error WriteResult = TextAPIWriter::writeToStream(OS, *File); | 
|  | EXPECT_TRUE(!WriteResult); | 
|  | EXPECT_EQ(stripWhitespace(TBDv4MultipleTargetsSamePlatform), | 
|  | stripWhitespace(Buffer.c_str())); | 
|  | } | 
|  |  | 
|  | TEST(TBDv4, Target_maccatalyst) { | 
|  | static const char TBDv4TargetMacCatalyst[] = | 
|  | "--- !tapi-tbd\n" | 
|  | "tbd-version: 4\n" | 
|  | "targets: [  x86_64-maccatalyst ]\n" | 
|  | "install-name: Test.dylib\n" | 
|  | "...\n"; | 
|  |  | 
|  | Expected<TBDFile> Result = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv4TargetMacCatalyst, "Test.tbd")); | 
|  | EXPECT_TRUE(!!Result); | 
|  | TBDFile File = std::move(Result.get()); | 
|  | EXPECT_EQ(FileType::TBD_V4, File->getFileType()); | 
|  | EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures()); | 
|  | EXPECT_EQ(File->getPlatforms().size(), 1U); | 
|  | EXPECT_EQ(PLATFORM_MACCATALYST, *File->getPlatforms().begin()); | 
|  |  | 
|  | SmallString<4096> Buffer; | 
|  | raw_svector_ostream OS(Buffer); | 
|  | Error WriteResult = TextAPIWriter::writeToStream(OS, *File); | 
|  | EXPECT_TRUE(!WriteResult); | 
|  | EXPECT_EQ(stripWhitespace(TBDv4TargetMacCatalyst), | 
|  | stripWhitespace(Buffer.c_str())); | 
|  | } | 
|  |  | 
|  | TEST(TBDv4, Target_maccatalyst2) { | 
|  | static const char TBDv4TargetMacCatalyst[] = | 
|  | "--- !tapi-tbd\n" | 
|  | "tbd-version: 4\n" | 
|  | "targets: [  x86_64-maccatalyst ]\n" | 
|  | "install-name: Test.dylib\n" | 
|  | "...\n"; | 
|  |  | 
|  | Expected<TBDFile> Result = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv4TargetMacCatalyst, "Test.tbd")); | 
|  | EXPECT_TRUE(!!Result); | 
|  | TBDFile File = std::move(Result.get()); | 
|  | EXPECT_EQ(File->getPlatforms().size(), 1U); | 
|  | EXPECT_EQ(getPlatformFromName("ios-macabi"), *File->getPlatforms().begin()); | 
|  | } | 
|  |  | 
|  | TEST(TBDv4, Target_x86_ios) { | 
|  | static const char TBDv4Targetx86iOS[] = "--- !tapi-tbd\n" | 
|  | "tbd-version: 4\n" | 
|  | "targets: [  x86_64-ios ]\n" | 
|  | "install-name: Test.dylib\n" | 
|  | "...\n"; | 
|  |  | 
|  | Expected<TBDFile> Result = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv4Targetx86iOS, "Test.tbd")); | 
|  | EXPECT_TRUE(!!Result); | 
|  | TBDFile File = std::move(Result.get()); | 
|  | EXPECT_EQ(FileType::TBD_V4, File->getFileType()); | 
|  | EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures()); | 
|  | EXPECT_EQ(File->getPlatforms().size(), 1U); | 
|  | EXPECT_EQ(PLATFORM_IOS, *File->getPlatforms().begin()); | 
|  |  | 
|  | SmallString<4096> Buffer; | 
|  | raw_svector_ostream OS(Buffer); | 
|  | Error WriteResult = TextAPIWriter::writeToStream(OS, *File); | 
|  | EXPECT_TRUE(!WriteResult); | 
|  | EXPECT_EQ(stripWhitespace(TBDv4Targetx86iOS), | 
|  | stripWhitespace(Buffer.c_str())); | 
|  | } | 
|  |  | 
|  | TEST(TBDv4, Target_arm_bridgeOS) { | 
|  | static const char TBDv4PlatformBridgeOS[] = "--- !tapi-tbd\n" | 
|  | "tbd-version: 4\n" | 
|  | "targets: [  armv7k-bridgeos ]\n" | 
|  | "install-name: Test.dylib\n" | 
|  | "...\n"; | 
|  |  | 
|  | Expected<TBDFile> Result = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv4PlatformBridgeOS, "Test.tbd")); | 
|  | EXPECT_TRUE(!!Result); | 
|  | TBDFile File = std::move(Result.get()); | 
|  | EXPECT_EQ(FileType::TBD_V4, File->getFileType()); | 
|  | EXPECT_EQ(File->getPlatforms().size(), 1U); | 
|  | EXPECT_EQ(PLATFORM_BRIDGEOS, *File->getPlatforms().begin()); | 
|  | EXPECT_EQ(ArchitectureSet(AK_armv7k), File->getArchitectures()); | 
|  |  | 
|  | SmallString<4096> Buffer; | 
|  | raw_svector_ostream OS(Buffer); | 
|  | Error WriteResult = TextAPIWriter::writeToStream(OS, *File); | 
|  | EXPECT_TRUE(!WriteResult); | 
|  | EXPECT_EQ(stripWhitespace(TBDv4PlatformBridgeOS), | 
|  | stripWhitespace(Buffer.c_str())); | 
|  | } | 
|  |  | 
|  | TEST(TBDv4, Target_arm_iOS) { | 
|  | static const char TBDv4ArchArm64e[] = "--- !tapi-tbd\n" | 
|  | "tbd-version: 4\n" | 
|  | "targets: [  arm64e-ios ]\n" | 
|  | "install-name: Test.dylib\n" | 
|  | "...\n"; | 
|  |  | 
|  | Expected<TBDFile> Result = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv4ArchArm64e, "Test.tbd")); | 
|  | EXPECT_TRUE(!!Result); | 
|  | TBDFile File = std::move(Result.get()); | 
|  | EXPECT_EQ(FileType::TBD_V4, File->getFileType()); | 
|  | EXPECT_EQ(File->getPlatforms().size(), 1U); | 
|  | EXPECT_EQ(PLATFORM_IOS, *File->getPlatforms().begin()); | 
|  | EXPECT_EQ(ArchitectureSet(AK_arm64e), File->getArchitectures()); | 
|  |  | 
|  | SmallString<4096> Buffer; | 
|  | raw_svector_ostream OS(Buffer); | 
|  | Error WriteResult = TextAPIWriter::writeToStream(OS, *File); | 
|  | EXPECT_TRUE(!WriteResult); | 
|  | EXPECT_EQ(stripWhitespace(TBDv4ArchArm64e), stripWhitespace(Buffer.c_str())); | 
|  | } | 
|  |  | 
|  | TEST(TBDv4, Target_x86_macos) { | 
|  | static const char TBDv4Targetx86MacOS[] = "--- !tapi-tbd\n" | 
|  | "tbd-version: 4\n" | 
|  | "targets: [  x86_64-macos ]\n" | 
|  | "install-name: Test.dylib\n" | 
|  | "...\n"; | 
|  |  | 
|  | Expected<TBDFile> Result = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv4Targetx86MacOS, "Test.tbd")); | 
|  | EXPECT_TRUE(!!Result); | 
|  | TBDFile File = std::move(Result.get()); | 
|  | EXPECT_EQ(FileType::TBD_V4, File->getFileType()); | 
|  | EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures()); | 
|  | EXPECT_EQ(File->getPlatforms().size(), 1U); | 
|  | EXPECT_EQ(PLATFORM_MACOS, *File->getPlatforms().begin()); | 
|  |  | 
|  | SmallString<4096> Buffer; | 
|  | raw_svector_ostream OS(Buffer); | 
|  | Error WriteResult = TextAPIWriter::writeToStream(OS, *File); | 
|  | EXPECT_TRUE(!WriteResult); | 
|  | EXPECT_EQ(stripWhitespace(TBDv4Targetx86MacOS), | 
|  | stripWhitespace(Buffer.c_str())); | 
|  | } | 
|  |  | 
|  | TEST(TBDv4, Target_x86_ios_simulator) { | 
|  | static const char TBDv4Targetx86iOSSim[] = | 
|  | "--- !tapi-tbd\n" | 
|  | "tbd-version: 4\n" | 
|  | "targets: [  x86_64-ios-simulator  ]\n" | 
|  | "install-name: Test.dylib\n" | 
|  | "...\n"; | 
|  |  | 
|  | Expected<TBDFile> Result = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv4Targetx86iOSSim, "Test.tbd")); | 
|  | EXPECT_TRUE(!!Result); | 
|  | TBDFile File = std::move(Result.get()); | 
|  | EXPECT_EQ(FileType::TBD_V4, File->getFileType()); | 
|  | EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures()); | 
|  | EXPECT_EQ(File->getPlatforms().size(), 1U); | 
|  | EXPECT_EQ(PLATFORM_IOSSIMULATOR, *File->getPlatforms().begin()); | 
|  |  | 
|  | SmallString<4096> Buffer; | 
|  | raw_svector_ostream OS(Buffer); | 
|  | Error WriteResult = TextAPIWriter::writeToStream(OS, *File); | 
|  | EXPECT_TRUE(!WriteResult); | 
|  | EXPECT_EQ(stripWhitespace(TBDv4Targetx86iOSSim), | 
|  | stripWhitespace(Buffer.c_str())); | 
|  | } | 
|  |  | 
|  | TEST(TBDv4, Target_x86_tvos_simulator) { | 
|  | static const char TBDv4x86tvOSSim[] = "--- !tapi-tbd\n" | 
|  | "tbd-version: 4\n" | 
|  | "targets: [  x86_64-tvos-simulator  ]\n" | 
|  | "install-name: Test.dylib\n" | 
|  | "...\n"; | 
|  |  | 
|  | Expected<TBDFile> Result = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv4x86tvOSSim, "Test.tbd")); | 
|  | EXPECT_TRUE(!!Result); | 
|  | TBDFile File = std::move(Result.get()); | 
|  | EXPECT_EQ(FileType::TBD_V4, File->getFileType()); | 
|  | EXPECT_EQ(ArchitectureSet(AK_x86_64), File->getArchitectures()); | 
|  | EXPECT_EQ(File->getPlatforms().size(), 1U); | 
|  | EXPECT_EQ(PLATFORM_TVOSSIMULATOR, *File->getPlatforms().begin()); | 
|  |  | 
|  | SmallString<4096> Buffer; | 
|  | raw_svector_ostream OS(Buffer); | 
|  | Error WriteResult = TextAPIWriter::writeToStream(OS, *File); | 
|  | EXPECT_TRUE(!WriteResult); | 
|  | EXPECT_EQ(stripWhitespace(TBDv4x86tvOSSim), stripWhitespace(Buffer.c_str())); | 
|  | } | 
|  |  | 
|  | TEST(TBDv4, Target_i386_watchos_simulator) { | 
|  | static const char TBDv4i386watchOSSim[] = | 
|  | "--- !tapi-tbd\n" | 
|  | "tbd-version: 4\n" | 
|  | "targets: [  i386-watchos-simulator  ]\n" | 
|  | "install-name: Test.dylib\n" | 
|  | "...\n"; | 
|  |  | 
|  | Expected<TBDFile> Result = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv4i386watchOSSim, "Test.tbd")); | 
|  | EXPECT_TRUE(!!Result); | 
|  | TBDFile File = std::move(Result.get()); | 
|  | EXPECT_EQ(FileType::TBD_V4, File->getFileType()); | 
|  | EXPECT_EQ(ArchitectureSet(AK_i386), File->getArchitectures()); | 
|  | EXPECT_EQ(File->getPlatforms().size(), 1U); | 
|  | EXPECT_EQ(PLATFORM_WATCHOSSIMULATOR, *File->getPlatforms().begin()); | 
|  |  | 
|  | SmallString<4096> Buffer; | 
|  | raw_svector_ostream OS(Buffer); | 
|  | Error WriteResult = TextAPIWriter::writeToStream(OS, *File); | 
|  | EXPECT_TRUE(!WriteResult); | 
|  | EXPECT_EQ(stripWhitespace(TBDv4i386watchOSSim), | 
|  | stripWhitespace(Buffer.c_str())); | 
|  | } | 
|  |  | 
|  | TEST(TBDv4, Target_i386_driverkit) { | 
|  | static const char TBDv4i386DriverKit[] = "--- !tapi-tbd\n" | 
|  | "tbd-version: 4\n" | 
|  | "targets: [  i386-driverkit  ]\n" | 
|  | "install-name: Test.dylib\n" | 
|  | "...\n"; | 
|  |  | 
|  | Expected<TBDFile> Result = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv4i386DriverKit, "Test.tbd")); | 
|  | EXPECT_TRUE(!!Result); | 
|  | TBDFile File = std::move(Result.get()); | 
|  | EXPECT_EQ(FileType::TBD_V4, File->getFileType()); | 
|  | EXPECT_EQ(ArchitectureSet(AK_i386), File->getArchitectures()); | 
|  | EXPECT_EQ(File->getPlatforms().size(), 1U); | 
|  | EXPECT_EQ(PLATFORM_DRIVERKIT, *File->getPlatforms().begin()); | 
|  |  | 
|  | SmallString<4096> Buffer; | 
|  | raw_svector_ostream OS(Buffer); | 
|  | Error WriteResult = TextAPIWriter::writeToStream(OS, *File); | 
|  | EXPECT_TRUE(!WriteResult); | 
|  | EXPECT_EQ(stripWhitespace(TBDv4i386DriverKit), | 
|  | stripWhitespace(Buffer.c_str())); | 
|  | } | 
|  |  | 
|  | TEST(TBDv4, Target_arm64_xros) { | 
|  | static const char TBDv4ArchArm64e[] = | 
|  | "--- !tapi-tbd\n" | 
|  | "tbd-version: 4\n" | 
|  | "targets: [ arm64e-xros, arm64e-xros-simulator ]\n" | 
|  | "install-name: Test.dylib\n" | 
|  | "...\n"; | 
|  |  | 
|  | auto Result = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv4ArchArm64e, "Test.tbd")); | 
|  | EXPECT_TRUE(!!Result); | 
|  | auto File = std::move(Result.get()); | 
|  | EXPECT_EQ(FileType::TBD_V4, File->getFileType()); | 
|  | PlatformSet ExpectedSet; | 
|  | ExpectedSet.insert(PLATFORM_XROS); | 
|  | ExpectedSet.insert(PLATFORM_XROS_SIMULATOR); | 
|  | EXPECT_EQ(File->getPlatforms().size(), 2U); | 
|  | for (auto Platform : File->getPlatforms()) | 
|  | EXPECT_EQ(ExpectedSet.count(Platform), 1U); | 
|  |  | 
|  | EXPECT_EQ(ArchitectureSet(AK_arm64e), File->getArchitectures()); | 
|  |  | 
|  | SmallString<4096> Buffer; | 
|  | raw_svector_ostream OS(Buffer); | 
|  | auto WriteResult = TextAPIWriter::writeToStream(OS, *File); | 
|  | EXPECT_TRUE(!WriteResult); | 
|  | EXPECT_EQ(stripWhitespace(TBDv4ArchArm64e), stripWhitespace(Buffer.c_str())); | 
|  | } | 
|  |  | 
|  | TEST(TBDv4, Swift_1) { | 
|  | static const char TBDv4SwiftVersion1[] = "--- !tapi-tbd\n" | 
|  | "tbd-version: 4\n" | 
|  | "targets: [  x86_64-macos ]\n" | 
|  | "install-name: Test.dylib\n" | 
|  | "swift-abi-version: 1\n" | 
|  | "...\n"; | 
|  |  | 
|  | Expected<TBDFile> Result = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv4SwiftVersion1, "Test.tbd")); | 
|  | EXPECT_TRUE(!!Result); | 
|  | TBDFile File = std::move(Result.get()); | 
|  | EXPECT_EQ(FileType::TBD_V4, File->getFileType()); | 
|  | EXPECT_EQ(1U, File->getSwiftABIVersion()); | 
|  |  | 
|  | // No writer test because we emit "swift-abi-version:1.0". | 
|  | } | 
|  |  | 
|  | TEST(TBDv4, Swift_2) { | 
|  | static const char TBDv4Swift2[] = "--- !tapi-tbd\n" | 
|  | "tbd-version: 4\n" | 
|  | "targets: [  x86_64-macos ]\n" | 
|  | "install-name: Test.dylib\n" | 
|  | "swift-abi-version: 2\n" | 
|  | "...\n"; | 
|  |  | 
|  | Expected<TBDFile> Result = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv4Swift2, "Test.tbd")); | 
|  | EXPECT_TRUE(!!Result); | 
|  | TBDFile File = std::move(Result.get()); | 
|  | EXPECT_EQ(FileType::TBD_V4, File->getFileType()); | 
|  | EXPECT_EQ(2U, File->getSwiftABIVersion()); | 
|  |  | 
|  | // No writer test because we emit "swift-abi-version:2.0". | 
|  | } | 
|  |  | 
|  | TEST(TBDv4, Swift_5) { | 
|  | static const char TBDv4SwiftVersion5[] = "--- !tapi-tbd\n" | 
|  | "tbd-version: 4\n" | 
|  | "targets: [  x86_64-macos ]\n" | 
|  | "install-name: Test.dylib\n" | 
|  | "swift-abi-version: 5\n" | 
|  | "...\n"; | 
|  |  | 
|  | Expected<TBDFile> Result = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv4SwiftVersion5, "Test.tbd")); | 
|  | EXPECT_TRUE(!!Result); | 
|  | TBDFile File = std::move(Result.get()); | 
|  | EXPECT_EQ(FileType::TBD_V4, File->getFileType()); | 
|  | EXPECT_EQ(5U, File->getSwiftABIVersion()); | 
|  |  | 
|  | SmallString<4096> Buffer; | 
|  | raw_svector_ostream OS(Buffer); | 
|  | Error WriteResult = TextAPIWriter::writeToStream(OS, *File); | 
|  | EXPECT_TRUE(!WriteResult); | 
|  | EXPECT_EQ(stripWhitespace(TBDv4SwiftVersion5), | 
|  | stripWhitespace(Buffer.c_str())); | 
|  | } | 
|  |  | 
|  | TEST(TBDv4, Swift_99) { | 
|  | static const char TBDv4SwiftVersion99[] = "--- !tapi-tbd\n" | 
|  | "tbd-version: 4\n" | 
|  | "targets: [  x86_64-macos ]\n" | 
|  | "install-name: Test.dylib\n" | 
|  | "swift-abi-version: 99\n" | 
|  | "...\n"; | 
|  |  | 
|  | Expected<TBDFile> Result = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv4SwiftVersion99, "Test.tbd")); | 
|  | EXPECT_TRUE(!!Result); | 
|  | TBDFile File = std::move(Result.get()); | 
|  | EXPECT_EQ(FileType::TBD_V4, File->getFileType()); | 
|  | EXPECT_EQ(99U, File->getSwiftABIVersion()); | 
|  |  | 
|  | SmallString<4096> Buffer; | 
|  | raw_svector_ostream OS(Buffer); | 
|  | Error WriteResult = TextAPIWriter::writeToStream(OS, *File); | 
|  | EXPECT_TRUE(!WriteResult); | 
|  | EXPECT_EQ(stripWhitespace(TBDv4SwiftVersion99), | 
|  | stripWhitespace(Buffer.c_str())); | 
|  | } | 
|  |  | 
|  | TEST(TBDv4, NotForSharedCache) { | 
|  |  | 
|  | static const char TBDv4NotForSharedCache[] = | 
|  | "--- !tapi-tbd\n" | 
|  | "tbd-version: 4\n" | 
|  | "targets: [  arm64-macos ]\n" | 
|  | "flags: [ not_for_dyld_shared_cache ]\n" | 
|  | "install-name: /S/L/F/Foo.framework/Foo\n" | 
|  | "...\n"; | 
|  |  | 
|  | Expected<TBDFile> Result = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv4NotForSharedCache, "Test.tbd")); | 
|  | EXPECT_TRUE(!!Result); | 
|  | Target ExpectedTarget = Target(AK_arm64, PLATFORM_MACOS); | 
|  | TBDFile ReadFile = std::move(Result.get()); | 
|  | EXPECT_EQ(FileType::TBD_V4, ReadFile->getFileType()); | 
|  | EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"), | 
|  | ReadFile->getInstallName()); | 
|  | EXPECT_TRUE(ReadFile->targets().begin() != ReadFile->targets().end()); | 
|  | EXPECT_EQ(*ReadFile->targets().begin(), ExpectedTarget); | 
|  | EXPECT_TRUE(ReadFile->isOSLibNotForSharedCache()); | 
|  | } | 
|  |  | 
|  | TEST(TBDv4, InvalidArchitecture) { | 
|  | static const char TBDv4UnknownArch[] = "--- !tapi-tbd\n" | 
|  | "tbd-version: 4\n" | 
|  | "targets: [ foo-macos ]\n" | 
|  | "install-name: Test.dylib\n" | 
|  | "...\n"; | 
|  |  | 
|  | Expected<TBDFile> Result = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv4UnknownArch, "Test.tbd")); | 
|  | EXPECT_FALSE(!!Result); | 
|  | std::string ErrorMessage = toString(Result.takeError()); | 
|  | EXPECT_EQ("malformed file\nTest.tbd:3:12: error: unknown " | 
|  | "architecture\ntargets: [ foo-macos ]\n" | 
|  | "           ^~~~~~~~~~\n", | 
|  | ErrorMessage); | 
|  | } | 
|  |  | 
|  | TEST(TBDv4, InvalidPlatform) { | 
|  | static const char TBDv4FInvalidPlatform[] = "--- !tapi-tbd\n" | 
|  | "tbd-version: 4\n" | 
|  | "targets: [ x86_64-maos ]\n" | 
|  | "install-name: Test.dylib\n" | 
|  | "...\n"; | 
|  |  | 
|  | Expected<TBDFile> Result = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv4FInvalidPlatform, "Test.tbd")); | 
|  | EXPECT_FALSE(!!Result); | 
|  | std::string ErrorMessage = toString(Result.takeError()); | 
|  | EXPECT_EQ("malformed file\nTest.tbd:3:12: error: unknown platform\ntargets: " | 
|  | "[ x86_64-maos ]\n" | 
|  | "           ^~~~~~~~~~~~\n", | 
|  | ErrorMessage); | 
|  | } | 
|  |  | 
|  | TEST(TBDv4, MalformedFile1) { | 
|  | static const char TBDv4MalformedFile1[] = "--- !tapi-tbd\n" | 
|  | "tbd-version: 4\n" | 
|  | "...\n"; | 
|  |  | 
|  | Expected<TBDFile> Result = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv4MalformedFile1, "Test.tbd")); | 
|  | EXPECT_FALSE(!!Result); | 
|  | std::string ErrorMessage = toString(Result.takeError()); | 
|  | ASSERT_EQ("malformed file\nTest.tbd:2:1: error: missing required key " | 
|  | "'targets'\ntbd-version: 4\n^\n", | 
|  | ErrorMessage); | 
|  | } | 
|  |  | 
|  | TEST(TBDv4, MalformedFile2) { | 
|  | static const char TBDv4MalformedFile2[] = "--- !tapi-tbd\n" | 
|  | "tbd-version: 4\n" | 
|  | "targets: [ x86_64-macos ]\n" | 
|  | "install-name: Test.dylib\n" | 
|  | "foobar: \"unsupported key\"\n" | 
|  | "...\n"; | 
|  |  | 
|  | Expected<TBDFile> Result = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv4MalformedFile2, "Test.tbd")); | 
|  | EXPECT_FALSE(!!Result); | 
|  | std::string ErrorMessage = toString(Result.takeError()); | 
|  | ASSERT_EQ( | 
|  | "malformed file\nTest.tbd:5:1: error: unknown key 'foobar'\nfoobar: " | 
|  | "\"unsupported key\"\n^~~~~~\n", | 
|  | ErrorMessage); | 
|  | } | 
|  |  | 
|  | TEST(TBDv4, MalformedFile3) { | 
|  | static const char TBDv4MalformedSwift[] = "--- !tapi-tbd\n" | 
|  | "tbd-version: 4\n" | 
|  | "targets: [  x86_64-macos ]\n" | 
|  | "install-name: Test.dylib\n" | 
|  | "swift-abi-version: 1.1\n" | 
|  | "...\n"; | 
|  |  | 
|  | Expected<TBDFile> Result = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv4MalformedSwift, "Test.tbd")); | 
|  | EXPECT_FALSE(!!Result); | 
|  | std::string ErrorMessage = toString(Result.takeError()); | 
|  | EXPECT_EQ("malformed file\nTest.tbd:5:20: error: invalid Swift ABI " | 
|  | "version.\nswift-abi-version: 1.1\n                   ^~~\n", | 
|  | ErrorMessage); | 
|  | } | 
|  |  | 
|  | TEST(TBDv4, InterfaceEquality) { | 
|  | static const char TBDv4File[] = | 
|  | "--- !tapi-tbd\n" | 
|  | "tbd-version: 4\n" | 
|  | "targets:  [ i386-macos, x86_64-macos, x86_64-ios, i386-maccatalyst, " | 
|  | "x86_64-maccatalyst ]\n" | 
|  | "install-name: Umbrella.framework/Umbrella\n" | 
|  | "current-version: 1.2.3\n" | 
|  | "compatibility-version: 1.2\n" | 
|  | "swift-abi-version: 5\n" | 
|  | "parent-umbrella:\n" | 
|  | "  - targets: [ i386-macos, x86_64-macos, x86_64-ios ]\n" | 
|  | "    umbrella: System\n" | 
|  | "allowable-clients:\n" | 
|  | "  - targets: [ i386-macos, x86_64-macos, x86_64-ios ]\n" | 
|  | "    clients: [ ClientA ]\n" | 
|  | "reexported-libraries:\n" | 
|  | "  - targets: [ i386-macos ]\n" | 
|  | "    libraries: [ /System/Library/Frameworks/A.framework/A ]\n" | 
|  | "exports:\n" | 
|  | "  - targets: [ i386-macos ]\n" | 
|  | "    symbols: [ _symA ]\n" | 
|  | "    objc-classes: []\n" | 
|  | "    objc-eh-types: []\n" | 
|  | "    objc-ivars: []\n" | 
|  | "    weak-symbols: []\n" | 
|  | "    thread-local-symbols: []\n" | 
|  | "  - targets: [ x86_64-ios ]\n" | 
|  | "    symbols: [_symB]\n" | 
|  | "  - targets: [ x86_64-macos, x86_64-ios ]\n" | 
|  | "    symbols: [_symAB]\n" | 
|  | "  - targets: [ i386-maccatalyst ]\n" | 
|  | "    weak-symbols: [ _symC ]\n" | 
|  | "  - targets: [ i386-maccatalyst, x86_64-maccatalyst ]\n" | 
|  | "    symbols: [ _symA ]\n" | 
|  | "    objc-classes: [ Class1 ]\n" | 
|  | "  - targets: [ x86_64-maccatalyst ]\n" | 
|  | "    symbols: [ _symAB ]\n" | 
|  | "reexports:\n" | 
|  | "  - targets: [ i386-macos ]\n" | 
|  | "    symbols: [_symC]\n" | 
|  | "    objc-classes: []\n" | 
|  | "    objc-eh-types: []\n" | 
|  | "    objc-ivars: []\n" | 
|  | "    weak-symbols: []\n" | 
|  | "    thread-local-symbols: []\n" | 
|  | "undefineds:\n" | 
|  | "  - targets: [ i386-macos ]\n" | 
|  | "    symbols: [ _symD ]\n" | 
|  | "    objc-classes: []\n" | 
|  | "    objc-eh-types: []\n" | 
|  | "    objc-ivars: []\n" | 
|  | "    weak-symbols: []\n" | 
|  | "    thread-local-symbols: []\n" | 
|  | "...\n"; | 
|  |  | 
|  | Expected<TBDFile> ResultA = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestA.tbd")); | 
|  | EXPECT_TRUE(!!ResultA); | 
|  | InterfaceFile FileA = std::move(*ResultA.get()); | 
|  | Expected<TBDFile> ResultB = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestB.tbd")); | 
|  | EXPECT_TRUE(!!ResultB); | 
|  | InterfaceFile FileB = std::move(*ResultB.get()); | 
|  | EXPECT_TRUE(FileA == FileB); | 
|  | } | 
|  |  | 
|  | TEST(TBDv4, InterfaceDiffVersionsEquality) { | 
|  | static const char TBDv4File[] = | 
|  | "--- !tapi-tbd\n" | 
|  | "tbd-version: 4\n" | 
|  | "targets:  [ i386-macos, x86_64-macos ]\n" | 
|  | "install-name: Umbrella.framework/Umbrella\n" | 
|  | "current-version: 1.2.3\n" | 
|  | "compatibility-version: 1.0\n" | 
|  | "swift-abi-version: 5\n" | 
|  | "parent-umbrella:\n" | 
|  | "  - targets: [ i386-macos, x86_64-macos ]\n" | 
|  | "    umbrella: System\n" | 
|  | "allowable-clients:\n" | 
|  | "  - targets: [ i386-macos, x86_64-macos ]\n" | 
|  | "    clients: [ ClientA ]\n" | 
|  | "reexported-libraries:\n" | 
|  | "  - targets: [ i386-macos ]\n" | 
|  | "    libraries: [ /System/Library/Frameworks/A.framework/A ]\n" | 
|  | "exports:\n" | 
|  | "  - targets: [ i386-macos ]\n" | 
|  | "    symbols: [ _sym5 ]\n" | 
|  | "    objc-classes: [ class3]\n" | 
|  | "    objc-eh-types: []\n" | 
|  | "    objc-ivars: [ class1._ivar3 ]\n" | 
|  | "    weak-symbols: [ _weak3 ]\n" | 
|  | "  - targets: [ x86_64-macos ]\n" | 
|  | "    symbols: [_symAB]\n" | 
|  | "  - targets: [ i386-macos, x86_64-macos ]\n" | 
|  | "    symbols: [_symA]\n" | 
|  | "    objc-classes: [ class1, class2 ]\n" | 
|  | "    objc-eh-types: [ class1 ]\n" | 
|  | "    objc-ivars: [ class1._ivar1, class1._ivar2 ]\n" | 
|  | "    weak-symbols: [ _weak1, _weak2 ]\n" | 
|  | "    thread-local-symbols: [ _tlv1, _tlv3 ]\n" | 
|  | "undefineds:\n" | 
|  | "  - targets: [ i386-macos ]\n" | 
|  | "    symbols: [ _symC ]\n" | 
|  | "    objc-classes: []\n" | 
|  | "    objc-eh-types: []\n" | 
|  | "    objc-ivars: []\n" | 
|  | "    weak-symbols: []\n" | 
|  | "    thread-local-symbols: []\n" | 
|  | "...\n"; | 
|  |  | 
|  | static const char TBDv3File[] = | 
|  | "--- !tapi-tbd-v3\n" | 
|  | "archs: [ i386, x86_64 ]\n" | 
|  | "platform: macosx\n" | 
|  | "install-name: Umbrella.framework/Umbrella\n" | 
|  | "current-version: 1.2.3\n" | 
|  | "compatibility-version: 1.0\n" | 
|  | "swift-abi-version: 5\n" | 
|  | "parent-umbrella: System\n" | 
|  | "exports:\n" | 
|  | "  - archs: [ i386, x86_64 ]\n" | 
|  | "    allowable-clients: [ ClientA ]\n" | 
|  | "    symbols: [ _symA ]\n" | 
|  | "    objc-classes: [ class1, class2 ]\n" | 
|  | "    objc-eh-types: [ class1 ]\n" | 
|  | "    objc-ivars: [ class1._ivar1, class1._ivar2 ]\n" | 
|  | "    weak-def-symbols: [ _weak1, _weak2 ]\n" | 
|  | "    thread-local-symbols: [ _tlv1, _tlv3 ]\n" | 
|  | "  - archs: [ i386 ]\n" | 
|  | "    re-exports: [ /System/Library/Frameworks/A.framework/A ]\n" | 
|  | "    symbols: [ _sym5 ]\n" | 
|  | "    objc-classes: [ class3 ]\n" | 
|  | "    objc-ivars: [ class1._ivar3 ]\n" | 
|  | "    weak-def-symbols: [ _weak3 ]\n" | 
|  | "  - archs: [ x86_64 ]\n" | 
|  | "    symbols: [ _symAB ]\n" | 
|  | "undefineds:\n" | 
|  | "  - archs: [ i386 ]\n" | 
|  | "    symbols: [ _symC ]\n" | 
|  | "...\n"; | 
|  |  | 
|  | Expected<TBDFile> ResultA = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestA.tbd")); | 
|  | EXPECT_TRUE(!!ResultA); | 
|  | InterfaceFile FileA = std::move(*ResultA.get()); | 
|  | Expected<TBDFile> ResultB = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv3File, "TestB.tbd")); | 
|  | EXPECT_TRUE(!!ResultB); | 
|  | InterfaceFile FileB = std::move(*ResultB.get()); | 
|  | EXPECT_TRUE(FileA == FileB); | 
|  | } | 
|  |  | 
|  | TEST(TBDv4, InterfaceInequality) { | 
|  | static const char TBDv4File[] = "--- !tapi-tbd\n" | 
|  | "tbd-version: 4\n" | 
|  | "targets:  [ i386-macos, x86_64-macos ]\n" | 
|  | "install-name: Umbrella.framework/Umbrella\n" | 
|  | "...\n"; | 
|  |  | 
|  | Expected<TBDFile> ResultA = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestA.tbd")); | 
|  | EXPECT_TRUE(!!ResultA); | 
|  | InterfaceFile FileA = std::move(*ResultA.get()); | 
|  | Expected<TBDFile> ResultB = | 
|  | TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestB.tbd")); | 
|  | EXPECT_TRUE(!!ResultB); | 
|  | InterfaceFile FileB = std::move(*ResultB.get()); | 
|  |  | 
|  | EXPECT_TRUE(checkEqualityOnTransform(FileA, FileB, [](InterfaceFile *File) { | 
|  | File->addTarget(Target(AK_x86_64, PLATFORM_IOS)); | 
|  | })); | 
|  | EXPECT_TRUE(checkEqualityOnTransform(FileA, FileB, [](InterfaceFile *File) { | 
|  | File->setCurrentVersion(PackedVersion(1, 2, 3)); | 
|  | File->setCompatibilityVersion(PackedVersion(1, 0, 0)); | 
|  | })); | 
|  | EXPECT_TRUE(checkEqualityOnTransform( | 
|  | FileA, FileB, [](InterfaceFile *File) { File->setSwiftABIVersion(5); })); | 
|  | EXPECT_TRUE(checkEqualityOnTransform(FileA, FileB, [](InterfaceFile *File) { | 
|  | File->setTwoLevelNamespace(false); | 
|  | })); | 
|  | EXPECT_TRUE(checkEqualityOnTransform(FileA, FileB, [](InterfaceFile *File) { | 
|  | File->setApplicationExtensionSafe(false); | 
|  | })); | 
|  | EXPECT_TRUE(checkEqualityOnTransform(FileA, FileB, [](InterfaceFile *File) { | 
|  | File->addParentUmbrella(Target(AK_x86_64, PLATFORM_MACOS), "System.dylib"); | 
|  | })); | 
|  | EXPECT_TRUE(checkEqualityOnTransform(FileA, FileB, [](InterfaceFile *File) { | 
|  | File->addAllowableClient("ClientA", Target(AK_i386, PLATFORM_MACOS)); | 
|  | })); | 
|  | EXPECT_TRUE(checkEqualityOnTransform(FileA, FileB, [](InterfaceFile *File) { | 
|  | File->addReexportedLibrary("/System/Library/Frameworks/A.framework/A", | 
|  | Target(AK_i386, PLATFORM_MACOS)); | 
|  | })); | 
|  | EXPECT_TRUE(checkEqualityOnTransform(FileA, FileB, [](InterfaceFile *File) { | 
|  | File->addSymbol(EncodeKind::GlobalSymbol, "_symA", | 
|  | {Target(AK_x86_64, PLATFORM_MACOS)}); | 
|  | })); | 
|  | EXPECT_TRUE(checkEqualityOnTransform(FileA, FileB, [](InterfaceFile *File) { | 
|  | InterfaceFile Document; | 
|  | Document.setFileType(FileType::TBD_V4); | 
|  | Document.addTargets(TargetList{Target(AK_i386, PLATFORM_MACOS), | 
|  | Target(AK_x86_64, PLATFORM_MACOS)}); | 
|  | Document.setInstallName("/System/Library/Frameworks/A.framework/A"); | 
|  | File->addDocument(std::make_shared<InterfaceFile>(std::move(Document))); | 
|  | })); | 
|  | } | 
|  |  | 
|  | } // end namespace TBDv4 |