@@ -32,8 +32,30 @@ func makeSingleUseSequence<T>(element: T, count: Int) -> UnfoldSequence<T, Void>
32
32
}
33
33
}
34
34
35
+ struct CountedOptionSet : OptionSet {
36
+ static var arrayLiteralCreationCount = 0
37
+
38
+ var rawValue : Int
39
+
40
+ static var one = Self ( rawValue: 1 )
41
+ static var two = Self ( rawValue: 1 )
42
+ }
43
+
44
+ extension CountedOptionSet {
45
+ init ( arrayLiteral: Self ... ) {
46
+ Self . arrayLiteralCreationCount += 1
47
+ self . rawValue = 0
48
+ for element in arrayLiteral {
49
+ self . insert ( element)
50
+ }
51
+ }
52
+ }
53
+
35
54
class AlgorithmTests : XCTestCase {
36
55
func testContains( ) {
56
+ XCTAssertTrue ( " abcde " . contains ( " a " ) )
57
+ XCTAssertTrue ( " abcde " . contains ( " e " as Character ) )
58
+
37
59
XCTAssertTrue ( " " . contains ( " " ) )
38
60
XCTAssertTrue ( " abcde " . contains ( " " ) )
39
61
XCTAssertTrue ( " abcde " . contains ( " abcd " ) )
@@ -51,7 +73,25 @@ class AlgorithmTests: XCTestCase {
51
73
}
52
74
}
53
75
54
- func testRanges( ) {
76
+ func testContainsSourceCompatibility( ) {
77
+ CountedOptionSet . arrayLiteralCreationCount = 0
78
+
79
+ let both : CountedOptionSet = [ . one, . two]
80
+ let none : CountedOptionSet = [ ]
81
+ XCTAssertEqual ( CountedOptionSet . arrayLiteralCreationCount, 2 )
82
+
83
+ let cosArray = [ both, . one, . two]
84
+ XCTAssertFalse ( cosArray. contains ( none) )
85
+
86
+ // This tests that `contains([])` uses the element-based `contains(_:)`
87
+ // method, interpreting `[]` as an instance of `CountedOptionSet`, rather
88
+ // than the collection-based overload, which would interpret `[]` as an
89
+ // `Array<CountedOptionSet>`.
90
+ XCTAssertFalse ( cosArray. contains ( [ ] ) )
91
+ XCTAssertEqual ( CountedOptionSet . arrayLiteralCreationCount, 3 )
92
+ }
93
+
94
+ func testRegexRanges( ) {
55
95
func expectRanges(
56
96
_ string: String ,
57
97
_ regex: String ,
@@ -78,6 +118,7 @@ class AlgorithmTests: XCTestCase {
78
118
expectRanges ( " " , " x " , [ ] )
79
119
expectRanges ( " " , " x+ " , [ ] )
80
120
expectRanges ( " " , " x* " , [ 0 ..< 0 ] )
121
+ expectRanges ( " aaa " , " a* " , [ 0 ..< 3 , 3 ..< 3 ] )
81
122
expectRanges ( " abc " , " " , [ 0 ..< 0 , 1 ..< 1 , 2 ..< 2 , 3 ..< 3 ] )
82
123
expectRanges ( " abc " , " x " , [ ] )
83
124
expectRanges ( " abc " , " x+ " , [ ] )
@@ -92,8 +133,10 @@ class AlgorithmTests: XCTestCase {
92
133
expectRanges ( " abc " , " (a|b)* " , [ 0 ..< 2 , 2 ..< 2 , 3 ..< 3 ] )
93
134
expectRanges ( " abc " , " (b|c)+ " , [ 1 ..< 3 ] )
94
135
expectRanges ( " abc " , " (b|c)* " , [ 0 ..< 0 , 1 ..< 3 , 3 ..< 3 ] )
95
-
96
- func expectStringRanges(
136
+ }
137
+
138
+ func testStringRanges( ) {
139
+ func expectRanges(
97
140
_ input: String ,
98
141
_ pattern: String ,
99
142
_ expected: [ Range < Int > ] ,
@@ -110,16 +153,16 @@ class AlgorithmTests: XCTestCase {
110
153
XCTAssertEqual ( firstRange, expected. first, file: file, line: line)
111
154
}
112
155
113
- expectStringRanges ( " " , " " , [ 0 ..< 0 ] )
114
- expectStringRanges ( " abcde " , " " , [ 0 ..< 0 , 1 ..< 1 , 2 ..< 2 , 3 ..< 3 , 4 ..< 4 , 5 ..< 5 ] )
115
- expectStringRanges ( " abcde " , " abcd " , [ 0 ..< 4 ] )
116
- expectStringRanges ( " abcde " , " bcde " , [ 1 ..< 5 ] )
117
- expectStringRanges ( " abcde " , " bcd " , [ 1 ..< 4 ] )
118
- expectStringRanges ( " ababacabababa " , " abababa " , [ 6 ..< 13 ] )
119
- expectStringRanges ( " ababacabababa " , " aba " , [ 0 ..< 3 , 6 ..< 9 , 10 ..< 13 ] )
156
+ expectRanges ( " " , " " , [ 0 ..< 0 ] )
157
+ expectRanges ( " abcde " , " " , [ 0 ..< 0 , 1 ..< 1 , 2 ..< 2 , 3 ..< 3 , 4 ..< 4 , 5 ..< 5 ] )
158
+ expectRanges ( " abcde " , " abcd " , [ 0 ..< 4 ] )
159
+ expectRanges ( " abcde " , " bcde " , [ 1 ..< 5 ] )
160
+ expectRanges ( " abcde " , " bcd " , [ 1 ..< 4 ] )
161
+ expectRanges ( " ababacabababa " , " abababa " , [ 6 ..< 13 ] )
162
+ expectRanges ( " ababacabababa " , " aba " , [ 0 ..< 3 , 6 ..< 9 , 10 ..< 13 ] )
120
163
}
121
164
122
- func testSplit ( ) {
165
+ func testRegexSplit ( ) {
123
166
func expectSplit(
124
167
_ string: String ,
125
168
_ regex: String ,
@@ -138,6 +181,26 @@ class AlgorithmTests: XCTestCase {
138
181
expectSplit ( " a " , " a " , [ " " , " " ] )
139
182
expectSplit ( " a____a____a " , " _+ " , [ " a " , " a " , " a " ] )
140
183
expectSplit ( " ____a____a____a____ " , " _+ " , [ " " , " a " , " a " , " a " , " " ] )
184
+ }
185
+
186
+ func testStringSplit( ) {
187
+ func expectSplit(
188
+ _ string: String ,
189
+ _ separator: String ,
190
+ _ expected: [ Substring ] ,
191
+ file: StaticString = #file, line: UInt = #line
192
+ ) {
193
+ let actual = Array ( string. split ( separator: separator, omittingEmptySubsequences: false ) )
194
+ XCTAssertEqual ( actual, expected, file: file, line: line)
195
+ }
196
+
197
+ expectSplit ( " " , " " , [ " " ] )
198
+ expectSplit ( " " , " x " , [ " " ] )
199
+ expectSplit ( " a " , " " , [ " " , " a " , " " ] )
200
+ expectSplit ( " a " , " x " , [ " a " ] )
201
+ expectSplit ( " a " , " a " , [ " " , " " ] )
202
+ expectSplit ( " a__a__a " , " _ " , [ " a " , " " , " a " , " " , " a " ] )
203
+ expectSplit ( " _a_a_a_ " , " _ " , [ " " , " a " , " a " , " a " , " " ] )
141
204
142
205
XCTAssertEqual ( " " . split ( separator: " " ) , [ ] )
143
206
XCTAssertEqual ( " " . split ( separator: " " , omittingEmptySubsequences: false ) , [ " " ] )
@@ -149,6 +212,24 @@ class AlgorithmTests: XCTestCase {
149
212
XCTAssert ( type ( of: splitParamsRef) == ( ( Character, Int, Bool) - > [ Substring] ) . self)
150
213
}
151
214
215
+ func testSplitSourceCompatibility( ) {
216
+ CountedOptionSet . arrayLiteralCreationCount = 0
217
+
218
+ let both : CountedOptionSet = [ . one, . two]
219
+ let none : CountedOptionSet = [ ]
220
+ XCTAssertEqual ( CountedOptionSet . arrayLiteralCreationCount, 2 )
221
+
222
+ let cosArray = [ both, . one, . two]
223
+ XCTAssertEqual ( cosArray. split ( separator: none) . count, 1 )
224
+
225
+ // This tests that `contains([])` uses the element-based `contains(_:)`
226
+ // method, interpreting `[]` as an instance of `CountedOptionSet`, rather
227
+ // than the collection-based overload, which would interpret `[]` as an
228
+ // `Array<CountedOptionSet>`.
229
+ XCTAssertEqual ( cosArray. split ( separator: [ ] ) . count, 1 )
230
+ XCTAssertEqual ( CountedOptionSet . arrayLiteralCreationCount, 3 )
231
+ }
232
+
152
233
func testSplitPermutations( ) throws {
153
234
let splitRegex = try Regex ( #"\|"# )
154
235
XCTAssertEqual (
@@ -276,7 +357,7 @@ class AlgorithmTests: XCTestCase {
276
357
XCTAssertEqual ( " a " . trimmingPrefix ( while: \. isWhitespace) , " a " )
277
358
}
278
359
279
- func testReplace ( ) {
360
+ func testRegexReplace ( ) {
280
361
func expectReplace(
281
362
_ string: String ,
282
363
_ regex: String ,
@@ -300,8 +381,33 @@ class AlgorithmTests: XCTestCase {
300
381
expectReplace ( " aab " , " a " , " X " , " XXb " )
301
382
expectReplace ( " aab " , " a+ " , " X " , " Xb " )
302
383
expectReplace ( " aab " , " a* " , " X " , " XXbX " )
384
+
385
+ // FIXME: Test maxReplacements
386
+ // FIXME: Test closure-based replacement
303
387
}
304
388
389
+ func testStringReplace( ) {
390
+ func expectReplace(
391
+ _ string: String ,
392
+ _ pattern: String ,
393
+ _ replacement: String ,
394
+ _ expected: String ,
395
+ file: StaticString = #file, line: UInt = #line
396
+ ) {
397
+ let actual = string. replacing ( pattern, with: replacement)
398
+ XCTAssertEqual ( actual, expected, file: file, line: line)
399
+ }
400
+
401
+ expectReplace ( " " , " " , " X " , " X " )
402
+ expectReplace ( " " , " x " , " X " , " " )
403
+ expectReplace ( " a " , " " , " X " , " XaX " )
404
+ expectReplace ( " a " , " x " , " X " , " a " )
405
+ expectReplace ( " a " , " a " , " X " , " X " )
406
+ expectReplace ( " aab " , " a " , " X " , " XXb " )
407
+
408
+ // FIXME: Test maxReplacements
409
+ }
410
+
305
411
func testSubstring( ) throws {
306
412
let s = " aaa | aaaaaa | aaaaaaaaaa "
307
413
let s1 = s. dropFirst ( 6 ) // "aaaaaa | aaaaaaaaaa"
0 commit comments