import Testing @testable import PureXML @Suite("RELAX NG typed value-space comparison") struct RelaxNGValueSpaceTests { private let xsd = "http://www.w3.org/2001/XMLSchema-datatypes" private func validXML(_ rng: String, _ xml: String) throws -> Bool { try PureXML.Schema.RelaxNG(rng).validate(xml) } private func validRNC(_ rnc: String, _ xml: String) throws -> Bool { try PureXML.Schema.RelaxNG(compact: rnc).validate(xml) } private func valueElement(_ type: String, _ literal: String) -> String { """ \(literal) """ } @Test("An integer value matches in value space, not lexically") func test_integerValueSpace() throws { let rng = valueElement("integer", "1") #expect(try validXML(rng, "1")) #expect(try validXML(rng, "01")) #expect(try validXML(rng, "+1")) #expect(try !validXML(rng, "2")) #expect(try !validXML(rng, "1x")) } @Test("A decimal value matches regardless of trailing zeros") func test_decimalValueSpace() throws { let rng = valueElement("decimal", "1.5") #expect(try validXML(rng, "1.5")) #expect(try validXML(rng, "1.50")) #expect(try validXML(rng, "01.500")) #expect(try !validXML(rng, "1.6")) } @Test("A boolean value treats 1/true and 0/false as equal") func test_booleanValueSpace() throws { let trueRNG = valueElement("boolean", "true") #expect(try validXML(trueRNG, "true")) #expect(try validXML(trueRNG, "1")) #expect(try !validXML(trueRNG, "false")) #expect(try !validXML(trueRNG, "0")) } @Test("A token value still compares by normalized lexical form") func test_tokenLexical() throws { // Untyped value defaults to token: whitespace collapses, then compares. let rng = """ yes please """ #expect(try validXML(rng, "yes please")) #expect(try validXML(rng, " yes please ")) #expect(try !validXML(rng, "no")) } @Test("A string value preserves and compares exactly after the type's whitespace rule") func test_stringPreserve() throws { let rng = valueElement("string", "abc") #expect(try validXML(rng, "abc")) #expect(try !validXML(rng, "abcd")) } @Test("Compact syntax typed value compares in value space") func test_compactIntegerValue() throws { let rnc = """ namespace x = "urn:x" element n { xsd:integer "10" } """ #expect(try validRNC(rnc, "10")) #expect(try validRNC(rnc, "010")) #expect(try !validRNC(rnc, "11")) } @Test("Compact bare string literal is a token value") func test_compactBareLiteral() throws { let rnc = "element flag { \"on\" }" #expect(try validRNC(rnc, "on")) #expect(try validRNC(rnc, " on ")) #expect(try !validRNC(rnc, "off")) } @Test("SimpleType.valueMatches compares numeric value space directly") func test_valueMatchesUnit() { let integer = PureXML.Schema.SimpleType(base: .integer) #expect(integer.valueMatches("007", literal: "7")) #expect(!integer.valueMatches("7", literal: "8")) let token = PureXML.Schema.SimpleType(base: .token) #expect(token.valueMatches(" a b ", literal: "a b")) #expect(!token.valueMatches("a b", literal: "ab")) } }