@@ -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 ,
@@ -75,6 +115,7 @@ class AlgorithmTests: XCTestCase {
75
115
expectRanges ( " " , " x " , [ ] )
76
116
expectRanges ( " " , " x+ " , [ ] )
77
117
expectRanges ( " " , " x* " , [ 0 ..< 0 ] )
118
+ expectRanges ( " aaa " , " a* " , [ 0 ..< 3 , 3 ..< 3 ] )
78
119
expectRanges ( " abc " , " " , [ 0 ..< 0 , 1 ..< 1 , 2 ..< 2 , 3 ..< 3 ] )
79
120
expectRanges ( " abc " , " x " , [ ] )
80
121
expectRanges ( " abc " , " x+ " , [ ] )
@@ -89,8 +130,10 @@ class AlgorithmTests: XCTestCase {
89
130
expectRanges ( " abc " , " (a|b)* " , [ 0 ..< 2 , 2 ..< 2 , 3 ..< 3 ] )
90
131
expectRanges ( " abc " , " (b|c)+ " , [ 1 ..< 3 ] )
91
132
expectRanges ( " abc " , " (b|c)* " , [ 0 ..< 0 , 1 ..< 3 , 3 ..< 3 ] )
92
-
93
- func expectStringRanges(
133
+ }
134
+
135
+ func testStringRanges( ) {
136
+ func expectRanges(
94
137
_ input: String ,
95
138
_ pattern: String ,
96
139
_ expected: [ Range < Int > ] ,
@@ -107,16 +150,16 @@ class AlgorithmTests: XCTestCase {
107
150
XCTAssertEqual ( firstRange, expected. first, file: file, line: line)
108
151
}
109
152
110
- expectStringRanges ( " " , " " , [ 0 ..< 0 ] )
111
- expectStringRanges ( " abcde " , " " , [ 0 ..< 0 , 1 ..< 1 , 2 ..< 2 , 3 ..< 3 , 4 ..< 4 , 5 ..< 5 ] )
112
- expectStringRanges ( " abcde " , " abcd " , [ 0 ..< 4 ] )
113
- expectStringRanges ( " abcde " , " bcde " , [ 1 ..< 5 ] )
114
- expectStringRanges ( " abcde " , " bcd " , [ 1 ..< 4 ] )
115
- expectStringRanges ( " ababacabababa " , " abababa " , [ 6 ..< 13 ] )
116
- expectStringRanges ( " ababacabababa " , " aba " , [ 0 ..< 3 , 6 ..< 9 , 10 ..< 13 ] )
153
+ expectRanges ( " " , " " , [ 0 ..< 0 ] )
154
+ expectRanges ( " abcde " , " " , [ 0 ..< 0 , 1 ..< 1 , 2 ..< 2 , 3 ..< 3 , 4 ..< 4 , 5 ..< 5 ] )
155
+ expectRanges ( " abcde " , " abcd " , [ 0 ..< 4 ] )
156
+ expectRanges ( " abcde " , " bcde " , [ 1 ..< 5 ] )
157
+ expectRanges ( " abcde " , " bcd " , [ 1 ..< 4 ] )
158
+ expectRanges ( " ababacabababa " , " abababa " , [ 6 ..< 13 ] )
159
+ expectRanges ( " ababacabababa " , " aba " , [ 0 ..< 3 , 6 ..< 9 , 10 ..< 13 ] )
117
160
}
118
161
119
- func testSplit ( ) {
162
+ func testRegexSplit ( ) {
120
163
func expectSplit(
121
164
_ string: String ,
122
165
_ regex: String ,
@@ -135,6 +178,26 @@ class AlgorithmTests: XCTestCase {
135
178
expectSplit ( " a " , " a " , [ " " , " " ] )
136
179
expectSplit ( " a____a____a " , " _+ " , [ " a " , " a " , " a " ] )
137
180
expectSplit ( " ____a____a____a____ " , " _+ " , [ " " , " a " , " a " , " a " , " " ] )
181
+ }
182
+
183
+ func testStringSplit( ) {
184
+ func expectSplit(
185
+ _ string: String ,
186
+ _ separator: String ,
187
+ _ expected: [ Substring ] ,
188
+ file: StaticString = #file, line: UInt = #line
189
+ ) {
190
+ let actual = Array ( string. split ( separator: separator, omittingEmptySubsequences: false ) )
191
+ XCTAssertEqual ( actual, expected, file: file, line: line)
192
+ }
193
+
194
+ expectSplit ( " " , " " , [ " " ] )
195
+ expectSplit ( " " , " x " , [ " " ] )
196
+ expectSplit ( " a " , " " , [ " " , " a " , " " ] )
197
+ expectSplit ( " a " , " x " , [ " a " ] )
198
+ expectSplit ( " a " , " a " , [ " " , " " ] )
199
+ expectSplit ( " a__a__a " , " _ " , [ " a " , " " , " a " , " " , " a " ] )
200
+ expectSplit ( " _a_a_a_ " , " _ " , [ " " , " a " , " a " , " a " , " " ] )
138
201
139
202
XCTAssertEqual ( " " . split ( separator: " " ) , [ ] )
140
203
XCTAssertEqual ( " " . split ( separator: " " , omittingEmptySubsequences: false ) , [ " " ] )
@@ -146,6 +209,24 @@ class AlgorithmTests: XCTestCase {
146
209
XCTAssert ( type ( of: splitParamsRef) == ( ( Character, Int, Bool) - > [ Substring] ) . self)
147
210
}
148
211
212
+ func testSplitSourceCompatibility( ) {
213
+ CountedOptionSet . arrayLiteralCreationCount = 0
214
+
215
+ let both : CountedOptionSet = [ . one, . two]
216
+ let none : CountedOptionSet = [ ]
217
+ XCTAssertEqual ( CountedOptionSet . arrayLiteralCreationCount, 2 )
218
+
219
+ let cosArray = [ both, . one, . two]
220
+ XCTAssertEqual ( cosArray. split ( separator: none) . count, 1 )
221
+
222
+ // This tests that `contains([])` uses the element-based `contains(_:)`
223
+ // method, interpreting `[]` as an instance of `CountedOptionSet`, rather
224
+ // than the collection-based overload, which would interpret `[]` as an
225
+ // `Array<CountedOptionSet>`.
226
+ XCTAssertEqual ( cosArray. split ( separator: [ ] ) . count, 1 )
227
+ XCTAssertEqual ( CountedOptionSet . arrayLiteralCreationCount, 3 )
228
+ }
229
+
149
230
func testSplitPermutations( ) throws {
150
231
let splitRegex = try Regex ( #"\|"# )
151
232
XCTAssertEqual (
@@ -273,7 +354,7 @@ class AlgorithmTests: XCTestCase {
273
354
XCTAssertEqual ( " a " . trimmingPrefix ( while: \. isWhitespace) , " a " )
274
355
}
275
356
276
- func testReplace ( ) {
357
+ func testRegexReplace ( ) {
277
358
func expectReplace(
278
359
_ string: String ,
279
360
_ regex: String ,
@@ -297,8 +378,33 @@ class AlgorithmTests: XCTestCase {
297
378
expectReplace ( " aab " , " a " , " X " , " XXb " )
298
379
expectReplace ( " aab " , " a+ " , " X " , " Xb " )
299
380
expectReplace ( " aab " , " a* " , " X " , " XXbX " )
381
+
382
+ // FIXME: Test maxReplacements
383
+ // FIXME: Test closure-based replacement
300
384
}
301
385
386
+ func testStringReplace( ) {
387
+ func expectReplace(
388
+ _ string: String ,
389
+ _ pattern: String ,
390
+ _ replacement: String ,
391
+ _ expected: String ,
392
+ file: StaticString = #file, line: UInt = #line
393
+ ) {
394
+ let actual = string. replacing ( pattern, with: replacement)
395
+ XCTAssertEqual ( actual, expected, file: file, line: line)
396
+ }
397
+
398
+ expectReplace ( " " , " " , " X " , " X " )
399
+ expectReplace ( " " , " x " , " X " , " " )
400
+ expectReplace ( " a " , " " , " X " , " XaX " )
401
+ expectReplace ( " a " , " x " , " X " , " a " )
402
+ expectReplace ( " a " , " a " , " X " , " X " )
403
+ expectReplace ( " aab " , " a " , " X " , " XXb " )
404
+
405
+ // FIXME: Test maxReplacements
406
+ }
407
+
302
408
func testSubstring( ) throws {
303
409
let s = " aaa | aaaaaa | aaaaaaaaaa "
304
410
let s1 = s. dropFirst ( 6 ) // "aaaaaa | aaaaaaaaaa"
0 commit comments