aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rwxr-xr-xtests/e2e.sh30
-rwxr-xr-xtests/fake-model.py11
-rwxr-xr-xtests/pi-live.sh25
3 files changed, 65 insertions, 1 deletions
diff --git a/tests/e2e.sh b/tests/e2e.sh
index 52367d2..d9b4381 100755
--- a/tests/e2e.sh
+++ b/tests/e2e.sh
@@ -1207,6 +1207,36 @@ expect "one sound, the finished one's" "cat $SOUNDS" done
expect "the menu lists it idle" "mb --print | grep -F 'can · c2' | cut -f1" "○ idle"
t kill-session -t can
+# --- 28. a failed run ---------------------------------------------------------
+echo "28. failed runs"
+error_report() { # pane error
+ python3 - "$HOOK" "$1" "$2" <<'PY'
+import json, socket, sys
+params = {"pane_id": sys.argv[2], "agent": "pi", "state": "idle", "error": sys.argv[3]}
+s = socket.socket(socket.AF_UNIX)
+s.connect(sys.argv[1])
+s.sendall((json.dumps({"method": "pane.report_agent", "params": params}) + "\n").encode())
+s.close()
+PY
+}
+t new-session -d -s fl -n f1 -c "$DIR" "$DIR/bin/pi"
+F1=$(t display -p -t fl:f1 '#{pane_id}')
+report "$F1" working ""
+expect "working" "opt $F1 @agent_state" working 50
+sleep 3.5; : >"$SOUNDS"; : >"$NOTES"
+error_report "$F1" "401: invalid x-api-key"
+expect "failed: done" "opt $F1 @agent_state" done 50
+expect "with why" "opt $F1 @dingger_error" "401: invalid x-api-key"
+expect "a 'failed' notification, with why" "grep -c '^pi failed|fl:f1 (pi): 401: invalid x-api-key$' $NOTES" 1 60
+expect "the 'needs attention' sound" "cat $SOUNDS" request
+expect "dingger status: failed, and why" "$DINGGER status | grep -F 'fl · f1' | grep -oE '^failed .* · 401: invalid x-api-key$' | wc -l | tr -d ' '" 1
+report "$F1" working ""
+expect "a new run: the failure goes" "opt $F1 @dingger_error" "" 50
+report "$F1" idle ""
+expect "finished: done" "opt $F1 @agent_state" done 50
+expect "with no failure" "opt $F1 @dingger_error" ""
+t kill-session -t fl
+
# Every daemon this run started must stop with it.
kill "$DAEMON_PID" "$DAEMON2_PID" 2>/dev/null
expect "the test daemons stop" "ps -o pid= -p $DAEMON_PID,$DAEMON2_PID | wc -l | tr -d ' '" 0
diff --git a/tests/fake-model.py b/tests/fake-model.py
index a02b98c..98a61db 100755
--- a/tests/fake-model.py
+++ b/tests/fake-model.py
@@ -1,7 +1,8 @@
#!/usr/bin/env python3
"""A fake OpenAI-compatible model for tests/pi-live.sh: streams a short reply
to /v1/chat/completions, after a delay taken from the last user message
-("slow 3" waits 3 seconds). Prints its port, then serves until killed."""
+("slow 3" waits 3 seconds), or fails as a provider does ("fail 401": an
+authentication error). Prints its port, then serves until killed."""
import json
import re
import sys
@@ -34,6 +35,14 @@ class Handler(BaseHTTPRequestHandler):
text = last_user_text(body)
match = re.search(r"slow (\d+(?:\.\d+)?)", text)
time.sleep(float(match.group(1)) if match else 0.2)
+ failure = re.search(r"fail (\d{3})", text)
+ if failure:
+ error = json.dumps({"type": "error", "error": {"type": "authentication_error", "message": "invalid x-api-key"}})
+ self.send_response(int(failure.group(1)))
+ self.send_header("Content-Type", "application/json")
+ self.end_headers()
+ self.wfile.write(error.encode())
+ return
self.send_response(200)
self.send_header("Content-Type", "text/event-stream")
self.send_header("Cache-Control", "no-cache")
diff --git a/tests/pi-live.sh b/tests/pi-live.sh
index 53115ec..04ef04a 100755
--- a/tests/pi-live.sh
+++ b/tests/pi-live.sh
@@ -277,6 +277,31 @@ same_cost() { python3 -c "import sys; a,b=sys.argv[1:]; print('same' if a and b
expect "cost: compaction counted, as pi's footer counts" same_cost same 30
t kill-window -t main:ctx
+# A failed run (the provider refuses the key): done, and why.
+t new-window -d -t main: -n fail -c "$D/work3"
+t send-keys -t main:fail "pi $NO_MCP" Enter
+expect "failures: an agent of its own" "st fail" idle 150
+type_line fail "fail 401 now"
+expect "a failed run: done" "st fail" done 80
+expect "with why, as one readable line" "t show -pv -t main:fail @dingger_error 2>/dev/null" "401: invalid x-api-key" 30
+expect "the menu says it failed" "\"$MENU\" --print | grep -F 'main · fail' | cut -f3 | grep -oE 'failed [^·]*· 401: invalid x-api-key'" "failed now · 401: invalid x-api-key"
+t set -p -t main:fail @dingger_ack 1; "$DINGGER" poke
+expect "seen: plain idle" "st fail" idle 50
+expect "and the failure is no longer shown" "t show -pv -t main:fail @dingger_error 2>/dev/null" "" 30
+type_line fail "fail 401 again"
+expect "failed again" "t show -pv -t main:fail @dingger_error 2>/dev/null" "401: invalid x-api-key" 80
+# A run cancelled after a failure is not a failure.
+type_line fail "slow 8 cancel me"
+expect "a new run: working" "st fail" working 50
+expect "the failure goes with it" "t show -pv -t main:fail @dingger_error 2>/dev/null" "" 30
+t send-keys -t main:fail Escape
+expect "cancelled: idle" "st fail" idle 50
+expect "with no failure" "t show -pv -t main:fail @dingger_error 2>/dev/null" ""
+type_line fail "slow 1 fine"
+expect "a run that works: done" "st fail" done 80
+expect "with no failure" "t show -pv -t main:fail @dingger_error 2>/dev/null" ""
+t kill-window -t main:fail
+
echo "2. screen detection (pi without the extension)"
t send-keys -t main:plain "PI_CODING_AGENT_DIR=$D/agent-plain pi $NO_MCP" Enter
expect "identified as pi" "t show -pv -t main:plain @agent 2>/dev/null" pi 150