package main import ( "strings" "testing" ) func TestRunFailureKey_StableAcrossWhitespace(t *testing.T) { cases := []struct{ a, b string }{ {"chown :10000 /mnt/media_local && chmod 2775 /mnt/media_local", "chown :10000 /mnt/media_local && chmod 2775 /mnt/media_local"}, {"chown :10000 /mnt/media_local\n&& chmod 2775 /mnt/media_local", "chown :10000 /mnt/media_local && chmod 2775 /mnt/media_local"}, {"chown :10000 /mnt/media_local && chmod 2775 /mnt/media_local ", " chown :10000 /mnt/media_local && chmod 2775 /mnt/media_local"}, } for i, c := range cases { ka := runFailureKey("host:strong", c.a) kb := runFailureKey("host:strong", c.b) if ka != kb { t.Errorf("case %d: keys differ for whitespace-equivalent commands:\n a=%q\n b=%q", i, c.a, c.b) } } } func TestRunFailureKey_DiffersByTarget(t *testing.T) { a := runFailureKey("host:strong", "echo hi") b := runFailureKey("host:hubris", "echo hi") if a == b { t.Error("keys should differ when target differs") } } func TestRunFailureKey_DiffersByCommand(t *testing.T) { a := runFailureKey("host:strong", "echo hi") b := runFailureKey("host:strong", "echo bye") if a == b { t.Error("keys should differ when command differs") } } func TestRunRetryTracker_CountsAndCaps(t *testing.T) { r := newRunRetryTracker() key := runFailureKey("host:strong", "chown :10000 /mnt/media_local") for i := 1; i <= maxRunRetries; i++ { if got := r.recordFailure(key); got != i { t.Errorf("recordFailure #%d = %d, want %d", i, got, i) } } // At the cap, failures() should report maxRunRetries, and the next // identical call should be refused by the agent loop (failures() >= // maxRunRetries). if got := r.failures(key); got != maxRunRetries { t.Errorf("failures = %d, want %d", got, maxRunRetries) } if r.failures(key) < maxRunRetries { t.Errorf("cap should be enforced at maxRunRetries=%d", maxRunRetries) } } func TestRunRetryTracker_PerTurnIsolation(t *testing.T) { // Different keys don't interfere. r := newRunRetryTracker() k1 := runFailureKey("host:strong", "echo a") k2 := runFailureKey("host:strong", "echo b") r.recordFailure(k1) r.recordFailure(k1) if got := r.failures(k2); got != 0 { t.Errorf("k2 failures = %d, want 0 (keys are isolated)", got) } } func TestIsRunFailure(t *testing.T) { cases := []struct { desc string tool string result string callErr error want bool }{ {"run with ERROR prefix", "run", "run on host:strong: ERROR ssh: signal: killed", nil, true}, {"run with exit error", "run", "run on lxc:caddy: ERROR exit status 1", nil, true}, {"run success (read-only auto)", "run", "run on host:strong (read_only, auto): hello", nil, false}, {"run success (assent window)", "run", "run on host:strong (config_mutation, auto via assent window): done", nil, false}, {"run queued for approval", "run", "run on host:strong requires approval (risk: config_mutation) — execution 019f4930 queued. Present the command and purpose to the operator and wait; do not re-request.", nil, false}, {"non-run tool", "get_entity", "lxc list result", nil, false}, {"callErr set (dispatch failure)", "run", "", errFake{}, true}, {"callErr set on non-run tool", "get_entity", "some result", errFake{}, true}, // callErr trumps name } for i, c := range cases { got := isRunFailure(c.tool, c.result, c.callErr) if got != c.want { t.Errorf("case %d (%s): isRunFailure = %v, want %v", i, c.desc, got, c.want) } } } type errFake struct{} func (errFake) Error() string { return "fake dispatch error" } func TestRunRetryDirective_Content(t *testing.T) { d := runRetryDirective("host:strong", "chown :10000 /mnt/media_local", 3) for _, want := range []string{ "Refused:", "host:strong", "3 times", "retry cap hit", "Do NOT retry", "strace", "ps aux", "lsof", "surface the blocker", } { if !strings.Contains(d, want) { t.Errorf("directive missing %q; got:\n%s", want, d) } } } func TestItoa(t *testing.T) { cases := map[int]string{0: "0", 1: "1", 9: "9", 10: "10", 42: "42", 100: "100", -1: "-1", -42: "-42"} for in, want := range cases { if got := itoa(in); got != want { t.Errorf("itoa(%d) = %q, want %q", in, got, want) } } }