import Testing
@testable import PureXML
/// The worked examples of Canonical XML 1.0 section 3 (W3C Recommendation,
/// https://www.w3.org/TR/xml-c14n, W3C Software and Document License), run as
/// input/expected-output vectors (#132). Each test cites its example number.
@Suite("C14N 1.0 spec examples")
struct C14NSpecExampleTests {
private func canonical(
_ input: String,
comments: Bool = false,
resolver: PureXML.Parsing.EntityResolver = .refusing,
) throws -> String {
var options = PureXML.Canonical.Options.inclusive
options.includeComments = comments
// C14N input is the validating-processor view: DTD defaults applied.
let node = try PureXML.parseApplyingInternalDTDDefaults(input, resolver: resolver)
return PureXML.Canonical.canonicalize(node, options: options)
}
@Test("3.1: PIs, comments, and content outside the document element")
func test_example31() throws {
let input = """
Hello, world!
"""
let uncommented = """
Hello, world!
"""
let commented = """
Hello, world!
"""
#expect(try canonical(input) == uncommented)
#expect(try canonical(input, comments: true) == commented)
}
@Test("3.2: whitespace in document content is preserved")
func test_example32() throws {
let input = """
A B
A
B
A B
C
"""
// The canonical form is byte-identical for this input.
#expect(try canonical(input) == input)
}
@Test("3.3: start and end tags, attribute sorting, superfluous namespaces")
func test_example33() throws {
let input = """
]>
"""
let expected = """
"""
#expect(try canonical(input) == expected)
}
@Test("3.4: character modifications and character references")
func test_example34() throws {
let input = """
]>
First line
Second line
2
"0" && value<"10" ?"valid":"error"]]>
valid
"""
let expected = """
First line
Second line
2
value>"0" && value<"10" ?"valid":"error"
valid
"""
#expect(try canonical(input) == expected)
}
@Test("3.5: entity references are expanded")
func test_example35() throws {
let input = """
]>
&ent1;, &ent2;!
"""
let expected = """
Hello, world!
"""
let resolver = PureXML.Parsing.EntityResolver(
resolveEntity: { name, _ in name == "ent2" ? "world" : nil },
resolveExternalSubset: { _ in nil },
)
#expect(try canonical(input, resolver: resolver) == expected)
}
@Test("3.6: output is UTF-8 regardless of input encoding")
func test_example36() throws {
// The declaration names ISO-8859-1 and the byte 0xA9 is the copyright
// sign there; the canonical form carries the UTF-8 character.
var bytes = Array("\n".utf8)
bytes.append(0xA9)
bytes += Array("".utf8)
let source = try PureXML.Parsing.ByteDecoder.decode(bytes)
let node = try PureXML.parse(source)
#expect(PureXML.Canonical.canonicalize(node) == "\u{A9}")
}
}