package docker import ( "fmt" "testing" ) func TestEngineCandidates(t *testing.T) { t.Setenv("DOCKER_HOST", "") t.Setenv("XDG_RUNTIME_DIR", "/run/user/1000") cands := engineCandidates("") if len(cands) != 3 { t.Fatalf("harusnya 3 kandidat: %+v", cands) } if cands[0].name != "docker" || cands[0].host != "" { t.Fatalf("kandidat pertama harus docker default: %+v", cands[0]) } if cands[1].name != "podman" || cands[1].host != "unix:///run/user/1000/podman/podman.sock" { t.Fatalf("kandidat kedua harus podman rootless: %+v", cands[1]) } if cands[2].host != "unix:///run/podman/podman.sock" { t.Fatalf("kandidat ketiga harus podman rootful: %+v", cands[2]) } // override menang dan namanya mengikuti isi host cands = engineCandidates("unix:///run/user/1000/podman/podman.sock") if len(cands) != 1 || cands[0].name != "podman" { t.Fatalf("override podman salah: %+v", cands) } cands = engineCandidates("tcp://192.168.1.5:2375") if len(cands) != 1 || cands[0].name != "docker" { t.Fatalf("override tcp harus docker: %+v", cands) } // DOCKER_HOST diset → satu kandidat, host dibiarkan kosong (FromEnv) t.Setenv("DOCKER_HOST", "unix:///custom.sock") cands = engineCandidates("") if len(cands) != 1 || cands[0].host != "" || cands[0].name != "docker" { t.Fatalf("DOCKER_HOST salah: %+v", cands) } } func TestDetectWith(t *testing.T) { cands := []candidate{{name: "docker", host: "d1"}, {name: "podman", host: "p1"}} // docker mati → jatuh ke podman connect := func(host string) (*Client, error) { if host == "p1" { return &Client{}, nil } return nil, fmt.Errorf("connection refused") } cl, info, err := detectWith(cands, connect) if err != nil || cl == nil || info.Name != "podman" || info.Host != "p1" { t.Fatalf("fallback salah: cl=%v info=%+v err=%v", cl, info, err) } // semua mati → error jelas connect = func(host string) (*Client, error) { return nil, fmt.Errorf("matilah") } if _, _, err := detectWith(cands, connect); err == nil { t.Fatal("semua gagal harus error") } } func TestPickCompose(t *testing.T) { have := func(bins ...string) func(string) (string, error) { m := map[string]bool{} for _, b := range bins { m[b] = true } return func(b string) (string, error) { if m[b] { return "/usr/bin/" + b, nil } return "", fmt.Errorf("tidak ada") } } // podman engine: binary podman ada → `podman compose` (subcommand bawaan) if got := pickCompose("auto", "podman", have("docker", "podman")); got[0] != "podman" || got[1] != "compose" { t.Fatalf("podman engine: %v", got) } // podman engine tanpa binary podman → jatuh ke podman-compose if got := pickCompose("auto", "podman", have("podman-compose")); got[0] != "podman-compose" { t.Fatalf("fallback podman-compose: %v", got) } // engine docker if got := pickCompose("auto", "docker", have("docker")); got[0] != "docker" || got[1] != "compose" { t.Fatalf("docker engine: %v", got) } // docker engine, tapi hanya podman yang ada → tetap pakai podman if got := pickCompose("auto", "docker", have("podman")); got[0] != "podman" { t.Fatalf("degradasi ke podman: %v", got) } // spec eksplisit selalu menang if got := pickCompose("docker-compose", "podman", have("docker-compose")); got[0] != "docker-compose" { t.Fatalf("eksplisit: %v", got) } }