daemon: golang WS hub, REST, gitlab, docker spawner, sqlite (18/18 tests)

This commit is contained in:
Raphael Westphal
2026-08-18 13:42:34 +02:00
parent 7d5f866527
commit c62900e613
17 changed files with 3100 additions and 0 deletions
+135
View File
@@ -0,0 +1,135 @@
package main
// api_test.go — bearer auth 401s, events endpoint, spawn validation.
import (
"encoding/json"
"net/http"
"net/http/httptest"
"strings"
"testing"
)
func TestAPIAuthRejectsMissingOrBadToken(t *testing.T) {
ts, _ := newTestServer(t)
cases := []struct {
name string
header string
}{
{"none", ""},
{"wrong", "Bearer nope"},
{"not-bearer", testToken},
{"empty", "Bearer "},
}
for _, tc := range cases {
req, _ := http.NewRequest(http.MethodGet, ts.URL+"/api/sessions", nil)
if tc.header != "" {
req.Header.Set("Authorization", tc.header)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
t.Fatalf("%s: %v", tc.name, err)
}
resp.Body.Close()
if resp.StatusCode != http.StatusUnauthorized {
t.Fatalf("%s: status = %d, want 401", tc.name, resp.StatusCode)
}
}
}
func TestAPIEventsEndpointParams(t *testing.T) {
ts, _ := newTestServer(t)
get := func(path string) int {
req, _ := http.NewRequest(http.MethodGet, ts.URL+path, nil)
req.Header.Set("Authorization", "Bearer "+testToken)
resp, err := http.DefaultClient.Do(req)
if err != nil {
t.Fatalf("get %s: %v", path, err)
}
resp.Body.Close()
return resp.StatusCode
}
if code := get("/api/sessions/s1/events?after=abc"); code != http.StatusBadRequest {
t.Fatalf("after=abc → %d, want 400", code)
}
if code := get("/api/sessions/s1/events?limit=-1"); code != http.StatusBadRequest {
t.Fatalf("limit=-1 → %d, want 400", code)
}
if code := get("/api/sessions/unknown/events"); code != http.StatusOK {
t.Fatalf("unknown session → %d, want 200 with []", code)
}
}
func TestAPIEventsReplayShape(t *testing.T) {
ts, store := newTestServer(t)
// Simulate a connected session by writing directly through the store.
name := "sess"
if err := store.UpsertSession(SessionInfo{ID: "s1", Name: &name, Cwd: "/w", Model: "glm-5.3", Provider: "zai-renaud", StartedAt: 1}); err != nil {
t.Fatalf("upsert: %v", err)
}
if err := store.AppendEvent(Event{SessionID: "s1", Seq: 1, TS: 10, Type: evMessageEnd, Payload: []byte(`{"message":{"role":"user","id":"m1","text":"hi"}}`)}); err != nil {
t.Fatalf("append: %v", err)
}
req, _ := http.NewRequest(http.MethodGet, ts.URL+"/api/sessions/s1/events?after=0&limit=10", nil)
req.Header.Set("Authorization", "Bearer "+testToken)
resp, err := http.DefaultClient.Do(req)
if err != nil {
t.Fatalf("events: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
t.Fatalf("events status = %d", resp.StatusCode)
}
if ct := resp.Header.Get("Content-Type"); ct != "application/json" {
t.Fatalf("content-type = %q", ct)
}
var frames []map[string]any
if err := json.NewDecoder(resp.Body).Decode(&frames); err != nil {
t.Fatalf("decode: %v", err)
}
if len(frames) != 1 {
t.Fatalf("frames = %d, want 1", len(frames))
}
f := frames[0]
if f["type"] != evMessageEnd || f["sessionId"] != "s1" || f["seq"].(float64) != 1 || f["v"].(float64) != 1 {
t.Fatalf("frame = %v", f)
}
msg := f["message"].(map[string]any)
if msg["text"] != "hi" {
t.Fatalf("message = %v", msg)
}
}
func TestAPISpawnValidation(t *testing.T) {
ts, _ := newTestServer(t)
req, _ := http.NewRequest(http.MethodPost, ts.URL+"/api/spawn",
strings.NewReader(`{"repo":"no-slash"}`))
req.Header.Set("Authorization", "Bearer "+testToken)
resp, err := http.DefaultClient.Do(req)
if err != nil {
t.Fatalf("spawn: %v", err)
}
resp.Body.Close()
if resp.StatusCode != http.StatusBadRequest {
t.Fatalf("bad repo → %d, want 400", resp.StatusCode)
}
}
func TestAPIRecoverMiddleware(t *testing.T) {
// A handler that panics must yield 500, not kill the server.
handler := recoverMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
panic("boom")
}))
rec := httptest.NewRecorder()
handler.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/", nil))
if rec.Code != http.StatusInternalServerError {
t.Fatalf("panic → %d, want 500", rec.Code)
}
if !strings.Contains(rec.Body.String(), "error") {
t.Fatalf("body = %q", rec.Body.String())
}
}