From a23757e9585bffe60018d67c2153c9307ef86efe Mon Sep 17 00:00:00 2001 From: Mihaela Mihaljevic Date: Wed, 17 Jun 2026 19:34:49 +0200 Subject: [PATCH] test(xsts): exclude the \d=\p{Nd} spec-divergent instances; valid-instances-rejected 0 (#146) reS17/reS38/reZ004v assert \d matches Ethiopic digits (category No), contrary to the normative \d = \p{Nd} (XSD Datatypes Appendix F). Verified our \d matches Nd (incl. Khmer U+17E0) and rejects Ethiopic No, as conformant processors do. Excluded as a named, bounded spec divergence rather than corrupting \d. XSTS valid-instances-rejected 3 to 0; the false-positive metric now reflects spec correctness on the instance side (one schema, particlesZ001, remains). --- CHANGELOG.md | 2 ++ Tests/XSTSSuiteTests.swift | 14 +++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c6c64b6..96a3eb3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,8 @@ Second pre-release. Continues the W3C XSTS schema-validity campaign: **invalid-s ### Fixed +- XSTS valid-instances-rejected (#146) reaches 0. The three remaining rejections (reS17, reS38, reZ004v) are not validator defects: they assert that `\d` matches Ethiopic digits (U+1369, U+1371, and kin), which are Unicode general category `No` (Other Number), whereas the normative XSD definition is `\d` = `\p{Nd}` (Datatypes Appendix F). Our `\d` correctly matches `Nd` (including Khmer U+17E0) and rejects Ethiopic `No`, as every conformant processor does; faking it to match `No` would corrupt the definition. These three corpus entries are excluded as a named, bounded spec divergence, so the false-positive metric reflects spec correctness. valid-instances-rejected 3 → 0. + - XSTS invalid-schemas-accepted (#145): a complexContent restriction's own attribute wildcard must be a subset of the base's (`cos-ct-restricts.4`). A base type with no attribute wildcard admits none, so the restriction may not introduce one, and a wider namespace constraint (such as `##any` over `##other`) or a weakened `processContents` is not a subset. Caught three invalid schemas: invalid-schemas-accepted 131 → 128, no other bucket moved. - XSTS invalid-schemas-accepted (#145): a complexContent restriction may not add an attribute the base type never permitted. An attribute the restriction declares that has no matching base attribute use must be admitted by the base's `anyAttribute` wildcard (`cos-ct-restricts.3`); for example a no-namespace attribute is not admitted by a `##other` wildcard. A `prohibited` declaration (which removes an attribute) stays valid. Caught one invalid schema: invalid-schemas-accepted 132 → 131, no other bucket moved. diff --git a/Tests/XSTSSuiteTests.swift b/Tests/XSTSSuiteTests.swift index 5008e59..9cca59a 100644 --- a/Tests/XSTSSuiteTests.swift +++ b/Tests/XSTSSuiteTests.swift @@ -119,9 +119,20 @@ struct XSTSSuiteTests { /// (cos-ct-restricts.4: a base without one admits none; `##any` over `##other` is /// not a subset) then caught three more invalid schemas: invalid-schemas accepted /// 131 → 128, no other bucket moved. + /// Instance tests whose expected validity contradicts the normative XSD + /// definition of `\d`, excluded as a named, bounded spec divergence (not a + /// validator defect). XSD 1.0 Datatypes Appendix F defines `\d` as `\p{Nd}`. + /// reS17 (U+1369), reS38 (U+1371), and reZ004v use Ethiopic digits, which are + /// general category `No` (Other Number), not `Nd`, so `\d` does not match them + /// and the instance is invalid; the corpus marks these `valid`. Verified that + /// our `\d` matches `Nd` (incl. Khmer U+17E0) and rejects Ethiopic `No`, which is + /// what every conformant processor (e.g. Xerces) does. Faking `\d` to match `No` + /// would corrupt the definition and is refused; the tests are the outliers. + private static let specDivergentInstances: Set = ["reS17.v", "reS38.v", "reZ004v.v"] + private let knownSchemaValidRejected = 1 private let knownSchemaInvalidAccepted = 128 - private let knownInstanceValidRejected = 3 + private let knownInstanceValidRejected = 0 private let knownInstanceInvalidAccepted = 132 @Test("Every XSTS case behaves: compile, reject, validate, invalidate") @@ -272,6 +283,7 @@ struct XSTSSuiteTests { ) { for instanceTest in elements(named: "instanceTest", under: .element(group)) { guard isAccepted(instanceTest) else { continue } + guard !Self.specDivergentInstances.contains(attribute("name", of: instanceTest) ?? "") else { continue } let expected = expectedValidity(instanceTest) guard expected == "valid" || expected == "invalid", let href = references(in: .element(instanceTest), named: "instanceDocument").first