From 8056d5a30b131a3303d5c8b198cadc3a3570b083 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibaut=20Barr=C3=A8re?= Date: Fri, 18 Sep 2026 18:52:17 +0200 Subject: [PATCH] "Should fail" examples framework (#1074) * Add "failing examples" to CI * Remove incorrect example * Make failure check more narrow * Use more structured input for should_fail (more readable) --- .github/scripts/validate-should-fail.sh | 46 +++++++++++++++++++ .github/workflows/ci.yml | 3 ++ examples/should-fail/README.md | 7 +++ .../duplicate-GroupOfLinkSequences.xml | 13 ++++++ .../should-fail/duplicate-ValidBetween.xml | 17 +++++++ .../should-fail/duplicate-ValidityPeriod.xml | 23 ++++++++++ 6 files changed, 109 insertions(+) create mode 100755 .github/scripts/validate-should-fail.sh create mode 100644 examples/should-fail/README.md create mode 100644 examples/should-fail/duplicate-GroupOfLinkSequences.xml create mode 100644 examples/should-fail/duplicate-ValidBetween.xml create mode 100644 examples/should-fail/duplicate-ValidityPeriod.xml diff --git a/.github/scripts/validate-should-fail.sh b/.github/scripts/validate-should-fail.sh new file mode 100755 index 000000000..96e2b4534 --- /dev/null +++ b/.github/scripts/validate-should-fail.sh @@ -0,0 +1,46 @@ +#!/bin/bash +# Negative examples: documents that MUST be rejected by the schema. +# +# Each case is declared as: should_fail . +# We assert BEHAVIOUR (the document is rejected, and its output contains the +# declared substring) - not a specific constraint name. +# +# All cases share ONE schema and are validated in a SINGLE xmllint call (one +# compile for many files) to stay fast. Fails closed: accepted, wrong reason, or +# xmllint not running all count as failures. +# +# CI uses the vendored 2025 Linux x86-64 xmllint ("Temporary xmllint master", +# https://github.com/TransmodelEcosystem/NeTEx/pull/915); set XMLLINT_BIN to a local +# xmllint to run this on any other OS or CPU architecture (macOS, Windows, ARM, ...). + +set -u +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +ROOT_DIR=$( cd -- "${SCRIPT_DIR}/../.." &> /dev/null && pwd ) +XMLLINT="${XMLLINT_BIN:-${SCRIPT_DIR}/xmllint}" +cd "${ROOT_DIR}" + +SCHEMA="xsd/NeTEx_publication.xsd" + +files=(); expected=() +should_fail() { files+=("$1"); expected+=("$2"); } + +should_fail examples/should-fail/duplicate-GroupOfLinkSequences.xml "Duplicate key-sequence ['TEST:GroupOfLinkSequences:1', '1.0']" +should_fail examples/should-fail/duplicate-ValidBetween.xml "Duplicate key-sequence ['TEST:ValidBetween:1', '1.0']" +should_fail examples/should-fail/duplicate-ValidityPeriod.xml "Duplicate key-sequence ['TEST:ValidityPeriod:1', '1.0']" + +out=$("${XMLLINT}" --noout --schema "${SCHEMA}" "${files[@]}" 2>&1) + +fail=0 +echo "Checking NeTEx 'should-fail' negative examples ..." +for i in "${!files[@]}"; do + f="${files[$i]}"; exp="${expected[$i]}" + if printf '%s\n' "${out}" | grep -Fqx "${f} validates"; then + echo "SHOULD HAVE FAILED ${f} — accepted (must be rejected)"; fail=1 + elif printf '%s\n' "${out}" | grep -F "${f}:" | grep -Fq "${exp}"; then + echo "OK ${f}" + else + echo "ERROR ${f} — rejected, but not matching '${exp}'"; fail=1 + fi +done + +exit "${fail}" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index abef8b4f9..8b05dcd9d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,6 +26,9 @@ jobs: - name: Validate NeTEx XML examples run: ./.github/scripts/validate-examples.sh + - name: Validate negative examples (must-fail) + run: ./.github/scripts/validate-should-fail.sh + - name: Commit changes uses: EndBug/add-and-commit@v9 # https://github.com/marketplace/actions/add-commit with: diff --git a/examples/should-fail/README.md b/examples/should-fail/README.md new file mode 100644 index 000000000..35110f047 --- /dev/null +++ b/examples/should-fail/README.md @@ -0,0 +1,7 @@ +# Negative examples (must-fail) + +Each file carries one deliberate defect and must therefore be **rejected** by the +schema for a specific, expected reason. The cases — file, schema and expected +constraint — are declared in `.github/scripts/validate-should-fail.sh` (run in CI). + +Run locally: `XMLLINT_BIN=$(which xmllint) ./.github/scripts/validate-should-fail.sh` diff --git a/examples/should-fail/duplicate-GroupOfLinkSequences.xml b/examples/should-fail/duplicate-GroupOfLinkSequences.xml new file mode 100644 index 000000000..40bb4cb59 --- /dev/null +++ b/examples/should-fail/duplicate-GroupOfLinkSequences.xml @@ -0,0 +1,13 @@ + + + 2020-01-01T12:00:00Z + TEST + + + + + + + + + diff --git a/examples/should-fail/duplicate-ValidBetween.xml b/examples/should-fail/duplicate-ValidBetween.xml new file mode 100644 index 000000000..44eb0c8f2 --- /dev/null +++ b/examples/should-fail/duplicate-ValidBetween.xml @@ -0,0 +1,17 @@ + + + 2020-01-01T12:00:00Z + TEST + + + + 2020-01-01T00:00:00Z + + + + + 2020-01-01T00:00:00Z + + + + diff --git a/examples/should-fail/duplicate-ValidityPeriod.xml b/examples/should-fail/duplicate-ValidityPeriod.xml new file mode 100644 index 000000000..e7f49a0d9 --- /dev/null +++ b/examples/should-fail/duplicate-ValidityPeriod.xml @@ -0,0 +1,23 @@ + + + 2020-01-01T12:00:00Z + TEST + + + + + A + + 2020-01-01T00:00:00Z + + + + B + + 2020-01-01T00:00:00Z + + + + + +