The two monolithic XSD content/identity rules only satisfied the OpenAPIKit validation idiom at the wrong granularity: no per-constraint removability, no isolable failing/near-miss tests. Split them into 32 named rules, each finding tagged at its origin and cached per XSDContext so the walk still runs once per document (the #101 decision against duplicating XSD's recursive type resolution still holds). Wired the streaming path's ID/IDREF and identity checks through the same framework instead of calling the validators imperatively, and added the unwrapAndLookup combinator the rule already named as required. Also includes the mandated repo-wide swiftformat/swiftlint pass.
85 lines
4.5 KiB
Swift
85 lines
4.5 KiB
Swift
import Testing
|
|
@testable import PureXML
|
|
|
|
/// Per-rule isolation tests (Validation rules XSD): the schema-consistency layer
|
|
/// (`PureXML.Validation.XSDSchema`), unrelated to instance validation.
|
|
@Suite("Validation rules XSD")
|
|
struct ValidationRuleXSDTests {
|
|
// MARK: XSDSchema (unchanged, schema-consistency layer)
|
|
|
|
@Test("XSDSchema.finalRespected rejects a derivation forbidden by final")
|
|
func test_xsdFinalRespected() throws {
|
|
let xsd = """
|
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
|
<xs:complexType name="ShapeT" final="extension">
|
|
<xs:sequence><xs:element name="name" type="xs:string"/></xs:sequence>
|
|
</xs:complexType>
|
|
<xs:complexType name="CircleT">
|
|
<xs:complexContent><xs:extension base="ShapeT"><xs:sequence><xs:element name="radius" type="xs:integer"/></xs:sequence></xs:extension></xs:complexContent>
|
|
</xs:complexType>
|
|
</xs:schema>
|
|
"""
|
|
let compiled = try PureXML.Schema.XSDParser.parse(xsd)
|
|
let facts = PureXML.Schema.CompiledSchemaFacts(types: compiled.types, typeDerivation: compiled.typeDerivation, typeFinal: compiled.typeFinal)
|
|
let fact = PureXML.Schema.SchemaTypeFact(name: "CircleT", derivation: compiled.typeDerivation["CircleT"])
|
|
let errors = PureXML.Validation.BuiltinValidation.xsdFinalRespected.apply(to: fact, at: [.element("CircleT")], in: facts)
|
|
#expect(errors.count == 1)
|
|
}
|
|
|
|
@Test("XSDSchema.finalRespected accepts a derivation the base permits")
|
|
func test_xsdFinalRespected_succeeds() throws {
|
|
let xsd = """
|
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
|
<xs:complexType name="ShapeT"><xs:sequence><xs:element name="name" type="xs:string"/></xs:sequence></xs:complexType>
|
|
</xs:schema>
|
|
"""
|
|
let compiled = try PureXML.Schema.XSDParser.parse(xsd)
|
|
let facts = PureXML.Schema.CompiledSchemaFacts(types: compiled.types, typeDerivation: compiled.typeDerivation, typeFinal: compiled.typeFinal)
|
|
let fact = PureXML.Schema.SchemaTypeFact(name: "ShapeT", derivation: nil)
|
|
#expect(PureXML.Validation.BuiltinValidation.xsdFinalRespected.apply(to: fact, at: [.element("ShapeT")], in: facts).isEmpty)
|
|
}
|
|
|
|
@Test("XSDSchema.restrictionsAreSubsets rejects an unfaithful restriction")
|
|
func test_xsdRestrictionsAreSubsets() throws {
|
|
let xsd = """
|
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
|
<xs:complexType name="B"><xs:sequence><xs:element name="a" type="xs:string"/></xs:sequence></xs:complexType>
|
|
<xs:complexType name="R">
|
|
<xs:complexContent>
|
|
<xs:restriction base="B">
|
|
<xs:sequence>
|
|
<xs:element name="a" type="xs:string"/>
|
|
<xs:element name="b" type="xs:string"/>
|
|
</xs:sequence>
|
|
</xs:restriction>
|
|
</xs:complexContent>
|
|
</xs:complexType>
|
|
</xs:schema>
|
|
"""
|
|
let compiled = try PureXML.Schema.XSDParser.parse(xsd)
|
|
let facts = PureXML.Schema.CompiledSchemaFacts(types: compiled.types, typeDerivation: compiled.typeDerivation, typeFinal: compiled.typeFinal)
|
|
let fact = PureXML.Schema.SchemaTypeFact(name: "R", derivation: compiled.typeDerivation["R"])
|
|
#expect(!PureXML.Validation.BuiltinValidation.xsdRestrictionsAreSubsets.apply(to: fact, at: [.element("R")], in: facts).isEmpty)
|
|
}
|
|
|
|
@Test("XSDSchema.restrictionsAreSubsets accepts a faithful restriction")
|
|
func test_xsdRestrictionsAreSubsets_succeeds() throws {
|
|
let xsd = """
|
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
|
<xs:complexType name="B"><xs:sequence><xs:element name="a" type="xs:string"/></xs:sequence></xs:complexType>
|
|
<xs:complexType name="R">
|
|
<xs:complexContent>
|
|
<xs:restriction base="B">
|
|
<xs:sequence><xs:element name="a" type="xs:string"/></xs:sequence>
|
|
</xs:restriction>
|
|
</xs:complexContent>
|
|
</xs:complexType>
|
|
</xs:schema>
|
|
"""
|
|
let compiled = try PureXML.Schema.XSDParser.parse(xsd)
|
|
let facts = PureXML.Schema.CompiledSchemaFacts(types: compiled.types, typeDerivation: compiled.typeDerivation, typeFinal: compiled.typeFinal)
|
|
let fact = PureXML.Schema.SchemaTypeFact(name: "R", derivation: compiled.typeDerivation["R"])
|
|
#expect(PureXML.Validation.BuiltinValidation.xsdRestrictionsAreSubsets.apply(to: fact, at: [.element("R")], in: facts).isEmpty)
|
|
}
|
|
}
|