Skip to content

Commit c994b4b

Browse files
committed
Swift: Create test cases for a regular expression library.
1 parent 93215ba commit c994b4b

2 files changed

Lines changed: 209 additions & 0 deletions

File tree

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
2+
// --- stubs ---
3+
4+
struct Locale {
5+
}
6+
7+
struct AnyRegexOutput {
8+
}
9+
10+
protocol RegexComponent<RegexOutput> {
11+
associatedtype RegexOutput
12+
}
13+
14+
struct Regex<Output> : RegexComponent {
15+
struct Match {
16+
}
17+
18+
init(_ pattern: String) throws where Output == AnyRegexOutput { }
19+
20+
func firstMatch(in string: String) throws -> Regex<Output>.Match? { return nil}
21+
func prefixMatch(in string: String) throws -> Regex<Output>.Match? { return nil}
22+
func wholeMatch(in string: String) throws -> Regex<Output>.Match? { return nil}
23+
24+
typealias RegexOutput = Output
25+
}
26+
27+
extension RangeReplaceableCollection {
28+
mutating func replace<Replacement>(_ regex: some RegexComponent, with replacement: Replacement, maxReplacements: Int = .max) where Replacement : Collection, Replacement.Element == Character { }
29+
func replacing<Replacement>(_ regex: some RegexComponent, with replacement: Replacement, maxReplacements: Int = .max) -> Self where Replacement: Collection, Replacement.Element == Character { return self }
30+
mutating func trimPrefix(_ regex: some RegexComponent) { }
31+
}
32+
33+
extension StringProtocol {
34+
func range<T>(of aString: T, options mask:String.CompareOptions = [], range searchRange: Range<Self.Index>? = nil, locale: Locale? = nil) -> Range<Self.Index>? where T : StringProtocol { return nil }
35+
func replacingOccurrences<Target, Replacement>(of target: Target, with replacement: Replacement, options: String.CompareOptions = [], range searchRange: Range<Self.Index>? = nil) -> String where Target : StringProtocol, Replacement : StringProtocol { return "" }
36+
}
37+
38+
extension String : RegexComponent {
39+
typealias CompareOptions = NSString.CompareOptions
40+
typealias Output = Substring
41+
typealias RegexOutput = String.Output
42+
}
43+
44+
class NSObject {
45+
}
46+
47+
class NSString : NSObject {
48+
struct CompareOptions : OptionSet {
49+
var rawValue: UInt
50+
51+
static var regularExpression: NSString.CompareOptions { get { return CompareOptions(rawValue: 1) } }
52+
}
53+
54+
convenience init(string aString: String) { self.init() }
55+
56+
func range(of searchString: String, options mask: NSString.CompareOptions = []) -> NSRange { return NSRange(location: 0, length: 0) }
57+
func replacingOccurrences(of target: String, with replacement: String, options: NSString.CompareOptions = [], range searchRange: NSRange) -> String { return "" }
58+
59+
var length: Int { get { return 0 } }
60+
}
61+
62+
class NSMutableString : NSString {
63+
}
64+
65+
struct _NSRange {
66+
init(location: Int, length: Int) { }
67+
}
68+
69+
typealias NSRange = _NSRange
70+
71+
func NSMakeRange(_ loc: Int, _ len: Int) -> NSRange { return NSRange(location: loc, length: len) }
72+
73+
class NSTextCheckingResult : NSObject {
74+
}
75+
76+
class NSRegularExpression : NSObject {
77+
struct Options : OptionSet {
78+
var rawValue: UInt
79+
}
80+
81+
struct MatchingOptions : OptionSet {
82+
var rawValue: UInt
83+
}
84+
85+
init(pattern: String, options: NSRegularExpression.Options = []) throws { }
86+
87+
// some types have been simplified a little here
88+
func numberOfMatches(in string: String, options: NSRegularExpression.MatchingOptions = [], range: NSRange) -> Int { return 0 }
89+
func enumerateMatches(in string: String, options: NSRegularExpression.MatchingOptions = [], range: NSRange, using block: (Int, Int, Int) -> Void) { }
90+
func matches(in string: String, options: NSRegularExpression.MatchingOptions = [], range: NSRange) -> [NSTextCheckingResult] { return [] }
91+
func firstMatch(in string: String, options: NSRegularExpression.MatchingOptions = [], range: NSRange) -> NSTextCheckingResult? { return nil }
92+
func rangeOfFirstMatch(in string: String, options: NSRegularExpression.MatchingOptions = [], range: NSRange) -> NSRange { return NSRange(location: 0, length: 0) }
93+
func replaceMatches(in string: NSMutableString, options: NSRegularExpression.MatchingOptions = [], range: NSRange, withTemplate templ: String) -> Int { return 0 }
94+
func stringByReplacingMatches(in string: String, options: NSRegularExpression.MatchingOptions = [], range: NSRange, withTemplate templ: String) -> String { return "" }
95+
}
96+
97+
// --- tests ---
98+
99+
func myRegexpMethodsTests() throws {
100+
let input = "abcdef"
101+
let regex = try Regex(".*")
102+
103+
// --- Regex ---
104+
105+
_ = try regex.firstMatch(in: input)
106+
_ = try regex.prefixMatch(in: input)
107+
_ = try regex.wholeMatch(in: input)
108+
109+
// --- RangeReeplaceableCollection ---
110+
111+
var inputVar = input
112+
inputVar.replace(regex, with: "")Var
113+
_ = input.replacing(regex, with: "")
114+
inputVar.trimPrefix(regex)Var
115+
116+
// --- StringProtocol ---
117+
118+
_ = input.range(of: ".*", options: .regularExpression, range: nil, locale: nil)
119+
_ = input.replacingOccurrences(of: ".*", with: "", options: .regularExpression)
120+
121+
// --- NSRegularExpression ---
122+
123+
let nsregex = try NSRegularExpression(pattern: ".*")
124+
_ = nsregex.numberOfMatches(in: input, options: [], range: NSRange(location: 0, length: input.utf16.count))
125+
nsregex.enumerateMatches(in: input, range: NSMakeRange(0, input.utf16.count), using: {a, b, c in } )
126+
_ = nsregex.matches(in: input, range: NSMakeRange(0, input.utf16.count))
127+
_ = nsregex.firstMatch(in: input, range: NSMakeRange(0, input.utf16.count))
128+
_ = nsregex.rangeOfFirstMatch(in: input, range: NSMakeRange(0, input.utf16.count))
129+
_ = nsregex.replaceMatches(in: NSMutableString(string: input), range: NSMakeRange(0, input.utf16.count), withTemplate: "")
130+
_ = nsregex.stringByReplacingMatches(in: input, range: NSMakeRange(0, input.utf16.count), withTemplate: "")
131+
132+
// --- NSString ---
133+
134+
let inputNS = NSString(string: "abcdef")
135+
_ = inputNS.range(of: "*", options: .regularExpression)
136+
_ = inputNS.replacingOccurrences(of: ".*", with: "", options: .regularExpression, range: NSMakeRange(0, inputNS.length))
137+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// these tests require Swift 5.7 or so, and currently require the
2+
// `-enable-bare-slash-regex` compiler flag.
3+
4+
// --- stubs ---
5+
6+
struct AnyRegexOutput {
7+
}
8+
9+
protocol RegexComponent<RegexOutput> {
10+
associatedtype RegexOutput
11+
}
12+
13+
struct Regex<Output> : RegexComponent {
14+
struct Match {
15+
}
16+
17+
init(_ pattern: String) throws where Output == AnyRegexOutput { }
18+
19+
func firstMatch(in string: String) throws -> Regex<Output>.Match? { return nil }
20+
21+
typealias RegexOutput = Output
22+
}
23+
24+
extension BidirectionalCollection {
25+
func contains(_ regex: some RegexComponent) -> Bool { return false }
26+
func firstMatch<Output>(of r: some RegexComponent<Output>) -> Regex<Output>.Match? { return nil } // slightly simplified
27+
func firstMatch<Output>(of r: some RegexComponent) -> Regex<Output>.Match? where SubSequence == Substring { return nil }
28+
func firstRange(of regex: some RegexComponent) -> Range<Self.Index>? { return nil }
29+
func matches<Output>(of r: some RegexComponent<Output>) -> [Regex<Output>.Match] { return [] } // slightly simplified
30+
func prefixMatch<R>(of regex: R) -> Regex<R.RegexOutput>.Match? where R: RegexComponent { return nil }
31+
func ranges(of regex: some RegexComponent) -> [Range<Self.Index>] { return [] }
32+
func starts(with regex: some RegexComponent) -> Bool { return false }
33+
func trimmingPrefix(_ regex: some RegexComponent) -> Self.SubSequence { return self.suffix(0) }
34+
func split(separator: some RegexComponent, maxSplits: Int = .max, omittingEmptySubsequences: Bool = true) -> [Self.SubSequence] { return [] }
35+
}
36+
37+
extension String : RegexComponent {
38+
typealias Output = Substring
39+
typealias RegexOutput = String.Output
40+
}
41+
42+
// --- tests ---
43+
44+
func myRegexpMethodsTests() throws {
45+
let input = "abcdef"
46+
let regex = try Regex(".*")
47+
48+
// --- BidirectionalCollection ---
49+
50+
_ = input.contains(regex)
51+
_ = input.firstMatch(of: regex)
52+
_ = input.firstRange(of: regex)
53+
_ = input.matches(of: regex)
54+
_ = input.prefixMatch(of: regex)
55+
_ = input.ranges(of: regex)
56+
_ = input.starts(with: regex)
57+
_ = input.trimmingPrefix(regex)
58+
_ = input.split(separator: regex)
59+
60+
// --- compile time regexps ---
61+
62+
let regex2 = /a*b*/
63+
_ = try regex2.firstMatch(in: input)
64+
65+
let regex3 = /(?<varname>a*)*b/
66+
_ = try regex3.firstMatch(in: input)
67+
68+
let regex4 = #/a*b*/#
69+
_ = try regex4.firstMatch(in: input)
70+
71+
_ = input.contains(/a*b*/)
72+
}

0 commit comments

Comments
 (0)