agent/pkg/agentic/dispatch_runtime_test.go
Snider edfcb1bdfe feat(agent): unblock factory dispatch, runtime-aware containers, RFC gaps
- paths.go: resolve relative workspace_root against $HOME/Code so workspaces
  land in the conventional location regardless of launch cwd (MCP stdio vs CLI)
- dispatch.go: container mounts use /home/agent (matches DEV_USER), plus
  runtime-aware dispatch (apple/docker/podman) with GPU toggle per RFC §15.5
- queue.go / runner/queue.go: DispatchConfig adds Runtime/Image/GPU fields;
  AgentIdentity parsing for the agents: block (RFC §10/§11)
- pr.go / commands_forge.go / actions.go: agentic_delete_branch tool +
  branch/delete CLI (RFC §7)
- brain/tools.go / provider.go: Org + IndexedAt fields on Memory (RFC §4)
- config/agents.yaml: document new dispatch fields, fix identity table
- tests: dispatch_runtime_test.go (21), expanded pr_test.go + queue_test.go,
  new CLI fixtures for branch/delete and pr/list

Co-Authored-By: Virgil <virgil@lethean.io>
2026-04-14 11:45:09 +01:00

203 lines
7.4 KiB
Go

// SPDX-License-Identifier: EUPL-1.2
package agentic
import (
"strings"
"testing"
core "dappco.re/go/core"
"github.com/stretchr/testify/assert"
)
// --- containerRuntimeBinary ---
func TestDispatchRuntime_ContainerRuntimeBinary_Good(t *testing.T) {
assert.Equal(t, "container", containerRuntimeBinary(RuntimeApple))
assert.Equal(t, "docker", containerRuntimeBinary(RuntimeDocker))
assert.Equal(t, "podman", containerRuntimeBinary(RuntimePodman))
}
func TestDispatchRuntime_ContainerRuntimeBinary_Bad(t *testing.T) {
// Unknown runtime falls back to docker so dispatch never silently breaks.
assert.Equal(t, "docker", containerRuntimeBinary(""))
assert.Equal(t, "docker", containerRuntimeBinary("kubernetes"))
}
func TestDispatchRuntime_ContainerRuntimeBinary_Ugly(t *testing.T) {
// Whitespace-laden runtime name is treated as unknown; docker fallback wins.
assert.Equal(t, "docker", containerRuntimeBinary(" apple "))
}
// --- runtimeAvailable ---
func TestDispatchRuntime_RuntimeAvailable_Good(t *testing.T) {
// Inspect only the failure path that doesn't depend on host binaries.
// Apple Container is by definition unavailable on non-darwin.
if !isDarwin() {
assert.False(t, runtimeAvailable(RuntimeApple))
}
}
func TestDispatchRuntime_RuntimeAvailable_Bad(t *testing.T) {
// Unknown runtimes are never available.
assert.False(t, runtimeAvailable(""))
assert.False(t, runtimeAvailable("kubernetes"))
}
func TestDispatchRuntime_RuntimeAvailable_Ugly(t *testing.T) {
// Apple Container on non-macOS hosts is always unavailable, regardless of
// whether a binary called "container" happens to be on PATH.
if !isDarwin() {
assert.False(t, runtimeAvailable(RuntimeApple))
}
}
// --- resolveContainerRuntime ---
func TestDispatchRuntime_ResolveContainerRuntime_Good(t *testing.T) {
// Empty preference falls back to one of the known runtimes (docker is the
// hard fallback, but the function may surface apple/podman when those
// binaries exist on the test host).
resolved := resolveContainerRuntime("")
assert.Contains(t, []string{RuntimeApple, RuntimeDocker, RuntimePodman}, resolved)
}
func TestDispatchRuntime_ResolveContainerRuntime_Bad(t *testing.T) {
// An unknown runtime preference still resolves to a known runtime.
resolved := resolveContainerRuntime("kubernetes")
assert.Contains(t, []string{RuntimeApple, RuntimeDocker, RuntimePodman}, resolved)
}
func TestDispatchRuntime_ResolveContainerRuntime_Ugly(t *testing.T) {
// Apple preference on non-darwin host falls back to a non-apple runtime.
if !isDarwin() {
resolved := resolveContainerRuntime(RuntimeApple)
assert.NotEqual(t, RuntimeApple, resolved)
}
}
// --- containerCommandFor ---
func TestDispatchRuntime_ContainerCommandFor_Good(t *testing.T) {
t.Setenv("AGENT_DOCKER_IMAGE", "")
t.Setenv("DIR_HOME", "/home/dev")
// Docker runtime emits docker binary and includes host-gateway alias.
cmd, args := containerCommandFor(RuntimeDocker, "core-dev", false, "codex", []string{"exec"}, "/ws", "/ws/.meta")
assert.Equal(t, "docker", cmd)
joined := strings.Join(args, " ")
assert.Contains(t, joined, "--add-host=host.docker.internal:host-gateway")
assert.Contains(t, joined, "core-dev")
}
func TestDispatchRuntime_ContainerCommandFor_Bad(t *testing.T) {
t.Setenv("AGENT_DOCKER_IMAGE", "")
t.Setenv("DIR_HOME", "/home/dev")
// Empty image resolves to the default rather than passing "" to docker.
cmd, args := containerCommandFor(RuntimeDocker, "", false, "codex", nil, "/ws", "/ws/.meta")
assert.Equal(t, "docker", cmd)
assert.Contains(t, args, defaultDockerImage)
}
func TestDispatchRuntime_ContainerCommandFor_Ugly(t *testing.T) {
t.Setenv("AGENT_DOCKER_IMAGE", "")
t.Setenv("DIR_HOME", "/home/dev")
// Apple runtime emits the `container` binary and SKIPS the host-gateway
// alias because Apple Containers don't support `--add-host=host-gateway`.
cmd, args := containerCommandFor(RuntimeApple, "core-dev", false, "codex", []string{"exec"}, "/ws", "/ws/.meta")
assert.Equal(t, "container", cmd)
joined := strings.Join(args, " ")
assert.NotContains(t, joined, "--add-host=host.docker.internal:host-gateway")
// Podman runtime emits the `podman` binary.
cmd2, _ := containerCommandFor(RuntimePodman, "core-dev", false, "codex", []string{"exec"}, "/ws", "/ws/.meta")
assert.Equal(t, "podman", cmd2)
// GPU passthrough on docker emits `--gpus=all`.
_, gpuArgs := containerCommandFor(RuntimeDocker, "core-dev", true, "codex", []string{"exec"}, "/ws", "/ws/.meta")
assert.Contains(t, strings.Join(gpuArgs, " "), "--gpus=all")
// GPU passthrough on apple emits `--gpu=metal` for Metal passthrough.
_, appleGPUArgs := containerCommandFor(RuntimeApple, "core-dev", true, "codex", []string{"exec"}, "/ws", "/ws/.meta")
assert.Contains(t, strings.Join(appleGPUArgs, " "), "--gpu=metal")
}
// --- dispatchRuntime / dispatchImage / dispatchGPU ---
func TestDispatchRuntime_DispatchRuntime_Good(t *testing.T) {
t.Setenv("CORE_AGENT_RUNTIME", "")
c := core.New()
c.Config().Set("agents.dispatch", DispatchConfig{Runtime: "podman"})
s := &PrepSubsystem{ServiceRuntime: core.NewServiceRuntime(c, AgentOptions{})}
assert.Equal(t, "podman", s.dispatchRuntime())
}
func TestDispatchRuntime_DispatchRuntime_Bad(t *testing.T) {
t.Setenv("CORE_AGENT_RUNTIME", "")
// Nil subsystem returns the auto default.
var s *PrepSubsystem
assert.Equal(t, RuntimeAuto, s.dispatchRuntime())
}
func TestDispatchRuntime_DispatchRuntime_Ugly(t *testing.T) {
// Env var override wins over configured runtime.
t.Setenv("CORE_AGENT_RUNTIME", "apple")
c := core.New()
c.Config().Set("agents.dispatch", DispatchConfig{Runtime: "podman"})
s := &PrepSubsystem{ServiceRuntime: core.NewServiceRuntime(c, AgentOptions{})}
assert.Equal(t, "apple", s.dispatchRuntime())
}
func TestDispatchRuntime_DispatchImage_Good(t *testing.T) {
t.Setenv("AGENT_DOCKER_IMAGE", "")
c := core.New()
c.Config().Set("agents.dispatch", DispatchConfig{Image: "core-ml"})
s := &PrepSubsystem{ServiceRuntime: core.NewServiceRuntime(c, AgentOptions{})}
assert.Equal(t, "core-ml", s.dispatchImage())
}
func TestDispatchRuntime_DispatchImage_Bad(t *testing.T) {
t.Setenv("AGENT_DOCKER_IMAGE", "")
// Nil subsystem falls back to the default image.
var s *PrepSubsystem
assert.Equal(t, defaultDockerImage, s.dispatchImage())
}
func TestDispatchRuntime_DispatchImage_Ugly(t *testing.T) {
// Env var override wins over configured image.
t.Setenv("AGENT_DOCKER_IMAGE", "ad-hoc-image")
c := core.New()
c.Config().Set("agents.dispatch", DispatchConfig{Image: "core-ml"})
s := &PrepSubsystem{ServiceRuntime: core.NewServiceRuntime(c, AgentOptions{})}
assert.Equal(t, "ad-hoc-image", s.dispatchImage())
}
func TestDispatchRuntime_DispatchGPU_Good(t *testing.T) {
c := core.New()
c.Config().Set("agents.dispatch", DispatchConfig{GPU: true})
s := &PrepSubsystem{ServiceRuntime: core.NewServiceRuntime(c, AgentOptions{})}
assert.True(t, s.dispatchGPU())
}
func TestDispatchRuntime_DispatchGPU_Bad(t *testing.T) {
// Nil subsystem returns false (GPU off by default).
var s *PrepSubsystem
assert.False(t, s.dispatchGPU())
}
func TestDispatchRuntime_DispatchGPU_Ugly(t *testing.T) {
// Missing dispatch config returns false instead of panicking.
c := core.New()
s := &PrepSubsystem{ServiceRuntime: core.NewServiceRuntime(c, AgentOptions{})}
assert.False(t, s.dispatchGPU())
}
// isDarwin checks the host operating system without importing runtime in the
// test file (the import happens in dispatch.go where it's needed for the real
// detection logic).
func isDarwin() bool {
return goosIsDarwin
}