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.
166 lines
6.3 KiB
Swift
166 lines
6.3 KiB
Swift
import Testing
|
|
@testable import PureXML
|
|
|
|
/// Per-rule isolation tests (Validation rules XSD): nillable and fixed-value rules.
|
|
@Suite("Validation rules XSD: nillable and fixed-value rules")
|
|
struct ValidationRuleXSDNilFixedTests {
|
|
// MARK: nilAttributeRequiresNillable
|
|
|
|
@Test("nilAttributeRequiresNillable rejects xsi:nil on a non-nillable element")
|
|
func test_nilAttributeRequiresNillable() throws {
|
|
let schema = """
|
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
|
<xs:element name="n" type="xs:string"/>
|
|
</xs:schema>
|
|
"""
|
|
let errors = try ValidationRuleTestSupport.xsdErrors(
|
|
PureXML.Validation.XSD.nilAttributeRequiresNillable,
|
|
schema: schema,
|
|
instance: "<n \(ValidationRuleTestSupport.xsiNS) xsi:nil=\"true\"/>",
|
|
rootName: "n",
|
|
)
|
|
#expect(errors.count == 1)
|
|
#expect(errors.first?.reason.contains("not nillable") == true)
|
|
}
|
|
|
|
@Test("nilAttributeRequiresNillable accepts xsi:nil on a nillable element")
|
|
func test_nilAttributeRequiresNillable_succeeds() throws {
|
|
let schema = """
|
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
|
<xs:element name="n" type="xs:string" nillable="true"/>
|
|
</xs:schema>
|
|
"""
|
|
let errors = try ValidationRuleTestSupport.xsdErrors(
|
|
PureXML.Validation.XSD.nilAttributeRequiresNillable,
|
|
schema: schema,
|
|
instance: "<n \(ValidationRuleTestSupport.xsiNS) xsi:nil=\"true\"/>",
|
|
rootName: "n",
|
|
)
|
|
#expect(errors.isEmpty)
|
|
}
|
|
|
|
// MARK: nilElementMustBeEmpty
|
|
|
|
@Test("nilElementMustBeEmpty rejects content on a nilled element")
|
|
func test_nilElementMustBeEmpty() throws {
|
|
let schema = """
|
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
|
<xs:element name="n" type="xs:string" nillable="true"/>
|
|
</xs:schema>
|
|
"""
|
|
let errors = try ValidationRuleTestSupport.xsdErrors(
|
|
PureXML.Validation.XSD.nilElementMustBeEmpty,
|
|
schema: schema,
|
|
instance: "<n \(ValidationRuleTestSupport.xsiNS) xsi:nil=\"true\">x</n>",
|
|
rootName: "n",
|
|
)
|
|
#expect(errors.count == 1)
|
|
#expect(errors.first?.reason.contains("must be empty") == true)
|
|
}
|
|
|
|
@Test("nilElementMustBeEmpty accepts an empty nilled element")
|
|
func test_nilElementMustBeEmpty_succeeds() throws {
|
|
let schema = """
|
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
|
<xs:element name="n" type="xs:string" nillable="true"/>
|
|
</xs:schema>
|
|
"""
|
|
let errors = try ValidationRuleTestSupport.xsdErrors(
|
|
PureXML.Validation.XSD.nilElementMustBeEmpty,
|
|
schema: schema,
|
|
instance: "<n \(ValidationRuleTestSupport.xsiNS) xsi:nil=\"true\"></n>",
|
|
rootName: "n",
|
|
)
|
|
#expect(errors.isEmpty)
|
|
}
|
|
|
|
// MARK: nilElementNoFixedConstraint
|
|
|
|
@Test("nilElementNoFixedConstraint rejects a nilled element declared fixed")
|
|
func test_nilElementNoFixedConstraint() throws {
|
|
let schema = """
|
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
|
<xs:element name="n" type="xs:string" nillable="true" fixed="5"/>
|
|
</xs:schema>
|
|
"""
|
|
let errors = try ValidationRuleTestSupport.xsdErrors(
|
|
PureXML.Validation.XSD.nilElementNoFixedConstraint,
|
|
schema: schema,
|
|
instance: "<n \(ValidationRuleTestSupport.xsiNS) xsi:nil=\"true\"></n>",
|
|
rootName: "n",
|
|
)
|
|
#expect(errors.count == 1)
|
|
#expect(errors.first?.reason.contains("fixed value constraint") == true)
|
|
}
|
|
|
|
@Test("nilElementNoFixedConstraint accepts a nilled element with no fixed constraint")
|
|
func test_nilElementNoFixedConstraint_succeeds() throws {
|
|
let schema = """
|
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
|
<xs:element name="n" type="xs:string" nillable="true"/>
|
|
</xs:schema>
|
|
"""
|
|
let errors = try ValidationRuleTestSupport.xsdErrors(
|
|
PureXML.Validation.XSD.nilElementNoFixedConstraint,
|
|
schema: schema,
|
|
instance: "<n \(ValidationRuleTestSupport.xsiNS) xsi:nil=\"true\"></n>",
|
|
rootName: "n",
|
|
)
|
|
#expect(errors.isEmpty)
|
|
}
|
|
|
|
// MARK: fixedElementNoChildren / fixedElementValueMatches
|
|
|
|
private let fixedStringSchema = """
|
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
|
<xs:element name="n" type="xs:string" fixed="5"/>
|
|
</xs:schema>
|
|
"""
|
|
|
|
@Test("fixedElementNoChildren rejects element children on a fixed element")
|
|
func test_fixedElementNoChildren() throws {
|
|
let errors = try ValidationRuleTestSupport.xsdErrors(
|
|
PureXML.Validation.XSD.fixedElementNoChildren,
|
|
schema: fixedStringSchema,
|
|
instance: "<n><child/></n>",
|
|
rootName: "n",
|
|
)
|
|
#expect(errors.count == 1)
|
|
#expect(errors.first?.reason.contains("must not have element children") == true)
|
|
}
|
|
|
|
@Test("fixedElementNoChildren accepts a fixed element with only text")
|
|
func test_fixedElementNoChildren_succeeds() throws {
|
|
let errors = try ValidationRuleTestSupport.xsdErrors(
|
|
PureXML.Validation.XSD.fixedElementNoChildren,
|
|
schema: fixedStringSchema,
|
|
instance: "<n>5</n>",
|
|
rootName: "n",
|
|
)
|
|
#expect(errors.isEmpty)
|
|
}
|
|
|
|
@Test("fixedElementValueMatches rejects text that differs from the fixed value")
|
|
func test_fixedElementValueMatches() throws {
|
|
let errors = try ValidationRuleTestSupport.xsdErrors(
|
|
PureXML.Validation.XSD.fixedElementValueMatches,
|
|
schema: fixedStringSchema,
|
|
instance: "<n>6</n>",
|
|
rootName: "n",
|
|
)
|
|
#expect(errors.count == 1)
|
|
#expect(errors.first?.reason.contains("is fixed and must be") == true)
|
|
}
|
|
|
|
@Test("fixedElementValueMatches accepts text equal to the fixed value")
|
|
func test_fixedElementValueMatches_succeeds() throws {
|
|
let errors = try ValidationRuleTestSupport.xsdErrors(
|
|
PureXML.Validation.XSD.fixedElementValueMatches,
|
|
schema: fixedStringSchema,
|
|
instance: "<n>5</n>",
|
|
rootName: "n",
|
|
)
|
|
#expect(errors.isEmpty)
|
|
}
|
|
}
|