Repository navigation
feat(conformance): add the openshell-conformance program - #5138
matthewgrossman wants to merge 6 commits into
Conversation
|
Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually. Contributors can view more details about this message here. |
|
/ok to test ca412d5 |
|
Label |
|
🌿 Preview your docs: https://nvidia-preview-pr-5138.docs.buildwithfern.com/openshell |
|
/ok to test 592a748 |
Compatibility review (advisory)New or updated breaking changes; see the full report for all findings. 1. cli — No explicit risk acceptance foundopenshell-test-runner replaces
Review details
Advisory review; publication gates are unchanged. |
592a748 to
2fecde6
Compare
|
/ok to test 2fecde6 |
2fecde6 to
f945820
Compare
|
/ok to test f945820 |
Compatibility review (advisory)New or updated breaking changes; see the full report for all findings. 1. cli — No explicit risk acceptance foundWith unchanged environment, installer, family and package arguments,
Review details
Advisory review; publication gates are unchanged. |
f945820 to
8835ce6
Compare
|
/ok to test 8835ce6 |
#[testkit::test] now also registers each test in a link-time registry, alongside the existing #[tokio::test] wrapper, so suites keep running under cargo test and nextest unchanged. testkit::main() runs the registered tests a binary links. Without a subcommand it speaks libtest's interface, so a harness = false target works under cargo test and nextest. Its subcommands are: - list: print each test's name and description - ready: wait for the gateway, sharing its check with testkit-ready, and exit 2 if it is not ready in time - run (Unix only): run tests one at a time, each in its own process group with a timeout (SIGTERM, grace, SIGKILL), write a JUnit report, and exit 1 when a test failed or 2 when tests could not run A stopped test does not clean up its sandboxes yet; the README notes this. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
Cargo builds each file in tests/ as its own test executable, which no other program can link. Move the conformance suites into src/ as modules of a library, so a test program can link them. Test code is unchanged; cargo test and nextest run the same 15 tests as the library's unit tests. Nextest now names them as binary `conformance`, test `<suite>::<fn>`, so filters that selected a suite by binary select it by test name instead. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
8835ce6 to
c03061b
Compare
|
/ok to test c03061b |
The conformance crate now also builds openshell-conformance, a binary whose main calls testkit::main() and links the crate's library. It lists, waits for the gateway, and runs the conformance tests without cargo or nextest. It runs only the conformance suite and promises only the conformance contract; feature and driver suites are not part of it. The binary has test = false, so cargo test and nextest still see one conformance test binary, the library's unit tests, and the e2e lanes and the runner's filters are unchanged. The library is linked without cfg(test), so the program gets the registrations and none of the tokio test wrappers. tasks/scripts/check-conformance-program.sh checks that openshell-conformance list names the same tests as nextest; Branch Checks and mise test:rust run it. A dependency that is never named is not linked, so a suite the program forgets to name would silently go missing. testkit::main() now fails with exit 2 when a program links no tests, under every command. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
|
/ok to test 1d3ed2d |
c03061b to
1d3ed2d
Compare
The Docker, Podman, VM and Kubernetes host lanes ran the conformance suite with cargo nextest. They now run it with openshell-conformance: ready, then run --junit, so CI exercises the program that gateway owners use. The script uses OPENSHELL_CONFORMANCE_BIN when set and otherwise builds the program from the checkout. The JUnit report goes to OPENSHELL_CONFORMANCE_JUNIT or results/conformance-<gateway>.xml; the Kubernetes runner names it after its report so credential-driver runs keep both. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
Each Docker, Podman, VM and Kubernetes host lane built the conformance suite itself. Branch E2E now builds openshell-conformance once per architecture as a static musl binary, checks that it is static and lists its tests, and uploads it. setup-e2e-cli downloads the one that matches the runner when a lane sets prebuilt-conformance, and the lane runs it through OPENSHELL_CONFORMANCE_BIN. The job is separate from build-binaries.yml, which the release workflows also call: the program has its own workspace and is not released. Lanes called without prebuilt-conformance, such as the release qualification lanes, still build the program from the checkout. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
|
/ok to test 62e1f57 |
|
/ok to test b8a1ef3 |
…t-program/matthewgrossman Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
|
/ok to test 7531d8a |
Summary
Turn the conformance suite into one program,
openshell-conformance, that anyone can run against their own gateway without a Rust toolchain, cargo or nextest.#[testkit::test]now also registers each test, andtestkit::main()turns a binary into a test program withlist,readyandrun. The conformance suite becomes a library, and the conformance crate builds the program as a[[bin]]. Existing suites still run undercargo testand nextest.The program promises only the conformance contract: passing it means a gateway meets the rules in
tests/suites/conformance/README.md. Feature and driver suites are not promised to join it. The Docker, Podman, VM and Kubernetes host lanes now run conformance through the program, built once per architecture. Switching the tmachine rows and publishing the program are later PRs.Related Issue
Part of #3954
Changes
Five commits (the crate rename to
conformancelanded in #5078):feat(testkit): register tests and add a standalone test program.#[testkit::test]keeps its#[cfg(test)] #[tokio::test]wrapper and also adds a link-time registry entry (linkme) with the test's family, name, description and#[ignore]reason.tests/suites/. It groups tests in the JUnit report. The name is the same name libtest and nextest use.cfgand lint attributes (allow,warn,deny,forbid).#[should_panic],#[cfg_attr]and#[expect]are rejected with an error explaining why.testkit::main():libtest-mimic), so it also works as aharness = falsetarget undercargo testand nextest.list [FILTER]...prints name and description, with ignored tests marked.ready [--timeout SECS]waits for the gateway, sharing its check withtestkit-ready. It exits 2 if the gateway isn't ready in time.run [FILTER]... [--include-ignored] [--timeout SECS] [--grace SECS] [--junit PATH]runs tests one at a time. Each test is a new process (<name> --exact --nocapture) in its own process group, so nothing a test starts outlives it. A test that runs past its timeout (900s by default) gets SIGTERM, then SIGKILL after the grace period (10s). Interruptingrunstops the current test and runs no more tests; a second interrupt skips the grace period. Output is shown live and kept (the last 4 MiB per stream) for the JUnit report.runexits 1 when a test failed and 2 when tests couldn't run or the run was interrupted. It is Unix-only; on other platforms it says to use cargo test or nextest.tests/testkit/README.mddocuments the program and its limits.refactor(conformance): move the conformance suites into a library. Cargo builds each file intests/as its own test executable, which no other program can link.tests/suites/conformance/tests/*.rsmove tosrc/as modules of alib.rs; test code is unchanged.cargo testand nextest run the same 15 tests as the library's unit tests.conformance::smoke create_exec_delete(binaryconformance::smoke) becomes binaryconformance, testsmoke::create_exec_delete. Filters that picked a suite by binary now pick it by test name, e.g.--filter 'test(/^policy_advisor::/)'.CI.md,e2e/policy-advisor/README.md, the runner's--filterhelp and the suite README are updated. This break is intentional: these filters are internal test tooling, not a published interface, and every in-repo use is updated here. It is what the advisory compatibility review flags.e2e/support/conformance.sh),mise run e2e:testkitand the tmachine runner select the suite by workspace or package, so they still select every test. Thekind(test)archive filters intests/tmachine/artifacts.nixaren't used for conformance.feat(conformance): add the openshell-conformance program.tests/suites/conformance/Cargo.tomladds[[bin]] name = "openshell-conformance"(src/main.rs,test = false). Itsmaincallstestkit::main()and names the library withuse conformance as _;.tasks/scripts/check-conformance-program.shchecks thatopenshell-conformance listnames the same tests ascargo nextest listfor the crate. Branch Checks (Rust test, all three systems) andmise run test:rustrun it. Neither command needs a gateway.TESTING.md, the testkit README and the conformance README describe the program. The conformance README says what it promises.test(e2e): run the conformance host lanes with openshell-conformance.e2e/support/conformance.shrunsopenshell-conformance ready, thenrun --junit, instead ofcargo nextest run. It usesOPENSHELL_CONFORMANCE_BINwhen set, and otherwise builds the program from the checkout, so localmise run e2e:dockerand the other runners work as before.OPENSHELL_CONFORMANCE_JUNIT, elseresults/conformance-<gateway>.xml. The Kubernetes runner names it after its report, so the two credential-driver runs keep both.ci(e2e): build openshell-conformance once per architecture in Branch E2E.build-conformancejob builds a static musl binary for x86_64 and aarch64, checks it withverify-static-binary.shandlist, and uploadsopenshell-conformance-<triple>.setup-e2e-cligets aconformanceinput that downloads the runner's binary and setsOPENSHELL_CONFORMANCE_BIN. The four lane workflows pass it through aprebuilt-conformanceinput, and all 15 Branch E2E lane callers set it and depend onbuild-conformance.build-binaries.yml, because the release workflows call that too and the program isn't released. Callers that don't setprebuilt-conformance(Release Dev, release qualification, GPU) build the program in the lane, as commit 4 does.Why a
[[bin]]in the conformance crate, not its own workspace:ALIGNED_WORKSPACESentry, and fmt, clippy and nextest lines in Branch Checks and the mise tasks.cfg(test)wrappers: the bin links the library built withoutcfg(test), so it gets thelinkmeregistrations and none of the#[tokio::test]wrappers. The library's own unit-test build is unchanged.test = false:mise run e2e:testkitand the tmachine runner run plaincargo nextest runon the whole crate. A bin test target would add an empty test binary to each. Without one, nextest still sees oneconformancebinary with 15 tests.conformance, so nextest binary IDs and filters such astest(/^policy_advisor::/)don't change again. The binary is namedopenshell-conformancefor the people who run it.tests/openshell-test/tests/list.rsintegration test would have been a test target in the crate. The list-vs-nextest script replaces it, and the runtime guard intestkit::main()catches a program that links nothing.Name note:
crates/openshell-conformance, the existing CLI conformance library, still exists onmainuntil #5137 merges. The newopenshell-conformanceis a binary in the separatetests/suites/conformanceworkspace (packageconformance), so cargo doesn't conflict. Once #5137 lands, the name has one meaning.Limits:
Release Notes
Design agreed with @elezar
This reverses two decisions from #4629: "no custom harness" and "one binary per suite". The reason is that the program should run where the user has no cargo or nextest. It keeps the standard tooling (the libtest interface, so nextest and
cargo testwork as before), per-test process isolation, and nextest archives in CI. Agreed with @elezar: thelibtest-mimicharness,list/ready/run, one process per test andlinkmeregistration, with the program narrowed to conformance and namedopenshell-conformance.Testing
--all-targets -D warnings) are clean for testkit, conformance (including the bin), features, support and the runner.tasks/scripts/check-conformance-program.sh:openshell-conformance listnames the same 15 tests ascargo nextest list. The libtest interface (--list --format terse) lists 15 too.cargo nextest liston the crate shows one binary,conformance, with 15 tests, andtest(/^policy_advisor::/)selects 3.testkit/tests/program.rs) run fixture tests through the subcommands. They cover thelistformat, pass, fail, timeout, SIGTERM ignored, interrupt during and between tests, leftover helper processes, JUnit output, and a program with no tests.testkit/tests/attribute.rschecks that the registry agrees with libtest's--listand--list --ignored.openshell-test, before the move into the conformance crate): against a live mTLS Docker gateway (e2e/with-docker-gateway.sh), nextest ran the conformance workspace with--no-tests fail: 15/15 passed. The program'sreadyexited 0, andrunpassed 15/15 and exited 0. Its JUnit report has oneconformancesuite with 15 test cases. The program code is unchanged by the move; only where it is built changed.e2e/support/conformance.shbuilds the program whenOPENSHELL_CONFORMANCE_BINis unset, uses it when set, fails with exit 2 when it isn't executable, and passes onready's exit 2 for an unreachable gateway. actionlint is clean on the changed workflows; zizmor (high) reports no new findings.openshell-conformance(built in the lane) and passed 15/15. Branch Checks green.build-conformancebuilt static-pie musl binaries for both architectures in about 3 minutes. All 15 host lanes downloaded the prebuilt binary, built nothing, and passed 15/15. Branch Checks and Workflow Security Reports green.CI coverage: Rust format, Rust lint and Rust test (x86_64-linux, aarch64-linux, aarch64-darwin) in Branch Checks build and test
tests/testkit, lint the conformance crate including the bin, and run the list check. Branch E2E builds the program and runs it in every Docker, Podman, VM and Kubernetes host lane. The tmachine conformance rows run the moved suite under its new names with nextest.Known red, not from this PR: both
ubuntu-k3sconformance rows fail before any test runs, becauseget.k3s.iono longer matches the checksum pinned intests/tmachine/ansible/playbooks/k3s.yaml. On commit 4's run,fedora-podman-rootless / rpmalso failed once:persistent_workspace_survives_stop_starthit a sandbox container that exited on create (ContainerExited). That row runs nextest archives, which commit 4 doesn't touch, and it passed on commit 5's run without a rerun.Not verified: the non-Unix
runpath, and the HA, credential-driver and GPU lanes (label-gated, not run here).Checklist
tests/testkit/README.md,TESTING.md,tests/suites/conformance/README.md