Repository navigation
test(testkit): add the testkit library for end-to-end suites - #4724
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. |
|
🌿 Preview your docs: https://nvidia-preview-pr-4724.docs.buildwithfern.com/openshell |
f595dd0 to
9c471d2
Compare
Rebuilds the runner on the rebuilt migration, the current #4724 head and the tmachine paths from main. The tree is the rebuilt runner; the extra parent keeps this branch a fast-forward of what was pushed before.
6c1654e to
c8d4223
Compare
|
Reviewed commit
The earlier attribute-forwarding issue is fixed: probes confirmed All 23 existing tests passed locally. No real-gateway E2E run was performed. |
Add tests/testkit as its own Cargo workspace: testkit, testkit-macros, and testkit-spec. testkit reads a target file, connects to the gateway through openshell-sdk, creates and cleans up sandboxes, and runs the installed CLI. #[testkit::test] requires a stable ID and a doc comment and declares capability requirements. testkit-ready waits for a target's gateway and CLI before tests run. Nothing uses testkit yet. The lockfile is seeded from the root lockfile so shared crates resolve to the same versions. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
Nothing else builds testkit, so check it in Branch Checks and the matching mise tasks to catch openshell-sdk changes that break it. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
Cleanup shared one two-minute budget across all of a test's sandboxes, so a slow delete left the rest with no time and could leak them on a shared gateway. Delete them concurrently, each with the full timeout. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
Nothing reads test IDs or capability requirements until a runner, waivers, or result history exist, so remove the id and requires arguments and the target file's capabilities section. Both can return as optional attribute arguments without changing existing tests. With them gone, testkit-spec only checked the function shape and read the doc comment, so fold it into testkit-macros. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
Replace the target file (OPENSHELL_TEST_TARGET) with the CLI's own gateway selection: OPENSHELL_GATEWAY_ENDPOINT, then OPENSHELL_GATEWAY, then the active gateway. A registered gateway's endpoint, auth mode, and mTLS material come from its CLI config directory. cx.cli runs OPENSHELL_BIN against the same gateway and workspace as the SDK. Suites now run unchanged under e2e/with-docker-gateway.sh and e2e/with-podman-gateway.sh, and environments need no extra file. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
The policy path creates the sandbox through gRPC and dropped the spec's labels without an error. Pass them in the create request. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
When OPENSHELL_GATEWAY_ENDPOINT is set, the CLI takes credentials from the gateway named by OPENSHELL_GATEWAY, or else the registered gateway with that endpoint. testkit connected without a client certificate instead, so an mTLS endpoint such as the one e2e/rust/e2e-vm.sh exports worked for cx.cli but not for the SDK. Resolve it the way the CLI does, and pass both the name and the endpoint to cx.cli. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
OPENSHELL_GATEWAY_ENDPOINT takes precedence over OPENSHELL_GATEWAY. Also mention OPENSHELL_BIN. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
#[testkit::test] left attributes such as #[ignore] and #[cfg] on the nested body function, where they have no effect on the test. Move them to the generated test, and reject a second test attribute such as Signed-off-by: Matthew Grossman <mgrossman@nvidia.com> #[test] or #[tokio::test].
Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
A testkit test panics on any failure, including an unreachable gateway or a failed cleanup, so #[should_panic] would let such a failure pass. Reject it and point to checking the expected failure in the body. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
Suites built on testkit exercise gateway resolution, the CLI wrapper, polling, errors, and cleanup against a real gateway. Keep one unit test for the macro's compile errors, which a passing suite never reaches, and drop the test-only seams the other tests needed. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
The SDK's ClientConfig now takes a client identity, so testkit no longer builds its own channel. It still resolves the registered gateway and reads its credential files, then hands the CA and client certificate to OpenShellClient::connect. That keeps TLS behavior, connect timeouts and keep-alive settings in the SDK, and drops testkit's direct tonic dependency. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
wait_ready checked elapsed time only after a health call returned, and cleanup started its timeout only after the delete returned, so a gateway that accepts a connection but never answers could hang either one. Wrap each whole operation in tokio::time::timeout: the readiness wait, including every connect and health call, and each sandbox's delete plus wait for deletion. A test covers a peer that accepts connections and never replies. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
d25d1b6 to
6427db9
Compare
|
Thanks, Drew. Status against your review of
The branch was rebased onto current main for #4817. No real-gateway run in CI yet; I ran the suite against a local mTLS Docker gateway. |
TL;DR
testkit, a small library for writing end-to-end tests against a running OpenShell gateway through the Rust SDK. A test is a documentedasync fnmarked#[testkit::test]that runs with plaincargo nextest.openshellCLI does, so they run unchanged undere2e/with-docker-gateway.shande2e/with-podman-gateway.shwith no extra config.cx.cli(...)runs the CLI against the same gateway and workspace as the SDK.Stack
Part of a stack of three; each PR targets the one below it. The tmachine move (#4726) has merged, so the stack uses its
tests/tmachine/paths.testkit-spec), the test runner, plans, and the tmachineSessionAPI, with a plan running a smoke test on CI.Still to come, on top of #4774: moving the release lanes onto plans and deleting the old suites, once the plan has run the ported suites green.
Summary
Adds
tests/testkit/, a support library for SDK-driven end-to-end suites, as its own Cargo workspace. This is a small first step to get the crate into main and checked in CI. Nothing uses it yet. The existing suites move onto it in one follow-up migration (#4774, stacked on this PR) that also deletes the old suites. Suites added after that arrive one at a time.The code comes from @elezar's draft #4629 (head
673928804). This PR takes only the testkit portion, adapted to current main and cut down to what's needed today (see "Deferred and follow-ups" below).Related Issue
Part of #3954
Changes
tests/testkit/: thetestkitandtestkit-macroscrates, plus thetestkit-readybinary, taken from test(conformance): run conformance suites from test plans in tmachine environments #4629.async fnmarked#[testkit::test]with a required doc comment. Other attributes such as#[ignore]apply to the generated test.#[should_panic]is rejected, because a testkit test panics on any failure.openshellCLI does:OPENSHELL_GATEWAY_ENDPOINT, thenOPENSHELL_GATEWAY, then the active gateway. A registered gateway's endpoint and mTLS material come from its CLI config directory. Like the CLI, an endpoint takes its credentials fromOPENSHELL_GATEWAYor the registered gateway with that endpoint.cx.clirunsOPENSHELL_BINagainst the same gateway and workspace. Each test logs the gateway it used.testkit-ready) is bounded as a whole, including each connect and health call, so a gateway that accepts connections but never answers cannot hang it.ClientConfigclient identity, so TLS, connect timeouts and keep-alive stay in the SDK.Cargo.lockis re-seeded from the root lockfile, because main'sopenshell-sdkhas more dependencies than when test(conformance): run conformance suites from test plans in tmachine environments #4629 was cut.rust:lint,rust:format,rust:format:check, andtest:rustmise tasks now run fmt, clippy, and nextest for the testkit workspace. This follows test(conformance): run conformance suites from test plans in tmachine environments #4629'scf72f1108, restricted to testkit.tests/testkit/README.mdcovers writing a test, whatContextprovides, and running against a gateway.TESTING.md,AGENTS.md, andCONTRIBUTING.mdpoint to it.Deferred and follow-ups
Dropped from #4629's testkit
Each can come back as an optional addition, without changing tests written in the meantime:
id = "t-…"). Until a runner, waivers, or result history need them, the nextest name identifies a test.requires = [...]. These belong with the runner, which selects tests per environment. Until then, a suite excludes a test that an environment can't support with a nextest filter or#[ignore].testkit-speccrate, for listing tests without compiling them. It returns with the runner's catalog.OPENSHELL_TEST_TARGET). It held a copy of the CLI's registered gateway plus capabilities, so testkit now reads the CLI's gateway config directly. As a result, step 3 no longer needs test(conformance): run conformance suites from test plans in tmachine environments #4629'sopenshell_clientrole change or the runner code that writestarget.yaml. The runner only setsOPENSHELL_GATEWAY(orOPENSHELL_GATEWAY_ENDPOINT) andOPENSHELL_BIN.Tests ported from #4629 must drop
idandrequires, because#[testkit::test]takes no arguments here. The runner PR (#4773) adds them back as optional arguments.Rest of #4629, for later steps
Sessionlibrary, and the Ansible andconfig.nixchanges.e2e-suites.yml.a37ebe917). It matters once testkit is built into the Nix test archives. Until then,check-cargo-lockfiles.shalready validatestests/testkit/Cargo.lock.Follow-ups found while landing this
gateway.rsrepeats the CLI's lookup: the endpoint-to-registered-gateway match,metadata.jsonauth modes, and themtls/files. The connection itself already goes through the SDK; only the lookup is copied, and the copies can drift apart. When step 3 lands or tmachine needs the same lookup, move it (gateway name or endpoint to endpoint, CA, and client identity) intoopenshell-bootstrapor an SDK helper so the CLI, testkit, and tmachine share one implementation.mtls/path, as the CLI does. Gateway names with only letters, digits,.,-, and_are unaffected.cx.sandbox(...). Tests must delete anything else they create, such as providers. This is documented in the README. Extend the cleanup registry when suites create other resources often.tests/testkit/targetisn't covered by the Rust cache. This adds roughly 1–2 minutes to each Rust lint and test job. Caching it would add about 2 GB per platform cache. Revisit if suites make the build slower.supervisor_network_mode = "bridge".e2e/with-docker-gateway.shsets neither. Linux CI isn't affected. Consider setting bridge mode in the wrapper on macOS when the first testkit lane lands.Raised in review and left as is
Sandboxhelpers have no caller yet (for exampleconfig,draft_policy, andset_setting). They came from test(conformance): run conformance suites from test plans in tmachine environments #4629 for the suites in the next PR, so removing them now would only mean adding them back.Testing
cargo fmt --manifest-path tests/testkit/Cargo.toml --all -- --checkcargo clippy --locked --manifest-path tests/testkit/Cargo.toml --all-targets -- -D warningscargo nextest run --locked --config-file .config/nextest.toml --manifest-path tests/testkit/Cargo.toml(2 tests: the macro rejects misuse, and the readiness wait gives up on a gateway that never answers. Gateway resolution, the CLI wrapper, and cleanup are exercised against a real gateway below and by the suites that adopt testkit.)tasks/scripts/check-cargo-lockfiles.shcoverstests/testkit/Cargo.lockmise run license:checkAgainst a real gateway
To check that testkit works end to end, I built a throwaway suite crate outside the repo. It depends on this branch's testkit and contains the six
sandbox_lifecycletests from #4629, plus a test that creates three sandboxes, checks thatcx.cli(["sandbox", "list"])shows them, and leaves them for cleanup. I ran it unchanged undere2e/with-docker-gateway.shon macOS with Docker Desktop. The wrapper's ownOPENSHELL_GATEWAYandOPENSHELL_BINwere the only configuration:e2e/with-docker-gateway.sh sh -c 'testkit-ready 120 && cargo nextest run --manifest-path <suite>/Cargo.toml --test-threads 1'testkit-readyresolved the wrapper's mTLS gateway, reported it healthy, and confirmed the CLI reaches it. All 7 tests passed in about 15s, andopenshell sandbox listshowed nothing left behind. Two#[ignore]tests, with the attribute above and below#[testkit::test], were skipped. With onlyOPENSHELL_GATEWAY_ENDPOINTset, ase2e/rust/e2e-vm.shdoes, testkit found the registered gateway's mTLS material, andtestkit-readyplus two tests passed.On Docker Desktop, sandboxes need either Docker Desktop's host networking turned on (Settings → Resources → Network) or
supervisor_network_mode = "bridge". Otherwise the supervisor cannot reach a gateway on the Mac's loopback. For this run I set bridge mode with a local, uncommitted change to the wrapper's gateway config.Checklist