Files
OpenShell/tests
Matthew Grossman fac82327b3 test(testkit): add the testkit library for end-to-end suites (#4724)
* test(testkit): add the testkit workspace for end-to-end suites

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>

* ci(tests): format, lint and test testkit in Branch Checks

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>

* docs(tests): describe how to write and run testkit tests

Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>

* fix(testkit): give each sandbox its own cleanup timeout

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>

* docs(testkit): show how to exclude tests by capability

Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>

* docs: list tests/testkit in the project structure tables

Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>

* refactor(testkit): drop test IDs and capabilities for now

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>

* docs(testkit): describe what testkit provides today

Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>

* refactor(testkit): find the gateway the way the CLI does

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>

* fix(testkit): keep labels when creating a sandbox with a policy

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>

* fix(testkit): use the registered gateway's credentials for an endpoint

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>

* docs(tests): list testkit's gateway variables in precedence order

OPENSHELL_GATEWAY_ENDPOINT takes precedence over OPENSHELL_GATEWAY. Also
mention OPENSHELL_BIN.

Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>

* fix(testkit): apply other attributes to the generated test

#[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].

* fix(testkit): show usage for testkit-ready --help

Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>

* test(testkit): cover cleanup after pass, failure, and panic

Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>

* fix(testkit): reject #[should_panic] on testkit tests

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>

* test(testkit): keep only the macro's misuse checks as unit tests

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>

* refactor(testkit): connect through the SDK's mTLS support

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>

* fix(testkit): bound readiness and cleanup with timeouts

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>

---------

Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
2026-10-22 17:11:31 +00:00
..