//go:build smoke package smoketest import "testing" // TestSmoke is the single top-level test that pins run-order across // scenario classes: // // - "pool" runs pure scenarios concurrently (each calls t.Parallel) // alongside the repodir chain, which runs its own subtests // sequentially. The pool subtest only returns once every t.Parallel // child has finished. // - "global" runs after pool, serially, in registry order. These // scenarios assert host-wide state (iptables, vm row counts, // ssh-config under a fake HOME, the update / rollback flow, daemon // stop) and would race with the parallel pool. // // `go test -parallel N` controls fan-out within the pool. `-run // TestSmoke/pool/bare_run` runs a single scenario without changing // the install preamble path. func TestSmoke(t *testing.T) { t.Run("pool", func(t *testing.T) { // Pure scenarios — t.Parallel inside each, fan out under -parallel. t.Run("bare_run", testBareRun) t.Run("exit_code", testExitCode) t.Run("concurrent_run", testConcurrentRun) t.Run("detach_run", testDetachRun) t.Run("bootstrap_precondition", testBootstrapPrecondition) t.Run("vm_lifecycle", testVMLifecycle) t.Run("vm_set", testVMSet) t.Run("vm_restart", testVMRestart) t.Run("vm_kill", testVMKill) t.Run("vm_ports", testVMPorts) t.Run("ssh_config", testSSHConfig) // Repodir chain — single virtual job in the pool. Subtests run // sequentially because they share the throwaway git repo at // repoDir and mutate it; t.Parallel() is intentionally absent. // The chain itself competes with the pure scenarios for a // parallel slot at this outer level. t.Run("repodir_chain", func(t *testing.T) { t.Parallel() t.Run("workspace_run", testWorkspaceRun) t.Run("workspace_dryrun", testWorkspaceDryrun) t.Run("include_untracked", testIncludeUntracked) t.Run("workspace_export", testWorkspaceExport) t.Run("workspace_full_copy", testWorkspaceFullCopy) t.Run("workspace_basecommit", testWorkspaceBasecommit) t.Run("workspace_restart", testWorkspaceRestart) t.Run("vm_exec", testVMExec) }) }) // Global scenarios — serial, after the pool drains. Order matters: // daemon_admin tears the installed services down and must be LAST. // The order otherwise mirrors scripts/smoke.sh's SMOKE_SCENARIOS // registry so the run shape is comparable. t.Run("global", func(t *testing.T) { t.Run("vm_prune", testVMPrune) t.Run("nat", testNAT) t.Run("invalid_spec", testInvalidSpec) t.Run("invalid_name", testInvalidName) t.Run("update_check", testUpdateCheck) t.Run("update_to_unknown", testUpdateToUnknown) t.Run("update_no_root", testUpdateNoRoot) t.Run("update_dry_run", testUpdateDryRun) t.Run("update_keeps_vm_alive", testUpdateKeepsVMAlive) t.Run("update_rollback_keeps_vm_alive", testUpdateRollbackKeepsVMAlive) t.Run("daemon_admin", testDaemonAdmin) }) }