Skip to content

✅ test(xslt): validate XSLT 1.0 against libxslt REC suite#590

Merged
gaborbernat merged 2 commits into
tox-dev:mainfrom
gaborbernat:test/537-xslt-conformance
Jul 7, 2026
Merged

✅ test(xslt): validate XSLT 1.0 against libxslt REC suite#590
gaborbernat merged 2 commits into
tox-dev:mainfrom
gaborbernat:test/537-xslt-conformance

Conversation

@gaborbernat

@gaborbernat gaborbernat commented Jul 7, 2026

Copy link
Copy Markdown
Member

The XSLT 1.0 processor from #537 shipped with green coverage, but coverage proves the code runs, not that it matches the spec. This validates turbohtml.transform against an authoritative external oracle: libxslt's own XSLT 1.0 Recommendation corpus, the REC and REC2 stylesheet/source/expected-output triples the reference implementation behind lxml.etree.XSLT ships. It vendors that corpus as the pinned tests/conformance/libxslt shallow submodule and runs turbohtml over every triple, asserting byte-equal output with whitespace normalized per output method.

Of the 79 cases, 56 pass exactly. The remaining 23 exercise features turbohtml does not model, so each is xfail tagged with the spec section it needs: whitespace stripping (xsl:strip-space), xsl:namespace-alias, attribute sets, multi-level xsl:number, cdata-section-elements, extension elements, and the html method's meta injection. 📋 The corpus is a git submodule, not a runtime library, so an absent checkout is a setup error: the module raises at import telling you to run git submodule update --init, and the dedicated conformance CI job always checks it out.

The oracle surfaced four conformance bugs, all fixed here. A literal result element now copies its in-scope stylesheet namespace declarations to the output per section 7.1.1, de-duplicated against the ancestors already in scope and filtered by exclude-result-prefixes, so a prefixed or default-namespaced result element stays well-formed instead of losing its declaration; xsl:* directive attributes on a literal result element are stripped rather than emitted. xsl:number honors the separators around a format token, so format="1. " yields 1. and format="(1)" yields (1), and a value with no alphabetic or roman form falls back to decimal 🔢. A roman numeral past 4999 previously produced an unbounded run of M, a memory-exhaustion hazard, and zero or a negative produced empty output. A processing instruction now serializes with the ?> terminator under the xml output method.

Line and branch C coverage stays at 100% on the changed xslt.c and document.c. Three existing unit tests that had pinned the pre-fix behavior are corrected to the libxslt-confirmed output.

validates #537

@gaborbernat gaborbernat added bug Something isn't working enhancement New feature or request labels Jul 7, 2026
@gaborbernat gaborbernat force-pushed the test/537-xslt-conformance branch 3 times, most recently from 591b41f to 57f0bd2 Compare July 7, 2026 15:06
@codspeed-hq

codspeed-hq Bot commented Jul 7, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 81 untouched benchmarks
⏩ 18 skipped benchmarks1


Comparing gaborbernat:test/537-xslt-conformance (59c51d8) with main (e16e98c)

Open in CodSpeed

Footnotes

  1. 18 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Add a conformance harness that runs turbohtml's XSLT 1.0 processor over
libxslt's own XSLT 1.0 Recommendation corpus -- the REC and REC2
stylesheet/source/expected-output triples the reference implementation
ships -- vendored as the pinned tests/conformance/libxslt submodule. Of
the 79 cases, 56 pass byte-equal (whitespace normalized per output
method); the other 23 use features turbohtml does not model and are
xfail with the spec section each needs. The file is coverage-omitted
like the differential suites so a missing submodule never drops the gate.

The oracle surfaced four conformance bugs, all fixed:

- A literal result element now copies its in-scope stylesheet namespace
  declarations to the output (section 7.1.1), de-duplicated against the
  output ancestors and filtered by exclude-result-prefixes, and XSLT
  directive attributes (xsl:*) are stripped rather than emitted.
- xsl:number honors the separators around a format token (format="1. "
  -> "1. ", "(1)" -> "(1)"), and a value with no alphabetic/roman form
  (zero, negative, or a roman numeral past 4999) falls back to decimal
  instead of emitting nothing or an unbounded run.
- A processing instruction serializes with the ?> terminator under the
  xml output method.

validates tox-dev#537
@gaborbernat gaborbernat force-pushed the test/537-xslt-conformance branch from 5dd66d6 to 59c51d8 Compare July 7, 2026 16:23
@gaborbernat gaborbernat merged commit 4406208 into tox-dev:main Jul 7, 2026
49 checks passed
@gaborbernat gaborbernat deleted the test/537-xslt-conformance branch July 10, 2026 17:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant