Skip to content

Commit f244394

Browse files
docs(tests): document the runner and the conformance suite
Describe how the runner runs a family in a tmachine environment, locally and on CI, in TESTING.md, add a README for the sandbox suite, point the testkit README at the runner, and add rows for tests/suites, tests/tmachine and tests/runner to the project-structure tables in AGENTS.md and CONTRIBUTING.md. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
1 parent 1205d47 commit f244394

5 files changed

Lines changed: 140 additions & 0 deletions

File tree

‎AGENTS.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ Do not rely on this file for a full inventory. The detailed public and contribut
6363
| `sdk/typescript/` | TypeScript SDK | Native Connect client, curated sandbox API, and generated protobuf types |
6464
| `proto/` | Protobuf definitions | gRPC service contracts |
6565
| `tests/testkit/` | E2E testkit | Support library and `#[testkit::test]` attribute for SDK-driven E2E suites |
66+
| `tests/suites/` | E2E suites | One Cargo workspace per test family; `conformance/sandbox` is the first testkit suite |
67+
| `tests/tmachine/` | Test machines | QEMU machines provisioned with Ansible, and the `Session` API that drives them |
68+
| `tests/runner/` | Test runner | `openshell-test-runner`: builds a family's tests, runs them in one tmachine environment, checks the JUnit results |
6669
| `deploy/` | Docker, Helm, K8s | Dockerfiles, Helm chart, manifests |
6770
| `docs/` | Published docs | MDX pages, navigation, and content assets |
6871
| `fern/` | Docs site config | Fern site config, components, and theme assets |

‎CONTRIBUTING.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,9 @@ These are the primary `mise` tasks for day-to-day development:
345345
| `proto/` | Protocol buffer definitions and [public API conventions](proto/README.md) |
346346
| `tasks/` | `mise` task definitions and build scripts |
347347
| `tests/testkit/` | Support library for SDK-driven end-to-end suites |
348+
| `tests/suites/` | End-to-end suites, one Cargo workspace per family |
349+
| `tests/tmachine/` | QEMU test machines provisioned with Ansible, and the `Session` API that drives them |
350+
| `tests/runner/` | `openshell-test-runner`: runs a test family in a tmachine environment and checks the results |
348351
| `deploy/` | Dockerfiles, Helm chart, Kubernetes manifests |
349352
| `docs/` | Published Fern docs source, navigation, and content assets |
350353
| `fern/` | Fern site config, components, and theme assets |

‎TESTING.md‎

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ python/openshell/ # Python unit tests (*_test.py suffix)
1717
e2e/python/ # Python E2E tests (test_*.py prefix)
1818
e2e/rust/ # Rust CLI E2E tests
1919
tests/testkit/ # Support library for SDK-driven E2E suites
20+
tests/suites/conformance/ # Testkit suites (the `sandbox` crate) beside the older CLI conformance crate
21+
tests/tmachine/ # QEMU test machines, Ansible playbooks, and the Session API
22+
tests/runner/ # openshell-test-runner: runs a test family in a tmachine environment
2023
```
2124

2225
## Rust Tests
@@ -140,6 +143,71 @@ by `OPENSHELL_BIN`. See
140143
[tests/testkit/README.md](tests/testkit/README.md) for how to write and run
141144
tests.
142145

146+
Suites live under `tests/suites/<family>/`. Each family is a Cargo workspace
147+
with its own lockfile. `tests/suites/conformance/sandbox` is the first testkit
148+
suite; it has one smoke test. Run it against a local Docker gateway with:
149+
150+
```shell
151+
mise run e2e:testkit
152+
```
153+
154+
That task runs `e2e/with-docker-gateway.sh`, which starts a gateway and exports
155+
`OPENSHELL_GATEWAY` and `OPENSHELL_BIN`, so the suite runs the same way the
156+
runner runs it in a guest.
157+
158+
Workspaces that build root crates through path dependencies must lock shared
159+
crates at the versions in the root `Cargo.lock`; otherwise CI can build against
160+
dependencies the Nix toolchain doesn't support. `mise run rust:lockfiles:check`
161+
verifies this, and `uv run tasks/scripts/check_cargo_lockfile_alignment.py --fix`
162+
re-locks a workspace from the root lockfile. Add new testkit workspaces to
163+
`ALIGNED_WORKSPACES` in that script.
164+
165+
### Running suites in a tmachine environment (`tests/runner/`)
166+
167+
`openshell-test-runner` runs a test family inside a tmachine VM, against the
168+
OpenShell that the VM's installer set up. It is adapted from the runner in
169+
NVIDIA/OpenShell#4629 by Evan Lezar.
170+
171+
```shell
172+
nix run .#openshell-test-runner -- \
173+
--environment ubuntu-docker-rootful --installer deb \
174+
--family conformance --package sandbox
175+
```
176+
177+
It:
178+
179+
1. builds the family's packages on the host as a nextest archive for the
180+
guest's musl target, with `testkit-ready`;
181+
2. boots the tmachine environment with the installer (this needs KVM, and
182+
tmachine only boots guests of the host's architecture);
183+
3. copies the archive in, waits for the gateway with `testkit-ready`, and runs
184+
the tests with the guest's `cargo-nextest`, pointing them at the installed
185+
CLI (`OPENSHELL_BIN`) and the gateway the installer registered
186+
(`OPENSHELL_GATEWAY`, `--gateway`, default `openshell`);
187+
4. writes `junit.xml`, `nextest.log` and, after a failure, the guest's
188+
diagnostics to `artifacts/test-results/` (`--results`);
189+
5. shuts the VM down, also on failure or SIGTERM.
190+
191+
A run passes if nextest succeeds and its JUnit report shows at least one test
192+
and no failures. `--filter <filterset>` narrows the tests with a nextest
193+
filterset, and `--keep` leaves the VM running until you press Enter. Every SSH
194+
and nextest step has a timeout. Two runs on one host need different
195+
`TMACHINE_SSH_PORT` values (default 2222). The installer inputs, such as the
196+
Debian package and the images, come from `artifacts/`, built by
197+
`nix run .#build-artifacts` or downloaded by CI.
198+
199+
A flaky or broken test is marked `#[ignore = "<issue link>"]`, which takes it
200+
out of every environment until it's fixed.
201+
202+
**CI.** `.github/workflows/e2e-suites.yml` lists the environments and suites as
203+
an explicit matrix and runs the runner once per row. Branch E2E calls it when
204+
the `test:e2e` label is set. It is advisory for now. To run a suite in another
205+
environment on CI, add a row.
206+
207+
The older conformance, feature and driver lanes in `.github/workflows/` still
208+
run through the tmachine testsuites in `tests/tmachine/config.nix`. They move
209+
to the runner as their suites move to testkit.
210+
143211
### Python E2E (`e2e/python/`)
144212

