Group @testable imports at the bottom, per public/rules-swift's swiftformat. A behavior-preserving import-ordering reformat across 252 files (mostly tests). --trailingclosures was deliberately not adopted (cosmetic, and swiftformat flags it as caution-worthy).
84 lines
2.9 KiB
Swift
84 lines
2.9 KiB
Swift
import Testing
|
|
@testable import PureXML
|
|
|
|
@Suite("Regex Unicode categories and class subtraction")
|
|
struct RegexCategoryTests {
|
|
private func matches(_ pattern: String, _ string: String) throws -> Bool {
|
|
try PureXML.Regex.matches(pattern, string)
|
|
}
|
|
|
|
@Test("\\p{L} matches a letter group and rejects non-letters")
|
|
func test_letterGroup() throws {
|
|
#expect(try matches("\\p{L}+", "abcÅ"))
|
|
#expect(try !matches("\\p{L}+", "ab1"))
|
|
}
|
|
|
|
@Test("\\p{Lu} and \\p{Ll} distinguish case")
|
|
func test_caseCategories() throws {
|
|
#expect(try matches("\\p{Lu}\\p{Ll}+", "Hello"))
|
|
#expect(try !matches("\\p{Lu}\\p{Ll}+", "hello"))
|
|
}
|
|
|
|
@Test("\\p{Nd} matches decimal digits")
|
|
func test_decimalNumber() throws {
|
|
#expect(try matches("\\p{Nd}+", "2026"))
|
|
#expect(try !matches("\\p{Nd}+", "12a"))
|
|
}
|
|
|
|
@Test("\\P{...} negates a category")
|
|
func test_negatedCategory() throws {
|
|
#expect(try matches("\\P{L}+", "123 !"))
|
|
#expect(try !matches("\\P{L}+", "12a"))
|
|
}
|
|
|
|
@Test("A category inside a character class composes with ranges")
|
|
func test_categoryInClass() throws {
|
|
// A letter or an underscore.
|
|
#expect(try matches("[\\p{L}_]+", "a_b"))
|
|
#expect(try !matches("[\\p{L}_]+", "a-b"))
|
|
}
|
|
|
|
@Test("\\p{IsBasicLatin} tests a Unicode block")
|
|
func test_block() throws {
|
|
#expect(try matches("\\p{IsBasicLatin}+", "abc"))
|
|
#expect(try !matches("\\p{IsBasicLatin}+", "abç"))
|
|
}
|
|
|
|
@Test("\\p{IsArabic} tests the Arabic block")
|
|
func test_arabicBlock() throws {
|
|
#expect(try matches("\\p{IsArabic}+", "\u{0627}\u{0628}"))
|
|
// Adjacent Arabic block scalars that Swift fuses into one grapheme cluster.
|
|
#expect(try matches("\\p{IsArabic}+", "\u{0600}\u{0601}"))
|
|
// Base letter plus combining mark: two XSD characters, one grapheme.
|
|
#expect(try matches("\\p{IsArabic}+", "\u{0627}\u{064B}"))
|
|
#expect(try !matches("\\p{IsArabic}+", "abc"))
|
|
}
|
|
|
|
@Test("An unknown category name is a compile error")
|
|
func test_unknownCategory() {
|
|
#expect(throws: PureXML.Regex.RegexError.self) {
|
|
_ = try PureXML.Regex.Pattern("\\p{Zz}")
|
|
}
|
|
}
|
|
|
|
@Test("Character-class subtraction removes the subtrahend")
|
|
func test_subtraction() throws {
|
|
#expect(try matches("[a-z-[aeiou]]+", "bcdfg"))
|
|
#expect(try !matches("[a-z-[aeiou]]+", "bce"))
|
|
}
|
|
|
|
@Test("Subtraction nests")
|
|
func test_nestedSubtraction() throws {
|
|
// a-z, minus (b-d minus c): so b and d are removed, c stays.
|
|
#expect(try matches("[a-z-[b-d-[c]]]+", "acez"))
|
|
#expect(try !matches("[a-z-[b-d-[c]]]+", "abz"))
|
|
}
|
|
|
|
@Test("Subtraction composes with a category subtrahend")
|
|
func test_subtractCategory() throws {
|
|
// Any letter that is not lowercase.
|
|
#expect(try matches("[\\p{L}-[\\p{Ll}]]+", "ABC"))
|
|
#expect(try !matches("[\\p{L}-[\\p{Ll}]]+", "ABc"))
|
|
}
|
|
}
|