Index: llvm/include/llvm/TextAPI/MachO/InterfaceFile.h =================================================================== --- llvm/include/llvm/TextAPI/MachO/InterfaceFile.h +++ llvm/include/llvm/TextAPI/MachO/InterfaceFile.h @@ -336,9 +336,7 @@ /// Add a library for inlining to top level library. /// ///\param Document The library to inline with top level library. - void addDocument(std::shared_ptr &&Document) { - Documents.emplace_back(std::move(Document)); - } + void addDocument(std::shared_ptr &&Document); /// Get the list of inlined libraries. /// @@ -397,6 +395,14 @@ fn); } + /// The equality is determined by attributes that impact linking + /// compatibilities. UUIDs, Path, & FileKind are irrelevant since these by + /// itself should not impact linking. + /// This is an expensive operation. + bool operator==(const InterfaceFile &O) const; + + bool operator!=(const InterfaceFile &O) const { return !(*this == O); } + private: llvm::BumpPtrAllocator Allocator; StringRef copyString(StringRef String) { @@ -427,6 +433,22 @@ SymbolMapType Symbols; }; +template +bool operator==(const DenseMapBase &LHS, + const DenseMapBase &RHS) { + if (LHS.size() != RHS.size()) { + return false; + } + for (auto KV : LHS) { + auto I = RHS.find(KV.first); + if (I == RHS.end() || *I->second != *KV.second) + return false; + } + return true; +} + } // end namespace MachO. } // end namespace llvm. Index: llvm/include/llvm/TextAPI/MachO/Symbol.h =================================================================== --- llvm/include/llvm/TextAPI/MachO/Symbol.h +++ llvm/include/llvm/TextAPI/MachO/Symbol.h @@ -104,6 +104,15 @@ void dump() const { dump(llvm::errs()); } #endif + bool operator==(const Symbol &O) const { + return (Kind == O.Kind) && (Name == O.Name) && (Targets == O.Targets) && + (Flags == O.Flags); + } + + bool operator!=(const Symbol &O) const { + return !(*this == O); + } + private: StringRef Name; TargetList Targets; Index: llvm/lib/TextAPI/MachO/InterfaceFile.cpp =================================================================== --- llvm/lib/TextAPI/MachO/InterfaceFile.cpp +++ llvm/lib/TextAPI/MachO/InterfaceFile.cpp @@ -117,3 +117,58 @@ for (const auto &Target : Targets) result.first->second->addTarget(Target); } + +void InterfaceFile::addDocument(std::shared_ptr &&Document) { + auto Pos = llvm::lower_bound(Documents, Document, + [](const std::shared_ptr &LHS, + const std::shared_ptr &RHS) { + return LHS->InstallName < RHS->InstallName; + }); + Documents.insert(Pos, Document); +} + +bool InterfaceFile::operator==(const InterfaceFile &O) const { + if (Targets != O.Targets) { + return false; + } + if (InstallName != O.InstallName) { + return false; + } + if ((CurrentVersion != O.CurrentVersion) || + (CompatibilityVersion != O.CompatibilityVersion)) { + return false; + } + if (SwiftABIVersion != O.SwiftABIVersion) { + return false; + } + if (IsTwoLevelNamespace != O.IsTwoLevelNamespace) { + return false; + } + if (IsAppExtensionSafe != O.IsAppExtensionSafe){ + return false; + } + if (IsInstallAPI != O.IsInstallAPI) { + return false; + } + if (ParentUmbrellas != O.ParentUmbrellas) { + return false; + } + if (AllowableClients != O.AllowableClients) { + return false; + } + if (ReexportedLibraries != O.ReexportedLibraries) { + return false; + } + if (Symbols != O.Symbols) { + return false; + } + if (!std::equal(Documents.begin(), Documents.end(), O.Documents.begin(), + O.Documents.end(), + [](const std::shared_ptr LHS, + const std::shared_ptr RHS) { + return *LHS == *RHS; + })) { + return false; + } + return true; +} Index: llvm/unittests/TextAPI/TextStubV3Tests.cpp =================================================================== --- llvm/unittests/TextAPI/TextStubV3Tests.cpp +++ llvm/unittests/TextAPI/TextStubV3Tests.cpp @@ -836,4 +836,211 @@ ErrorMessage); } +TEST(TBDv3, InterfaceEquality) { + static const char TBDv3File[] = + "--- !tapi-tbd-v3\n" + "archs: [ armv7, arm64 ]\n" + "uuids: [ 'armv7: 00000000-0000-0000-0000-000000000000',\n" + " 'arm64: 11111111-1111-1111-1111-111111111111']\n" + "platform: ios\n" + "flags: [ installapi ]\n" + "install-name: Test.dylib\n" + "current-version: 2.3.4\n" + "compatibility-version: 1.0\n" + "swift-abi-version: 1.1\n" + "parent-umbrella: Umbrella.dylib\n" + "exports:\n" + " - archs: [ armv7, arm64 ]\n" + " allowable-clients: [ clientA ]\n" + " re-exports: [ /usr/lib/libfoo.dylib ]\n" + " symbols: [ _sym1, _sym2, _sym3, _sym4, $ld$hide$os9.0$_sym1 ]\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: [ armv7 ]\n" + " symbols: [ _sym5 ]\n" + " objc-classes: [ class3 ]\n" + " objc-ivars: [ class1._ivar3 ]\n" + " weak-def-symbols: [ _weak3 ]\n" + " thread-local-symbols: [ _tlv3 ]\n" + "--- !tapi-tbd-v3\n" + "archs: [ i386 ]\n" + "platform: macosx\n" + "install-name: '/usr/lib/libbar.dylib'\n" + "current-version: 0\n" + "compatibility-version: 0\n" + "swift-abi-version: 5\n" + "objc-constraint: none\n" + "exports:\n" + " - archs: [ i386 ]\n" + " symbols: [ _sym3, _sym4 ]\n" + "...\n"; + Expected ResultA = + TextAPIReader::get(MemoryBufferRef(TBDv3File, "TestA.tbd")); + EXPECT_TRUE(!!ResultA); + InterfaceFile FileA = std::move(*ResultA.get()); + Expected ResultB = + TextAPIReader::get(MemoryBufferRef(TBDv3File, "TestB.tbd")); + EXPECT_TRUE(!!ResultB); + InterfaceFile FileB = std::move(*ResultB.get()); + EXPECT_FALSE(FileA.getPath() == FileB.getPath()); + EXPECT_TRUE(FileA == FileB); +} + +TEST(TBDv3, InterfaceInequality) { + static const char TBDv3File[] = "--- !tapi-tbd-v3\n" + "archs: [ armv7, arm64 ]\n" + "platform: ios\n" + "install-name: Test.dylib\n" + "...\n"; + TargetList Targets = {Target(AK_armv7, PlatformKind::iOS), + Target(AK_arm64, PlatformKind::iOS)}; + Expected ResultA = + TextAPIReader::get(MemoryBufferRef(TBDv3File, "TestA.tbd")); + EXPECT_TRUE(!!ResultA); + InterfaceFile FileA = std::move(*ResultA.get()); + Expected ResultB = + TextAPIReader::get(MemoryBufferRef(TBDv3File, "TestB.tbd")); + EXPECT_TRUE(!!ResultB); + InterfaceFile FileB = std::move(*ResultB.get()); + FileB.addTarget(Target(AK_x86_64, PlatformKind::iOS)); + EXPECT_FALSE(FileA == FileB); + ResultB = TextAPIReader::get(MemoryBufferRef(TBDv3File, "TestB.tbd")); + EXPECT_TRUE(!!ResultB); + FileB = std::move(*ResultB.get()); + FileA.setCurrentVersion(PackedVersion(1, 2, 3)); + FileA.setCompatibilityVersion(PackedVersion(1, 0, 0)); + FileB.setCurrentVersion(PackedVersion(1, 3, 3)); + FileB.setCompatibilityVersion(PackedVersion(1, 0, 0)); + EXPECT_FALSE(FileA == FileB); + // Set CurrentVersion back to equal. + FileB.setCurrentVersion(PackedVersion(1, 2, 3)); + FileA.setSwiftABIVersion(5); + FileB.setSwiftABIVersion(4); + EXPECT_FALSE(FileA == FileB); + // Set SwiftABIVersion back to equal. + FileB.setSwiftABIVersion(5); + FileA.setTwoLevelNamespace(false); + FileB.setTwoLevelNamespace(true); + EXPECT_FALSE(FileA == FileB); + // Set TwoLevelNamespace back to equal. + FileB.setTwoLevelNamespace(false); + FileA.setInstallAPI(true); + FileB.setInstallAPI(false); + EXPECT_FALSE(FileA == FileB); + // Set InstallAPI back to equal. + FileB.setInstallAPI(true); + FileB.setInstallName("Testing.dylib"); + EXPECT_FALSE(FileA == FileB); + // Set InstallName back to equal. + FileB.setInstallName("Test.dylib"); + FileA.setApplicationExtensionSafe(false); + FileB.setApplicationExtensionSafe(true); + EXPECT_FALSE(FileA == FileB); + // Set ApplicationExtensionSafe back to equal. + FileB.setApplicationExtensionSafe(false); + FileA.addParentUmbrella(Targets[0], "Umbrella.dylib"); + EXPECT_FALSE(FileA == FileB); + FileB.addParentUmbrella(Targets[0], "System.dylib"); + EXPECT_FALSE(FileA == FileB); + ResultA = TextAPIReader::get(MemoryBufferRef(TBDv3File, "TestA.tbd")); + EXPECT_TRUE(!!ResultA); + FileA = std::move(*ResultA.get()); + ResultB = TextAPIReader::get(MemoryBufferRef(TBDv3File, "TestB.tbd")); + EXPECT_TRUE(!!ResultB); + FileB = std::move(*ResultB.get()); + FileA.addAllowableClient("ClientA", Targets[0]); + EXPECT_FALSE(FileA == FileB); + FileB.addAllowableClient("ClientB", Targets[0]); + EXPECT_FALSE(FileA == FileB); + ResultA = TextAPIReader::get(MemoryBufferRef(TBDv3File, "TestA.tbd")); + EXPECT_TRUE(!!ResultA); + FileA = std::move(*ResultA.get()); + ResultB = TextAPIReader::get(MemoryBufferRef(TBDv3File, "TestB.tbd")); + EXPECT_TRUE(!!ResultB); + FileB = std::move(*ResultB.get()); + FileA.addReexportedLibrary("/System/Library/Frameworks/A.framework/A", + Targets[0]); + EXPECT_FALSE(FileA == FileB); + FileB.addReexportedLibrary("/System/Library/Frameworks/B.framework/B", + Targets[0]); + EXPECT_FALSE(FileA == FileB); + ResultA = TextAPIReader::get(MemoryBufferRef(TBDv3File, "TestA.tbd")); + EXPECT_TRUE(!!ResultA); + FileA = std::move(*ResultA.get()); + ResultB = TextAPIReader::get(MemoryBufferRef(TBDv3File, "TestB.tbd")); + EXPECT_TRUE(!!ResultB); + FileB = std::move(*ResultB.get()); + FileA.addReexportedLibrary("/System/Library/Frameworks/A.framework/A", + Targets[0]); + FileB.addReexportedLibrary("/System/Library/Frameworks/A.framework/A", + Targets[1]); + EXPECT_FALSE(FileA == FileB); + ResultA = TextAPIReader::get(MemoryBufferRef(TBDv3File, "TestA.tbd")); + EXPECT_TRUE(!!ResultA); + FileA = std::move(*ResultA.get()); + ResultB = TextAPIReader::get(MemoryBufferRef(TBDv3File, "TestB.tbd")); + EXPECT_TRUE(!!ResultB); + FileB = std::move(*ResultB.get()); + FileA.addSymbol(SymbolKind::GlobalSymbol, "_symA", {Targets[1]}); + FileA.addSymbol(SymbolKind::GlobalSymbol, "_symB", {Targets[1]}); + ResultA = TextAPIReader::get(MemoryBufferRef(TBDv3File, "TestA.tbd")); + EXPECT_TRUE(!!ResultA); + FileA = std::move(*ResultA.get()); + ResultB = TextAPIReader::get(MemoryBufferRef(TBDv3File, "TestB.tbd")); + EXPECT_TRUE(!!ResultB); + FileB = std::move(*ResultB.get()); + FileA.addSymbol(SymbolKind::ObjectiveCClass, "Class1", {Targets[1]}); + FileB.addSymbol(SymbolKind::ObjectiveCInstanceVariable, "Class1", + {Targets[1]}); + EXPECT_FALSE(FileA == FileB); + ResultA = TextAPIReader::get(MemoryBufferRef(TBDv3File, "TestA.tbd")); + EXPECT_TRUE(!!ResultA); + FileA = std::move(*ResultA.get()); + ResultB = TextAPIReader::get(MemoryBufferRef(TBDv3File, "TestB.tbd")); + EXPECT_TRUE(!!ResultB); + FileB = std::move(*ResultB.get()); + FileA.addSymbol(SymbolKind::GlobalSymbol, "_symA", {Targets[1]}); + FileB.addSymbol(SymbolKind::GlobalSymbol, "_symA", {Targets[1]}, + SymbolFlags::WeakDefined); + EXPECT_FALSE(FileA == FileB); + ResultA = TextAPIReader::get(MemoryBufferRef(TBDv3File, "TestA.tbd")); + EXPECT_TRUE(!!ResultA); + FileA = std::move(*ResultA.get()); + ResultB = TextAPIReader::get(MemoryBufferRef(TBDv3File, "TestB.tbd")); + EXPECT_TRUE(!!ResultB); + FileB = std::move(*ResultB.get()); + FileA.addSymbol(SymbolKind::GlobalSymbol, "_symA", {Targets[1]}, + SymbolFlags::WeakDefined); + FileB.addSymbol(SymbolKind::GlobalSymbol, "_symB", {Targets[1]}, + SymbolFlags::WeakDefined); + EXPECT_FALSE(FileA == FileB); + ResultA = TextAPIReader::get(MemoryBufferRef(TBDv3File, "TestA.tbd")); + EXPECT_TRUE(!!ResultA); + FileA = std::move(*ResultA.get()); + ResultB = TextAPIReader::get(MemoryBufferRef(TBDv3File, "TestB.tbd")); + EXPECT_TRUE(!!ResultB); + FileB = std::move(*ResultB.get()); + InterfaceFile DocumentA, DocumentB, DocumentC, DocumentD; + DocumentA.addTargets(Targets); + DocumentA.setInstallName("/System/Library/Frameworks/A.framework/A"); + FileA.addDocument(std::make_shared(std::move(DocumentA))); + EXPECT_FALSE(FileA == FileB); + DocumentB.addTargets(Targets); + DocumentB.setInstallName("/System/Library/Frameworks/B.framework/B"); + FileB.addDocument(std::make_shared(std::move(DocumentB))); + EXPECT_FALSE(FileA == FileB); + DocumentB.addTargets(Targets); + DocumentC.addTargets(Targets); + DocumentC.setInstallName("/System/Library/Frameworks/C.framework/C"); + FileA.addDocument(std::make_shared(std::move(DocumentC))); + EXPECT_FALSE(FileA == FileB); + DocumentD.addTargets(Targets); + DocumentD.setInstallName("/System/Library/Frameworks/A.framework/A"); + FileB.addDocument(std::make_shared(std::move(DocumentD))); + EXPECT_FALSE(FileA == FileB); +} + } // namespace TBDv3 Index: llvm/unittests/TextAPI/TextStubV4Tests.cpp =================================================================== --- llvm/unittests/TextAPI/TextStubV4Tests.cpp +++ llvm/unittests/TextAPI/TextStubV4Tests.cpp @@ -938,4 +938,339 @@ ErrorMessage); } +TEST(TBDv4, InterfaceEquality) { + 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: []\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" + "tbd-version: 4\n" + "targets: [ i386-maccatalyst, x86_64-maccatalyst ]\n" + "uuids:\n" + " - target: i386-maccatalyst\n" + " value: 00000000-0000-0000-0000-000000000000\n" + " - target: x86_64-maccatalyst\n" + " value: 11111111-1111-1111-1111-111111111111\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"; + + Expected ResultA = + TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestA.tbd")); + EXPECT_TRUE(!!ResultA); + InterfaceFile FileA = std::move(*ResultA.get()); + Expected 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" + "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" + "flags: [ installapi ]\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" + "uuids: [ 'i386: 00000000-0000-0000-0000-000000000000',\n" + " 'x86_64: 22222222-2222-2222-2222-222222222222']\n" + "platform: macosx\n" + "flags: [ installapi ]\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 ResultA = + TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestA.tbd")); + EXPECT_TRUE(!!ResultA); + InterfaceFile FileA = std::move(*ResultA.get()); + Expected ResultB = + TextAPIReader::get(MemoryBufferRef(TBDv3File, "TestB.tbd")); + EXPECT_TRUE(!!ResultB); + InterfaceFile FileB = std::move(*ResultB.get()); + EXPECT_NE(FileA.uuids(), FileB.uuids()); + 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"; + TargetList Targets = { + Target(AK_i386, PlatformKind::macOS), + Target(AK_x86_64, PlatformKind::macOS), + }; + Expected ResultA = + TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestA.tbd")); + EXPECT_TRUE(!!ResultA); + InterfaceFile FileA = std::move(*ResultA.get()); + Expected ResultB = + TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestB.tbd")); + EXPECT_TRUE(!!ResultB); + InterfaceFile FileB = std::move(*ResultB.get()); + FileB.addTarget(Target(AK_x86_64, PlatformKind::iOS)); + EXPECT_FALSE(FileA == FileB); + ResultB = TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestB.tbd")); + EXPECT_TRUE(!!ResultB); + FileB = std::move(*ResultB.get()); + FileA.setCurrentVersion(PackedVersion(1, 2, 3)); + FileA.setCompatibilityVersion(PackedVersion(1, 0, 0)); + FileB.setCurrentVersion(PackedVersion(1, 3, 3)); + FileB.setCompatibilityVersion(PackedVersion(1, 0, 0)); + EXPECT_FALSE(FileA == FileB); + // Set CurrentVersion to equal. + FileB.setCurrentVersion(PackedVersion(1, 2, 3)); + FileA.setSwiftABIVersion(5); + FileB.setSwiftABIVersion(4); + EXPECT_FALSE(FileA == FileB); + // Set SwiftABIVersion to equal. + FileB.setSwiftABIVersion(5); + FileA.setTwoLevelNamespace(false); + FileB.setTwoLevelNamespace(true); + EXPECT_FALSE(FileA == FileB); + // Set TwoLevelNamespace to equal. + FileB.setTwoLevelNamespace(false); + FileA.setInstallAPI(true); + FileB.setInstallAPI(false); + EXPECT_FALSE(FileA == FileB); + // Set InstallAPI to equal. + FileB.setInstallAPI(true); + FileB.setInstallName("System.framework/System"); + EXPECT_FALSE(FileA == FileB); + // Set InstallName to equal. + FileB.setInstallName("Umbrella.framework/Umbrella"); + FileA.setApplicationExtensionSafe(false); + FileB.setApplicationExtensionSafe(true); + EXPECT_FALSE(FileA == FileB); + // Set ApplicationExtensionSafe back to equal. + FileB.setApplicationExtensionSafe(false); + FileA.addParentUmbrella(Targets[1], "System.dylib"); + EXPECT_FALSE(FileA == FileB); + FileB.addParentUmbrella(Targets[1], "Umbrella.dylib"); + EXPECT_FALSE(FileA == FileB); + ResultA = TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestA.tbd")); + EXPECT_TRUE(!!ResultA); + FileA = std::move(*ResultA.get()); + ResultB = TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestB.tbd")); + EXPECT_TRUE(!!ResultB); + FileB = std::move(*ResultB.get()); + FileA.addAllowableClient("ClientA", Targets[0]); + EXPECT_FALSE(FileA == FileB); + FileB.addAllowableClient("ClientB", Targets[0]); + EXPECT_FALSE(FileA == FileB); + ResultA = TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestA.tbd")); + EXPECT_TRUE(!!ResultA); + FileA = std::move(*ResultA.get()); + ResultB = TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestB.tbd")); + EXPECT_TRUE(!!ResultB); + FileB = std::move(*ResultB.get()); + FileA.addReexportedLibrary("/System/Library/Frameworks/A.framework/A", + Targets[0]); + EXPECT_FALSE(FileA == FileB); + FileB.addReexportedLibrary("/System/Library/Frameworks/B.framework/B", + Targets[0]); + EXPECT_FALSE(FileA == FileB); + ResultA = TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestA.tbd")); + EXPECT_TRUE(!!ResultA); + FileA = std::move(*ResultA.get()); + ResultB = TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestB.tbd")); + EXPECT_TRUE(!!ResultB); + FileB = std::move(*ResultB.get()); + FileA.addReexportedLibrary("/System/Library/Frameworks/A.framework/A", + Targets[0]); + FileB.addReexportedLibrary("/System/Library/Frameworks/A.framework/A", + Targets[1]); + EXPECT_FALSE(FileA == FileB); + ResultA = TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestA.tbd")); + EXPECT_TRUE(!!ResultA); + FileA = std::move(*ResultA.get()); + ResultB = TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestB.tbd")); + EXPECT_TRUE(!!ResultB); + FileB = std::move(*ResultB.get()); + FileA.addSymbol(SymbolKind::GlobalSymbol, "_symA", {Targets[1]}); + FileB.addSymbol(SymbolKind::GlobalSymbol, "_symB", {Targets[1]}); + EXPECT_FALSE(FileA == FileB); + ResultA = TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestA.tbd")); + EXPECT_TRUE(!!ResultA); + FileA = std::move(*ResultA.get()); + ResultB = TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestB.tbd")); + EXPECT_TRUE(!!ResultB); + FileB = std::move(*ResultB.get()); + FileA.addSymbol(SymbolKind::ObjectiveCClass, "Class1", {Targets[1]}); + FileB.addSymbol(SymbolKind::ObjectiveCInstanceVariable, "Class1", + {Targets[1]}); + EXPECT_FALSE(FileA == FileB); + ResultA = TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestA.tbd")); + EXPECT_TRUE(!!ResultA); + FileA = std::move(*ResultA.get()); + ResultB = TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestB.tbd")); + EXPECT_TRUE(!!ResultB); + FileB = std::move(*ResultB.get()); + FileA.addSymbol(SymbolKind::GlobalSymbol, "_symA", {Targets[1]}); + FileB.addSymbol(SymbolKind::GlobalSymbol, "_symA", {Targets[1]}, + SymbolFlags::WeakDefined); + EXPECT_FALSE(FileA == FileB); + ResultA = TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestA.tbd")); + EXPECT_TRUE(!!ResultA); + FileA = std::move(*ResultA.get()); + ResultB = TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestB.tbd")); + EXPECT_TRUE(!!ResultB); + FileB = std::move(*ResultB.get()); + FileA.addSymbol(SymbolKind::GlobalSymbol, "_symA", {Targets[1]}, + SymbolFlags::WeakDefined); + FileB.addSymbol(SymbolKind::GlobalSymbol, "_symB", {Targets[1]}, + SymbolFlags::WeakDefined); + EXPECT_FALSE(FileA == FileB); + ResultA = TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestA.tbd")); + EXPECT_TRUE(!!ResultA); + FileA = std::move(*ResultA.get()); + ResultB = TextAPIReader::get(MemoryBufferRef(TBDv4File, "TestB.tbd")); + EXPECT_TRUE(!!ResultB); + FileB = std::move(*ResultB.get()); + InterfaceFile DocumentA, DocumentB, DocumentC, DocumentD; + DocumentA.addTargets(Targets); + DocumentA.setInstallName("/System/Library/Frameworks/A.framework/A"); + FileA.addDocument(std::make_shared(std::move(DocumentA))); + EXPECT_FALSE(FileA == FileB); + DocumentB.addTargets(Targets); + DocumentB.setInstallName("/System/Library/Frameworks/B.framework/B"); + FileB.addDocument(std::make_shared(std::move(DocumentB))); + EXPECT_FALSE(FileA == FileB); + DocumentC.addTargets(Targets); + DocumentC.setInstallName("/System/Library/Frameworks/C.framework/C"); + FileA.addDocument(std::make_shared(std::move(DocumentC))); + EXPECT_FALSE(FileA == FileB); + DocumentD.addTargets(Targets); + DocumentD.setInstallName("/System/Library/Frameworks/A.framework/A"); + FileB.addDocument(std::make_shared(std::move(DocumentD))); + EXPECT_FALSE(FileA == FileB); +} + } // end namespace TBDv4