Skip to content

test(cli): box lifecycle journey suite — surfaces logs/stdout gap#630

Open
G4614 wants to merge 1 commit into
boxlite-ai:mainfrom
G4614:fix/cp-into-runtime-mounts
Open

test(cli): box lifecycle journey suite — surfaces logs/stdout gap#630
G4614 wants to merge 1 commit into
boxlite-ai:mainfrom
G4614:fix/cp-into-runtime-mounts

Conversation

@G4614
Copy link
Copy Markdown
Contributor

@G4614 G4614 commented May 31, 2026

box lifecycle test
create->run->rm
run->exec(logs/stats/ps/cp)->rm
run->rm while exec(should be rejected)

Test plan

5 tests run via cargo nextest run -p boxlite-cli --test lifecycle_journey --profile vm, last green: 4 PASS + 1 #[ignore]d (the surfaced gap), no leftover boxes / shims.

  • box_full_user_journey_birth_to_death (29s) — pull → run -d → ps → exec → cp host→box → exec cat verify → exec sh -c mutate → cp box→host + byte check → stats → stop → inspect (asserts "Running": false) → start → exec verify the rootfs survived stop/start → restart → rm --force → inspect-fails. A regression in any single transition surfaces here even when isolation tests pass.
  • cp_roundtrip_persistent_path_binary_fidelity (~16s) — 257-byte payload (all 0..=255 + \n), host → box:/root/blob → host, assert_eq!(read_back, payload). Stays on /root to keep this orthogonal to fix(guest): cp into a running box's runtime mounts (/tmp) via the container mnt ns #628's tmpfs surface.
  • stats_json_snapshot_for_running_box (~10s) — stats --format json for a running box returns a parseable JSON value.
  • error_paths_along_the_journey (~19s) — rm-running-without-force fails; start/stop/inspect/logs on a non-existent box all fail cleanly (no panic).
  • logs_captures_box_stdout#[ignore]d. Asserts the user-expected behavior (a box that prints MARK_LOGS_42 should show it via boxlite logs); fails on main because src/cli/src/commands/logs.rs reads box_layout.console_output_path() — the VM console file (kernel + zygote + tmpfs + network tracing), not the container's PID-1 stdout. Doc comment on the test explains the gap; removing #[ignore] becomes the gate when fixed.
observed on main with this PR
src/cli/tests/cp*.rs empty (cp.rs / cp_runtime_mount.rs live only on this branch's previous state) cp_roundtrip_persistent_path_binary_fidelity — orthogonal binary-fidelity check on /root
no stats test stats_json_snapshot_for_running_box
test_list_lifecycle covers only create + list, not a composed flow full pull → run → exec → cp → stop/start/restart → rm journey asserted as one transaction
logs behavior unasserted logs_captures_box_stdout documents the guest console vs container stdout gap + acts as the future-fix gate

Centerpiece is deliberately a single composed flow so a regression at any single verb-to-verb seam fails here. The logs finding is the kind of thing a journey-style test catches that a feature-PR test plan never does — shipped #[ignore] so the CI is green on main today, while the doc keeps the gap visible for the eventual fix.

…p-fills

Five end-to-end tests in src/cli/tests/lifecycle_journey.rs that string
the verbs a user actually types together as a composed flow rather than
each in isolation.

Centerpiece — box_full_user_journey_birth_to_death — walks one named box
through pull → run -d → ps → exec → cp in → exec verify → exec mutate →
cp out + byte check → stats → stop → inspect → start → exec verify rootfs
survived → restart → rm --force → inspect-gone.

Gap-fills for verbs with no `src/cli/tests/` coverage on main today:
cp (binary roundtrip on a persistent rootfs path — orthogonal to the boxlite-ai#628
tmpfs surface), stats (single JSON snapshot for a running box), and
negative paths (rm-running-without-force, ops on a non-existent box).

Surfaces one real product gap: `boxlite logs` reads the VM/guest agent
console.log (kernel + zygote + network setup tracing), NOT the
container's PID-1 stdout, so a box that prints a marker via the
foreground command never shows it through `logs`. The corresponding
test is shipped #[ignore]d with a doc explaining what `logs` should do;
removing the ignore is the gate when the gap is fixed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@G4614 G4614 force-pushed the fix/cp-into-runtime-mounts branch from a627541 to 647832c Compare June 2, 2026 12:37
@G4614 G4614 marked this pull request as ready for review June 2, 2026 12:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant