Conformance evidence
한국어.
contracts/features.json is the standard every runtime is
measured against. Each feature declares its supported runtimes (pass) and the shared fixtures that prove it.
The manifest's fixtures list registers every fixture: a cases.json family, or a module fixture with its declared cases or the module
export that lists them.
Fixture applicability is explicit when a family exercises only some implementations. A fixture's runtimes lists
its actual execution runtimes; without it every supported runtime remains required. featureCases maps each owning
feature to its exact case names when a family tests several operations. Every case must belong to a feature, every
owning feature must select cases, and every supported feature runtime must still have applicable cases. Unknown
runtimes, unknown cases and empty selections fail the check.
featureRuntimes restricts one owning feature to the fixture runtimes in which that operation actually runs. An omitted
feature keeps the fixture's default runtime coverage. Each override must select nonempty runtimes supported by that
feature and allowed by the fixture. Python outline cases compile and bind their template before building the outline;
other outline checks record only the target operations that they execute.
A support-module entry names its actual shared module and the registered case fixtures in supports that execute
through it. It declares no invented case and supplies no passing evidence. Each supported fixture must be registered
and proven by a feature; the module file must exist. The form-state registration module supports the state fixture units.
Runtime keys
| Key | Implementation |
|---|---|
javascript |
@polyspec/crudui-validator and the @polyspec/crudui-generator-core model |
javascript-html |
the @polyspec/crudui-generator-html string renderer |
javascript-dom |
the @polyspec/crudui-generator-core DOM binding over @polyspec/crudui-generator-html markup |
react, vue, svelte |
the framework packages |
php, go, rust, python |
the server libraries |
php-native |
the PHP C extension |
JavaScript has two keys for server output because its model and its string renderer are separate packages; PHP, Go and Rust ship both in one library and prove model and HTML features under one key.
Evidence
A test that runs a shared fixture case records one line for each feature the case proves:
{"feature", "fixture", "runtime", "case", "passed"}. passed is true only when every assertion
of that case succeeded. The recorders are
tests/conformance/evidence.mts,
the class Polyspec\Crudui\Conformance\Evidence of
tests/conformance/php/Evidence.php, the Go package
packages/validator/go/testsupport/conformance and the Rust test module tests/common. They write only when
CRUDUI_CONFORMANCE_EVIDENCE names a directory.
scripts/check-conformance.mts reads that directory and
fails when:
- a supported runtime has no evidence, or failing evidence, for a case of a fixture its feature names;
- evidence exists for a feature, fixture, runtime or case the standard does not declare, such as a test for a runtime outside the fixture applicability, or a case assigned to another operation;
- a directory under
tests/fixtureshas no registered fixture, or a registered case fixture is proven by no feature; - a feature names a fixture that is not a registered case fixture.
The optional phpExtensions field records the PHP modules requested by the runner, relative to the repository root.
A generator PHP source run and an extension run are separate suite commands even when their case arguments match.
Suite status describes command execution only; passing case evidence still comes from the test's actual runtime.
Suite runs
A missing case does not tell whether its suite failed, did not finish or did not run, so each run of
a suite that records evidence also leaves a run record in runs/ of the evidence directory:
tests/conformance/run-suite.mts for the test command of a suite that it
starts through node_modules/@polyspec/kit/dist/run-tests.mjs and
tests/native-generators/run.mts for itself, through
tests/conformance/runs.mts. A record
{"program", "tool", "cwd", "args", "started", "status"} is written with status null when the run
starts and again with the exit status when its process exits, so a stopped run keeps null. The
Python suites run through run-suite.mts too, with the Python of the environment var/python that
make crudui-install-python makes, and record their evidence with the package polyspec.crudui.conformance of
tests/conformance/python.
evidenceSuites of the check declares each suite with the command that runs it and the runtimes it
proves. For each feature, fixture and runtime with missing or failing evidence, the check names every
suite that proves the runtime with its state: did not run when no record matches its command,
did not finish when a record has no status, ended with failure (exit <status>) or passed. The
latest record of each matching command decides, and a suite run by several commands takes the worst
state of them. Every runtime that a feature supports is proven by a declared suite.
Server runtimes are compared byte for byte with the JavaScript reference output by
tests/native-generators/run.mts; client renderers are
compared with the fixture's normalized HTML, where only differences a framework itself causes are
normalized.
CI runs make crudui-test-cross-language-equivalence in the independent cross-language-equivalence job.
It compares JavaScript, HTML, Go, Rust, Python, PHP and the native PHP extension without waiting for language unit jobs.
The job prepares its own build and dependencies and uploads both comparison reports and conformance evidence.
Both conformance and ci-passed require this job.
make conformance clears the directory, runs every suite that records evidence and runs the
check. CI uploads each job's evidence under an artifact name of its own and runs the check once
over all of it: the conformance job downloads each artifact into a directory of its own, and the
check reads the evidence files and the runs/ records of the directory and of its subdirectories,
so no file of one job replaces a file of the same name from another job.