Skip to content

Commit ca8af77

Browse files
[test] Adding missing BidirectionalCollection::partition(subrange:) and MutableCollection::partition(subrange:) unit tests (#95)
1 parent e077f67 commit ca8af77

File tree

2 files changed

+108
-8
lines changed

2 files changed

+108
-8
lines changed

Tests/SwiftAlgorithmsTests/PartitionTests.swift

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,17 @@ final class PartitionTests: XCTestCase {
6464
func testStablePartitionWithSubrange() {
6565
for length in 10...20 {
6666
let a = Array(0..<length)
67-
for j in 0..<length {
68-
var b = a
69-
let partitionRange = 0..<j
70-
let condition = { $0 < j - 1 }
71-
let p = b.stablePartition(subrange: partitionRange, by: condition)
72-
XCTAssertEqual(p, partitionRange.count > 0 ? 1 : 0)
73-
XCTAssertEqualSequences(b[partitionRange.lowerBound..<p], a[partitionRange].filter { !condition($0) })
74-
XCTAssertEqualSequences(b[p..<partitionRange.upperBound], a[partitionRange].filter(condition))
67+
for i in 0..<length {
68+
for j in 0...i {
69+
var b = a
70+
let partitionRange = j..<i
71+
let condition = { $0 < i - 1 }
72+
let p = b.stablePartition(subrange: partitionRange, by: condition)
73+
74+
XCTAssertEqual(p, partitionRange.count == 0 ? j : j + 1)
75+
XCTAssertEqualSequences(b[partitionRange.lowerBound..<p], a[partitionRange].filter { !condition($0) })
76+
XCTAssertEqualSequences(b[p..<partitionRange.upperBound], a[partitionRange].filter(condition))
77+
}
7578
}
7679
}
7780
}
@@ -88,4 +91,46 @@ final class PartitionTests: XCTestCase {
8891
}
8992
}
9093
}
94+
95+
func testPartitionWithSubrangeBidirectionalCollection() {
96+
for length in 10...20 {
97+
let a = Array(0..<length)
98+
for i in 0..<length {
99+
for j in 0...i {
100+
var b = a
101+
let partitionRange = j..<i
102+
let condition = { $0 < i - 1 }
103+
let p = b.partition(subrange: partitionRange, by: condition)
104+
105+
XCTAssertEqual(p, partitionRange.count == 0 ? j : j + 1)
106+
XCTAssertEqualSequences(b[partitionRange.lowerBound..<p], a[partitionRange].filter { !condition($0) })
107+
XCTAssertUnorderedEqualSequences(b[p..<partitionRange.upperBound], a[partitionRange].filter(condition))
108+
}
109+
}
110+
}
111+
}
112+
113+
func testPartitionWithSubrangeMutableCollection() {
114+
for length in 10...20 {
115+
let a = Array(0..<length)
116+
for i in 0..<length {
117+
for j in 0...i {
118+
var b = a.eraseToAnyMutableCollection()
119+
var bdc = a
120+
let partitionRange = j..<i
121+
let condition = { $0 < i - 1 }
122+
let p = b.partition(subrange: partitionRange, by: condition)
123+
let bdcp = bdc.partition(subrange: partitionRange, by: condition)
124+
125+
XCTAssertEqual(p, partitionRange.count == 0 ? j : j + 1)
126+
XCTAssertEqualSequences(b[partitionRange.lowerBound..<p], a[partitionRange].filter { !condition($0) })
127+
XCTAssertUnorderedEqualSequences(b[p..<partitionRange.upperBound], a[partitionRange].filter(condition))
128+
129+
// Must produce the same result as the `BidirectionalCollection` specialized overload.
130+
XCTAssertEqualSequences(b[partitionRange.lowerBound..<p], bdc[partitionRange.lowerBound..<bdcp])
131+
XCTAssertUnorderedEqualSequences(b[p..<partitionRange.upperBound], bdc[bdcp..<partitionRange.upperBound])
132+
}
133+
}
134+
}
135+
}
91136
}

Tests/SwiftAlgorithmsTests/TestUtilities.swift

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,34 @@ struct SplitMix64: RandomNumberGenerator {
4646
}
4747
}
4848

49+
// An eraser helper to any mutable collection
50+
struct AnyMutableCollection<Base> where Base: MutableCollection {
51+
var base: Base
52+
}
53+
54+
extension AnyMutableCollection: MutableCollection {
55+
typealias Index = Base.Index
56+
typealias Element = Base.Element
57+
58+
var startIndex: Base.Index { base.startIndex }
59+
var endIndex: Base.Index { base.endIndex }
60+
61+
func index(after i: Index) -> Index {
62+
return base.index(after: i)
63+
}
64+
65+
subscript(position: Base.Index) -> Base.Element {
66+
_read { yield base[position] }
67+
set { base[position] = newValue }
68+
}
69+
}
70+
71+
extension MutableCollection {
72+
func eraseToAnyMutableCollection() -> AnyMutableCollection<Self> {
73+
AnyMutableCollection(base: self)
74+
}
75+
}
76+
4977
func XCTAssertEqualSequences<S1: Sequence, S2: Sequence>(
5078
_ expression1: @autoclosure () throws -> S1,
5179
_ expression2: @autoclosure () throws -> S2,
@@ -56,6 +84,33 @@ func XCTAssertEqualSequences<S1: Sequence, S2: Sequence>(
5684
message(), file: file, line: line)
5785
}
5886

87+
// Two sequences contains exactly the same element but not necessarily in the same order.
88+
func XCTAssertUnorderedEqualSequences<S1: Sequence, S2: Sequence>(
89+
_ expression1: @autoclosure () throws -> S1,
90+
_ expression2: @autoclosure () throws -> S2,
91+
file: StaticString = #file, line: UInt = #line
92+
) rethrows where S1.Element: Equatable, S1.Element == S2.Element {
93+
var s1 = Array(try expression1())
94+
var missing: [S1.Element] = []
95+
for elt in try expression2() {
96+
guard let idx = s1.firstIndex(of: elt) else {
97+
missing.append(elt)
98+
continue
99+
}
100+
s1.remove(at: idx)
101+
}
102+
103+
XCTAssertTrue(
104+
missing.isEmpty, "first sequence missing '\(missing)' elements from second sequence",
105+
file: file, line: line
106+
)
107+
108+
XCTAssertTrue(
109+
s1.isEmpty, "first sequence contains \(s1) missing from second sequence",
110+
file: file, line: line
111+
)
112+
}
113+
59114
func XCTAssertEqualSequences<S1: Sequence, S2: Sequence>(
60115
_ expression1: @autoclosure () throws -> S1,
61116
_ expression2: @autoclosure () throws -> S2,

0 commit comments

Comments
 (0)