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.
134 lines
5.7 KiB
Swift
134 lines
5.7 KiB
Swift
import Testing
|
|
@testable import PureXML
|
|
|
|
/// Per-rule isolation tests (Validation rules XSD): Validation rules XSD: simple type and structure.
|
|
@Suite("Validation rules XSD: simple type and structure")
|
|
struct ValidationRuleXSDStructureTests {
|
|
// MARK: simpleTypeDisallowedAttribute / simpleTypeForbidsChildren / simpleTypeValueValid
|
|
|
|
private let simpleStringSchema = """
|
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
|
<xs:element name="n" type="xs:string"/>
|
|
</xs:schema>
|
|
"""
|
|
|
|
@Test("simpleTypeDisallowedAttribute rejects an attribute on a simple-typed element")
|
|
func test_simpleTypeDisallowedAttribute() throws {
|
|
let errors = try ValidationRuleTestSupport.xsdErrors(
|
|
PureXML.Validation.XSD.simpleTypeDisallowedAttribute,
|
|
schema: simpleStringSchema,
|
|
instance: "<n foo=\"bar\">text</n>",
|
|
rootName: "n",
|
|
)
|
|
#expect(errors.count == 1)
|
|
#expect(errors.first?.reason.contains("has a simple type") == true)
|
|
}
|
|
|
|
@Test("simpleTypeDisallowedAttribute accepts a simple-typed element with no attributes")
|
|
func test_simpleTypeDisallowedAttribute_succeeds() throws {
|
|
let errors = try ValidationRuleTestSupport.xsdErrors(
|
|
PureXML.Validation.XSD.simpleTypeDisallowedAttribute,
|
|
schema: simpleStringSchema,
|
|
instance: "<n>text</n>",
|
|
rootName: "n",
|
|
)
|
|
#expect(errors.isEmpty)
|
|
}
|
|
|
|
@Test("simpleTypeForbidsChildren rejects element children on a simple-typed element")
|
|
func test_simpleTypeForbidsChildren() throws {
|
|
let errors = try ValidationRuleTestSupport.xsdErrors(
|
|
PureXML.Validation.XSD.simpleTypeForbidsChildren,
|
|
schema: simpleStringSchema,
|
|
instance: "<n><child/></n>",
|
|
rootName: "n",
|
|
)
|
|
#expect(errors.count == 1)
|
|
#expect(errors.first?.reason.contains("must not have children") == true)
|
|
}
|
|
|
|
@Test("simpleTypeForbidsChildren accepts a simple-typed element with only text")
|
|
func test_simpleTypeForbidsChildren_succeeds() throws {
|
|
let errors = try ValidationRuleTestSupport.xsdErrors(
|
|
PureXML.Validation.XSD.simpleTypeForbidsChildren,
|
|
schema: simpleStringSchema,
|
|
instance: "<n>text</n>",
|
|
rootName: "n",
|
|
)
|
|
#expect(errors.isEmpty)
|
|
}
|
|
|
|
@Test("simpleTypeValueValid locates a simple-type violation at the root element")
|
|
func test_simpleTypeValueValid() throws {
|
|
let schema = """
|
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
|
<xs:element name="n" type="xs:integer"/>
|
|
</xs:schema>
|
|
"""
|
|
let errors = try ValidationRuleTestSupport.xsdErrors(PureXML.Validation.XSD.simpleTypeValueValid, schema: schema, instance: "<n>x</n>", rootName: "n")
|
|
#expect(errors.count == 1)
|
|
#expect(errors.first?.reason.contains("n") == true)
|
|
#expect(errors.first.map(ValidationRuleTestSupport.path) == ["n"])
|
|
}
|
|
|
|
@Test("simpleTypeValueValid accepts a valid integer at the boundary")
|
|
func test_simpleTypeValueValid_succeeds() throws {
|
|
let schema = """
|
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
|
<xs:element name="n" type="xs:integer"/>
|
|
</xs:schema>
|
|
"""
|
|
let errors = try ValidationRuleTestSupport.xsdErrors(PureXML.Validation.XSD.simpleTypeValueValid, schema: schema, instance: "<n>0</n>", rootName: "n")
|
|
#expect(errors.isEmpty)
|
|
}
|
|
|
|
// MARK: typeReferenceResolves
|
|
|
|
@Test("typeReferenceResolves rejects a reference to an undeclared type")
|
|
func test_typeReferenceResolves() throws {
|
|
let schema = """
|
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
|
<xs:element name="n" type="Missing"/>
|
|
</xs:schema>
|
|
"""
|
|
let errors = try ValidationRuleTestSupport.xsdErrors(PureXML.Validation.XSD.typeReferenceResolves, schema: schema, instance: "<n/>", rootName: "n")
|
|
#expect(errors.count == 1)
|
|
#expect(errors.first?.reason.contains("unknown type") == true)
|
|
}
|
|
|
|
@Test("typeReferenceResolves accepts a reference that resolves to a declared type")
|
|
func test_typeReferenceResolves_succeeds() throws {
|
|
let schema = """
|
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
|
<xs:complexType name="T"><xs:sequence><xs:element name="a" type="xs:string" minOccurs="0"/></xs:sequence></xs:complexType>
|
|
<xs:element name="n" type="T"/>
|
|
</xs:schema>
|
|
"""
|
|
let errors = try ValidationRuleTestSupport.xsdErrors(PureXML.Validation.XSD.typeReferenceResolves, schema: schema, instance: "<n/>", rootName: "n")
|
|
#expect(errors.isEmpty)
|
|
}
|
|
|
|
// MARK: contentModelStructure
|
|
|
|
private let sequenceSchema = """
|
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
|
<xs:element name="n">
|
|
<xs:complexType><xs:sequence><xs:element name="a" type="xs:string"/></xs:sequence></xs:complexType>
|
|
</xs:element>
|
|
</xs:schema>
|
|
"""
|
|
|
|
@Test("contentModelStructure rejects a child the content model does not allow")
|
|
func test_contentModelStructure() throws {
|
|
let errors = try ValidationRuleTestSupport.xsdErrors(PureXML.Validation.XSD.contentModelStructure, schema: sequenceSchema, instance: "<n><b/></n>", rootName: "n")
|
|
#expect(errors.count == 1)
|
|
#expect(errors.first?.reason.contains("is not allowed here") == true)
|
|
}
|
|
|
|
@Test("contentModelStructure accepts children matching the content model")
|
|
func test_contentModelStructure_succeeds() throws {
|
|
let errors = try ValidationRuleTestSupport.xsdErrors(PureXML.Validation.XSD.contentModelStructure, schema: sequenceSchema, instance: "<n><a>x</a></n>", rootName: "n")
|
|
#expect(errors.isEmpty)
|
|
}
|
|
}
|