import Testing
@testable import PureXML
/// Every QName a schema names (a `type`/`base`/`itemType`/`memberTypes` type, an
/// element/attribute/group/attributeGroup `ref`, an element `substitutionGroup`)
/// must resolve to a declared component or a built-in. An undeclared reference
/// was previously accepted at compile time and only surfaced (if at all) lazily
/// during instance validation. The check is skipped when the document pulls in
/// external definitions through `import`/`include`/`redefine`, which the default
/// compile does not load.
@Suite("Schema reference resolution")
struct SchemaReferenceTests {
private func compile(_ body: String) throws {
_ = try PureXML.Schema.Document("""
\(body)
""")
}
private func rejects(_ body: String) -> Bool {
do { try compile(body)
return false
} catch { return true }
}
@Test("a reference to a declared component or a built-in resolves")
func test_resolves() throws {
try compile(#""#)
try compile(#""#)
try compile(#""#)
}
@Test("an undeclared reference is rejected")
func test_undeclared() {
#expect(rejects(#""#))
#expect(rejects(#""#))
#expect(rejects(#""#))
#expect(rejects(#""#))
}
@Test("a reference value tolerates surrounding whitespace (whiteSpace collapse)")
func test_whitespacePadded() throws {
try compile("")
}
@Test("a ref resolving to the XSD namespace is undeclared")
func test_refResolvingToXSDNamespaceIsUndeclared() throws {
// The default xmlns is the XSD namespace, so an unprefixed `ref="root"`
// resolves to {XSD}root, not {foo}root, and the XSD namespace declares no
// referenceable user element: undeclared (XSTS xsd013/xsd014).
let refRoot = """
"""
#expect(throws: (any Error).self) { _ = try PureXML.Schema.Document(refRoot) }
let refUndef = """
"""
#expect(throws: (any Error).self) { _ = try PureXML.Schema.Document(refUndef) }
// Guard: the same shape with the ref qualified to the target resolves, so the
// XSD-namespace rule does not reject a correctly-namespaced reference.
let qualified = """
"""
_ = try PureXML.Schema.Document(qualified)
}
@Test("an unprefixed type reference to a target-namespace type is undeclared")
func test_unprefixedTypeRefToTargetNamespace() throws {
// No default xmlns, so `type="t"` resolves to {}t, not {urn:x}t where the
// type is declared: undeclared (XSTS addB009 / test66059).
let unprefixed = """
"""
#expect(throws: (any Error).self) { _ = try PureXML.Schema.Document(unprefixed) }
// Guard: qualifying the reference to the target namespace resolves.
let qualified = """
"""
_ = try PureXML.Schema.Document(qualified)
}
@Test("references are not checked when an import may supply them")
func test_importSkipsCheck() throws {
// A dangling reference into an imported namespace is tolerated: the default
// compile does not load the import, so the reference cannot be verified.
try compile(#"""
"""#)
}
@Test("references are checked strictly against the targetNamespace")
func test_referenceNamespaceChecking() throws {
// Without targetNamespace, unprefixed ref resolves to no namespace and is accepted
_ = try PureXML.Schema.Document("""
""")
// With targetNamespace, unprefixed ref without default namespace resolves to no namespace but declaration is in targetNamespace -> rejected
#expect(throws: Error.self) {
_ = try PureXML.Schema.Document("""
""")
}
// With targetNamespace, prefix matching targetNamespace is accepted
_ = try PureXML.Schema.Document("""
""")
// With targetNamespace, default namespace matching targetNamespace is accepted
_ = try PureXML.Schema.Document("""
""")
}
}