1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
|
/*
This source file is part of the Swift.org open source project
Copyright (c) 2021 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception
See https://swift.org/LICENSE.txt for license information
See https://swift.org/CONTRIBUTORS.txt for Swift project authors
*/
import Foundation
import XCTest
import SymbolKit
class HashableTests: XCTestCase {
/// Test hashing works as expected if Mixins conform to Hashable
func testHashingWithHashableMixins() throws {
var a1 = SymbolGraph.Relationship(source: "a.source", target: "a.target", kind: .conformsTo, targetFallback: nil)
a1.mixins[SymbolGraph.Relationship.SourceOrigin.mixinKey] = SymbolGraph.Relationship.SourceOrigin(identifier: "a.1.origin", displayName: "a.1.origin")
var a2 = SymbolGraph.Relationship(source: "a.source", target: "a.target", kind: .conformsTo, targetFallback: nil)
a2.mixins[SymbolGraph.Relationship.SourceOrigin.mixinKey] = SymbolGraph.Relationship.SourceOrigin(identifier: "a.2.origin", displayName: "a.2.origin")
XCTAssertEqual(Set([a1, a2]).count, 2)
}
/// Check that Mixins that do not implement Hashable are ignored, so that
/// they don't render the Hashable implementation of Relationship useless.
func testHashingWithNonHashableMixins() throws {
var a1 = SymbolGraph.Relationship(source: "a.source", target: "a.target", kind: .conformsTo, targetFallback: nil)
a1.mixins[NotHashableMixin<String>.mixinKey] = NotHashableMixin(value: "a.1.value")
var a2 = SymbolGraph.Relationship(source: "a.source", target: "a.target", kind: .conformsTo, targetFallback: nil)
a2.mixins[NotHashableMixin<String>.mixinKey] = NotHashableMixin(value: "a.2.value")
XCTAssertEqual(Set([a1, a2]).count, 1)
}
/// Check that Hashable Mixins without any Mixin for the respective `mixinKey` on the other
/// relationship fail equality.
func testHashingWithMissingEquatableMixin() throws {
var a1 = SymbolGraph.Relationship(source: "a.source", target: "a.target", kind: .conformsTo, targetFallback: nil)
a1.mixins["1"] = SymbolGraph.Relationship.SourceOrigin(identifier: "a.1.origin", displayName: "a.1.origin")
var a2 = SymbolGraph.Relationship(source: "a.source", target: "a.target", kind: .conformsTo, targetFallback: nil)
a2.mixins["2"] = SymbolGraph.Relationship.SourceOrigin(identifier: "a.2.origin", displayName: "a.2.origin")
XCTAssertEqual(Set([a1, a2]).count, 2)
}
/// Check that Non-Hashable Mixins without any Mixin for the respective `mixinKey` on the other
/// relationship do not fail equality.
func testHashingWithMissingNonEquatableMixin() throws {
var a1 = SymbolGraph.Relationship(source: "a.source", target: "a.target", kind: .conformsTo, targetFallback: nil)
a1.mixins["1"] = NotHashableMixin(value: 1)
let a2 = SymbolGraph.Relationship(source: "a.source", target: "a.target", kind: .conformsTo, targetFallback: nil)
XCTAssertEqual(Set([a1, a2]).count, 1)
}
/// Check that Mixins of different type that both do not implement Hashable
/// are considered equal.
func testHashingWithDifferentTypeNonHashableMixins() throws {
var a1 = SymbolGraph.Relationship(source: "a.source", target: "a.target", kind: .conformsTo, targetFallback: nil)
a1.mixins[NotHashableMixin<String>.mixinKey] = NotHashableMixin(value: "a.1.value")
var a2 = SymbolGraph.Relationship(source: "a.source", target: "a.target", kind: .conformsTo, targetFallback: nil)
a2.mixins[NotHashableMixin<Int>.mixinKey] = NotHashableMixin(value: 2)
XCTAssertEqual(Set([a1, a2]).count, 1)
}
/// Check that Mixins of different type where one does implement Hashable
/// are considered unequal.
func testHashingWithDifferentTypeOneHashableMixinOneNonHashable() throws {
// in this first test, equality should return false based on the count of equatable mixins
var a1 = SymbolGraph.Relationship(source: "a.source", target: "a.target", kind: .conformsTo, targetFallback: nil)
a1.mixins["a"] = NotHashableMixin(value: "a.1.value")
var a2 = SymbolGraph.Relationship(source: "a.source", target: "a.target", kind: .conformsTo, targetFallback: nil)
a2.mixins["a"] = SymbolGraph.Relationship.SourceOrigin(identifier: "a.2.origin", displayName: "a.2.origin")
XCTAssertEqual(Set([a1, a2]).count, 2)
// This test is interesting because the equality implementation of relationship
// only iterates over the `lhs` mixins. Thus, depending on what relationship comes out
// as the `lhs`, the equality might fail at different times (though it will always fail).
// In this example, if `a1` is `lhs`, the comparison for `"a"` will be skipped (since the
// lhs is not `Equatable`), but the comparison for `"b"` will return false.
// In contrast, if `a2` is `lhs`, the comparison for `"a"` will return false right away.
a1 = SymbolGraph.Relationship(source: "a.source", target: "a.target", kind: .conformsTo, targetFallback: nil)
a1.mixins["a"] = NotHashableMixin(value: "a.1.value")
a1.mixins["b"] = SymbolGraph.Relationship.SourceOrigin(identifier: "a.1.origin", displayName: "a.1.origin")
a2 = SymbolGraph.Relationship(source: "a.source", target: "a.target", kind: .conformsTo, targetFallback: nil)
a2.mixins["a"] = SymbolGraph.Relationship.SourceOrigin(identifier: "a.2.origin", displayName: "a.2.origin")
a2.mixins["b"] = NotHashableMixin(value: "a.2.value")
XCTAssertEqual(Set([a1, a2]).count, 2)
XCTAssertEqual(Set([a2, a1]).count, 2)
}
}
private struct NotHashableMixin<T>: Mixin where T: Codable {
static var mixinKey: String { "nothashable" }
let value: T
}
|