test(schema): reclassify particlesZ001.i as a contested XSTS test, not a deviation (#384)

particlesZ001 declares Derived as a complexContent restriction of Base and an
instance whose <elem> (type Derived) content is annotation + four elements. The
suite pairs a valid schemaTest with an invalid instanceTest, but the two are
mutually exclusive for a consistent conformant processor, and the manifest's own
documentation labels the governing rule, Particle Derivation OK (RecurseAsIfGroup),
ambiguous.

cvc-complex-type (§3.4.4) validates an instance against the element's own
{content type}: for <elem> that is Derived = sequence(annotation?, element*),
which the instance satisfies, so the instance is valid. Particle Valid
(Restriction) / RecurseAsIfGroup (§3.9.6) is a schema-assembly constraint that is
never re-run during instance validation, so there is no path from an accepted
schema to an invalid instance. The only way to reach the suite's invalid is to
reject the schema as an invalid restriction, which is a valid-schema-rejected
false positive and would still fail the suite's own valid schemaTest. libxml2
accepts both schema and instance, agreeing with PureXML.

Exclude particlesZ001.i via specDivergentInstances with the spec-grounded
justification in code and docs/xsts-deviations.md. invalid-instances-accepted
5 -> 4; full XSTS in release now 0/8/0/4, both false-positive buckets at 0. No
library behaviour change. Confirmed by an adversarial analysis that found no
spec-coherent reading yielding valid-schema + invalid-instance.
This commit is contained in:
Mihaela Mihaljevic 2026-06-29 10:27:46 +02:00 committed by GitHub
parent 20da41995a
commit c55522669e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 34 additions and 7 deletions

View File

@ -95,7 +95,10 @@ struct XSTSSuiteTests {
/// context, so with no default namespace it names no namespace and does not match
/// a namespaced type of the same local name (targetns00101m). See
/// ``ComplexValidator/xsiTypeReference(_:namespaceBindings:)``.
private let knownInstanceInvalidAccepted = 5
/// 5 -> 4: particlesZ001.i reclassified as contested (see the excluded set). Its
/// `invalid` is unsatisfiable jointly with its own `valid` schemaTest, and the
/// manifest itself labels the governing restriction rule ambiguous.
private let knownInstanceInvalidAccepted = 4
/// Instance tests excluded from the counts because their expected validity is not
/// authoritative, mirroring how the suite's own `status="queried"` entries are
/// skipped. Each must carry a spec-grounded justification; this is never a place to
@ -142,7 +145,18 @@ struct XSTSSuiteTests {
/// single-`e1` instance is valid. The `valid` schema and `invalid` instance
/// expectations are mutually exclusive; libxml2 accepts both. Confirmed by an
/// adversarial analysis that found no third path.
private static let specDivergentInstances: Set<String> = ["anyURI_a004_1339.i", "schA2.i", "schA5.i", "mgO013.i"]
///
/// - `particlesZ001.i`: a `complexContent` restriction `Derived` of `Base`, with an
/// instance valid against `Derived`'s own content model. cvc-complex-type (§3.4.4)
/// validates an instance against the element's own `{content type}` and never
/// re-runs Particle Valid (Restriction) / RecurseAsIfGroup (§3.9.6, a schema-
/// assembly constraint), so schema-valid + instance-invalid is unreachable. The
/// manifest itself labels the governing rule ambiguous; libxml2 accepts both.
/// Reaching `invalid` would require rejecting the schema (a valid-schema-rejected
/// false positive) and would still fail the suite's own `valid` schemaTest.
private static let specDivergentInstances: Set<String> = [
"anyURI_a004_1339.i", "schA2.i", "schA5.i", "mgO013.i", "particlesZ001.i",
]
@Test("Every XSTS case behaves: compile, reject, validate, invalidate")
func test_suite() throws {

View File

@ -143,13 +143,26 @@ accepts both. An adversarial analysis found no third path. The identity-field
case `idZ010` (a `key`/`keyref` field selecting a non-simple `anyType` node) was a
genuine bug and is fixed (reject per cvc-identity-constraint.3).
`particlesZ001.i` is reclassified as contested (`invalid-instances-accepted` 5 -> 4).
`Derived` complexContent-restricts `Base`, and the instance is valid against
`Derived`'s own content model. cvc-complex-type (§3.4.4) validates an instance
against the element's own `{content type}` and never re-runs Particle Valid
(Restriction) / RecurseAsIfGroup (§3.9.6, a schema-assembly constraint), so
schema-valid + instance-invalid is unreachable. The manifest documentation itself
labels the governing rule ambiguous; libxml2 accepts both. The identity-field
`idZ010` (a `key`/`keyref` field selecting a non-simple `anyType` node) and the
`xsi:type` namespace case `targetns00101m` (an unprefixed `xsi:type` resolves in
the instance namespace context, not by bare local name) were genuine bugs and are
fixed.
Takeaway: on the schema side, libxml2 parity is reached except the one case now
fixed; the remaining nine are a deliberate choice to exceed the reference. On the
instance side the Ethiopic-digit `\d`/`\D` and `\i`/`\c` name-class cases and the
identity-field `idZ010` are now fixed (reference-aligned); `anyURI_a004`, `schA2`,
`schA5`, and `mgO013` are shown contested; the remaining cases (`schA7` policy,
`schU3/4/5` circular redefine that exceeds libxml2, `particlesZ001` which the suite
itself marks ambiguous, `targetns00101m`) are real but each needs its own analysis.
instance side the Ethiopic-digit `\d`/`\D`, `\i`/`\c`, identity-field `idZ010`, and
`xsi:type` `targetns00101m` cases are now fixed (reference-aligned); `anyURI_a004`,
`schA2`, `schA5`, `mgO013`, and `particlesZ001` are shown contested. The remaining
instance deviations are `schA7` (a genuine schema-location policy choice) and
`schU3/4/5` (circular `redefine` composition, which libxml2 does not implement);
both are deliberate, not clean bugs.
## Category A: genuine correctness bugs