Skip to content

Commit 3609ca5

Browse files
committed
Add utility functions for testing hash implementations
1 parent 707896f commit 3609ca5

File tree

3 files changed

+114
-0
lines changed

3 files changed

+114
-0
lines changed

Foundation.xcodeproj/project.pbxproj

+8
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,8 @@
324324
6EB768281D18C12C00D4B719 /* UUID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EB768271D18C12C00D4B719 /* UUID.swift */; };
325325
7900433B1CACD33E00ECCBF1 /* TestNSCompoundPredicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 790043391CACD33E00ECCBF1 /* TestNSCompoundPredicate.swift */; };
326326
7900433C1CACD33E00ECCBF1 /* TestNSPredicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7900433A1CACD33E00ECCBF1 /* TestNSPredicate.swift */; };
327+
7D0DE86E211883F500540061 /* TestDateComponents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D0DE86C211883F500540061 /* TestDateComponents.swift */; };
328+
7D0DE86F211883F500540061 /* Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D0DE86D211883F500540061 /* Utilities.swift */; };
327329
90E645DF1E4C89A400D0D47C /* TestNSCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90E645DE1E4C89A400D0D47C /* TestNSCache.swift */; };
328330
9F0DD3521ECD73D000F68030 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F0041781ECD5962004138BD /* main.swift */; };
329331
9F0DD3571ECD783500F68030 /* SwiftFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B5D885D1BBC938800234F36 /* SwiftFoundation.framework */; };
@@ -815,6 +817,8 @@
815817
790043391CACD33E00ECCBF1 /* TestNSCompoundPredicate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSCompoundPredicate.swift; sourceTree = "<group>"; };
816818
7900433A1CACD33E00ECCBF1 /* TestNSPredicate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSPredicate.swift; sourceTree = "<group>"; };
817819
7A7D6FBA1C16439400957E2E /* TestURLResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestURLResponse.swift; sourceTree = "<group>"; };
820+
7D0DE86C211883F500540061 /* TestDateComponents.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestDateComponents.swift; sourceTree = "<group>"; };
821+
7D0DE86D211883F500540061 /* Utilities.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Utilities.swift; sourceTree = "<group>"; };
818822
83712C8D1C1684900049AD49 /* TestNSURLRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSURLRequest.swift; sourceTree = "<group>"; };
819823
844DC3321C17584F005611F9 /* TestScanner.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestScanner.swift; sourceTree = "<group>"; };
820824
848A30571C137B3500C83206 /* TestHTTPCookie.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TestHTTPCookie.swift; path = TestFoundation/TestHTTPCookie.swift; sourceTree = SOURCE_ROOT; };
@@ -1489,6 +1493,8 @@
14891493
EA66F65A1BF1976100136161 /* Tests */ = {
14901494
isa = PBXGroup;
14911495
children = (
1496+
7D0DE86D211883F500540061 /* Utilities.swift */,
1497+
7D0DE86C211883F500540061 /* TestDateComponents.swift */,
14921498
6E203B8C1C1303BB003B2576 /* TestBundle.swift */,
14931499
A5A34B551C18C85D00FD972B /* TestByteCountFormatter.swift */,
14941500
2EBE67A31C77BF05006583D5 /* TestDateFormatter.swift */,
@@ -2521,6 +2527,7 @@
25212527
D5C40F331CDA1D460005690C /* TestOperationQueue.swift in Sources */,
25222528
BDBB65901E256BFA001A7286 /* TestEnergyFormatter.swift in Sources */,
25232529
5B13B32F1C582D4C00651CE2 /* TestNSGeometry.swift in Sources */,
2530+
7D0DE86E211883F500540061 /* TestDateComponents.swift in Sources */,
25242531
EA08126C1DA810BE00651B70 /* ProgressFraction.swift in Sources */,
25252532
5B13B3351C582D4C00651CE2 /* TestNSKeyedUnarchiver.swift in Sources */,
25262533
5B13B33D1C582D4C00651CE2 /* TestPipe.swift in Sources */,
@@ -2547,6 +2554,7 @@
25472554
B951B5EC1F4E2A2000D8B332 /* TestNSLock.swift in Sources */,
25482555
5B13B33A1C582D4C00651CE2 /* TestNSNumber.swift in Sources */,
25492556
5B13B3521C582D4C00651CE2 /* TestNSValue.swift in Sources */,
2557+
7D0DE86F211883F500540061 /* Utilities.swift in Sources */,
25502558
5B13B3311C582D4C00651CE2 /* TestIndexPath.swift in Sources */,
25512559
5B13B3271C582D4C00651CE2 /* TestNSArray.swift in Sources */,
25522560
5B13B3461C582D4C00651CE2 /* TestProcess.swift in Sources */,

TestFoundation/Utilities.swift

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// This source file is part of the Swift.org open source project
2+
//
3+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
4+
// Licensed under Apache License v2.0 with Runtime Library Exception
5+
//
6+
// See http://swift.org/LICENSE.txt for license information
7+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
8+
//
9+
10+
11+
func checkHashableMutations_ValueType<Item: Hashable, S: Sequence>(
12+
_ item: Item,
13+
_ keyPath: WritableKeyPath<Item, S.Element>,
14+
_ values: S,
15+
file: StaticString = #file,
16+
line: UInt = #line
17+
) {
18+
_checkHashableMutations(
19+
Item.self, Item.self,
20+
item,
21+
{ $0 },
22+
keyPath,
23+
values)
24+
}
25+
26+
func checkHashableMutations_NSCopying<Item: NSObject & NSCopying, S: Sequence>(
27+
_ item: Item,
28+
_ keyPath: ReferenceWritableKeyPath<Item, S.Element>,
29+
_ values: S,
30+
file: StaticString = #file,
31+
line: UInt = #line
32+
) {
33+
_checkHashableMutations(
34+
Item.self, Item.self,
35+
item,
36+
{ $0.copy() as! Item },
37+
keyPath,
38+
values)
39+
}
40+
41+
func checkHashableMutations_NSMutableCopying<
42+
Source: NSObject & NSMutableCopying,
43+
Target: NSObject & NSMutableCopying,
44+
S: Sequence
45+
>(
46+
_ item: Source,
47+
_ keyPath: ReferenceWritableKeyPath<Target, S.Element>,
48+
_ values: S,
49+
file: StaticString = #file,
50+
line: UInt = #line
51+
) {
52+
_checkHashableMutations(
53+
Source.self, Target.self,
54+
item,
55+
{ $0.mutableCopy() as! Target },
56+
keyPath,
57+
values)
58+
}
59+
60+
// Check that mutating `object` via the specified key path affects its
61+
// hash value.
62+
func _checkHashableMutations<Source: Hashable, Target: Hashable, S: Sequence>(
63+
_ source: Source.Type,
64+
_ target: Target.Type,
65+
_ object: Source,
66+
_ copyBlock: (Source) -> Target,
67+
_ keyPath: WritableKeyPath<Target, S.Element>,
68+
_ values: S,
69+
file: StaticString = #file,
70+
line: UInt = #line
71+
) {
72+
let reference = copyBlock(object)
73+
let referenceHash = reference.hashValue
74+
75+
XCTAssertEqual(
76+
reference.hashValue, referenceHash,
77+
"\(type(of: reference)).hashValue is nondeterministic",
78+
file: file, line: line)
79+
80+
var found = false
81+
for value in values {
82+
var copy = copyBlock(object)
83+
XCTAssertEqual(
84+
copy, reference,
85+
"Invalid copy operation",
86+
file: file, line: line)
87+
XCTAssertEqual(
88+
copy.hashValue, referenceHash,
89+
"Invalid copy operation",
90+
file: file, line: line)
91+
copy[keyPath: keyPath] = value
92+
XCTAssertNotEqual(
93+
reference, copy,
94+
"\(keyPath) did not affect object equality",
95+
file: file, line: line)
96+
if referenceHash != copy.hashValue {
97+
found = true
98+
}
99+
}
100+
if !found {
101+
XCTFail(
102+
"\(keyPath) does not seem to contribute to the hash value",
103+
file: file, line: line)
104+
}
105+
}

build.py

+1
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,7 @@
523523
'TestFoundation/main.swift',
524524
'TestFoundation/HTTPServer.swift',
525525
'Foundation/ProgressFraction.swift',
526+
'TestFoundation/Utilities.swift',
526527
] + glob.glob('./TestFoundation/Test*.swift')) # all TestSomething.swift are considered sources to the test project in the TestFoundation directory
527528

528529
Configuration.current.extra_ld_flags += ' -L'+Configuration.current.variables["LIBDISPATCH_BUILD_DIR"]+'/src/.libs'

0 commit comments

Comments
 (0)