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
|
|
@ -121,11 +121,8 @@ func TestLegacyRemovedCommandIsRejected(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestDoctorCommandPrintsReportAndFailsOnHardFailures(t *testing.T) {
|
||||
original := doctorFunc
|
||||
t.Cleanup(func() {
|
||||
doctorFunc = original
|
||||
})
|
||||
doctorFunc = func(context.Context) (system.Report, error) {
|
||||
d := defaultDeps()
|
||||
d.doctor = func(context.Context) (system.Report, error) {
|
||||
return system.Report{
|
||||
Checks: []system.CheckResult{
|
||||
{Name: "runtime bundle", Status: system.CheckStatusPass, Details: []string{"runtime dir /tmp/runtime"}},
|
||||
|
|
@ -134,7 +131,7 @@ func TestDoctorCommandPrintsReportAndFailsOnHardFailures(t *testing.T) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
cmd := NewBangerCommand()
|
||||
cmd := d.newRootCommand()
|
||||
var stdout bytes.Buffer
|
||||
cmd.SetOut(&stdout)
|
||||
cmd.SetErr(&stdout)
|
||||
|
|
@ -154,15 +151,12 @@ func TestDoctorCommandPrintsReportAndFailsOnHardFailures(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestDoctorCommandReturnsUnderlyingError(t *testing.T) {
|
||||
original := doctorFunc
|
||||
t.Cleanup(func() {
|
||||
doctorFunc = original
|
||||
})
|
||||
doctorFunc = func(context.Context) (system.Report, error) {
|
||||
d := defaultDeps()
|
||||
d.doctor = func(context.Context) (system.Report, error) {
|
||||
return system.Report{}, errors.New("load failed")
|
||||
}
|
||||
|
||||
cmd := NewBangerCommand()
|
||||
cmd := d.newRootCommand()
|
||||
cmd.SetArgs([]string{"doctor"})
|
||||
err := cmd.Execute()
|
||||
if err == nil || !strings.Contains(err.Error(), "load failed") {
|
||||
|
|
@ -509,14 +503,7 @@ func TestVMCreateParamsFromFlagsRejectsNonPositiveCPUAndMemory(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRunVMCreatePollsUntilDone(t *testing.T) {
|
||||
origBegin := vmCreateBeginFunc
|
||||
origStatus := vmCreateStatusFunc
|
||||
origCancel := vmCreateCancelFunc
|
||||
t.Cleanup(func() {
|
||||
vmCreateBeginFunc = origBegin
|
||||
vmCreateStatusFunc = origStatus
|
||||
vmCreateCancelFunc = origCancel
|
||||
})
|
||||
d := defaultDeps()
|
||||
|
||||
vm := model.VMRecord{
|
||||
ID: "vm-id",
|
||||
|
|
@ -528,7 +515,7 @@ func TestRunVMCreatePollsUntilDone(t *testing.T) {
|
|||
DNSName: "devbox.vm",
|
||||
},
|
||||
}
|
||||
vmCreateBeginFunc = func(context.Context, string, api.VMCreateParams) (api.VMCreateBeginResult, error) {
|
||||
d.vmCreateBegin = func(context.Context, string, api.VMCreateParams) (api.VMCreateBeginResult, error) {
|
||||
return api.VMCreateBeginResult{
|
||||
Operation: api.VMCreateOperation{
|
||||
ID: "op-1",
|
||||
|
|
@ -538,7 +525,7 @@ func TestRunVMCreatePollsUntilDone(t *testing.T) {
|
|||
}, nil
|
||||
}
|
||||
statusCalls := 0
|
||||
vmCreateStatusFunc = func(context.Context, string, string) (api.VMCreateStatusResult, error) {
|
||||
d.vmCreateStatus = func(context.Context, string, string) (api.VMCreateStatusResult, error) {
|
||||
statusCalls++
|
||||
if statusCalls == 1 {
|
||||
return api.VMCreateStatusResult{
|
||||
|
|
@ -560,14 +547,14 @@ func TestRunVMCreatePollsUntilDone(t *testing.T) {
|
|||
},
|
||||
}, nil
|
||||
}
|
||||
vmCreateCancelFunc = func(context.Context, string, string) error {
|
||||
d.vmCreateCancel = func(context.Context, string, string) error {
|
||||
t.Fatal("cancel should not be called")
|
||||
return nil
|
||||
}
|
||||
|
||||
got, err := runVMCreate(context.Background(), "/tmp/bangerd.sock", &bytes.Buffer{}, api.VMCreateParams{Name: "devbox"})
|
||||
got, err := d.runVMCreate(context.Background(), "/tmp/bangerd.sock", &bytes.Buffer{}, api.VMCreateParams{Name: "devbox"})
|
||||
if err != nil {
|
||||
t.Fatalf("runVMCreate: %v", err)
|
||||
t.Fatalf("d.runVMCreate: %v", err)
|
||||
}
|
||||
if got.Name != vm.Name || got.Runtime.GuestIP != vm.Runtime.GuestIP {
|
||||
t.Fatalf("vm = %+v, want %+v", got, vm)
|
||||
|
|
@ -878,23 +865,18 @@ func TestPrintVMPortsTableSortsAndRendersURLEndpoints(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRunSSHSessionPrintsReminderWhenHealthCheckPasses(t *testing.T) {
|
||||
origSSHExec := sshExecFunc
|
||||
origHealth := vmHealthFunc
|
||||
t.Cleanup(func() {
|
||||
sshExecFunc = origSSHExec
|
||||
vmHealthFunc = origHealth
|
||||
})
|
||||
d := defaultDeps()
|
||||
|
||||
sshExecFunc = func(ctx context.Context, stdin io.Reader, stdout, stderr io.Writer, args []string) error {
|
||||
d.sshExec = func(ctx context.Context, stdin io.Reader, stdout, stderr io.Writer, args []string) error {
|
||||
return nil
|
||||
}
|
||||
vmHealthFunc = func(ctx context.Context, socketPath, idOrName string) (api.VMHealthResult, error) {
|
||||
d.vmHealth = func(ctx context.Context, socketPath, idOrName string) (api.VMHealthResult, error) {
|
||||
return api.VMHealthResult{Name: "devbox", Healthy: true}, nil
|
||||
}
|
||||
|
||||
var stderr bytes.Buffer
|
||||
if err := runSSHSession(context.Background(), "/tmp/bangerd.sock", "devbox", strings.NewReader(""), &bytes.Buffer{}, &stderr, []string{"root@127.0.0.1"}, false); err != nil {
|
||||
t.Fatalf("runSSHSession: %v", err)
|
||||
if err := d.runSSHSession(context.Background(), "/tmp/bangerd.sock", "devbox", strings.NewReader(""), &bytes.Buffer{}, &stderr, []string{"root@127.0.0.1"}, false); err != nil {
|
||||
t.Fatalf("d.runSSHSession: %v", err)
|
||||
}
|
||||
if !strings.Contains(stderr.String(), "devbox is still running") {
|
||||
t.Fatalf("stderr = %q, want reminder", stderr.String())
|
||||
|
|
@ -902,25 +884,20 @@ func TestRunSSHSessionPrintsReminderWhenHealthCheckPasses(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRunSSHSessionPreservesSSHExitStatusOnHealthWarning(t *testing.T) {
|
||||
origSSHExec := sshExecFunc
|
||||
origHealth := vmHealthFunc
|
||||
t.Cleanup(func() {
|
||||
sshExecFunc = origSSHExec
|
||||
vmHealthFunc = origHealth
|
||||
})
|
||||
d := defaultDeps()
|
||||
|
||||
sshExecFunc = func(ctx context.Context, stdin io.Reader, stdout, stderr io.Writer, args []string) error {
|
||||
d.sshExec = func(ctx context.Context, stdin io.Reader, stdout, stderr io.Writer, args []string) error {
|
||||
return exitErrorWithCode(t, 1)
|
||||
}
|
||||
vmHealthFunc = func(ctx context.Context, socketPath, idOrName string) (api.VMHealthResult, error) {
|
||||
d.vmHealth = func(ctx context.Context, socketPath, idOrName string) (api.VMHealthResult, error) {
|
||||
return api.VMHealthResult{}, errors.New("dial failed")
|
||||
}
|
||||
|
||||
var stderr bytes.Buffer
|
||||
err := runSSHSession(context.Background(), "/tmp/bangerd.sock", "devbox", strings.NewReader(""), &bytes.Buffer{}, &stderr, []string{"root@127.0.0.1"}, false)
|
||||
err := d.runSSHSession(context.Background(), "/tmp/bangerd.sock", "devbox", strings.NewReader(""), &bytes.Buffer{}, &stderr, []string{"root@127.0.0.1"}, false)
|
||||
var exitErr *exec.ExitError
|
||||
if !errors.As(err, &exitErr) {
|
||||
t.Fatalf("runSSHSession error = %v, want exit error", err)
|
||||
t.Fatalf("d.runSSHSession error = %v, want exit error", err)
|
||||
}
|
||||
if !strings.Contains(stderr.String(), "failed to check whether devbox is still running") {
|
||||
t.Fatalf("stderr = %q, want warning", stderr.String())
|
||||
|
|
@ -928,27 +905,22 @@ func TestRunSSHSessionPreservesSSHExitStatusOnHealthWarning(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRunSSHSessionSkipsReminderOnSSHAuthFailure(t *testing.T) {
|
||||
origSSHExec := sshExecFunc
|
||||
origHealth := vmHealthFunc
|
||||
t.Cleanup(func() {
|
||||
sshExecFunc = origSSHExec
|
||||
vmHealthFunc = origHealth
|
||||
})
|
||||
d := defaultDeps()
|
||||
|
||||
healthCalled := false
|
||||
sshExecFunc = func(ctx context.Context, stdin io.Reader, stdout, stderr io.Writer, args []string) error {
|
||||
d.sshExec = func(ctx context.Context, stdin io.Reader, stdout, stderr io.Writer, args []string) error {
|
||||
return exitErrorWithCode(t, 255)
|
||||
}
|
||||
vmHealthFunc = func(ctx context.Context, socketPath, idOrName string) (api.VMHealthResult, error) {
|
||||
d.vmHealth = func(ctx context.Context, socketPath, idOrName string) (api.VMHealthResult, error) {
|
||||
healthCalled = true
|
||||
return api.VMHealthResult{Name: "devbox", Healthy: true}, nil
|
||||
}
|
||||
|
||||
var stderr bytes.Buffer
|
||||
err := runSSHSession(context.Background(), "/tmp/bangerd.sock", "devbox", strings.NewReader(""), &bytes.Buffer{}, &stderr, []string{"root@127.0.0.1"}, false)
|
||||
err := d.runSSHSession(context.Background(), "/tmp/bangerd.sock", "devbox", strings.NewReader(""), &bytes.Buffer{}, &stderr, []string{"root@127.0.0.1"}, false)
|
||||
var exitErr *exec.ExitError
|
||||
if !errors.As(err, &exitErr) || exitErr.ExitCode() != 255 {
|
||||
t.Fatalf("runSSHSession error = %v, want exit 255", err)
|
||||
t.Fatalf("d.runSSHSession error = %v, want exit 255", err)
|
||||
}
|
||||
if healthCalled {
|
||||
t.Fatal("vm health should not run after ssh auth failure")
|
||||
|
|
@ -1141,6 +1113,7 @@ func TestValidateSSHPrereqsFailsForMissingKey(t *testing.T) {
|
|||
// gets a fast error instead of an orphaned VM.
|
||||
|
||||
func TestVMRunPreflightRejectsSubmodules(t *testing.T) {
|
||||
d := defaultDeps()
|
||||
repoRoot := t.TempDir()
|
||||
|
||||
origHostCommandOutput := workspace.HostCommandOutputFunc
|
||||
|
|
@ -1166,36 +1139,16 @@ func TestVMRunPreflightRejectsSubmodules(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
_, err := vmRunPreflightRepo(context.Background(), repoRoot)
|
||||
_, err := d.vmRunPreflightRepo(context.Background(), repoRoot)
|
||||
if err == nil || !strings.Contains(err.Error(), "submodules") {
|
||||
t.Fatalf("vmRunPreflightRepo() error = %v, want submodule rejection", err)
|
||||
t.Fatalf("d.vmRunPreflightRepo() error = %v, want submodule rejection", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunVMRunWorkspacePreparesAndAttaches(t *testing.T) {
|
||||
d := defaultDeps()
|
||||
repoRoot := t.TempDir()
|
||||
|
||||
origBegin := vmCreateBeginFunc
|
||||
origStatus := vmCreateStatusFunc
|
||||
origCancel := vmCreateCancelFunc
|
||||
origWaitForSSH := guestWaitForSSHFunc
|
||||
origGuestDial := guestDialFunc
|
||||
origBuildVMRunToolingPlan := buildVMRunToolingPlanFunc
|
||||
origVMWorkspacePrepare := vmWorkspacePrepareFunc
|
||||
origSSHExec := sshExecFunc
|
||||
origHealth := vmHealthFunc
|
||||
t.Cleanup(func() {
|
||||
vmCreateBeginFunc = origBegin
|
||||
vmCreateStatusFunc = origStatus
|
||||
vmCreateCancelFunc = origCancel
|
||||
guestWaitForSSHFunc = origWaitForSSH
|
||||
guestDialFunc = origGuestDial
|
||||
buildVMRunToolingPlanFunc = origBuildVMRunToolingPlan
|
||||
vmWorkspacePrepareFunc = origVMWorkspacePrepare
|
||||
sshExecFunc = origSSHExec
|
||||
vmHealthFunc = origHealth
|
||||
})
|
||||
|
||||
vm := model.VMRecord{
|
||||
ID: "vm-id",
|
||||
Name: "devbox",
|
||||
|
|
@ -1205,7 +1158,7 @@ func TestRunVMRunWorkspacePreparesAndAttaches(t *testing.T) {
|
|||
DNSName: "devbox.vm",
|
||||
},
|
||||
}
|
||||
vmCreateBeginFunc = func(context.Context, string, api.VMCreateParams) (api.VMCreateBeginResult, error) {
|
||||
d.vmCreateBegin = func(context.Context, string, api.VMCreateParams) (api.VMCreateBeginResult, error) {
|
||||
return api.VMCreateBeginResult{
|
||||
Operation: api.VMCreateOperation{
|
||||
ID: "op-1", Stage: "ready", Detail: "vm is ready",
|
||||
|
|
@ -1213,45 +1166,45 @@ func TestRunVMRunWorkspacePreparesAndAttaches(t *testing.T) {
|
|||
},
|
||||
}, nil
|
||||
}
|
||||
vmCreateStatusFunc = func(context.Context, string, string) (api.VMCreateStatusResult, error) {
|
||||
t.Fatal("vmCreateStatusFunc should not be called")
|
||||
d.vmCreateStatus = func(context.Context, string, string) (api.VMCreateStatusResult, error) {
|
||||
t.Fatal("d.vmCreateStatus should not be called")
|
||||
return api.VMCreateStatusResult{}, nil
|
||||
}
|
||||
vmCreateCancelFunc = func(context.Context, string, string) error {
|
||||
t.Fatal("vmCreateCancelFunc should not be called")
|
||||
d.vmCreateCancel = func(context.Context, string, string) error {
|
||||
t.Fatal("d.vmCreateCancel should not be called")
|
||||
return nil
|
||||
}
|
||||
|
||||
fakeClient := &testVMRunGuestClient{}
|
||||
guestWaitForSSHFunc = func(ctx context.Context, address, privateKeyPath string, interval time.Duration) error {
|
||||
d.guestWaitForSSH = func(ctx context.Context, address, privateKeyPath string, interval time.Duration) error {
|
||||
return nil
|
||||
}
|
||||
guestDialFunc = func(ctx context.Context, address, privateKeyPath string) (vmRunGuestClient, error) {
|
||||
d.guestDial = func(ctx context.Context, address, privateKeyPath string) (vmRunGuestClient, error) {
|
||||
return fakeClient, nil
|
||||
}
|
||||
var workspaceParams api.VMWorkspacePrepareParams
|
||||
vmWorkspacePrepareFunc = func(ctx context.Context, socketPath string, params api.VMWorkspacePrepareParams) (api.VMWorkspacePrepareResult, error) {
|
||||
d.vmWorkspacePrepare = func(ctx context.Context, socketPath string, params api.VMWorkspacePrepareParams) (api.VMWorkspacePrepareResult, error) {
|
||||
workspaceParams = params
|
||||
return api.VMWorkspacePrepareResult{Workspace: model.WorkspacePrepareResult{VMID: vm.ID, GuestPath: "/root/repo", RepoName: "repo", RepoRoot: "/tmp/repo"}}, nil
|
||||
}
|
||||
buildVMRunToolingPlanFunc = func(context.Context, string) toolingplan.Plan {
|
||||
d.buildVMRunToolingPlan = func(context.Context, string) toolingplan.Plan {
|
||||
return toolingplan.Plan{
|
||||
RepoManagedTools: []string{"go"},
|
||||
Steps: []toolingplan.InstallStep{{Tool: "go", Version: "1.25.0", Source: "go.mod"}},
|
||||
}
|
||||
}
|
||||
var sshArgsSeen []string
|
||||
sshExecFunc = func(ctx context.Context, stdin io.Reader, stdout, stderr io.Writer, args []string) error {
|
||||
d.sshExec = func(ctx context.Context, stdin io.Reader, stdout, stderr io.Writer, args []string) error {
|
||||
sshArgsSeen = args
|
||||
return nil
|
||||
}
|
||||
vmHealthFunc = func(context.Context, string, string) (api.VMHealthResult, error) {
|
||||
d.vmHealth = func(context.Context, string, string) (api.VMHealthResult, error) {
|
||||
return api.VMHealthResult{Name: "devbox", Healthy: false}, nil
|
||||
}
|
||||
|
||||
repo := vmRunRepo{sourcePath: repoRoot}
|
||||
var stdout, stderr bytes.Buffer
|
||||
err := runVMRun(
|
||||
err := d.runVMRun(
|
||||
context.Background(),
|
||||
"/tmp/bangerd.sock",
|
||||
model.DaemonConfig{SSHKeyPath: "/tmp/id_ed25519"},
|
||||
|
|
@ -1263,7 +1216,7 @@ func TestRunVMRunWorkspacePreparesAndAttaches(t *testing.T) {
|
|||
false,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("runVMRun: %v", err)
|
||||
t.Fatalf("d.runVMRun: %v", err)
|
||||
}
|
||||
if workspaceParams.IDOrName != "devbox" || workspaceParams.SourcePath != repoRoot {
|
||||
t.Fatalf("workspaceParams = %+v", workspaceParams)
|
||||
|
|
@ -1283,24 +1236,7 @@ func TestRunVMRunWorkspacePreparesAndAttaches(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestVMRunPrintsPostCreateProgress(t *testing.T) {
|
||||
origBegin := vmCreateBeginFunc
|
||||
origStatus := vmCreateStatusFunc
|
||||
origCancel := vmCreateCancelFunc
|
||||
origWaitForSSH := guestWaitForSSHFunc
|
||||
origGuestDial := guestDialFunc
|
||||
origVMWorkspacePrepare := vmWorkspacePrepareFunc
|
||||
origSSHExec := sshExecFunc
|
||||
origHealth := vmHealthFunc
|
||||
t.Cleanup(func() {
|
||||
vmCreateBeginFunc = origBegin
|
||||
vmCreateStatusFunc = origStatus
|
||||
vmCreateCancelFunc = origCancel
|
||||
guestWaitForSSHFunc = origWaitForSSH
|
||||
guestDialFunc = origGuestDial
|
||||
vmWorkspacePrepareFunc = origVMWorkspacePrepare
|
||||
sshExecFunc = origSSHExec
|
||||
vmHealthFunc = origHealth
|
||||
})
|
||||
d := defaultDeps()
|
||||
|
||||
vm := model.VMRecord{
|
||||
ID: "vm-id",
|
||||
|
|
@ -1310,7 +1246,7 @@ func TestVMRunPrintsPostCreateProgress(t *testing.T) {
|
|||
GuestIP: "172.16.0.2",
|
||||
},
|
||||
}
|
||||
vmCreateBeginFunc = func(context.Context, string, api.VMCreateParams) (api.VMCreateBeginResult, error) {
|
||||
d.vmCreateBegin = func(context.Context, string, api.VMCreateParams) (api.VMCreateBeginResult, error) {
|
||||
return api.VMCreateBeginResult{
|
||||
Operation: api.VMCreateOperation{
|
||||
ID: "op-1", Stage: "ready", Detail: "vm is ready",
|
||||
|
|
@ -1318,33 +1254,33 @@ func TestVMRunPrintsPostCreateProgress(t *testing.T) {
|
|||
},
|
||||
}, nil
|
||||
}
|
||||
vmCreateStatusFunc = func(context.Context, string, string) (api.VMCreateStatusResult, error) {
|
||||
t.Fatal("vmCreateStatusFunc should not be called")
|
||||
d.vmCreateStatus = func(context.Context, string, string) (api.VMCreateStatusResult, error) {
|
||||
t.Fatal("d.vmCreateStatus should not be called")
|
||||
return api.VMCreateStatusResult{}, nil
|
||||
}
|
||||
vmCreateCancelFunc = func(context.Context, string, string) error {
|
||||
t.Fatal("vmCreateCancelFunc should not be called")
|
||||
d.vmCreateCancel = func(context.Context, string, string) error {
|
||||
t.Fatal("d.vmCreateCancel should not be called")
|
||||
return nil
|
||||
}
|
||||
guestWaitForSSHFunc = func(ctx context.Context, address, privateKeyPath string, interval time.Duration) error {
|
||||
d.guestWaitForSSH = func(ctx context.Context, address, privateKeyPath string, interval time.Duration) error {
|
||||
return nil
|
||||
}
|
||||
guestDialFunc = func(ctx context.Context, address, privateKeyPath string) (vmRunGuestClient, error) {
|
||||
d.guestDial = func(ctx context.Context, address, privateKeyPath string) (vmRunGuestClient, error) {
|
||||
return &testVMRunGuestClient{}, nil
|
||||
}
|
||||
vmWorkspacePrepareFunc = func(ctx context.Context, socketPath string, params api.VMWorkspacePrepareParams) (api.VMWorkspacePrepareResult, error) {
|
||||
d.vmWorkspacePrepare = func(ctx context.Context, socketPath string, params api.VMWorkspacePrepareParams) (api.VMWorkspacePrepareResult, error) {
|
||||
return api.VMWorkspacePrepareResult{Workspace: model.WorkspacePrepareResult{VMID: vm.ID, GuestPath: "/root/repo", RepoName: "repo", RepoRoot: "/tmp/repo"}}, nil
|
||||
}
|
||||
sshExecFunc = func(context.Context, io.Reader, io.Writer, io.Writer, []string) error {
|
||||
d.sshExec = func(context.Context, io.Reader, io.Writer, io.Writer, []string) error {
|
||||
return nil
|
||||
}
|
||||
vmHealthFunc = func(context.Context, string, string) (api.VMHealthResult, error) {
|
||||
d.vmHealth = func(context.Context, string, string) (api.VMHealthResult, error) {
|
||||
return api.VMHealthResult{Name: "devbox", Healthy: false}, nil
|
||||
}
|
||||
|
||||
repo := vmRunRepo{sourcePath: t.TempDir()}
|
||||
var stdout, stderr bytes.Buffer
|
||||
err := runVMRun(
|
||||
err := d.runVMRun(
|
||||
context.Background(),
|
||||
"/tmp/bangerd.sock",
|
||||
model.DaemonConfig{SSHKeyPath: "/tmp/id_ed25519"},
|
||||
|
|
@ -1356,7 +1292,7 @@ func TestVMRunPrintsPostCreateProgress(t *testing.T) {
|
|||
false,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("runVMRun: %v", err)
|
||||
t.Fatalf("d.runVMRun: %v", err)
|
||||
}
|
||||
|
||||
output := stderr.String()
|
||||
|
|
@ -1377,24 +1313,7 @@ func TestVMRunPrintsPostCreateProgress(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRunVMRunWarnsWhenToolingHarnessStartFails(t *testing.T) {
|
||||
origBegin := vmCreateBeginFunc
|
||||
origStatus := vmCreateStatusFunc
|
||||
origCancel := vmCreateCancelFunc
|
||||
origWaitForSSH := guestWaitForSSHFunc
|
||||
origGuestDial := guestDialFunc
|
||||
origVMWorkspacePrepare := vmWorkspacePrepareFunc
|
||||
origSSHExec := sshExecFunc
|
||||
origHealth := vmHealthFunc
|
||||
t.Cleanup(func() {
|
||||
vmCreateBeginFunc = origBegin
|
||||
vmCreateStatusFunc = origStatus
|
||||
vmCreateCancelFunc = origCancel
|
||||
guestWaitForSSHFunc = origWaitForSSH
|
||||
guestDialFunc = origGuestDial
|
||||
vmWorkspacePrepareFunc = origVMWorkspacePrepare
|
||||
sshExecFunc = origSSHExec
|
||||
vmHealthFunc = origHealth
|
||||
})
|
||||
d := defaultDeps()
|
||||
|
||||
vm := model.VMRecord{
|
||||
ID: "vm-id",
|
||||
|
|
@ -1404,39 +1323,39 @@ func TestRunVMRunWarnsWhenToolingHarnessStartFails(t *testing.T) {
|
|||
GuestIP: "172.16.0.2",
|
||||
},
|
||||
}
|
||||
vmCreateBeginFunc = func(context.Context, string, api.VMCreateParams) (api.VMCreateBeginResult, error) {
|
||||
d.vmCreateBegin = func(context.Context, string, api.VMCreateParams) (api.VMCreateBeginResult, error) {
|
||||
return api.VMCreateBeginResult{Operation: api.VMCreateOperation{ID: "op-1", Stage: "ready", Detail: "vm is ready", Done: true, Success: true, VM: &vm}}, nil
|
||||
}
|
||||
vmCreateStatusFunc = func(context.Context, string, string) (api.VMCreateStatusResult, error) {
|
||||
t.Fatal("vmCreateStatusFunc should not be called")
|
||||
d.vmCreateStatus = func(context.Context, string, string) (api.VMCreateStatusResult, error) {
|
||||
t.Fatal("d.vmCreateStatus should not be called")
|
||||
return api.VMCreateStatusResult{}, nil
|
||||
}
|
||||
vmCreateCancelFunc = func(context.Context, string, string) error {
|
||||
t.Fatal("vmCreateCancelFunc should not be called")
|
||||
d.vmCreateCancel = func(context.Context, string, string) error {
|
||||
t.Fatal("d.vmCreateCancel should not be called")
|
||||
return nil
|
||||
}
|
||||
guestWaitForSSHFunc = func(ctx context.Context, address, privateKeyPath string, interval time.Duration) error {
|
||||
d.guestWaitForSSH = func(ctx context.Context, address, privateKeyPath string, interval time.Duration) error {
|
||||
return nil
|
||||
}
|
||||
fakeClient := &testVMRunGuestClient{launchErr: errors.New("launch failed")}
|
||||
guestDialFunc = func(ctx context.Context, address, privateKeyPath string) (vmRunGuestClient, error) {
|
||||
d.guestDial = func(ctx context.Context, address, privateKeyPath string) (vmRunGuestClient, error) {
|
||||
return fakeClient, nil
|
||||
}
|
||||
vmWorkspacePrepareFunc = func(ctx context.Context, socketPath string, params api.VMWorkspacePrepareParams) (api.VMWorkspacePrepareResult, error) {
|
||||
d.vmWorkspacePrepare = func(ctx context.Context, socketPath string, params api.VMWorkspacePrepareParams) (api.VMWorkspacePrepareResult, error) {
|
||||
return api.VMWorkspacePrepareResult{Workspace: model.WorkspacePrepareResult{VMID: vm.ID, GuestPath: "/root/repo", RepoName: "repo", RepoRoot: "/tmp/repo"}}, nil
|
||||
}
|
||||
sshExecCalls := 0
|
||||
sshExecFunc = func(context.Context, io.Reader, io.Writer, io.Writer, []string) error {
|
||||
d.sshExec = func(context.Context, io.Reader, io.Writer, io.Writer, []string) error {
|
||||
sshExecCalls++
|
||||
return nil
|
||||
}
|
||||
vmHealthFunc = func(context.Context, string, string) (api.VMHealthResult, error) {
|
||||
d.vmHealth = func(context.Context, string, string) (api.VMHealthResult, error) {
|
||||
return api.VMHealthResult{Healthy: false}, nil
|
||||
}
|
||||
|
||||
repo := vmRunRepo{sourcePath: t.TempDir()}
|
||||
var stdout, stderr bytes.Buffer
|
||||
err := runVMRun(
|
||||
err := d.runVMRun(
|
||||
context.Background(),
|
||||
"/tmp/bangerd.sock",
|
||||
model.DaemonConfig{SSHKeyPath: "/tmp/id_ed25519"},
|
||||
|
|
@ -1448,7 +1367,7 @@ func TestRunVMRunWarnsWhenToolingHarnessStartFails(t *testing.T) {
|
|||
false,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("runVMRun: %v", err)
|
||||
t.Fatalf("d.runVMRun: %v", err)
|
||||
}
|
||||
if !strings.Contains(stderr.String(), "[vm run] warning: guest tooling bootstrap start failed: launch guest tooling bootstrap") {
|
||||
t.Fatalf("stderr = %q, want tooling bootstrap warning", stderr.String())
|
||||
|
|
@ -1459,48 +1378,35 @@ func TestRunVMRunWarnsWhenToolingHarnessStartFails(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRunVMRunBareModeSkipsWorkspaceAndTooling(t *testing.T) {
|
||||
origBegin := vmCreateBeginFunc
|
||||
origWaitForSSH := guestWaitForSSHFunc
|
||||
origGuestDial := guestDialFunc
|
||||
origVMWorkspacePrepare := vmWorkspacePrepareFunc
|
||||
origSSHExec := sshExecFunc
|
||||
origHealth := vmHealthFunc
|
||||
t.Cleanup(func() {
|
||||
vmCreateBeginFunc = origBegin
|
||||
guestWaitForSSHFunc = origWaitForSSH
|
||||
guestDialFunc = origGuestDial
|
||||
vmWorkspacePrepareFunc = origVMWorkspacePrepare
|
||||
sshExecFunc = origSSHExec
|
||||
vmHealthFunc = origHealth
|
||||
})
|
||||
d := defaultDeps()
|
||||
|
||||
vm := model.VMRecord{
|
||||
ID: "vm-id", Name: "bare",
|
||||
Runtime: model.VMRuntime{State: model.VMStateRunning, GuestIP: "172.16.0.2"},
|
||||
}
|
||||
vmCreateBeginFunc = func(context.Context, string, api.VMCreateParams) (api.VMCreateBeginResult, error) {
|
||||
d.vmCreateBegin = func(context.Context, string, api.VMCreateParams) (api.VMCreateBeginResult, error) {
|
||||
return api.VMCreateBeginResult{Operation: api.VMCreateOperation{ID: "op-1", Stage: "ready", Done: true, Success: true, VM: &vm}}, nil
|
||||
}
|
||||
guestWaitForSSHFunc = func(context.Context, string, string, time.Duration) error { return nil }
|
||||
guestDialFunc = func(context.Context, string, string) (vmRunGuestClient, error) {
|
||||
t.Fatal("guestDialFunc should not be called in bare mode")
|
||||
d.guestWaitForSSH = func(context.Context, string, string, time.Duration) error { return nil }
|
||||
d.guestDial = func(context.Context, string, string) (vmRunGuestClient, error) {
|
||||
t.Fatal("d.guestDial should not be called in bare mode")
|
||||
return nil, nil
|
||||
}
|
||||
vmWorkspacePrepareFunc = func(context.Context, string, api.VMWorkspacePrepareParams) (api.VMWorkspacePrepareResult, error) {
|
||||
t.Fatal("vmWorkspacePrepareFunc should not be called in bare mode")
|
||||
d.vmWorkspacePrepare = func(context.Context, string, api.VMWorkspacePrepareParams) (api.VMWorkspacePrepareResult, error) {
|
||||
t.Fatal("d.vmWorkspacePrepare should not be called in bare mode")
|
||||
return api.VMWorkspacePrepareResult{}, nil
|
||||
}
|
||||
sshExecCalls := 0
|
||||
sshExecFunc = func(context.Context, io.Reader, io.Writer, io.Writer, []string) error {
|
||||
d.sshExec = func(context.Context, io.Reader, io.Writer, io.Writer, []string) error {
|
||||
sshExecCalls++
|
||||
return nil
|
||||
}
|
||||
vmHealthFunc = func(context.Context, string, string) (api.VMHealthResult, error) {
|
||||
d.vmHealth = func(context.Context, string, string) (api.VMHealthResult, error) {
|
||||
return api.VMHealthResult{Healthy: false}, nil
|
||||
}
|
||||
|
||||
var stdout, stderr bytes.Buffer
|
||||
err := runVMRun(
|
||||
err := d.runVMRun(
|
||||
context.Background(),
|
||||
"/tmp/bangerd.sock",
|
||||
model.DaemonConfig{SSHKeyPath: "/tmp/id_ed25519"},
|
||||
|
|
@ -1512,7 +1418,7 @@ func TestRunVMRunBareModeSkipsWorkspaceAndTooling(t *testing.T) {
|
|||
false,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("runVMRun: %v", err)
|
||||
t.Fatalf("d.runVMRun: %v", err)
|
||||
}
|
||||
if sshExecCalls != 1 {
|
||||
t.Fatalf("sshExec calls = %d, want 1", sshExecCalls)
|
||||
|
|
@ -1523,39 +1429,28 @@ func TestRunVMRunBareModeSkipsWorkspaceAndTooling(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRunVMRunRMDeletesAfterSessionExits(t *testing.T) {
|
||||
origBegin := vmCreateBeginFunc
|
||||
origWaitForSSH := guestWaitForSSHFunc
|
||||
origSSHExec := sshExecFunc
|
||||
origHealth := vmHealthFunc
|
||||
origDelete := vmDeleteFunc
|
||||
t.Cleanup(func() {
|
||||
vmCreateBeginFunc = origBegin
|
||||
guestWaitForSSHFunc = origWaitForSSH
|
||||
sshExecFunc = origSSHExec
|
||||
vmHealthFunc = origHealth
|
||||
vmDeleteFunc = origDelete
|
||||
})
|
||||
d := defaultDeps()
|
||||
|
||||
vm := model.VMRecord{
|
||||
ID: "vm-id", Name: "tmpbox",
|
||||
Runtime: model.VMRuntime{State: model.VMStateRunning, GuestIP: "172.16.0.2"},
|
||||
}
|
||||
vmCreateBeginFunc = func(context.Context, string, api.VMCreateParams) (api.VMCreateBeginResult, error) {
|
||||
d.vmCreateBegin = func(context.Context, string, api.VMCreateParams) (api.VMCreateBeginResult, error) {
|
||||
return api.VMCreateBeginResult{Operation: api.VMCreateOperation{ID: "op-1", Stage: "ready", Done: true, Success: true, VM: &vm}}, nil
|
||||
}
|
||||
guestWaitForSSHFunc = func(context.Context, string, string, time.Duration) error { return nil }
|
||||
sshExecFunc = func(context.Context, io.Reader, io.Writer, io.Writer, []string) error { return nil }
|
||||
vmHealthFunc = func(context.Context, string, string) (api.VMHealthResult, error) {
|
||||
d.guestWaitForSSH = func(context.Context, string, string, time.Duration) error { return nil }
|
||||
d.sshExec = func(context.Context, io.Reader, io.Writer, io.Writer, []string) error { return nil }
|
||||
d.vmHealth = func(context.Context, string, string) (api.VMHealthResult, error) {
|
||||
return api.VMHealthResult{Healthy: false}, nil
|
||||
}
|
||||
deletedRef := ""
|
||||
vmDeleteFunc = func(_ context.Context, _, idOrName string) error {
|
||||
d.vmDelete = func(_ context.Context, _, idOrName string) error {
|
||||
deletedRef = idOrName
|
||||
return nil
|
||||
}
|
||||
|
||||
var stdout, stderr bytes.Buffer
|
||||
err := runVMRun(
|
||||
err := d.runVMRun(
|
||||
context.Background(),
|
||||
"/tmp/bangerd.sock",
|
||||
model.DaemonConfig{SSHKeyPath: "/tmp/id_ed25519"},
|
||||
|
|
@ -1567,7 +1462,7 @@ func TestRunVMRunRMDeletesAfterSessionExits(t *testing.T) {
|
|||
true, // --rm
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("runVMRun: %v", err)
|
||||
t.Fatalf("d.runVMRun: %v", err)
|
||||
}
|
||||
if deletedRef != "tmpbox" {
|
||||
t.Fatalf("deletedRef = %q, want tmpbox", deletedRef)
|
||||
|
|
@ -1580,15 +1475,10 @@ func TestRunVMRunRMDeletesAfterSessionExits(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRunVMRunRMSkipsDeleteOnSSHWaitTimeout(t *testing.T) {
|
||||
origBegin := vmCreateBeginFunc
|
||||
origWaitForSSH := guestWaitForSSHFunc
|
||||
origDelete := vmDeleteFunc
|
||||
d := defaultDeps()
|
||||
origTimeout := vmRunSSHTimeout
|
||||
vmRunSSHTimeout = 50 * time.Millisecond
|
||||
t.Cleanup(func() {
|
||||
vmCreateBeginFunc = origBegin
|
||||
guestWaitForSSHFunc = origWaitForSSH
|
||||
vmDeleteFunc = origDelete
|
||||
vmRunSSHTimeout = origTimeout
|
||||
})
|
||||
|
||||
|
|
@ -1596,21 +1486,21 @@ func TestRunVMRunRMSkipsDeleteOnSSHWaitTimeout(t *testing.T) {
|
|||
ID: "vm-id", Name: "slowvm",
|
||||
Runtime: model.VMRuntime{State: model.VMStateRunning, GuestIP: "172.16.0.2"},
|
||||
}
|
||||
vmCreateBeginFunc = func(context.Context, string, api.VMCreateParams) (api.VMCreateBeginResult, error) {
|
||||
d.vmCreateBegin = func(context.Context, string, api.VMCreateParams) (api.VMCreateBeginResult, error) {
|
||||
return api.VMCreateBeginResult{Operation: api.VMCreateOperation{ID: "op-1", Stage: "ready", Done: true, Success: true, VM: &vm}}, nil
|
||||
}
|
||||
guestWaitForSSHFunc = func(ctx context.Context, _, _ string, _ time.Duration) error {
|
||||
d.guestWaitForSSH = func(ctx context.Context, _, _ string, _ time.Duration) error {
|
||||
<-ctx.Done()
|
||||
return ctx.Err()
|
||||
}
|
||||
deleteCalled := false
|
||||
vmDeleteFunc = func(context.Context, string, string) error {
|
||||
d.vmDelete = func(context.Context, string, string) error {
|
||||
deleteCalled = true
|
||||
return nil
|
||||
}
|
||||
|
||||
var stdout, stderr bytes.Buffer
|
||||
err := runVMRun(
|
||||
err := d.runVMRun(
|
||||
context.Background(),
|
||||
"/tmp/bangerd.sock",
|
||||
model.DaemonConfig{SSHKeyPath: "/tmp/id_ed25519"},
|
||||
|
|
@ -1630,13 +1520,10 @@ func TestRunVMRunRMSkipsDeleteOnSSHWaitTimeout(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRunVMRunSSHTimeoutReturnsActionableError(t *testing.T) {
|
||||
origBegin := vmCreateBeginFunc
|
||||
origWaitForSSH := guestWaitForSSHFunc
|
||||
d := defaultDeps()
|
||||
origTimeout := vmRunSSHTimeout
|
||||
vmRunSSHTimeout = 50 * time.Millisecond
|
||||
t.Cleanup(func() {
|
||||
vmCreateBeginFunc = origBegin
|
||||
guestWaitForSSHFunc = origWaitForSSH
|
||||
vmRunSSHTimeout = origTimeout
|
||||
})
|
||||
|
||||
|
|
@ -1644,18 +1531,18 @@ func TestRunVMRunSSHTimeoutReturnsActionableError(t *testing.T) {
|
|||
ID: "vm-id", Name: "slowvm",
|
||||
Runtime: model.VMRuntime{State: model.VMStateRunning, GuestIP: "172.16.0.2"},
|
||||
}
|
||||
vmCreateBeginFunc = func(context.Context, string, api.VMCreateParams) (api.VMCreateBeginResult, error) {
|
||||
d.vmCreateBegin = func(context.Context, string, api.VMCreateParams) (api.VMCreateBeginResult, error) {
|
||||
return api.VMCreateBeginResult{Operation: api.VMCreateOperation{ID: "op-1", Stage: "ready", Done: true, Success: true, VM: &vm}}, nil
|
||||
}
|
||||
// Simulate the guest never bringing sshd up — the wait-for-ssh
|
||||
// child context fires its deadline, returning a DeadlineExceeded.
|
||||
guestWaitForSSHFunc = func(ctx context.Context, _, _ string, _ time.Duration) error {
|
||||
d.guestWaitForSSH = func(ctx context.Context, _, _ string, _ time.Duration) error {
|
||||
<-ctx.Done()
|
||||
return ctx.Err()
|
||||
}
|
||||
|
||||
var stdout, stderr bytes.Buffer
|
||||
err := runVMRun(
|
||||
err := d.runVMRun(
|
||||
context.Background(),
|
||||
"/tmp/bangerd.sock",
|
||||
model.DaemonConfig{SSHKeyPath: "/tmp/id_ed25519"},
|
||||
|
|
@ -1683,37 +1570,28 @@ func TestRunVMRunSSHTimeoutReturnsActionableError(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRunVMRunCommandModePropagatesExitCode(t *testing.T) {
|
||||
origBegin := vmCreateBeginFunc
|
||||
origWaitForSSH := guestWaitForSSHFunc
|
||||
origVMWorkspacePrepare := vmWorkspacePrepareFunc
|
||||
origSSHExec := sshExecFunc
|
||||
t.Cleanup(func() {
|
||||
vmCreateBeginFunc = origBegin
|
||||
guestWaitForSSHFunc = origWaitForSSH
|
||||
vmWorkspacePrepareFunc = origVMWorkspacePrepare
|
||||
sshExecFunc = origSSHExec
|
||||
})
|
||||
d := defaultDeps()
|
||||
|
||||
vm := model.VMRecord{
|
||||
ID: "vm-id", Name: "cmdbox",
|
||||
Runtime: model.VMRuntime{State: model.VMStateRunning, GuestIP: "172.16.0.2"},
|
||||
}
|
||||
vmCreateBeginFunc = func(context.Context, string, api.VMCreateParams) (api.VMCreateBeginResult, error) {
|
||||
d.vmCreateBegin = func(context.Context, string, api.VMCreateParams) (api.VMCreateBeginResult, error) {
|
||||
return api.VMCreateBeginResult{Operation: api.VMCreateOperation{ID: "op-1", Stage: "ready", Done: true, Success: true, VM: &vm}}, nil
|
||||
}
|
||||
guestWaitForSSHFunc = func(context.Context, string, string, time.Duration) error { return nil }
|
||||
vmWorkspacePrepareFunc = func(context.Context, string, api.VMWorkspacePrepareParams) (api.VMWorkspacePrepareResult, error) {
|
||||
d.guestWaitForSSH = func(context.Context, string, string, time.Duration) error { return nil }
|
||||
d.vmWorkspacePrepare = func(context.Context, string, api.VMWorkspacePrepareParams) (api.VMWorkspacePrepareResult, error) {
|
||||
t.Fatal("workspace prepare should not run without spec")
|
||||
return api.VMWorkspacePrepareResult{}, nil
|
||||
}
|
||||
var sshArgsSeen []string
|
||||
sshExecFunc = func(_ context.Context, _ io.Reader, _, _ io.Writer, args []string) error {
|
||||
d.sshExec = func(_ context.Context, _ io.Reader, _, _ io.Writer, args []string) error {
|
||||
sshArgsSeen = args
|
||||
return exitErrorWithCode(t, 7)
|
||||
}
|
||||
|
||||
var stdout, stderr bytes.Buffer
|
||||
err := runVMRun(
|
||||
err := d.runVMRun(
|
||||
context.Background(),
|
||||
"/tmp/bangerd.sock",
|
||||
model.DaemonConfig{SSHKeyPath: "/tmp/id_ed25519"},
|
||||
|
|
@ -1726,7 +1604,7 @@ func TestRunVMRunCommandModePropagatesExitCode(t *testing.T) {
|
|||
)
|
||||
var exitErr ExitCodeError
|
||||
if !errors.As(err, &exitErr) || exitErr.Code != 7 {
|
||||
t.Fatalf("runVMRun error = %v, want ExitCodeError{7}", err)
|
||||
t.Fatalf("d.runVMRun error = %v, want ExitCodeError{7}", err)
|
||||
}
|
||||
if len(sshArgsSeen) == 0 || sshArgsSeen[len(sshArgsSeen)-1] != "false" {
|
||||
t.Fatalf("sshArgsSeen = %v, want trailing command 'false'", sshArgsSeen)
|
||||
|
|
@ -1843,6 +1721,7 @@ func TestNewBangerdCommandRejectsArgs(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestDaemonOutdated(t *testing.T) {
|
||||
d := defaultDeps()
|
||||
dir := t.TempDir()
|
||||
current := filepath.Join(dir, "bangerd-current")
|
||||
same := filepath.Join(dir, "bangerd-same")
|
||||
|
|
@ -1857,27 +1736,20 @@ func TestDaemonOutdated(t *testing.T) {
|
|||
t.Fatalf("write stale: %v", err)
|
||||
}
|
||||
|
||||
origBangerdPath := bangerdPathFunc
|
||||
origDaemonExePath := daemonExePath
|
||||
t.Cleanup(func() {
|
||||
bangerdPathFunc = origBangerdPath
|
||||
daemonExePath = origDaemonExePath
|
||||
})
|
||||
|
||||
bangerdPathFunc = func() (string, error) {
|
||||
d.bangerdPath = func() (string, error) {
|
||||
return current, nil
|
||||
}
|
||||
daemonExePath = func(pid int) string {
|
||||
d.daemonExePath = func(pid int) string {
|
||||
if pid == 1 {
|
||||
return same
|
||||
}
|
||||
return stale
|
||||
}
|
||||
|
||||
if daemonOutdated(1) {
|
||||
if d.daemonOutdated(1) {
|
||||
t.Fatal("expected matching daemon executable to be current")
|
||||
}
|
||||
if !daemonOutdated(2) {
|
||||
if !d.daemonOutdated(2) {
|
||||
t.Fatal("expected replaced daemon executable to be outdated")
|
||||
}
|
||||
}
|
||||
|
|
@ -1912,10 +1784,7 @@ func TestDaemonStatusIncludesLogPathWhenStopped(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestDaemonStatusIncludesDaemonBuildInfoWhenRunning(t *testing.T) {
|
||||
origDaemonPing := daemonPingFunc
|
||||
t.Cleanup(func() {
|
||||
daemonPingFunc = origDaemonPing
|
||||
})
|
||||
d := defaultDeps()
|
||||
|
||||
configHome := filepath.Join(t.TempDir(), "config")
|
||||
stateHome := filepath.Join(t.TempDir(), "state")
|
||||
|
|
@ -1924,7 +1793,7 @@ func TestDaemonStatusIncludesDaemonBuildInfoWhenRunning(t *testing.T) {
|
|||
t.Setenv("XDG_STATE_HOME", stateHome)
|
||||
t.Setenv("XDG_RUNTIME_DIR", runtimeHome)
|
||||
|
||||
daemonPingFunc = func(context.Context, string) (api.PingResult, error) {
|
||||
d.daemonPing = func(context.Context, string) (api.PingResult, error) {
|
||||
return api.PingResult{
|
||||
Status: "ok",
|
||||
PID: 42,
|
||||
|
|
@ -1934,7 +1803,7 @@ func TestDaemonStatusIncludesDaemonBuildInfoWhenRunning(t *testing.T) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
cmd := NewBangerCommand()
|
||||
cmd := d.newRootCommand()
|
||||
var stdout bytes.Buffer
|
||||
cmd.SetOut(&stdout)
|
||||
cmd.SetErr(&stdout)
|
||||
|
|
@ -2073,26 +1942,26 @@ func TestVMSessionSendRejectsWrongArgCount(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func stubEnsureDaemonForSend(t *testing.T) {
|
||||
// stubEnsureDaemonForSend isolates XDG dirs and installs a daemon-ping
|
||||
// fake onto the caller's *deps so `ensureDaemon` short-circuits without
|
||||
// trying to spawn bangerd. `vm session send` uses this to avoid needing
|
||||
// a built binary on disk.
|
||||
func stubEnsureDaemonForSend(t *testing.T, d *deps) {
|
||||
t.Helper()
|
||||
t.Setenv("XDG_CONFIG_HOME", filepath.Join(t.TempDir(), "config"))
|
||||
t.Setenv("XDG_STATE_HOME", filepath.Join(t.TempDir(), "state"))
|
||||
t.Setenv("XDG_RUNTIME_DIR", filepath.Join(t.TempDir(), "run"))
|
||||
origPing := daemonPingFunc
|
||||
t.Cleanup(func() { daemonPingFunc = origPing })
|
||||
daemonPingFunc = func(context.Context, string) (api.PingResult, error) {
|
||||
d.daemonPing = func(context.Context, string) (api.PingResult, error) {
|
||||
return api.PingResult{Status: "ok", PID: os.Getpid()}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMSessionSendWithMessageFlag(t *testing.T) {
|
||||
stubEnsureDaemonForSend(t)
|
||||
|
||||
original := guestSessionSendFunc
|
||||
t.Cleanup(func() { guestSessionSendFunc = original })
|
||||
d := defaultDeps()
|
||||
stubEnsureDaemonForSend(t, d)
|
||||
|
||||
var capturedParams api.GuestSessionSendParams
|
||||
guestSessionSendFunc = func(_ context.Context, _ string, params api.GuestSessionSendParams) (api.GuestSessionSendResult, error) {
|
||||
d.guestSessionSend = func(_ context.Context, _ string, params api.GuestSessionSendParams) (api.GuestSessionSendResult, error) {
|
||||
capturedParams = params
|
||||
return api.GuestSessionSendResult{
|
||||
Session: model.GuestSession{ID: "sess-id", Name: "planner"},
|
||||
|
|
@ -2100,7 +1969,7 @@ func TestVMSessionSendWithMessageFlag(t *testing.T) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
cmd := NewBangerCommand()
|
||||
cmd := d.newRootCommand()
|
||||
var out bytes.Buffer
|
||||
cmd.SetOut(&out)
|
||||
cmd.SetArgs([]string{"vm", "session", "send", "devbox", "planner", "--message", `{"type":"abort"}`})
|
||||
|
|
@ -2124,13 +1993,11 @@ func TestVMSessionSendWithMessageFlag(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestVMSessionSendMessageAlreadyHasNewline(t *testing.T) {
|
||||
stubEnsureDaemonForSend(t)
|
||||
|
||||
original := guestSessionSendFunc
|
||||
t.Cleanup(func() { guestSessionSendFunc = original })
|
||||
d := defaultDeps()
|
||||
stubEnsureDaemonForSend(t, d)
|
||||
|
||||
var capturedPayload []byte
|
||||
guestSessionSendFunc = func(_ context.Context, _ string, params api.GuestSessionSendParams) (api.GuestSessionSendResult, error) {
|
||||
d.guestSessionSend = func(_ context.Context, _ string, params api.GuestSessionSendParams) (api.GuestSessionSendResult, error) {
|
||||
capturedPayload = params.Payload
|
||||
return api.GuestSessionSendResult{
|
||||
Session: model.GuestSession{Name: "s"},
|
||||
|
|
@ -2138,7 +2005,7 @@ func TestVMSessionSendMessageAlreadyHasNewline(t *testing.T) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
cmd := NewBangerCommand()
|
||||
cmd := d.newRootCommand()
|
||||
cmd.SetOut(io.Discard)
|
||||
cmd.SetArgs([]string{"vm", "session", "send", "devbox", "s", "--message", "{\"type\":\"abort\"}\n"})
|
||||
if err := cmd.Execute(); err != nil {
|
||||
|
|
@ -2155,13 +2022,11 @@ func TestVMSessionSendMessageAlreadyHasNewline(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestVMSessionSendFromStdin(t *testing.T) {
|
||||
stubEnsureDaemonForSend(t)
|
||||
|
||||
original := guestSessionSendFunc
|
||||
t.Cleanup(func() { guestSessionSendFunc = original })
|
||||
d := defaultDeps()
|
||||
stubEnsureDaemonForSend(t, d)
|
||||
|
||||
var capturedPayload []byte
|
||||
guestSessionSendFunc = func(_ context.Context, _ string, params api.GuestSessionSendParams) (api.GuestSessionSendResult, error) {
|
||||
d.guestSessionSend = func(_ context.Context, _ string, params api.GuestSessionSendParams) (api.GuestSessionSendResult, error) {
|
||||
capturedPayload = params.Payload
|
||||
return api.GuestSessionSendResult{
|
||||
Session: model.GuestSession{Name: "planner"},
|
||||
|
|
@ -2170,7 +2035,7 @@ func TestVMSessionSendFromStdin(t *testing.T) {
|
|||
}
|
||||
|
||||
stdinPayload := `{"type":"steer","message":"Focus on src/"}` + "\n"
|
||||
cmd := NewBangerCommand()
|
||||
cmd := d.newRootCommand()
|
||||
cmd.SetOut(io.Discard)
|
||||
cmd.SetIn(strings.NewReader(stdinPayload))
|
||||
cmd.SetArgs([]string{"vm", "session", "send", "devbox", "planner"})
|
||||
|
|
@ -2208,13 +2073,11 @@ func TestVMWorkspaceExportRejectsMissingArg(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestVMWorkspaceExportWritesToStdout(t *testing.T) {
|
||||
stubEnsureDaemonForSend(t)
|
||||
|
||||
origExport := vmWorkspaceExportFunc
|
||||
t.Cleanup(func() { vmWorkspaceExportFunc = origExport })
|
||||
d := defaultDeps()
|
||||
stubEnsureDaemonForSend(t, d)
|
||||
|
||||
patch := []byte("diff --git a/main.go b/main.go\nindex 0000000..1111111 100644\n")
|
||||
vmWorkspaceExportFunc = func(_ context.Context, _ string, params api.WorkspaceExportParams) (api.WorkspaceExportResult, error) {
|
||||
d.vmWorkspaceExport = func(_ context.Context, _ string, params api.WorkspaceExportParams) (api.WorkspaceExportResult, error) {
|
||||
return api.WorkspaceExportResult{
|
||||
GuestPath: params.GuestPath,
|
||||
Patch: patch,
|
||||
|
|
@ -2223,7 +2086,7 @@ func TestVMWorkspaceExportWritesToStdout(t *testing.T) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
cmd := NewBangerCommand()
|
||||
cmd := d.newRootCommand()
|
||||
var out bytes.Buffer
|
||||
cmd.SetOut(&out)
|
||||
cmd.SetErr(io.Discard)
|
||||
|
|
@ -2237,13 +2100,11 @@ func TestVMWorkspaceExportWritesToStdout(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestVMWorkspaceExportWritesToFile(t *testing.T) {
|
||||
stubEnsureDaemonForSend(t)
|
||||
|
||||
origExport := vmWorkspaceExportFunc
|
||||
t.Cleanup(func() { vmWorkspaceExportFunc = origExport })
|
||||
d := defaultDeps()
|
||||
stubEnsureDaemonForSend(t, d)
|
||||
|
||||
patch := []byte("diff --git a/main.go b/main.go\n")
|
||||
vmWorkspaceExportFunc = func(_ context.Context, _ string, _ api.WorkspaceExportParams) (api.WorkspaceExportResult, error) {
|
||||
d.vmWorkspaceExport = func(_ context.Context, _ string, _ api.WorkspaceExportParams) (api.WorkspaceExportResult, error) {
|
||||
return api.WorkspaceExportResult{
|
||||
GuestPath: "/root/repo",
|
||||
Patch: patch,
|
||||
|
|
@ -2253,7 +2114,7 @@ func TestVMWorkspaceExportWritesToFile(t *testing.T) {
|
|||
}
|
||||
|
||||
outFile := filepath.Join(t.TempDir(), "worker.diff")
|
||||
cmd := NewBangerCommand()
|
||||
cmd := d.newRootCommand()
|
||||
cmd.SetOut(io.Discard)
|
||||
var stderr bytes.Buffer
|
||||
cmd.SetErr(&stderr)
|
||||
|
|
@ -2275,19 +2136,17 @@ func TestVMWorkspaceExportWritesToFile(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestVMWorkspaceExportNoChanges(t *testing.T) {
|
||||
stubEnsureDaemonForSend(t)
|
||||
d := defaultDeps()
|
||||
stubEnsureDaemonForSend(t, d)
|
||||
|
||||
origExport := vmWorkspaceExportFunc
|
||||
t.Cleanup(func() { vmWorkspaceExportFunc = origExport })
|
||||
|
||||
vmWorkspaceExportFunc = func(_ context.Context, _ string, _ api.WorkspaceExportParams) (api.WorkspaceExportResult, error) {
|
||||
d.vmWorkspaceExport = func(_ context.Context, _ string, _ api.WorkspaceExportParams) (api.WorkspaceExportResult, error) {
|
||||
return api.WorkspaceExportResult{
|
||||
GuestPath: "/root/repo",
|
||||
HasChanges: false,
|
||||
}, nil
|
||||
}
|
||||
|
||||
cmd := NewBangerCommand()
|
||||
cmd := d.newRootCommand()
|
||||
var out bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
cmd.SetOut(&out)
|
||||
|
|
@ -2305,18 +2164,16 @@ func TestVMWorkspaceExportNoChanges(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestVMWorkspaceExportGuestPathFlag(t *testing.T) {
|
||||
stubEnsureDaemonForSend(t)
|
||||
|
||||
origExport := vmWorkspaceExportFunc
|
||||
t.Cleanup(func() { vmWorkspaceExportFunc = origExport })
|
||||
d := defaultDeps()
|
||||
stubEnsureDaemonForSend(t, d)
|
||||
|
||||
var capturedParams api.WorkspaceExportParams
|
||||
vmWorkspaceExportFunc = func(_ context.Context, _ string, params api.WorkspaceExportParams) (api.WorkspaceExportResult, error) {
|
||||
d.vmWorkspaceExport = func(_ context.Context, _ string, params api.WorkspaceExportParams) (api.WorkspaceExportResult, error) {
|
||||
capturedParams = params
|
||||
return api.WorkspaceExportResult{HasChanges: false}, nil
|
||||
}
|
||||
|
||||
cmd := NewBangerCommand()
|
||||
cmd := d.newRootCommand()
|
||||
cmd.SetOut(io.Discard)
|
||||
cmd.SetErr(io.Discard)
|
||||
cmd.SetArgs([]string{"vm", "workspace", "export", "devbox", "--guest-path", "/root/project"})
|
||||
|
|
@ -2332,13 +2189,11 @@ func TestVMWorkspaceExportGuestPathFlag(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestVMWorkspaceExportBaseCommitFlag(t *testing.T) {
|
||||
stubEnsureDaemonForSend(t)
|
||||
|
||||
origExport := vmWorkspaceExportFunc
|
||||
t.Cleanup(func() { vmWorkspaceExportFunc = origExport })
|
||||
d := defaultDeps()
|
||||
stubEnsureDaemonForSend(t, d)
|
||||
|
||||
var capturedParams api.WorkspaceExportParams
|
||||
vmWorkspaceExportFunc = func(_ context.Context, _ string, params api.WorkspaceExportParams) (api.WorkspaceExportResult, error) {
|
||||
d.vmWorkspaceExport = func(_ context.Context, _ string, params api.WorkspaceExportParams) (api.WorkspaceExportResult, error) {
|
||||
capturedParams = params
|
||||
return api.WorkspaceExportResult{
|
||||
HasChanges: false,
|
||||
|
|
@ -2346,7 +2201,7 @@ func TestVMWorkspaceExportBaseCommitFlag(t *testing.T) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
cmd := NewBangerCommand()
|
||||
cmd := d.newRootCommand()
|
||||
cmd.SetOut(io.Discard)
|
||||
cmd.SetErr(io.Discard)
|
||||
cmd.SetArgs([]string{"vm", "workspace", "export", "devbox", "--base-commit", "abc1234deadbeef"})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue