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
+134
View File
@@ -0,0 +1,134 @@
package main
// store_test.go — persistence: events replay, sessions, settings, containers.
import (
"path/filepath"
"testing"
)
func openTestStore(t *testing.T) *Store {
t.Helper()
store, err := OpenStore(filepath.Join(t.TempDir(), "lvmh.db"))
if err != nil {
t.Fatalf("open store: %v", err)
}
t.Cleanup(func() { _ = store.Close() })
return store
}
func TestStoreEventPersistAndReplayAfterSeq(t *testing.T) {
store := openTestStore(t)
events := []Event{
{SessionID: "s1", Seq: 1, TS: 1000, Type: evMessageStart, Payload: []byte(`{"message":{"role":"user","id":"m1"}}`)},
{SessionID: "s1", Seq: 2, TS: 1001, Type: evMessageEnd, Payload: []byte(`{"message":{"role":"user","id":"m1"}}`)},
{SessionID: "s1", Seq: 3, TS: 1002, Type: evAgentSettled, Payload: []byte(`{}`)},
}
for _, e := range events {
if err := store.AppendEvent(e); err != nil {
t.Fatalf("append seq %d: %v", e.Seq, err)
}
}
if last, _ := store.LastSeq("s1"); last != 3 {
t.Fatalf("lastSeq = %d, want 3", last)
}
all, err := store.EventsAfter("s1", 0, 100)
if err != nil {
t.Fatalf("events after 0: %v", err)
}
if len(all) != 3 {
t.Fatalf("after=0 returned %d events, want 3", len(all))
}
for i, e := range all {
if e.Seq != int64(i+1) {
t.Fatalf("event %d has seq %d, want ascending from 1", i, e.Seq)
}
}
tail, err := store.EventsAfter("s1", 2, 100)
if err != nil {
t.Fatalf("events after 2: %v", err)
}
if len(tail) != 1 || tail[0].Seq != 3 {
t.Fatalf("after=2 returned %v, want only seq 3", tail)
}
limited, _ := store.EventsAfter("s1", 0, 2)
if len(limited) != 2 {
t.Fatalf("limit=2 returned %d events", len(limited))
}
// Duplicate (sessionId, seq) is ignored — replay idempotence.
if err := store.AppendEvent(events[0]); err != nil {
t.Fatalf("duplicate append: %v", err)
}
dup, _ := store.EventsAfter("s1", 0, 100)
if len(dup) != 3 {
t.Fatalf("duplicate append created extra row: %d", len(dup))
}
}
func TestStoreSessionsOnlineAndTouch(t *testing.T) {
store := openTestStore(t)
name := "my session"
info := SessionInfo{ID: "s1", Name: &name, Cwd: "/w", Model: "glm-5.3", Provider: "zai-renaud", Agent: true, Repo: nil, StartedAt: 42}
if err := store.UpsertSession(info); err != nil {
t.Fatalf("upsert: %v", err)
}
if err := store.TouchSession("s1", 7, 4242); err != nil {
t.Fatalf("touch: %v", err)
}
if err := store.TouchSession("s1", 3, 9999); err != nil { // lastSeq monotonic
t.Fatalf("touch lower: %v", err)
}
if err := store.SetOnline("s1", true); err != nil {
t.Fatalf("online: %v", err)
}
rows, err := store.Sessions()
if err != nil || len(rows) != 1 {
t.Fatalf("sessions: %v %d", err, len(rows))
}
row := rows[0]
if row.LastSeq != 7 || row.LastEventAt != 9999 || !row.OnlineDB {
t.Fatalf("row = %+v, want lastSeq 7, lastEventAt 9999, online", row)
}
if row.Info.Name == nil || *row.Info.Name != name {
t.Fatalf("name not roundtripped: %+v", row.Info)
}
if last, _ := store.LastSeq("nope"); last != 0 {
t.Fatalf("missing session lastSeq = %d, want 0", last)
}
}
func TestStoreSettingsAndContainers(t *testing.T) {
store := openTestStore(t)
if _, ok, _ := store.GetSetting(settingGitLabToken); ok {
t.Fatal("unset setting should not exist")
}
if err := store.SetSetting(settingGitLabToken, "pat"); err != nil {
t.Fatalf("set: %v", err)
}
if v, ok, _ := store.GetSetting(settingGitLabToken); !ok || v != "pat" {
t.Fatalf("get = %q %v", v, ok)
}
if err := store.DeleteSetting(settingGitLabToken); err != nil {
t.Fatalf("delete: %v", err)
}
if err := store.UpsertContainer("s1", "cid1", "group/proj"); err != nil {
t.Fatalf("upsert container: %v", err)
}
row, ok, err := store.GetContainer("s1")
if err != nil || !ok || row.ContainerID != "cid1" || row.Repo != "group/proj" {
t.Fatalf("get container = %+v %v %v", row, ok, err)
}
if err := store.DeleteContainer("s1"); err != nil {
t.Fatalf("delete container: %v", err)
}
if _, ok, _ := store.GetContainer("s1"); ok {
t.Fatal("container row should be gone")
}
}