import Testing @testable import PureXML /// XSD regex (`xs:pattern`) conformance, driven through the validation /// framework (Tier 2): the XML Schema regex flavor against its spec semantics, /// exercised end to end through pattern-facet validation. @Suite("Conformance corpus: XSD regex patterns") struct ConformanceRegexTests { private struct PatternSpec { let name: String let pattern: String let value: String let valid: Bool } private func corpus() throws -> [PureXML.Validation.ConformanceCase] { let specs = [ // Whole-string anchoring is implicit in the XSD flavor. PatternSpec(name: "implicit-anchoring", pattern: "abc", value: "xabcx", valid: false), PatternSpec(name: "exact-match", pattern: "abc", value: "abc", valid: true), // Character-class escapes. PatternSpec(name: "digits-ok", pattern: "\\d{3}", value: "123", valid: true), PatternSpec(name: "digits-fail", pattern: "\\d{3}", value: "12a", valid: false), // XSD \w excludes punctuation, so the connector `_` (Pc) is not a word char. PatternSpec(name: "word-chars", pattern: "\\w+", value: "abc1", valid: true), PatternSpec(name: "word-chars-no-underscore", pattern: "\\w", value: "_", valid: false), PatternSpec(name: "whitespace-escape", pattern: "a\\sb", value: "a b", valid: true), // Unicode categories and blocks. PatternSpec(name: "category-letters", pattern: "\\p{L}+", value: "abcé", valid: true), PatternSpec(name: "category-rejects-digit", pattern: "\\p{L}+", value: "ab1", valid: false), PatternSpec(name: "negated-category", pattern: "\\P{Nd}+", value: "abc", valid: true), // Quantifier ranges. PatternSpec(name: "range-min-ok", pattern: "a{2,3}", value: "aa", valid: true), PatternSpec(name: "range-over-max", pattern: "a{2,3}", value: "aaaa", valid: false), PatternSpec(name: "open-range", pattern: "a{2,}", value: "aaaaa", valid: true), // Alternation, grouping, class negation, subtraction. PatternSpec(name: "alternation", pattern: "(cat|dog)", value: "dog", valid: true), PatternSpec(name: "negated-class", pattern: "[^0-9]+", value: "abc", valid: true), PatternSpec(name: "negated-class-fail", pattern: "[^0-9]+", value: "a1c", valid: false), PatternSpec(name: "class-subtraction", pattern: "[a-z-[aeiou]]+", value: "bcd", valid: true), PatternSpec(name: "class-subtraction-fail", pattern: "[a-z-[aeiou]]+", value: "bad", valid: false), ] return try specs.map { spec in let xsd = """ """ let errors = try PureXML.Schema.Document(xsd).validate("\(spec.value)") return PureXML.Validation.ConformanceCase( name: spec.name, actual: errors.isEmpty ? "valid" : "invalid", expected: spec.valid ? "valid" : "invalid", ) } } @Test("The XSD regex conformance corpus passes with no located failures") func test_regexCorpusConforms() throws { let failures = try PureXML.Validation.Conformance.failures(in: corpus()) #expect(failures.isEmpty, "\(failures.map(\.reason))") } }