Files
docker-agent/pkg/runtime/command_source_test.go
David Gageot 61c8529f08 refactor: narrow command resolution contracts
LookupCommand, ResolveCommand, and executeToolCommands now take the
minimal interface they need instead of the full Runtime, so tests
mock less surface.

Assisted-By: cagent
2026-10-09 14:48:35 +02:00

98 lines
3.0 KiB
Go

package runtime
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/docker/docker-agent/pkg/config/types"
"github.com/docker/docker-agent/pkg/tools"
)
type lookupOnlySource struct {
calls int
}
func (s *lookupOnlySource) CurrentAgentInfo(context.Context) CurrentAgentInfo {
s.calls++
return CurrentAgentInfo{Commands: types.Commands{"test": {Instruction: "instruction"}}}
}
func TestCommandLookupNeedsOnlyAgentInfo(t *testing.T) {
t.Parallel()
source := &lookupOnlySource{}
_, _, ok := LookupCommand(t.Context(), source, "ordinary message")
assert.False(t, ok)
assert.Zero(t, source.calls)
command, rest, ok := LookupCommand(t.Context(), source, "/test arguments")
assert.True(t, ok)
assert.Equal(t, "instruction", command.Instruction)
assert.Equal(t, "arguments", rest)
assert.Equal(t, 1, source.calls)
}
type recordingCommandSource struct {
commands types.Commands
calls []string
}
func (s *recordingCommandSource) CurrentAgentInfo(context.Context) CurrentAgentInfo {
s.calls = append(s.calls, "info")
return CurrentAgentInfo{Commands: s.commands}
}
func (s *recordingCommandSource) CurrentAgentTools(context.Context) ([]tools.Tool, error) {
s.calls = append(s.calls, "tools")
return []tools.Tool{{Name: "echo", Handler: func(context.Context, tools.ToolCall, tools.Runtime) (*tools.ToolCallResult, error) {
s.calls = append(s.calls, "handler")
return tools.ResultSuccess("${untrusted}"), nil
}}}, nil
}
func (s *recordingCommandSource) CommandEvaluatorFactory() CommandEvaluatorFactory {
s.calls = append(s.calls, "factory")
return func([]tools.Tool) CommandEvaluator {
return commandEvaluatorFunc(func(_ context.Context, instruction string, _ []string) string {
s.calls = append(s.calls, "evaluate")
return instruction
})
}
}
func TestCommandSourcePreservesLazyDiscovery(t *testing.T) {
t.Parallel()
source := &recordingCommandSource{commands: types.Commands{
"agent": {Agent: "worker"},
"test": {Instruction: "!echo()"},
}}
assert.Equal(t, "message", ResolveCommand(t.Context(), source, "message"))
assert.Empty(t, source.calls)
assert.Equal(t, "/unknown", ResolveCommand(t.Context(), source, "/unknown"))
assert.Equal(t, []string{"info"}, source.calls)
source.calls = nil
assert.Equal(t, "task", ResolveCommand(t.Context(), source, "/agent task"))
assert.Equal(t, []string{"info"}, source.calls)
source.calls = nil
assert.Equal(t, "${untrusted}", ResolveCommand(t.Context(), source, "/test"))
assert.Equal(t, []string{"info", "factory", "tools", "evaluate", "tools", "handler"}, source.calls)
}
type toolsOnlySource struct {
calls int
}
func (s *toolsOnlySource) CurrentAgentTools(context.Context) ([]tools.Tool, error) {
s.calls++
return nil, nil
}
func TestToolCommandsNeedOnlyTools(t *testing.T) {
t.Parallel()
source := &toolsOnlySource{}
assert.Equal(t, "ordinary text", executeToolCommands(t.Context(), source, "ordinary text"))
assert.Zero(t, source.calls)
assert.Contains(t, executeToolCommands(t.Context(), source, "!missing()"), "not found")
assert.Equal(t, 1, source.calls)
}