145213
`mise run e2e:python` builds `openshell/e2e-python:dev` from
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Sandbox conformance suite
2+
3+
The `sandbox` crate holds testkit suites for sandbox behavior that every compute
4+
driver must provide. It is a member of the `conformance` workspace. Each file in
5+
`tests/` is one suite.
6+
7+
| Suite | Covers |
8+
|---|---|
9+
| `smoke` | Create a sandbox, run `echo` in it, delete it |
10+
11+
The suite is small on purpose. It proves that the runner can run a real test in
12+
a tmachine environment on CI. The older suites move to testkit by adding suites
13+
here, or a new family under `tests/suites/`.
14+
15+
## Running it
16+
17+
Against a local Docker gateway:
18+
19+
```shell
20+
mise run e2e:testkit
21+
```
22+
23+
Against any gateway the CLI can reach, with the testkit environment variables
24+
described in [tests/testkit/README.md](../../../testkit/README.md):
25+
26+
```shell
27+
OPENSHELL_GATEWAY=<name> cargo nextest run --locked \
28+
--manifest-path tests/suites/conformance/Cargo.toml -p sandbox --test-threads 1
29+
```
30+
31+
In a tmachine VM, as CI runs it (see [TESTING.md](../../../../TESTING.md)):
32+
33+
```shell
34+
nix run .#openshell-test-runner -- \
35+
--environment ubuntu-docker-rootful --installer deb \
36+
--family conformance --package sandbox
37+
```
38+
39+
## Adding a test
40+
41+
Add a `#[testkit::test]` function to a suite, or a new file in `tests/` for a new
42+
area. No playbook, test archive or workflow entry is needed: the runner builds
43+
and runs every test in the package.
44+
45+
## What a test may assert
46+
47+
These tests run on every compute driver, so they check the public contract and
48+
leave driver behavior alone.
49+
50+
- Assert only what the public contract promises: the proto comments and the
51+
published docs.
52+
- Assert `phase` and `exit_code`. Don't assert condition reasons.
53+
- Check that something did not happen by reading state, not by sleeping.
54+
- Every environment must pass every test here. If a behavior is left to the
55+
driver, the test belongs in a `features` or `drivers` suite instead.
56+
- Use the CLI for upload, download, connect and forward. Rely on its exit code
57+
and `--output json`.
58+
- Add a testkit helper instead of calling raw gRPC from a test.
59+
60+
Guidance adapted from NVIDIA/OpenShell#4629 by Evan Lezar.

‎tests/testkit/README.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,12 @@ time or the CLI does not report it connected.
8989
ephemeral gateway and export `OPENSHELL_GATEWAY` and `OPENSHELL_BIN`, so a
9090
suite runs under them unchanged.
9191

92+
`mise run e2e:testkit` does this for the suites in `tests/suites/conformance`.
93+
In a tmachine VM, the test runner (`tests/runner/`) does the same: it sets
94+
`OPENSHELL_GATEWAY` to the gateway the installer registered and
95+
`OPENSHELL_BIN` to the installed CLI, then runs the suites with nextest. See
96+
[TESTING.md](../../TESTING.md).
97+
9298
## Checks
9399

94100
```shell

0 commit comments

Comments
 (0)