@testable import PureXML import Testing @Suite("Streaming XSD validation") struct StreamingXSDTests { private let schema = """ """ /// Streaming validation must agree with the tree validator on the same /// document (these schemas carry no identity constraints, so the tree output /// is exactly the content/attribute errors streaming produces). Agreement on /// every document is the correctness proof. private func check(_ xml: String, expectValid: Bool) throws { let document = try PureXML.Schema.Document(schema) let tree = try document.validate(xml).map(\.reason).sorted() let streamed = try document.validate(streaming: xml).map(\.reason).sorted() #expect(tree == streamed, "streaming disagreed with tree on: \(xml)\n tree: \(tree)\n stream: \(streamed)") #expect(streamed.isEmpty == expectValid, "wrong verdict for: \(xml) -> \(streamed)") } @Test("Valid documents agree and pass") func test_valid() throws { try check("1x2", expectValid: true) // Repeated item (maxOccurs unbounded), optional ref omitted. try check( "1x2" + "y9", expectValid: true, ) } @Test("Invalid documents agree and fail") func test_invalid() throws { // Missing required attribute sku. try check("1x2", expectValid: false) // A bad xs:int value for id. try check("notanintx2", expectValid: false) // A bad xs:positiveInteger value for qty. try check("1x0", expectValid: false) // Missing required child qty. try check("1x", expectValid: false) // Children out of order. try check("12x", expectValid: false) // An undeclared extra child. try check("1x2", expectValid: false) // An undeclared attribute. try check("1x2", expectValid: false) // No items at all (item is required, maxOccurs unbounded but minOccurs 1). try check("1", expectValid: false) } @Test("The streaming content check is a composable Validation value") func test_shallowValidityRule() { // The streaming content check applied directly through the Validation rule. let validator = PureXML.Schema.ComplexValidator() let rule = PureXML.Schema.ComplexValidator.shallowValidity #expect(rule.description == "Each streamed element is valid against its declared XSD type") // An empty-content element carrying a child element is invalid. let bad = PureXML.Schema.ResolvedElement( element: PureXML.Model.Element("v", children: [.element(.init("child"))]), type: .complex(PureXML.Schema.ComplexType(content: .empty)), ) let errors = rule.apply(to: bad, at: [.element("v")], in: validator) #expect(errors.contains { $0.reason.contains("must be empty") }) #expect(errors.first?.codingPath.map(\.stringValue) == ["v"]) } }