Files
bootstrap_dev_env/post_test.go
T
2026-05-26 13:21:31 -05:00

800 lines
21 KiB
Go

package main
import (
"fmt"
"os"
"os/user"
"path/filepath"
"strings"
"testing"
"time"
)
func TestInstallPyenv(t *testing.T) {
defer resetMocks()
var runShellCmd string
runShell = func(cmd string, opts CmdOpts) CmdResult {
runShellCmd = cmd
return CmdResult{ExitCode: 0}
}
installPyenv()
if !strings.Contains(runShellCmd, "pyenv.run | bash") {
t.Errorf("unexpected shell command: %q", runShellCmd)
}
}
func TestPython3DecimalOK(t *testing.T) {
defer resetMocks()
hasCmd = func(name string) bool { return true }
probe = func(argv []string, timeout time.Duration) (CmdResult, bool) {
return CmdResult{ExitCode: 0}, true
}
if !python3DecimalOK() {
t.Error("expected decimal OK")
}
probe = func(argv []string, timeout time.Duration) (CmdResult, bool) {
return CmdResult{ExitCode: 1}, true
}
if python3DecimalOK() {
t.Error("expected decimal NOT OK")
}
}
func TestFixPython3Decimal(t *testing.T) {
defer resetMocks()
pkgMgr = "apt-get"
var runCmdCalls [][]string
runCmd = func(argv []string, opts CmdOpts) CmdResult {
runCmdCalls = append(runCmdCalls, argv)
return CmdResult{ExitCode: 0}
}
hasCmd = func(name string) bool { return true }
probe = func(argv []string, timeout time.Duration) (CmdResult, bool) {
// Mock python3DecimalOK to return true after fix is called
return CmdResult{ExitCode: 0}, true
}
ok := fixPython3Decimal()
if !ok {
t.Error("expected fix to succeed")
}
if len(runCmdCalls) != 1 || runCmdCalls[0][0] != "apt-get" || runCmdCalls[0][3] != "python3-full" {
t.Errorf("expected apt-get install python3-full, got: %v", runCmdCalls)
}
}
func TestLatestStablePython(t *testing.T) {
defer resetMocks()
probe = func(argv []string, timeout time.Duration) (CmdResult, bool) {
output := `
3.10.1
3.11.2
3.12.0
3.12.1
3.12.2
2.7.18
system
`
return CmdResult{ExitCode: 0, Stdout: []byte(output)}, true
}
latest := latestStablePython("/path/to/pyenv")
if latest != "3.12.2" {
t.Errorf("expected 3.12.2, got %q", latest)
}
}
func TestInstallNVM(t *testing.T) {
defer resetMocks()
fetchJSON = func(url string, v any) bool {
rel := v.(*ghRelease)
rel.TagName = "v0.39.5"
return true
}
var runShellCmd string
runShell = func(cmd string, opts CmdOpts) CmdResult {
runShellCmd = cmd
return CmdResult{ExitCode: 0}
}
installNVM()
if !strings.Contains(runShellCmd, "nvm/v0.39.5/install.sh") {
t.Errorf("unexpected NVM install script: %q", runShellCmd)
}
}
func TestInstallOhMyZsh(t *testing.T) {
defer resetMocks()
hasCmd = func(name string) bool { return true }
osStat = func(name string) (os.FileInfo, error) {
return nil, os.ErrNotExist // Not present, trigger install
}
var runShellCmd string
runShell = func(cmd string, opts CmdOpts) CmdResult {
runShellCmd = cmd
return CmdResult{ExitCode: 0}
}
tmp := t.TempDir()
t.Setenv("HOME", tmp)
zshrc := filepath.Join(tmp, ".zshrc")
osWriteFile(zshrc, []byte("ZSH_THEME=\"robbyrussell\""), 0644)
osReadFile = func(name string) ([]byte, error) {
if name == zshrc {
return []byte("ZSH_THEME=\"robbyrussell\""), nil
}
return nil, os.ErrNotExist
}
var writtenContent string
osWriteFile = func(name string, data []byte, perm os.FileMode) error {
if name == zshrc {
writtenContent = string(data)
}
return nil
}
installOhMyZsh()
if !strings.Contains(runShellCmd, "ohmyzsh/master/tools/install.sh") {
t.Errorf("unexpected installer: %q", runShellCmd)
}
if !strings.Contains(writtenContent, "ZSH_THEME=\"gnzh\"") {
t.Errorf("expected theme replaced to gnzh, got: %q", writtenContent)
}
}
func TestEnsureZshDefault(t *testing.T) {
defer resetMocks()
hasCmd = func(name string) bool { return true }
probe = func(argv []string, timeout time.Duration) (CmdResult, bool) {
return CmdResult{ExitCode: 0, Stdout: []byte("/bin/zsh")}, true
}
u, err := user.Current()
if err != nil {
t.Fatal(err)
}
t.Setenv("SUDO_USER", u.Username)
passwdPath = filepath.Join(t.TempDir(), "passwd")
passwdContent := fmt.Sprintf("%s:x:%s:%s::/home/%s:/bin/bash\n", u.Username, u.Uid, u.Gid, u.Username)
osWriteFile(passwdPath, []byte(passwdContent), 0644)
var runCmdCalls [][]string
runCmd = func(argv []string, opts CmdOpts) CmdResult {
runCmdCalls = append(runCmdCalls, argv)
return CmdResult{ExitCode: 0}
}
isRHELFamily = false
ensureZshDefault()
if len(runCmdCalls) != 1 || runCmdCalls[0][0] != "chsh" || runCmdCalls[0][2] != "/bin/zsh" {
t.Errorf("expected chsh call to zsh, got: %v", runCmdCalls)
}
}
func TestCloneNvimConfig(t *testing.T) {
defer resetMocks()
tmp := t.TempDir()
t.Setenv("HOME", tmp)
var statCalls []string
osStat = func(name string) (os.FileInfo, error) {
statCalls = append(statCalls, name)
if strings.HasSuffix(name, "nvim") {
return nil, nil // config directory exists
}
return nil, os.ErrNotExist // backup folder doesn't exist
}
var renameCalls [][]string
osRename = func(oldpath, newpath string) error {
renameCalls = append(renameCalls, []string{oldpath, newpath})
return nil
}
var runCmdCalls [][]string
runCmd = func(argv []string, opts CmdOpts) CmdResult {
runCmdCalls = append(runCmdCalls, argv)
return CmdResult{ExitCode: 0}
}
cloneNvimConfig()
// Should have at least one rename call (for backup or tempClone rename)
if len(renameCalls) < 2 {
t.Fatalf("expected at least 2 rename calls, got: %v", renameCalls)
}
if !strings.HasSuffix(renameCalls[0][0], "nvim") || !strings.Contains(renameCalls[0][1], "nvim-1") {
t.Errorf("expected backup rename first, got: %v", renameCalls[0])
}
if !strings.HasSuffix(renameCalls[1][0], "nvim-config") || !strings.HasSuffix(renameCalls[1][1], "nvim") {
t.Errorf("expected temp clone rename second, got: %v", renameCalls[1])
}
if len(runCmdCalls) != 1 || runCmdCalls[0][0] != "git" || runCmdCalls[0][1] != "clone" {
t.Errorf("expected git clone call, got: %v", runCmdCalls)
}
}
func TestCheckAndSetupSSH(t *testing.T) {
defer resetMocks()
hasCmd = func(name string) bool { return true }
probe = func(argv []string, timeout time.Duration) (CmdResult, bool) {
// Mock ghLoggedIn to return false (requires auth)
return CmdResult{ExitCode: 1}, true
}
stdin = strings.NewReader("y\n") // agree to login
var runCmdCalls [][]string
runCmd = func(argv []string, opts CmdOpts) CmdResult {
runCmdCalls = append(runCmdCalls, argv)
return CmdResult{ExitCode: 0}
}
checkAndSetupSSH()
if len(runCmdCalls) != 1 || runCmdCalls[0][0] != "gh" || runCmdCalls[0][2] != "login" {
t.Errorf("expected gh auth login command, got: %v", runCmdCalls)
}
}
func TestInstallPipAgyNpm(t *testing.T) {
defer resetMocks()
// Case 1: python3 not installed for pip
hasCmd = func(name string) bool { return false }
installPip() // should log error and return
// Case 2: installPip when python3 is installed
resetMocks()
hasCmd = func(name string) bool { return true }
probe = func(argv []string, timeout time.Duration) (CmdResult, bool) {
return CmdResult{ExitCode: 0}, true // decimal OK and pip check OK
}
var runCmdCalls [][]string
runCmd = func(argv []string, opts CmdOpts) CmdResult {
runCmdCalls = append(runCmdCalls, argv)
return CmdResult{ExitCode: 0}
}
installPip()
if len(runCmdCalls) < 2 {
t.Errorf("expected ensurepip and upgrade pip calls, got: %v", runCmdCalls)
}
// Test installAgy
resetMocks()
var runShellCmd string
runShell = func(cmd string, opts CmdOpts) CmdResult {
runShellCmd = cmd
return CmdResult{ExitCode: 0}
}
installAgy()
if !strings.Contains(runShellCmd, "antigravity.google/cli/install.sh") {
t.Errorf("unexpected agy install command: %q", runShellCmd)
}
// Test installNpmPackage
resetMocks()
var runShellCmds []string
runShell = func(cmd string, opts CmdOpts) CmdResult {
runShellCmds = append(runShellCmds, cmd)
return CmdResult{ExitCode: 0}
}
osStat = func(name string) (os.FileInfo, error) {
return nil, nil // nvm exists
}
installNpmPackage("my-package")
if len(runShellCmds) < 1 || !strings.Contains(runShellCmds[len(runShellCmds)-1], "pnpm add -g my-package") {
t.Errorf("unexpected npm install command: %v", runShellCmds)
}
}
func TestEnsurePythonAndNode(t *testing.T) {
defer resetMocks()
// Test ensurePythonLatest
osStat = func(name string) (os.FileInfo, error) {
return nil, nil // pyenvDir and pyenvBin exist
}
probe = func(argv []string, timeout time.Duration) (CmdResult, bool) {
if argv[1] == "install" {
return CmdResult{ExitCode: 0, Stdout: []byte(" 3.12.0\n")}, true
}
if argv[1] == "versions" {
return CmdResult{ExitCode: 0, Stdout: []byte(" 3.12.0\n")}, true // already installed
}
return CmdResult{ExitCode: 0}, true
}
var runCmdCalls [][]string
runCmd = func(argv []string, opts CmdOpts) CmdResult {
runCmdCalls = append(runCmdCalls, argv)
return CmdResult{ExitCode: 0}
}
wg := ensurePythonLatest()
if wg != nil {
t.Error("expected nil waitgroup since Python 3.12.0 is already installed")
}
if len(runCmdCalls) != 1 || runCmdCalls[0][1] != "global" {
t.Errorf("expected global 3.12.0 command, got: %v", runCmdCalls)
}
// Test ensureNodeLTS
resetMocks()
osStat = func(name string) (os.FileInfo, error) {
return nil, nil // nvm exists
}
var runShellCmds []string
runShell = func(cmd string, opts CmdOpts) CmdResult {
runShellCmds = append(runShellCmds, cmd)
if strings.Contains(cmd, "nvm version lts/*") {
return CmdResult{ExitCode: 0, Stdout: []byte("N/A")} // Not installed yet
}
return CmdResult{ExitCode: 0}
}
ensureNodeLTS()
hasInstall := false
for _, cmd := range runShellCmds {
if strings.Contains(cmd, "nvm install --lts") {
hasInstall = true
}
}
if !hasInstall {
t.Errorf("expected nvm install --lts, got: %v", runShellCmds)
}
}
func TestInstallPipEdgeCases(t *testing.T) {
defer resetMocks()
hasCmd = func(name string) bool { return true }
var probeCalls [][]string
probe = func(argv []string, timeout time.Duration) (CmdResult, bool) {
probeCalls = append(probeCalls, argv)
if len(probeCalls) == 1 {
return CmdResult{ExitCode: 1}, true
}
return CmdResult{ExitCode: 0}, true
}
var runCmdCalls [][]string
runCmd = func(argv []string, opts CmdOpts) CmdResult {
runCmdCalls = append(runCmdCalls, argv)
return CmdResult{ExitCode: 0}
}
pkgMgr = "dnf"
installPip()
if len(runCmdCalls) < 3 {
t.Errorf("expected python3-libs fix, ensurepip, and upgrade, got: %v", runCmdCalls)
}
resetMocks()
hasCmd = func(name string) bool { return true }
probe = func(argv []string, timeout time.Duration) (CmdResult, bool) {
return CmdResult{ExitCode: 1}, true
}
runCmd = func(argv []string, opts CmdOpts) CmdResult {
return CmdResult{ExitCode: 0}
}
installPip()
resetMocks()
pkgMgr = "apt-get"
hasCmd = func(name string) bool { return true }
probe = func(argv []string, timeout time.Duration) (CmdResult, bool) {
return CmdResult{ExitCode: 0}, true
}
runCmd = func(argv []string, opts CmdOpts) CmdResult {
if argv[0] == "python3" && argv[2] == "ensurepip" {
return CmdResult{ExitCode: 1}
}
return CmdResult{ExitCode: 0}
}
installPip()
resetMocks()
pkgMgr = "pacman"
hasCmd = func(name string) bool { return true }
probe = func(argv []string, timeout time.Duration) (CmdResult, bool) {
return CmdResult{ExitCode: 0}, true
}
runCmd = func(argv []string, opts CmdOpts) CmdResult {
if argv[0] == "python3" && argv[2] == "ensurepip" {
return CmdResult{ExitCode: 1}
}
return CmdResult{ExitCode: 0}
}
installPip()
resetMocks()
pkgMgr = "brew"
hasCmd = func(name string) bool { return true }
probe = func(argv []string, timeout time.Duration) (CmdResult, bool) {
return CmdResult{ExitCode: 0}, true
}
runCmd = func(argv []string, opts CmdOpts) CmdResult {
if argv[0] == "python3" && argv[2] == "ensurepip" {
return CmdResult{ExitCode: 1}
}
return CmdResult{ExitCode: 0}
}
installPip()
resetMocks()
hasCmd = func(name string) bool { return true }
probe = func(argv []string, timeout time.Duration) (CmdResult, bool) {
return CmdResult{ExitCode: 0}, true
}
runCmd = func(argv []string, opts CmdOpts) CmdResult {
if argv[0] == "python3" && argv[3] == "install" {
return CmdResult{ExitCode: 1}
}
return CmdResult{ExitCode: 0}
}
installPip()
}
func TestEnsureZshDefaultEdgeCases(t *testing.T) {
defer resetMocks()
hasCmd = func(name string) bool { return false }
ensureZshDefault()
resetMocks()
hasCmd = func(name string) bool {
return name == "zsh"
}
probe = func(argv []string, timeout time.Duration) (CmdResult, bool) {
if argv[0] == "which" {
return CmdResult{ExitCode: 1}, true
}
return CmdResult{ExitCode: 0, Stdout: []byte("")}, true
}
runCmd = func(argv []string, opts CmdOpts) CmdResult {
return CmdResult{ExitCode: 0}
}
passwdPath = filepath.Join(t.TempDir(), "passwd")
ensureZshDefault()
resetMocks()
isRHELFamily = true
hasCmd = func(name string) bool { return true }
probe = func(argv []string, timeout time.Duration) (CmdResult, bool) {
return CmdResult{ExitCode: 0, Stdout: []byte("/bin/zsh")}, true
}
u, _ := user.Current()
t.Setenv("SUDO_USER", u.Username)
passwdPath = filepath.Join(t.TempDir(), "passwd")
passwdContent := fmt.Sprintf("%s:x:%s:%s::/home/%s:/bin/zsh\n", u.Username, u.Uid, u.Gid, u.Username)
osWriteFile(passwdPath, []byte(passwdContent), 0644)
ensureZshDefault()
resetMocks()
isRHELFamily = true
hasCmd = func(name string) bool { return true }
probe = func(argv []string, timeout time.Duration) (CmdResult, bool) {
return CmdResult{ExitCode: 0, Stdout: []byte("/bin/zsh")}, true
}
t.Setenv("SUDO_USER", u.Username)
passwdContent = fmt.Sprintf("%s:x:%s:%s::/home/%s:/bin/bash\n", u.Username, u.Uid, u.Gid, u.Username)
osWriteFile(passwdPath, []byte(passwdContent), 0644)
runCmd = func(argv []string, opts CmdOpts) CmdResult {
return CmdResult{ExitCode: 1}
}
ensureZshDefault()
}
func TestUserLoginShellEdgeCases(t *testing.T) {
defer resetMocks()
passwdPath = "/nonexistent"
if shell := userLoginShell("1000"); shell != "" {
t.Errorf("expected empty shell, got %q", shell)
}
passwdPath = filepath.Join(t.TempDir(), "passwd")
content := "root:x:0:0:root:/root\nmalformed:line\n"
osWriteFile(passwdPath, []byte(content), 0644)
if shell := userLoginShell("0"); shell != "" {
t.Errorf("expected empty shell for malformed/short lines, got %q", shell)
}
}
func TestCloneNvimConfigEdgeCases(t *testing.T) {
defer resetMocks()
tmp := t.TempDir()
t.Setenv("HOME", tmp)
osStat = func(name string) (os.FileInfo, error) {
if strings.HasSuffix(name, "nvim") {
return nil, nil
}
return nil, os.ErrNotExist
}
osRename = func(oldpath, newpath string) error {
return fmt.Errorf("rename failed error")
}
cloneNvimConfig()
resetMocks()
t.Setenv("HOME", tmp)
osStat = func(name string) (os.FileInfo, error) {
return nil, os.ErrNotExist
}
runCmd = func(argv []string, opts CmdOpts) CmdResult {
return CmdResult{ExitCode: 1}
}
cloneNvimConfig()
}
func TestCheckAndSetupSSHEdgeCases(t *testing.T) {
defer resetMocks()
hasCmd = func(name string) bool {
return name != "gh"
}
checkAndSetupSSH()
resetMocks()
hasCmd = func(name string) bool { return true }
probe = func(argv []string, timeout time.Duration) (CmdResult, bool) {
return CmdResult{ExitCode: 0}, true
}
checkAndSetupSSH()
resetMocks()
hasCmd = func(name string) bool { return true }
probe = func(argv []string, timeout time.Duration) (CmdResult, bool) {
return CmdResult{ExitCode: 1}, true
}
stdin = strings.NewReader("n\n")
checkAndSetupSSH()
resetMocks()
hasCmd = func(name string) bool { return true }
probe = func(argv []string, timeout time.Duration) (CmdResult, bool) {
return CmdResult{ExitCode: 1}, true
}
stdin = strings.NewReader("y\n")
runCmd = func(argv []string, opts CmdOpts) CmdResult {
return CmdResult{ExitCode: 1}
}
checkAndSetupSSH()
}
func TestAskYNEdgeCases(t *testing.T) {
defer resetMocks()
stdin = &errReader{}
if askYN("Prompt: ") {
t.Error("expected false for stdin error")
}
}
type errReader struct{}
func (e *errReader) Read(p []byte) (n int, err error) {
return 0, fmt.Errorf("simulated read error")
}
func TestInstallGHExtension(t *testing.T) {
defer resetMocks()
// gh not installed
hasCmd = func(name string) bool { return false }
installGHExtension("JMR-dev/gh-repo-bootstrap") // should log error and return
// gh installed, install succeeds
resetMocks()
hasCmd = func(name string) bool { return true }
var runCmdCalls [][]string
runCmd = func(argv []string, opts CmdOpts) CmdResult {
runCmdCalls = append(runCmdCalls, argv)
return CmdResult{ExitCode: 0}
}
installGHExtension("JMR-dev/gh-repo-bootstrap")
if len(runCmdCalls) != 1 ||
runCmdCalls[0][0] != "gh" ||
runCmdCalls[0][1] != "extension" ||
runCmdCalls[0][2] != "install" ||
runCmdCalls[0][3] != "JMR-dev/gh-repo-bootstrap" {
t.Errorf("expected gh extension install command, got: %v", runCmdCalls)
}
// gh installed, install fails
resetMocks()
hasCmd = func(name string) bool { return true }
runCmd = func(argv []string, opts CmdOpts) CmdResult {
return CmdResult{ExitCode: 1}
}
installGHExtension("JMR-dev/gh-repo-bootstrap") // should log error
}
func TestInstallNpmPackageEdgeCases(t *testing.T) {
defer resetMocks()
osStat = func(name string) (os.FileInfo, error) {
return nil, os.ErrNotExist
}
installNpmPackage("test-pkg")
}
func TestInstallPlaywright(t *testing.T) {
defer resetMocks()
// Edge case: NVM not installed
osStat = func(name string) (os.FileInfo, error) {
return nil, os.ErrNotExist
}
installPlaywright() // should log error and return
// Happy path
resetMocks()
osStat = func(name string) (os.FileInfo, error) {
return nil, nil // nvm exists
}
var runShellCmds []string
runShell = func(cmd string, opts CmdOpts) CmdResult {
runShellCmds = append(runShellCmds, cmd)
return CmdResult{ExitCode: 0}
}
installPlaywright()
hasPnpmInstall := false
hasPlaywrightBrowsers := false
for _, cmd := range runShellCmds {
if strings.Contains(cmd, "pnpm add -g playwright") {
hasPnpmInstall = true
}
if strings.Contains(cmd, "pnpx playwright install --with-deps") {
hasPlaywrightBrowsers = true
}
}
if !hasPnpmInstall {
t.Errorf("expected pnpm add -g playwright, got: %v", runShellCmds)
}
if !hasPlaywrightBrowsers {
t.Errorf("expected pnpx playwright install --with-deps, got: %v", runShellCmds)
}
// Failure path: pnpm install fails, browser install should be skipped
resetMocks()
osStat = func(name string) (os.FileInfo, error) {
return nil, nil
}
var failShellCmds []string
runShell = func(cmd string, opts CmdOpts) CmdResult {
failShellCmds = append(failShellCmds, cmd)
if strings.Contains(cmd, "pnpm add -g playwright") {
return CmdResult{ExitCode: 1}
}
return CmdResult{ExitCode: 0}
}
installPlaywright()
for _, cmd := range failShellCmds {
if strings.Contains(cmd, "pnpx playwright install") {
t.Errorf("browser install should be skipped when pnpm install fails, got: %v", failShellCmds)
}
}
}
func TestEnsureNodeLTSEdgeCases(t *testing.T) {
defer resetMocks()
osStat = func(name string) (os.FileInfo, error) {
return nil, nil
}
var runShellCalls []string
runShell = func(cmd string, opts CmdOpts) CmdResult {
runShellCalls = append(runShellCalls, cmd)
if strings.Contains(cmd, "nvm version lts/*") {
return CmdResult{ExitCode: 0, Stdout: []byte("N/A")}
}
if strings.Contains(cmd, "nvm install --lts") {
return CmdResult{ExitCode: 1}
}
return CmdResult{ExitCode: 0}
}
ensureNodeLTS()
resetMocks()
osStat = func(name string) (os.FileInfo, error) {
return nil, nil
}
runShell = func(cmd string, opts CmdOpts) CmdResult {
if strings.Contains(cmd, "nvm version lts/*") {
return CmdResult{ExitCode: 0, Stdout: []byte("v20.0.0")}
}
if strings.Contains(cmd, "nvm alias default") {
return CmdResult{ExitCode: 1}
}
return CmdResult{ExitCode: 0}
}
ensureNodeLTS()
resetMocks()
osStat = func(name string) (os.FileInfo, error) {
return nil, nil
}
runShell = func(cmd string, opts CmdOpts) CmdResult {
if strings.Contains(cmd, "nvm version lts/*") {
return CmdResult{ExitCode: 0, Stdout: []byte("v20.0.0")}
}
if strings.Contains(cmd, "corepack enable") {
return CmdResult{ExitCode: 1}
}
return CmdResult{ExitCode: 0}
}
ensureNodeLTS()
}
func TestEnsurePythonLatestBackgroundInstall(t *testing.T) {
defer resetMocks()
osStat = func(name string) (os.FileInfo, error) {
return nil, nil
}
probe = func(argv []string, timeout time.Duration) (CmdResult, bool) {
if argv[1] == "install" {
return CmdResult{ExitCode: 0, Stdout: []byte(" 3.12.0\n")}, true
}
if argv[1] == "versions" {
return CmdResult{ExitCode: 0, Stdout: []byte(" 3.11.0\n")}, true
}
return CmdResult{ExitCode: 0}, true
}
var runCmdCalls [][]string
runCmd = func(argv []string, opts CmdOpts) CmdResult {
runCmdCalls = append(runCmdCalls, argv)
return CmdResult{ExitCode: 0}
}
wg := ensurePythonLatest()
if wg == nil {
t.Fatal("expected waitgroup since Python 3.12.0 needs install")
}
wg.Wait()
// Failure case
probe = func(argv []string, timeout time.Duration) (CmdResult, bool) {
if argv[1] == "install" {
return CmdResult{ExitCode: 0, Stdout: []byte(" 3.12.0\n")}, true
}
if argv[1] == "versions" {
return CmdResult{ExitCode: 0, Stdout: []byte(" 3.11.0\n")}, true
}
return CmdResult{ExitCode: 0}, true
}
runCmd = func(argv []string, opts CmdOpts) CmdResult {
if argv[1] == "install" {
return CmdResult{ExitCode: 1, Stderr: []byte("error lines\nline 2")}
}
return CmdResult{ExitCode: 0}
}
wg = ensurePythonLatest()
if wg != nil {
wg.Wait()
}
}