package aitools import ( "context" "os" "path/filepath" "strings" "testing" ) func TestSaveLoadPolicyRoundTrip(t *testing.T) { dir := t.TempDir() t.Setenv("HOME", dir) // PolicyPath uses UserHomeDir → ~/.opsxdb/mcp.json p := Policy{ AllowedConnectionIDs: []string{" a ", "b", "a", ""}, Mode: "READ_WRITE", AllowDangerous: true, DefaultLimit: 50, MaxLimit: 200, } if err := SavePolicy(p); err != nil { t.Fatal(err) } path := filepath.Join(dir, ".opsxdb", "mcp.json") if _, err := os.Stat(path); err != nil { t.Fatal(err) } got, err := LoadPolicy() if err != nil { t.Fatal(err) } if got.Mode != ModeReadWrite { t.Fatalf("mode=%s", got.Mode) } if !got.AllowDangerous { t.Fatal("want allow_dangerous") } if len(got.AllowedConnectionIDs) != 2 || got.AllowedConnectionIDs[0] != "a" || got.AllowedConnectionIDs[1] != "b" { t.Fatalf("ids=%v", got.AllowedConnectionIDs) } if got.DefaultLimit != 50 || got.MaxLimit != 200 { t.Fatalf("limits %d/%d", got.DefaultLimit, got.MaxLimit) } } func TestDangerousSQLRequiresAllowFlag(t *testing.T) { rt := NewRuntime(Policy{ AllowedConnectionIDs: []string{"c1"}, Mode: ModeReadWrite, AllowDangerous: false, }) rt.FindConn = func(id string) (*SavedConnection, error) { return &SavedConnection{ID: id, Name: "c1", Driver: "mysql", Host: "127.0.0.1", Port: 3306}, nil } rt.Audit = func(AuditEntry) {} rt.AllowConfirmedWrite = true _, err := rt.Call(context.Background(), ToolExecuteQuery, map[string]any{ "connection_id": "c1", "sql": "DROP TABLE users", "confirm_danger": true, }) if err == nil || !contains(err.Error(), "dangerous sql disabled") { t.Fatalf("want dangerous disabled, got %v", err) } } func contains(s, sub string) bool { return strings.Contains(s, sub) }