ollie/cmd/olliesrv/internal/agent/runtime_dispatch_test.go

145 lines
4.0 KiB
Go

package agent
import (
"encoding/json"
"strings"
"testing"
)
func TestInjectDispatchFlags(t *testing.T) {
schema := json.RawMessage(`{"type":"object","required":["cmd"],"properties":{"cmd":{"type":"string"}}}`)
result := injectDispatchFlags(schema)
var obj map[string]json.RawMessage
if err := json.Unmarshal(result, &obj); err != nil {
t.Fatalf("unmarshal result: %v", err)
}
var props map[string]json.RawMessage
if err := json.Unmarshal(obj["properties"], &props); err != nil {
t.Fatalf("unmarshal properties: %v", err)
}
// Original property preserved
if _, ok := props["cmd"]; !ok {
t.Error("original property 'cmd' missing")
}
// Dispatch flags injected
for _, flag := range []string{"bypass", "timeout", "sandbox", "background"} {
if _, ok := props[flag]; !ok {
t.Errorf("dispatch flag %q not injected", flag)
}
}
}
func TestInjectDispatchFlags_NoOverwrite(t *testing.T) {
// If a tool already declares "timeout", don't overwrite it
schema := json.RawMessage(`{"type":"object","properties":{"timeout":{"type":"string","description":"custom"}}}`)
result := injectDispatchFlags(schema)
var obj map[string]json.RawMessage
json.Unmarshal(result, &obj)
var props map[string]json.RawMessage
json.Unmarshal(obj["properties"], &props)
// timeout should keep original definition
var timeoutDef map[string]string
json.Unmarshal(props["timeout"], &timeoutDef)
if timeoutDef["description"] != "custom" {
t.Errorf("timeout was overwritten: got %q", timeoutDef["description"])
}
// Other flags should still be injected
if _, ok := props["bypass"]; !ok {
t.Error("bypass not injected")
}
}
func TestInjectDispatchFlags_EmptySchema(t *testing.T) {
// Empty or malformed schemas pass through unchanged
if got := injectDispatchFlags(nil); got != nil {
t.Errorf("nil schema: got %s", got)
}
if got := injectDispatchFlags(json.RawMessage(`{}`)); string(got) != `{}` {
t.Errorf("no properties: got %s", got)
}
}
func TestIsBackground(t *testing.T) {
tests := []struct {
name string
args string
want bool
}{
{"true bool", `{"cmd":"ls","background":true}`, true},
{"false bool", `{"cmd":"ls","background":false}`, false},
{"string true", `{"cmd":"ls","background":"true"}`, true},
{"string 1", `{"cmd":"ls","background":"1"}`, true},
{"absent", `{"cmd":"ls"}`, false},
{"empty", `{}`, false},
{"malformed", `not json`, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := isBackground(json.RawMessage(tt.args))
if got != tt.want {
t.Errorf("isBackground(%s) = %v, want %v", tt.args, got, tt.want)
}
})
}
}
func TestStripBackgroundFlag(t *testing.T) {
args := json.RawMessage(`{"cmd":"make test","background":true,"timeout":60}`)
got := stripBackgroundFlag(args)
var m map[string]json.RawMessage
if err := json.Unmarshal(got, &m); err != nil {
t.Fatalf("unmarshal: %v", err)
}
if _, ok := m["background"]; ok {
t.Error("background flag not stripped")
}
if _, ok := m["cmd"]; !ok {
t.Error("cmd was removed")
}
if _, ok := m["timeout"]; !ok {
t.Error("timeout was removed")
}
}
func TestExtractCmdDesc(t *testing.T) {
// Normal cmd
got := extractCmdDesc("shell", json.RawMessage(`{"cmd":"go test ./..."}`))
if got != "go test ./..." {
t.Errorf("got %q, want %q", got, "go test ./...")
}
// Long cmd gets truncated to 80 chars + "..."
longCmd := `{"cmd":"echo ` + strings.Repeat("a", 200) + `"}`
got = extractCmdDesc("shell", json.RawMessage(longCmd))
if len(got) != 83 { // 80 + "..."
t.Errorf("long cmd: got len %d, want 83", len(got))
}
if !strings.HasSuffix(got, "...") {
t.Errorf("long cmd should end with ..., got %q", got[len(got)-10:])
}
// No cmd field returns tool name
got = extractCmdDesc("file_edit", json.RawMessage(`{"path":"/a"}`))
if got != "file_edit" {
t.Errorf("got %q, want %q", got, "file_edit")
}
// Malformed JSON returns tool name
got = extractCmdDesc("shell", json.RawMessage(`bad`))
if got != "shell" {
t.Errorf("got %q, want %q", got, "shell")
}
}