Files
Agent-System-Backend/pkg/extension/hostoptions_test.go
T
weichenandCursor 4c9743ae42 Let compiled plugins prepare startup after host defaults merge
Why: RDM's sandbox policy must run after HostOptions are merged and be able to refuse startup when bwrap is missing.
Evidence: go test ./pkg/extension/ ./cmd/agent-system/ -count=1 passed on this tree (SELF).
Impact: InProc.Prepare and PrepareCompiled; serve applies plugin rewrites before app.Run.
Refs: feature/svc-plugin-host-options
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 15:15:16 +00:00

112 lines
2.8 KiB
Go

package extension
import (
"errors"
"flag"
"testing"
)
func TestMergeHostOptionsORAndExecConflict(t *testing.T) {
ResetCompiled()
t.Cleanup(ResetCompiled)
RegisterCompiled(InProc{
ID: "a",
HostOptions: func() Options {
return Options{DisableUploadIndexing: true, ExecBackend: "sandbox"}
},
})
RegisterCompiled(InProc{
ID: "b",
HostOptions: func() Options {
return Options{DisableExecTools: true, DisableConvCardMirror: true}
},
})
got, err := MergeHostOptions(Options{Addr: "127.0.0.1:1"})
if err != nil {
t.Fatal(err)
}
if !got.DisableUploadIndexing || !got.DisableExecTools || !got.DisableConvCardMirror {
t.Fatalf("bool merge: %+v", got)
}
if got.ExecBackend != "sandbox" || got.Addr != "127.0.0.1:1" {
t.Fatalf("kept caller addr and first exec backend: %+v", got)
}
RegisterCompiled(InProc{
ID: "c",
HostOptions: func() Options { return Options{ExecBackend: "direct"} },
})
if _, err := MergeHostOptions(Options{}); err == nil {
t.Fatal("expected exec backend conflict")
}
}
func TestPrepareCompiledCanRejectStartup(t *testing.T) {
ResetCompiled()
t.Cleanup(ResetCompiled)
RegisterCompiled(InProc{
ID: "rdm",
Prepare: func(opt *Options) error {
if opt.ExecBackend == "sandbox" {
return errors.New("no bwrap")
}
opt.DisableExecTools = true
return nil
},
})
opt := Options{ExecBackend: "sandbox"}
if err := PrepareCompiled(&opt); err == nil {
t.Fatal("expected prepare error")
}
opt.ExecBackend = "direct"
if err := PrepareCompiled(&opt); err != nil {
t.Fatal(err)
}
if !opt.DisableExecTools {
t.Fatal("prepare should be able to rewrite options")
}
}
func TestCLIHookHandlesBeforeServe(t *testing.T) {
ResetCompiled()
t.Cleanup(ResetCompiled)
var admin *string
RegisterCompiled(InProc{
ID: "rdm",
CLI: &CLIHook{
Register: func(fs *flag.FlagSet) {
admin = fs.String("bootstrap-admin", "", "owner")
},
AfterParse: func(opt Options) (bool, error) {
if admin == nil || *admin == "" {
return false, nil
}
if opt.DataDir == "" {
return true, errors.New("missing data")
}
return true, nil
},
},
})
fs := flag.NewFlagSet("serve", flag.ContinueOnError)
RegisterCLIFlags(fs)
if err := fs.Parse([]string{"-bootstrap-admin", "owner"}); err != nil {
t.Fatal(err)
}
if fs.Lookup("data") != nil {
t.Fatal("plugin must not redefine base flags")
}
handled, err := RunCLIHooks(Options{DataDir: "/tmp/data"})
if err != nil || !handled {
t.Fatalf("handled=%v err=%v", handled, err)
}
fs2 := flag.NewFlagSet("serve", flag.ContinueOnError)
RegisterCLIFlags(fs2)
if err := fs2.Parse(nil); err != nil {
t.Fatal(err)
}
handled, err = RunCLIHooks(Options{DataDir: "/tmp/data"})
if err != nil || handled {
t.Fatalf("empty flag should not handle: handled=%v err=%v", handled, err)
}
}