Generalise the wildcard {namespace constraint} model to the four XSD 1.0 (with
Errata E1-10) expressible forms -- any; a set (with absent); a pair of not and
a namespace name; a pair of not and absent -- replacing the any/##other/set
model that could not represent the union/intersection results. Both not forms
exclude absent, so a union admitting "every namespace except a name, plus
absent" (E1-10 rule 5.1.3) has no expressible form.
A new SchemaWildcardExpressibility compile rule rejects a complexContent
extension whose attribute-wildcard union with its base is not expressible
(src-ct.5), closing XSTS wildZ013 (test328873i). The expressible unions are
computed exactly in XSDComplexContent, so a derived type's wildcard admits the
correct attributes at instance time, closing wildZ013a and wildZ013d.
invalid-schemas-accepted 12 -> 11, invalid-instances-accepted 17 -> 15, with
valid-schemas-rejected and valid-instances-rejected held at 0 (full XSTS
archive). The model is additive for element wildcards (which never produce the
new forms); admits/narrows/UPA-overlap updated and verified unchanged for the
##other cases.
The intersection of two not forms negating different namespace names is not
expressible (src-ct.4), a deferred rule: rather than drop the wildcard and
over-reject valid cross-namespace attributes on an accepted schema, the
intersection stays the less-restrictive not(lhs) over-approximation (FP-safe,
matching prior behaviour). Union/intersection algebra taken clean-room from
Xerces-J XSWildcardDecl. Guarded by SchemaWildcardUnionExpressibilityTests.
131 lines
6.4 KiB
Swift
131 lines
6.4 KiB
Swift
import Testing
|
|
@testable import PureXML
|
|
|
|
/// Configuration-pin tests: every validator variant lists exactly its active rule
|
|
/// descriptions, so adding or rewording a rule fails a test before it is accidental.
|
|
@Suite("Validation configuration pins")
|
|
struct ValidationConfigurationTests {
|
|
@Test("The structural default validator lists its rules")
|
|
func test_structuralDefault() {
|
|
#expect(PureXML.Validation.Validator<Void>().validationDescriptions == [
|
|
"Element attribute names are unique",
|
|
])
|
|
}
|
|
|
|
@Test("The blank validator carries no rules")
|
|
func test_blank() {
|
|
#expect(PureXML.Validation.Validator<Void>.blank.validationDescriptions.isEmpty)
|
|
#expect(PureXML.Validation.Validator<PureXML.Validation.DTDSchema>.blank.validationDescriptions.isEmpty)
|
|
}
|
|
|
|
@Test("The lenient DTD validator lists its non-strict rules in order")
|
|
func test_dtdLenient() {
|
|
let validator = PureXML.Validation.DTD.validator(strict: false)
|
|
#expect(validator.nonReferenceValidationDescriptions == [
|
|
"Element content matches its DTD content model",
|
|
"Required DTD attributes are present",
|
|
"#FIXED DTD attributes hold their fixed value",
|
|
"Enumerated DTD attributes hold a listed value",
|
|
"Tokenized DTD attributes match their declared type",
|
|
"NOTATION DTD attributes name a declared notation",
|
|
"The DTD declarations satisfy their validity constraints",
|
|
"The root element matches the DOCTYPE name",
|
|
"Standalone documents do not depend on external attribute declarations",
|
|
"Standalone documents have no whitespace in externally-declared element content",
|
|
"Parse-time DTD advisories are reviewed",
|
|
])
|
|
#expect(validator.referenceValidationDescriptions == [
|
|
"DTD ID values are unique and IDREFs resolve",
|
|
])
|
|
}
|
|
|
|
@Test("The strict DTD validator appends undeclared element and attribute rules to the reference tier")
|
|
func test_dtdStrict() {
|
|
let validator = PureXML.Validation.DTD.validator(strict: true)
|
|
#expect(validator.referenceValidationDescriptions.suffix(2) == [
|
|
"Element is declared in the DTD",
|
|
"Every attribute is declared in the DTD",
|
|
])
|
|
}
|
|
|
|
@Test("The HTML validator splits local and document-scoped rules across tiers")
|
|
func test_html() {
|
|
let validator = PureXML.Validation.HTML.validator()
|
|
#expect(validator.nonReferenceValidationDescriptions == [
|
|
"Void HTML elements have no content",
|
|
"HTML elements appear inside their required parent",
|
|
])
|
|
#expect(validator.referenceValidationDescriptions == [
|
|
"HTML id attributes are unique",
|
|
])
|
|
}
|
|
|
|
@Test("The XSD instance validator splits content and identity rules across tiers")
|
|
func test_xsdInstance() {
|
|
let validator = PureXML.Validation.XSD.validator()
|
|
#expect(validator.nonReferenceValidationDescriptions == [
|
|
"The document element is valid against its XSD type",
|
|
])
|
|
#expect(validator.referenceValidationDescriptions == [
|
|
"XSD identity constraints hold",
|
|
])
|
|
}
|
|
|
|
@Test("The XSD schema-consistency validator lists named-type rules in tier order")
|
|
func test_xsdSchemaConsistency() {
|
|
let validator = PureXML.Validation.XSDSchema.validator()
|
|
#expect(validator.nonReferenceValidationDescriptions == [
|
|
"A type derives from its base only by methods the base permits",
|
|
])
|
|
#expect(validator.referenceValidationDescriptions == [
|
|
"A restriction's content model accepts a subset of its base's",
|
|
])
|
|
}
|
|
|
|
@Test("The schema compile validators pin their pre and post rule sets")
|
|
func test_schemaCompile() {
|
|
#expect(PureXML.Validation.SchemaCompile.preCompileValidator().validationDescriptions == [
|
|
"Schema component id attributes are valid NCNames and unique",
|
|
"Schema vocabulary elements follow the schema-for-schemas structure",
|
|
"Top-level declarations in included or imported documents follow the global-component constraints",
|
|
"Global schema component names are unique within their symbol spaces",
|
|
"Simple-type final controls are declared consistently",
|
|
"Schema content models are deterministic (UPA)",
|
|
"Attribute declarations are not in the XSI namespace",
|
|
"A resolved schemaLocation reference is a valid schema",
|
|
"A redefined type restricts or extends itself",
|
|
"A redefined group or attribute group has a well-formed self-reference",
|
|
"A redefined attribute group keeps the original's required attributes",
|
|
"Type derivation chains contain no cycles",
|
|
"Schema type references contain no cycles",
|
|
"xs:all group references appear only where permitted",
|
|
"Included schemas are chameleon or match the includer targetNamespace",
|
|
])
|
|
#expect(PureXML.Validation.SchemaCompile.postCompileValidator().validationDescriptions == [
|
|
"Attribute uses are unique and declare at most one ID attribute",
|
|
"An attribute's type is a simple type",
|
|
"ID-typed value constraints are valid",
|
|
"Element value constraints are valid against their declared types",
|
|
"Complex types extending xs:all groups satisfy XSD placement rules",
|
|
"Anonymous complex-type restrictions accept a subset of their base's",
|
|
"A content-model derivation is consistent with its base type",
|
|
"A redefined model group restricts the group it redefines",
|
|
"Attribute restrictions are faithful to their bases",
|
|
"Simple types do not derive from complex types",
|
|
"Simple-type varieties are declared consistently",
|
|
"Notation declarations are valid",
|
|
"Simple-type facets are valid for their base type",
|
|
"Attribute wildcard unions in type extensions are expressible",
|
|
"Every schema reference resolves to a declared component",
|
|
"Substitution-group members derive correctly from their head",
|
|
])
|
|
}
|
|
|
|
@Test("Every builtin description is unique and pinned")
|
|
func test_builtinRegistry() {
|
|
let descriptions = PureXML.Validation.BuiltinValidation.allDescriptions
|
|
#expect(descriptions.count == Set(descriptions).count)
|
|
#expect(descriptions.count == 24)
|
|
}
|
|
}
|