daemon: golang WS hub, REST, gitlab, docker spawner, sqlite (18/18 tests)
This commit is contained in:
@@ -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())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user