import Testing
@testable import PureXML
/// Cross-cutting conformance fixtures for both schema languages: realistic
/// schemas validated against valid and invalid instances.
@Suite("Schema conformance")
struct SchemaConformanceTests {
// MARK: A realistic XSD: a purchase order
private let purchaseOrderXSD = """
"""
@Test("Purchase order: a fully conforming document")
func test_orderValid() throws {
let schema = try PureXML.Schema.Document(purchaseOrderXSD)
let xml = """
- 123-AB5
\
- 999-ZZ999
"""
#expect(try schema.validate(xml).isEmpty)
}
@Test("Purchase order: each constraint is enforced")
func test_orderViolations() throws {
let schema = try PureXML.Schema.Document(purchaseOrderXSD)
// Bad SKU pattern.
#expect(try !schema.validate("- bad5
").isEmpty)
// Quantity above the maxInclusive.
#expect(try !schema.validate("- 123-AB1000
").isEmpty)
// Quantity not positive.
#expect(try !schema.validate("- 123-AB0
").isEmpty)
// Missing the required id attribute.
#expect(try !schema.validate("- 123-AB5
").isEmpty)
// At least one item is required.
#expect(try !schema.validate("").isEmpty)
}
// MARK: A realistic RELAX NG: a contact card with attributes and interleave
private let contactRNG = """
personcompany
"""
@Test("Contact: valid documents in varying order")
func test_contactValid() throws {
let schema = try PureXML.Schema.RelaxNG(contactRNG)
#expect(try schema.validate("Ada"))
#expect(try schema.validate("""
1Acme\
a@b.c2
"""))
}
@Test("Contact: invalid documents are rejected")
func test_contactInvalid() throws {
let schema = try PureXML.Schema.RelaxNG(contactRNG)
// Missing the required kind attribute.
#expect(try !schema.validate("Ada"))
// kind not one of the allowed values.
#expect(try !schema.validate("Ada"))
// Missing the required name element.
#expect(try !schema.validate("a@b.c"))
// Two names (name is not repeatable).
#expect(try !schema.validate("AB"))
}
// MARK: Datatype boundary fixtures
private struct DatatypeCase {
let value: String
let type: PureXML.Schema.BuiltinType
let expected: Bool
}
@Test("Datatype boundaries across the type library")
func test_datatypeBoundaries() {
let cases: [DatatypeCase] = [
.init(value: "2024-02-29", type: .date, expected: true),
.init(value: "2025-02-29", type: .date, expected: false),
.init(value: "9223372036854775807", type: .long, expected: true),
.init(value: "9223372036854775808", type: .long, expected: false),
.init(value: "P1Y", type: .duration, expected: true),
.init(value: "1Y", type: .duration, expected: false),
.init(value: "0.1", type: .decimal, expected: true),
.init(value: "1.0e3", type: .decimal, expected: false),
.init(value: "true", type: .boolean, expected: true),
.init(value: "urn:example:x", type: .anyURI, expected: true),
]
for testCase in cases {
#expect(
PureXML.Schema.isValid(testCase.value, type: testCase.type) == testCase.expected,
"\(testCase.value) as \(testCase.type.rawValue)",
)
}
}
}