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.
160 lines
5.9 KiB
Swift
160 lines
5.9 KiB
Swift
import Testing
|
|
@testable import PureXML
|
|
|
|
/// Per-rule isolation tests (Validation rules XSD): content and wildcard rules.
|
|
@Suite("Validation rules XSD: content and wildcard rules")
|
|
struct ValidationRuleXSDContentTests {
|
|
// MARK: emptyContentForbidsChildren
|
|
|
|
private let emptyContentSchema = """
|
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
|
<xs:element name="n"><xs:complexType/></xs:element>
|
|
</xs:schema>
|
|
"""
|
|
|
|
@Test("emptyContentForbidsChildren rejects children on an empty-content element")
|
|
func test_emptyContentForbidsChildren() throws {
|
|
let errors = try ValidationRuleTestSupport.xsdErrors(
|
|
PureXML.Validation.XSD.emptyContentForbidsChildren,
|
|
schema: emptyContentSchema,
|
|
instance: "<n><child/></n>",
|
|
rootName: "n",
|
|
)
|
|
#expect(errors.count == 1)
|
|
#expect(errors.first?.reason == "element must be empty")
|
|
}
|
|
|
|
@Test("emptyContentForbidsChildren accepts a truly empty element")
|
|
func test_emptyContentForbidsChildren_succeeds() throws {
|
|
let errors = try ValidationRuleTestSupport.xsdErrors(
|
|
PureXML.Validation.XSD.emptyContentForbidsChildren,
|
|
schema: emptyContentSchema,
|
|
instance: "<n/>",
|
|
rootName: "n",
|
|
)
|
|
#expect(errors.isEmpty)
|
|
}
|
|
|
|
// MARK: simpleContentForbidsChildren / simpleContentTypeValid
|
|
|
|
private let simpleContentSchema = """
|
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
|
<xs:element name="n">
|
|
<xs:complexType><xs:simpleContent><xs:extension base="xs:integer"/></xs:simpleContent></xs:complexType>
|
|
</xs:element>
|
|
</xs:schema>
|
|
"""
|
|
|
|
@Test("simpleContentForbidsChildren rejects element children under simpleContent")
|
|
func test_simpleContentForbidsChildren() throws {
|
|
let errors = try ValidationRuleTestSupport.xsdErrors(
|
|
PureXML.Validation.XSD.simpleContentForbidsChildren,
|
|
schema: simpleContentSchema,
|
|
instance: "<n><child/></n>",
|
|
rootName: "n",
|
|
)
|
|
#expect(errors.count == 1)
|
|
#expect(errors.first?.reason == "element must not have children")
|
|
}
|
|
|
|
@Test("simpleContentForbidsChildren accepts text-only simpleContent")
|
|
func test_simpleContentForbidsChildren_succeeds() throws {
|
|
let errors = try ValidationRuleTestSupport.xsdErrors(
|
|
PureXML.Validation.XSD.simpleContentForbidsChildren,
|
|
schema: simpleContentSchema,
|
|
instance: "<n>5</n>",
|
|
rootName: "n",
|
|
)
|
|
#expect(errors.isEmpty)
|
|
}
|
|
|
|
@Test("simpleContentTypeValid rejects text invalid against the simpleContent type")
|
|
func test_simpleContentTypeValid() throws {
|
|
let errors = try ValidationRuleTestSupport.xsdErrors(
|
|
PureXML.Validation.XSD.simpleContentTypeValid,
|
|
schema: simpleContentSchema,
|
|
instance: "<n>x</n>",
|
|
rootName: "n",
|
|
)
|
|
#expect(errors.count == 1)
|
|
#expect(errors.first?.reason.hasPrefix("content:") == true)
|
|
}
|
|
|
|
@Test("simpleContentTypeValid accepts text valid against the simpleContent type")
|
|
func test_simpleContentTypeValid_succeeds() throws {
|
|
let errors = try ValidationRuleTestSupport.xsdErrors(
|
|
PureXML.Validation.XSD.simpleContentTypeValid,
|
|
schema: simpleContentSchema,
|
|
instance: "<n>5</n>",
|
|
rootName: "n",
|
|
)
|
|
#expect(errors.isEmpty)
|
|
}
|
|
|
|
// MARK: textForbidden
|
|
|
|
private let elementOnlyOptionalSchema = """
|
|
<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" minOccurs="0"/></xs:sequence></xs:complexType>
|
|
</xs:element>
|
|
</xs:schema>
|
|
"""
|
|
|
|
@Test("textForbidden rejects text under element-only content")
|
|
func test_textForbidden() throws {
|
|
let errors = try ValidationRuleTestSupport.xsdErrors(
|
|
PureXML.Validation.XSD.textForbidden,
|
|
schema: elementOnlyOptionalSchema,
|
|
instance: "<n>hello</n>",
|
|
rootName: "n",
|
|
)
|
|
#expect(errors.count == 1)
|
|
#expect(errors.first?.reason == "element must not contain text")
|
|
}
|
|
|
|
@Test("textForbidden accepts element-only content with no text")
|
|
func test_textForbidden_succeeds() throws {
|
|
let errors = try ValidationRuleTestSupport.xsdErrors(
|
|
PureXML.Validation.XSD.textForbidden,
|
|
schema: elementOnlyOptionalSchema,
|
|
instance: "<n></n>",
|
|
rootName: "n",
|
|
)
|
|
#expect(errors.isEmpty)
|
|
}
|
|
|
|
// MARK: wildcardElementUndeclared
|
|
|
|
private let strictWildcardElementSchema = """
|
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
|
<xs:element name="n">
|
|
<xs:complexType><xs:sequence><xs:any processContents="strict" minOccurs="0"/></xs:sequence></xs:complexType>
|
|
</xs:element>
|
|
</xs:schema>
|
|
"""
|
|
|
|
@Test("wildcardElementUndeclared rejects a strict wildcard match with no global declaration")
|
|
func test_wildcardElementUndeclared() throws {
|
|
let errors = try ValidationRuleTestSupport.xsdErrors(
|
|
PureXML.Validation.XSD.wildcardElementUndeclared,
|
|
schema: strictWildcardElementSchema,
|
|
instance: "<n><undeclared/></n>",
|
|
rootName: "n",
|
|
)
|
|
#expect(errors.count == 1)
|
|
#expect(errors.first?.reason.contains("no declaration for wildcard-matched element") == true)
|
|
}
|
|
|
|
@Test("wildcardElementUndeclared accepts an optional wildcard with no match")
|
|
func test_wildcardElementUndeclared_succeeds() throws {
|
|
let errors = try ValidationRuleTestSupport.xsdErrors(
|
|
PureXML.Validation.XSD.wildcardElementUndeclared,
|
|
schema: strictWildcardElementSchema,
|
|
instance: "<n/>",
|
|
rootName: "n",
|
|
)
|
|
#expect(errors.isEmpty)
|
|
}
|
|
}
|