/
RegexTests.swift
204 lines (161 loc) · 7.15 KB
/
RegexTests.swift
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
import XCTest
@testable import POSIX
public class RegexTests: XCTestCase {
func testInvalidRegex() {
XCTAssertThrowsError(try Regex(pattern: "("))
XCTAssertThrowsError(try Regex(pattern: "*"))
}
func testMatches() throws {
let regex = try Regex(pattern: "hello")
let matches = regex.matches(in: "hello")
XCTAssert(matches)
}
func testNotMatches() throws {
let regex = try Regex(pattern: "hello")
let matches = regex.matches(in: "bye")
XCTAssert(!matches)
}
func testGroup() throws {
let regex = try Regex(pattern: "(hello)")
let groups = regex.groups(in: "hello")
XCTAssert(groups == ["hello"])
}
func testGroups() throws {
let regex = try Regex(pattern: "(hello) (world)")
let groups = regex.groups(in: "hello world")
XCTAssert(groups == ["hello", "world"])
}
func testNoGroups() throws {
let regex = try Regex(pattern: "(hello)")
let groups = regex.groups(in: "bye")
XCTAssert(groups == [])
}
/// Replace one occurence by a shorter template string
func testReplaceOneOccurenceWithShorterTemplate() throws {
let regex = try Regex(pattern: "hello")
let string = regex.replace(in: "hello world", with: "bye")
XCTAssert(string == "bye world")
}
/// Replace one occurence by a longer template string
func testReplaceOneOccurenceWithLongerTemplate() throws {
let regex = try Regex(pattern: "o")
let string = regex.replace(in: "hello", with: "ooo!")
XCTAssertEqual(string, "hellooo!")
}
/// Replace multiple occurences each by a shorter template string
func testReplaceManyOccurencesWithShorterTemplate() throws {
let regex = try Regex(pattern: "mm")
let string = regex.replace(in: "mm-mm", with: "M")
XCTAssertEqual(string, "M-M")
}
/// Replace multiple occurences each by a longer template string
func testReplaceManyOccurencesWithLongerTemplate() throws {
let regex = try Regex(pattern: "l")
let string = regex.replace(in: "lol", with: "LL")
XCTAssertEqual(string, "LLoLL")
}
/// Replace each digit
func testReplaceDigits() throws {
let regex = try Regex(pattern: "[0-9]")
let string = regex.replace(in: "1234", with: ".")
XCTAssertEqual(string, "....")
}
/// Replace number
func testReplaceNumber() throws {
let regex = try Regex(pattern: "[0-9]+")
let string = regex.replace(in: "1234", with: ".")
XCTAssertEqual(string, ".")
}
func testNoReplace() throws {
let regex = try Regex(pattern: "bye")
let string = regex.replace(in: "hello world", with: "bye")
XCTAssert(string == "hello world")
}
func testReplaceUTF8() throws {
let r0 = try Regex(pattern: "coffee")
let actual0 = r0.replace(in: "Paulo loves coffee", with: "☕️")
XCTAssertEqual(actual0, "Paulo loves ☕️")
}
func testMultipleReplacesUTF8() throws {
let r1 = try Regex(pattern: "[[:digit:]]{4}")
let actual1 = r1.replace(in: "1234-2345-3456-4567", with: "💳")
XCTAssertEqual(actual1, "💳-💳-💳-💳")
}
/// MARK: - matching test
func testMatchesUsingOperators() throws {
XCTAssert(try ("hello world" ~ "hello"))
XCTAssert(("hello world" ~? "hello")!)
XCTAssert(try "hello world" ~ "[[:alpha:]]")
XCTAssert(try "hello world 1" ~ "[[:digit:]]")
XCTAssertFalse(try "hello world" ~ "[[:digit:]]")
// invalid Regex
XCTAssertThrowsError(try "hello world 1" ~ "*")
XCTAssertNil( "hello world 1" ~? "*")
// slightly more complex regexes
XCTAssert( try "111-2222-333" ~ "[[:digit:]]{3}-[[:digit:]]{4}-[[:digit:]]{3}")
XCTAssert( try "111-aaaa-333" ~ "[[:digit:]]{3}-[[:alpha:]]{4}-[[:digit:]]{3}")
XCTAssertFalse(try "111-aaaa-333" ~ "[[:digit:]]{3}-[[:digit:]]{4}-[[:digit:]]{3}")
// no throws or optionals if regex pre-exists
let r0 = try Regex(pattern: "[[:alpha:]]")
XCTAssert("hello world 1" ~ r0)
let r1 = try Regex(pattern: "[[:digit:]]{3}-[[:digit:]]{4}-[[:digit:]]{3}")
XCTAssert("111-2222-333" ~ r1)
}
func testGroupsUsingOperators() throws {
// one group
let digits = try Regex(pattern: "[[:digit:]]{3}-([[:digit:]]{4})-[[:digit:]]{3}")
XCTAssertEqual("111-2222-333" ~* digits, ["2222"])
let actual0 = ("111-2222-333" ~* digits).map { s in Int(s)! }
XCTAssertEqual(actual0, [2222])
// two groups
let actual1 = (try "hel lo world" ~* "(hel)[[:space:]]?(lo)")
XCTAssertEqual(actual1, ["hel", "lo"])
// using map
let actual2 = (try "hel lo world" ~* "(hel)[[:space:]]?(lo)").map { s in s.uppercased() }
XCTAssertEqual(actual2, ["HEL", "LO"])
// casting with flatMap
let actual3 = (try "Paulo have 3 cats" ~* "([[:digit:]]+)").flatMap { (v: String) -> Int? in
return Int(v)
}
XCTAssertEqual(actual3, [3])
// matching the empty string bails out
let actual4 = try "I have 3 cats" ~* "([[:digit:]]*)"
XCTAssertEqual(actual4, [])
XCTAssertEqual(try "I have 3 cats" ~* "([[:digit:]]+)", ["3"])
XCTAssertEqual(try "Paulo has 3 cats" ~* "([[:alpha:]]+).*([[:digit:]]+)", ["Paulo", "3"])
// using utf8
XCTAssertEqual(try "Paulo likes ☕️" ~* "([[:alpha:]]+).*(☕️)", ["Paulo", "☕️"])
//: using an existing Regex instance
let r1 = try Regex(pattern: "(hel)(lo)")
XCTAssertEqual("hello world" ~* r1, ["hel", "lo"])
/// example with mapped
let actual5 = ("hello world" ~* r1).map { match in return match.uppercased() }
XCTAssertEqual(actual5, ["HEL", "LO"])
/// example with flatMap
let actual6 = ("hello world" ~* r1).flatMap { (v: String) -> String? in
return v.contains("lo") ? v.uppercased() : nil
}
XCTAssertEqual(actual6, ["LO"])
}
}
extension RegexTests {
public static var allTests: [(String, (RegexTests) -> () throws -> Void)] {
return [
("testInvalidRegex", testInvalidRegex),
("testMatches", testMatches),
("testNotMatches", testNotMatches),
("testGroup", testGroup),
("testGroups", testGroups),
("testNoGroups", testNoGroups),
("testReplaceOneOccurenceWithShorterTemplate", testReplaceOneOccurenceWithShorterTemplate),
("testReplaceOneOccurenceWithLongerTemplate", testReplaceOneOccurenceWithLongerTemplate),
("testReplaceManyOccurencesWithShorterTemplate", testReplaceManyOccurencesWithShorterTemplate),
("testReplaceManyOccurencesWithLongerTemplate", testReplaceManyOccurencesWithLongerTemplate),
("testReplaceDigits", testReplaceDigits),
("testReplaceNumber", testReplaceNumber),
("testNoReplace", testNoReplace),
("testMatchesUsingOperators", testMatchesUsingOperators),
("testGroupsUsingOperators", testGroupsUsingOperators),
]
}
}