PureXML/Tests/NamespaceConstraintTests.swift
Mihaela Mihaljevic 83e6e27d12 style(format): adopt --importgrouping testable-bottom from canonical rules-swift
Group @testable imports at the bottom, per public/rules-swift's swiftformat. A
behavior-preserving import-ordering reformat across 252 files (mostly tests).
--trailingclosures was deliberately not adopted (cosmetic, and swiftformat flags
it as caution-worthy).
2026-06-18 20:33:07 +02:00

71 lines
2.8 KiB
Swift

import Testing
@testable import PureXML
/// The Namespaces 1.0 constraints (#136): reserved prefixes and namespace
/// names, qualified-name shape, duplicate expanded-name attributes, NCName
/// rules for PI targets and entity/notation names, and DTD-typed
/// normalization of binding values.
@Suite("Namespace constraints")
struct NamespaceConstraintTests {
private func rejects(_ xml: String) -> Bool {
(try? PureXML.parse(xml, limits: .init(allowDoctype: true))) == nil
}
@Test("Malformed qualified names are rejected")
func test_qualifiedNameShape() {
#expect(rejects("<foo: />"))
#expect(rejects("<:foo />"))
#expect(rejects("<a:b:c xmlns:a=\"urn:x\"/>"))
#expect(rejects("<foo xmlns:=\"urn:x\"/>"))
#expect(!rejects("<a:b xmlns:a=\"urn:x\"/>"))
}
@Test("Reserved prefixes and namespace names are protected")
func test_reservedBindings() {
#expect(rejects("<f xmlns:xml=\"urn:wrong\"/>"))
#expect(!rejects("<f xmlns:xml=\"http://www.w3.org/XML/1998/namespace\"/>"))
#expect(rejects("<f xmlns:yml=\"http://www.w3.org/XML/1998/namespace\"/>"))
#expect(rejects("<f xmlns:xmlns=\"http://www.w3.org/2000/xmlns/\"/>"))
#expect(rejects("<f xmlns:xmlns=\"urn:other\"/>"))
#expect(rejects("<f xmlns:ymlns=\"http://www.w3.org/2000/xmlns/\"/>"))
#expect(rejects("<f xmlns=\"http://www.w3.org/XML/1998/namespace\"/>"))
#expect(rejects("<f xmlns=\"http://www.w3.org/2000/xmlns/\"/>"))
}
@Test("A prefix may not be undeclared in Namespaces 1.0")
func test_noPrefixUndeclaration() {
#expect(rejects("<f xmlns:a=\"\"/>"))
#expect(!rejects("<f xmlns=\"\"/>"))
}
@Test("Attributes must be distinct by expanded name")
func test_duplicateExpandedNames() {
let xml = "<f xmlns:a=\"urn:x\" xmlns:b=\"urn:x\"><g a:attr=\"1\" b:attr=\"2\"/></f>"
#expect(rejects(xml))
let distinct = "<f xmlns:a=\"urn:x\" xmlns:b=\"urn:y\"><g a:attr=\"1\" b:attr=\"2\"/></f>"
#expect(!rejects(distinct))
}
@Test("PI targets and entity/notation names are NCNames")
func test_ncNames() {
#expect(rejects("<?a:b data?>\n<f/>"))
#expect(rejects("<!DOCTYPE f [<!ELEMENT f ANY><!ENTITY a:b \"x\">]>\n<f/>"))
#expect(rejects("<!DOCTYPE f [<!ELEMENT f ANY><!NOTATION a:b SYSTEM \"n\">]>\n<f/>"))
}
@Test("A DTD-typed xmlns value binds its normalized form")
func test_typedBindingNormalization() {
let xml = """
<!DOCTYPE f [
<!ELEMENT f ANY><!ELEMENT g ANY>
<!ATTLIST f xmlns:a CDATA #IMPLIED xmlns:b NMTOKEN #IMPLIED>
<!ATTLIST g a:attr CDATA #IMPLIED b:attr CDATA #IMPLIED>
]>
<f xmlns:a="urn:xyzzy" xmlns:b=" urn:xyzzy ">
<g a:attr="1" b:attr="2"/>
</f>
"""
#expect(rejects(xml))
}
}