cli + daemon: move test seams off package globals onto injected structs
CLI: introduce internal/cli.deps which owns every RPC/SSH/host-command seam the tree used to reach through mutable package vars. Command builders, orchestrators, and the completion helpers become methods on *deps. Tests construct their own deps per case, so fakes no longer leak across cases and tests are free to run in parallel. Daemon: move workspaceInspectRepoFunc + workspaceImportFunc onto the Daemon struct (workspaceInspectRepo / workspaceImport), mirroring the existing guestWaitForSSH / guestDial pattern. Workspace-prepare tests drop t.Parallel() guards now that they no longer mutate process-wide state. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d38f580e00
commit
c42fcbe012
19 changed files with 664 additions and 733 deletions
|
|
@ -14,22 +14,17 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// stubPruneSeams installs fakes for vmListFunc and vmDeleteFunc, and
|
||||
// restores originals on cleanup.
|
||||
func stubPruneSeams(t *testing.T, vms []model.VMRecord, listErr error, deleteErr map[string]error) *[]string {
|
||||
// stubPruneSeams installs list + delete fakes onto the caller's *deps
|
||||
// and returns a pointer to a slice that records every ID passed to the
|
||||
// delete fake.
|
||||
func stubPruneSeams(t *testing.T, d *deps, vms []model.VMRecord, listErr error, deleteErr map[string]error) *[]string {
|
||||
t.Helper()
|
||||
origList := vmListFunc
|
||||
origDelete := vmDeleteFunc
|
||||
t.Cleanup(func() {
|
||||
vmListFunc = origList
|
||||
vmDeleteFunc = origDelete
|
||||
})
|
||||
|
||||
var deleted []string
|
||||
vmListFunc = func(ctx context.Context, socketPath string) (api.VMListResult, error) {
|
||||
d.vmList = func(ctx context.Context, socketPath string) (api.VMListResult, error) {
|
||||
return api.VMListResult{VMs: vms}, listErr
|
||||
}
|
||||
vmDeleteFunc = func(ctx context.Context, socketPath, idOrName string) error {
|
||||
d.vmDelete = func(ctx context.Context, socketPath, idOrName string) error {
|
||||
if err, ok := deleteErr[idOrName]; ok {
|
||||
return err
|
||||
}
|
||||
|
|
@ -89,13 +84,14 @@ func TestPromptYesNoEOF(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRunVMPruneNoVictims(t *testing.T) {
|
||||
stubPruneSeams(t, []model.VMRecord{
|
||||
d := defaultDeps()
|
||||
stubPruneSeams(t, d, []model.VMRecord{
|
||||
{ID: "id-1", Name: "running-vm", State: model.VMStateRunning},
|
||||
}, nil, nil)
|
||||
|
||||
cmd, stdout, _ := newPruneTestCmd("")
|
||||
if err := runVMPrune(cmd, "sock", false); err != nil {
|
||||
t.Fatalf("runVMPrune: %v", err)
|
||||
if err := d.runVMPrune(cmd, "sock", false); err != nil {
|
||||
t.Fatalf("d.runVMPrune: %v", err)
|
||||
}
|
||||
if !strings.Contains(stdout.String(), "no non-running VMs") {
|
||||
t.Errorf("expected no-op message, got %q", stdout.String())
|
||||
|
|
@ -103,13 +99,14 @@ func TestRunVMPruneNoVictims(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRunVMPruneAbortedByUser(t *testing.T) {
|
||||
deleted := stubPruneSeams(t, []model.VMRecord{
|
||||
d := defaultDeps()
|
||||
deleted := stubPruneSeams(t, d, []model.VMRecord{
|
||||
{ID: "id-1", Name: "stale", State: model.VMStateStopped},
|
||||
}, nil, nil)
|
||||
|
||||
cmd, stdout, _ := newPruneTestCmd("n\n")
|
||||
if err := runVMPrune(cmd, "sock", false); err != nil {
|
||||
t.Fatalf("runVMPrune: %v", err)
|
||||
if err := d.runVMPrune(cmd, "sock", false); err != nil {
|
||||
t.Fatalf("d.runVMPrune: %v", err)
|
||||
}
|
||||
if !strings.Contains(stdout.String(), "aborted") {
|
||||
t.Errorf("expected 'aborted' output, got %q", stdout.String())
|
||||
|
|
@ -120,7 +117,8 @@ func TestRunVMPruneAbortedByUser(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRunVMPruneConfirmedDeletesNonRunning(t *testing.T) {
|
||||
deleted := stubPruneSeams(t, []model.VMRecord{
|
||||
d := defaultDeps()
|
||||
deleted := stubPruneSeams(t, d, []model.VMRecord{
|
||||
{ID: "id-run", Name: "keeper", State: model.VMStateRunning},
|
||||
{ID: "id-stop", Name: "stale", State: model.VMStateStopped},
|
||||
{ID: "id-err", Name: "broken", State: model.VMStateError},
|
||||
|
|
@ -128,8 +126,8 @@ func TestRunVMPruneConfirmedDeletesNonRunning(t *testing.T) {
|
|||
}, nil, nil)
|
||||
|
||||
cmd, stdout, _ := newPruneTestCmd("y\n")
|
||||
if err := runVMPrune(cmd, "sock", false); err != nil {
|
||||
t.Fatalf("runVMPrune: %v", err)
|
||||
if err := d.runVMPrune(cmd, "sock", false); err != nil {
|
||||
t.Fatalf("d.runVMPrune: %v", err)
|
||||
}
|
||||
// Deleted must be exactly the three non-running IDs, in list order.
|
||||
want := []string{"id-stop", "id-err", "id-created"}
|
||||
|
|
@ -152,14 +150,15 @@ func TestRunVMPruneConfirmedDeletesNonRunning(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRunVMPruneForceSkipsPrompt(t *testing.T) {
|
||||
deleted := stubPruneSeams(t, []model.VMRecord{
|
||||
d := defaultDeps()
|
||||
deleted := stubPruneSeams(t, d, []model.VMRecord{
|
||||
{ID: "id-1", Name: "stale", State: model.VMStateStopped},
|
||||
}, nil, nil)
|
||||
|
||||
// Empty stdin + force=true: must not block on prompt.
|
||||
cmd, stdout, _ := newPruneTestCmd("")
|
||||
if err := runVMPrune(cmd, "sock", true); err != nil {
|
||||
t.Fatalf("runVMPrune: %v", err)
|
||||
if err := d.runVMPrune(cmd, "sock", true); err != nil {
|
||||
t.Fatalf("d.runVMPrune: %v", err)
|
||||
}
|
||||
if len(*deleted) != 1 || (*deleted)[0] != "id-1" {
|
||||
t.Errorf("deleted = %v, want [id-1]", *deleted)
|
||||
|
|
@ -171,7 +170,8 @@ func TestRunVMPruneForceSkipsPrompt(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRunVMPruneReportsPartialFailure(t *testing.T) {
|
||||
stubPruneSeams(t,
|
||||
d := defaultDeps()
|
||||
stubPruneSeams(t, d,
|
||||
[]model.VMRecord{
|
||||
{ID: "id-a", Name: "a", State: model.VMStateStopped},
|
||||
{ID: "id-b", Name: "b", State: model.VMStateStopped},
|
||||
|
|
@ -181,7 +181,7 @@ func TestRunVMPruneReportsPartialFailure(t *testing.T) {
|
|||
)
|
||||
|
||||
cmd, _, stderr := newPruneTestCmd("")
|
||||
err := runVMPrune(cmd, "sock", true)
|
||||
err := d.runVMPrune(cmd, "sock", true)
|
||||
if err == nil {
|
||||
t.Fatal("expected non-zero exit when any delete fails")
|
||||
}
|
||||
|
|
@ -194,10 +194,11 @@ func TestRunVMPruneReportsPartialFailure(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRunVMPruneListErrorPropagates(t *testing.T) {
|
||||
stubPruneSeams(t, nil, fmt.Errorf("rpc failed"), nil)
|
||||
d := defaultDeps()
|
||||
stubPruneSeams(t, d, nil, fmt.Errorf("rpc failed"), nil)
|
||||
|
||||
cmd, _, _ := newPruneTestCmd("")
|
||||
err := runVMPrune(cmd, "sock", true)
|
||||
err := d.runVMPrune(cmd, "sock", true)
|
||||
if err == nil || !strings.Contains(err.Error(), "rpc failed") {
|
||||
t.Fatalf("expected rpc error to propagate, got %v", err)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue