test(conformance): add a C14N exclusive/2.0 modes corpus
Grow the Tier-2 conformance corpus with 4 Canonical XML mode cases: exclusive drops an unused namespace and renders one at its point of use; Canonical XML 2.0 drops whitespace-only text nodes and trims surrounding whitespace. Its own suite (ConformanceCanonicalModesTests). Part of #105 (Tier 2)
This commit is contained in:
parent
1f2dcc64f2
commit
f8e9938f4a
@ -14,7 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Added
|
||||
|
||||
- Conformance corpus harness (#105, Tier 2): the start of conformance-suite checking, expressed through the validation framework (the OpenAPIKit idiom). A `PureXML.Validation.ConformanceCase` is a `Validatable` named expectation (actual vs spec-authoritative expected output), and `Conformance.matchesExpected` is a `Validation<ConformanceCase, Void>` rule that emits one located `ValidationError` per diverging case, so a whole suite reports every failure at once with the case name as its coding path. Seeded with a Canonical XML 1.0 corpus (attribute ordering, empty-element expansion, comment removal, CDATA-to-escaped-text, processing instructions, namespace rendering) an XPath 1.0 core-function corpus, and an XSD datatype/facet corpus (length, range, pattern, enumeration, lexical space), a RELAX NG pattern corpus (text, optional, repetition, choice, ordered group, attribute, interleave, empty), an XSLT 1.0 transformation corpus (value-of, for-each, if, choose, sort, variable, format-number, apply-templates, call-template), an HTML5 tree-construction corpus (void elements, implied tag closing, case normalization, the adoption agency, entities), and a Schematron corpus (assert, report, rule context). The HTML corpus surfaced its first divergence (the fragment parser does not reconstruct active formatting elements like the document parser, tracked as #109). Growing the corpora against the official W3C/OASIS suites is the ongoing Tier-2 work.
|
||||
- Conformance corpus harness (#105, Tier 2): the start of conformance-suite checking, expressed through the validation framework (the OpenAPIKit idiom). A `PureXML.Validation.ConformanceCase` is a `Validatable` named expectation (actual vs spec-authoritative expected output), and `Conformance.matchesExpected` is a `Validation<ConformanceCase, Void>` rule that emits one located `ValidationError` per diverging case, so a whole suite reports every failure at once with the case name as its coding path. Seeded with a Canonical XML 1.0 corpus (attribute ordering, empty-element expansion, comment removal, CDATA-to-escaped-text, processing instructions, namespace rendering) an XPath 1.0 core-function corpus, and an XSD datatype/facet corpus (length, range, pattern, enumeration, lexical space), a RELAX NG pattern corpus (text, optional, repetition, choice, ordered group, attribute, interleave, empty), an XSLT 1.0 transformation corpus (value-of, for-each, if, choose, sort, variable, format-number, apply-templates, call-template), an HTML5 tree-construction corpus (void elements, implied tag closing, case normalization, the adoption agency, entities), a Schematron corpus (assert, report, rule context), and a C14N exclusive/2.0 corpus (unused-namespace dropping, render-at-use, whitespace trimming). The HTML corpus surfaced its first divergence (the fragment parser does not reconstruct active formatting elements like the document parser, tracked as #109). Growing the corpora against the official W3C/OASIS suites is the ongoing Tier-2 work.
|
||||
- EXSLT extension functions (#105, Tier 3): the `common`, `math`, and `sets` EXSLT modules, dispatched by resolving a function's prefix to its namespace (so any prefix bound to an EXSLT namespace works). `math:min`, `math:max`, `math:highest`, `math:lowest`, `math:abs`, `math:sqrt` (with the EXSLT NaN rule for non-numeric nodes); `set:distinct`, `set:difference`, `set:intersection`, `set:has-same-node`, `set:leading`, `set:trailing` (by node identity and document order); `exsl:object-type`. `math:power` and the other transcendentals are omitted because they need a C math library, which the pure-Swift, Foundation-free target excludes; `exsl:node-set` awaits result-tree-fragment support.
|
||||
- Canonical XML 1.1 (#105, Tier 3): a `Canonical.Options.canonical11` preset and a `mergeInheritedBase` option. When canonicalizing a document subset, the `xml:base` values of the apex's omitted ancestors are merged into the apex by RFC 3986 reference resolution (vs. 1.0's nearest-ancestor rule), the apex's own relative `xml:base` is resolved against that chain, and `xml:id` is no longer inherited; `xml:lang` and `xml:space` still inherit the nearest. A self-contained RFC 3986 resolver (scheme/authority/path parsing, path merging, dot-segment removal) backs the merge.
|
||||
- Single-byte legacy encodings (#97): the byte decoder gains a table-based single-byte path and the full set of single-byte legacy encodings, selected by the XML declaration's `encoding` name for both the whole-buffer and streaming decoders: the complete ISO-8859 family (parts 2 through 16), Windows-1250/1251/1253/1254/1255/1256/1257/1258, and KOI8-R/U. Most are vendored verbatim from the authoritative `unicode.org` mapping files; ISO-8859-5/9/15 are derived exactly; Windows-1254 composes from Windows-1252. Multi-byte CJK encodings (#99) are tracked separately.
|
||||
|
||||
@ -99,7 +99,7 @@ flowchart TB
|
||||
|
||||
PureXML is a working, dependency-free XML library today: parse, emit, validate,
|
||||
query, and stream documents on macOS, Linux, Windows, and WASM. The test suite
|
||||
currently runs **817 tests in 126 suites** (`swift test`).
|
||||
currently runs **818 tests in 127 suites** (`swift test`).
|
||||
|
||||
### Shipped (libxml2-aligned surface)
|
||||
|
||||
|
||||
35
Tests/ConformanceCanonicalModesTests.swift
Normal file
35
Tests/ConformanceCanonicalModesTests.swift
Normal file
@ -0,0 +1,35 @@
|
||||
@testable import PureXML
|
||||
import Testing
|
||||
|
||||
/// Canonical XML exclusive and 2.0 mode conformance, driven through the
|
||||
/// validation framework (its own suite to keep the main corpus under the cap).
|
||||
@Suite("Conformance corpus: C14N exclusive and 2.0")
|
||||
struct ConformanceCanonicalModesTests {
|
||||
private struct ModeSpec {
|
||||
let name: String
|
||||
let input: String
|
||||
let options: PureXML.Canonical.Options
|
||||
let expected: String
|
||||
}
|
||||
|
||||
/// Exclusive C14N renders a namespace only where it is visibly used; Canonical
|
||||
/// XML 2.0 trims and drops ignorable whitespace text.
|
||||
private func corpus() throws -> [PureXML.Validation.ConformanceCase] {
|
||||
let specs = [
|
||||
ModeSpec(name: "exclusive-drops-unused-ns", input: "<r xmlns:x=\"urn:x\"><c/></r>", options: .exclusive, expected: "<r><c></c></r>"),
|
||||
ModeSpec(name: "exclusive-renders-at-use", input: "<r xmlns:x=\"urn:x\"><x:c/></r>", options: .exclusive, expected: "<r><x:c xmlns:x=\"urn:x\"></x:c></r>"),
|
||||
ModeSpec(name: "c2-drops-whitespace-nodes", input: "<r> <c/> </r>", options: .canonical2, expected: "<r><c></c></r>"),
|
||||
ModeSpec(name: "c2-trims-text", input: "<r> hi </r>", options: .canonical2, expected: "<r>hi</r>"),
|
||||
]
|
||||
return try specs.map { spec in
|
||||
let actual = try PureXML.Canonical.canonicalize(PureXML.parse(spec.input), options: spec.options)
|
||||
return PureXML.Validation.ConformanceCase(name: spec.name, actual: actual, expected: spec.expected)
|
||||
}
|
||||
}
|
||||
|
||||
@Test("The C14N exclusive/2.0 conformance corpus passes with no located failures")
|
||||
func test_canonicalModesCorpusConforms() throws {
|
||||
let failures = try PureXML.Validation.Conformance.failures(in: corpus())
|
||||
#expect(failures.isEmpty, "\(failures.map(\.reason))")
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user