test(02-01): add failing tests for protocol types, registry, and label store
- TestRequestMarshal, TestResponseWithSessions - TestRegistryUpdate, TestRegistryWaitingSince, TestRegistryRemoveStale - TestLabelStoreSetGet, TestLabelStorePersistence, TestLabelStoreLoadMissing
This commit is contained in:
179
daemon_test.go
Normal file
179
daemon_test.go
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRegistryUpdate(t *testing.T) {
|
||||||
|
reg := NewRegistry()
|
||||||
|
|
||||||
|
info := SessionInfo{
|
||||||
|
PID: 1234,
|
||||||
|
SessionID: "sess-1",
|
||||||
|
Cwd: "/home/user/project",
|
||||||
|
State: "Working",
|
||||||
|
}
|
||||||
|
|
||||||
|
reg.Update(info)
|
||||||
|
|
||||||
|
list := reg.List()
|
||||||
|
if len(list) != 1 {
|
||||||
|
t.Fatalf("list len = %d, want 1", len(list))
|
||||||
|
}
|
||||||
|
if list[0].SessionID != "sess-1" {
|
||||||
|
t.Errorf("session_id = %q, want %q", list[0].SessionID, "sess-1")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRegistryWaitingSince(t *testing.T) {
|
||||||
|
reg := NewRegistry()
|
||||||
|
|
||||||
|
// Session starts Working
|
||||||
|
reg.Update(SessionInfo{
|
||||||
|
PID: 1234,
|
||||||
|
SessionID: "sess-1",
|
||||||
|
State: "Working",
|
||||||
|
})
|
||||||
|
|
||||||
|
list := reg.List()
|
||||||
|
if list[0].WaitingSince != nil {
|
||||||
|
t.Error("WaitingSince should be nil when Working")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Session transitions to NeedsInput
|
||||||
|
reg.Update(SessionInfo{
|
||||||
|
PID: 1234,
|
||||||
|
SessionID: "sess-1",
|
||||||
|
State: "Needs Input",
|
||||||
|
})
|
||||||
|
|
||||||
|
list = reg.List()
|
||||||
|
if list[0].WaitingSince == nil {
|
||||||
|
t.Fatal("WaitingSince should be set when NeedsInput")
|
||||||
|
}
|
||||||
|
|
||||||
|
waitStart := *list[0].WaitingSince
|
||||||
|
|
||||||
|
// Session goes back to Working -> WaitingSince reset
|
||||||
|
reg.Update(SessionInfo{
|
||||||
|
PID: 1234,
|
||||||
|
SessionID: "sess-1",
|
||||||
|
State: "Working",
|
||||||
|
})
|
||||||
|
|
||||||
|
list = reg.List()
|
||||||
|
if list[0].WaitingSince != nil {
|
||||||
|
t.Errorf("WaitingSince should be nil after returning to Working, got %v", list[0].WaitingSince)
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = waitStart
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRegistryRemoveStale(t *testing.T) {
|
||||||
|
reg := NewRegistry()
|
||||||
|
|
||||||
|
reg.Update(SessionInfo{SessionID: "sess-1", State: "Working"})
|
||||||
|
reg.Update(SessionInfo{SessionID: "sess-2", State: "Working"})
|
||||||
|
|
||||||
|
// Only sess-1 is still active
|
||||||
|
active := map[string]bool{"sess-1": true}
|
||||||
|
reg.RemoveStale(active)
|
||||||
|
|
||||||
|
list := reg.List()
|
||||||
|
if len(list) != 1 {
|
||||||
|
t.Fatalf("list len = %d, want 1", len(list))
|
||||||
|
}
|
||||||
|
if list[0].SessionID != "sess-1" {
|
||||||
|
t.Errorf("session_id = %q, want %q", list[0].SessionID, "sess-1")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLabelStoreSetGet(t *testing.T) {
|
||||||
|
dir := t.TempDir()
|
||||||
|
path := filepath.Join(dir, "labels.json")
|
||||||
|
|
||||||
|
ls, err := NewLabelStore(path)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("new: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ls.Set("sess-1", "review MR"); err != nil {
|
||||||
|
t.Fatalf("set: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
got := ls.Get("sess-1")
|
||||||
|
if got != "review MR" {
|
||||||
|
t.Errorf("get = %q, want %q", got, "review MR")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non-existent key returns empty
|
||||||
|
if got := ls.Get("unknown"); got != "" {
|
||||||
|
t.Errorf("get unknown = %q, want empty", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLabelStorePersistence(t *testing.T) {
|
||||||
|
dir := t.TempDir()
|
||||||
|
path := filepath.Join(dir, "labels.json")
|
||||||
|
|
||||||
|
ls, err := NewLabelStore(path)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("new: %v", err)
|
||||||
|
}
|
||||||
|
if err := ls.Set("sess-1", "review MR"); err != nil {
|
||||||
|
t.Fatalf("set: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new LabelStore from the same file
|
||||||
|
ls2, err := NewLabelStore(path)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("new2: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
got := ls2.Get("sess-1")
|
||||||
|
if got != "review MR" {
|
||||||
|
t.Errorf("persisted get = %q, want %q", got, "review MR")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLabelStoreLoadMissing(t *testing.T) {
|
||||||
|
dir := t.TempDir()
|
||||||
|
path := filepath.Join(dir, "nonexistent", "labels.json")
|
||||||
|
|
||||||
|
ls, err := NewLabelStore(path)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("should not error on missing file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if got := ls.Get("anything"); got != "" {
|
||||||
|
t.Errorf("get = %q, want empty", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRegistryUpdateTimestamp(t *testing.T) {
|
||||||
|
reg := NewRegistry()
|
||||||
|
|
||||||
|
before := time.Now()
|
||||||
|
reg.Update(SessionInfo{
|
||||||
|
SessionID: "sess-1",
|
||||||
|
State: "Needs Input",
|
||||||
|
})
|
||||||
|
after := time.Now()
|
||||||
|
|
||||||
|
list := reg.List()
|
||||||
|
if list[0].WaitingSince == nil {
|
||||||
|
t.Fatal("WaitingSince should be set")
|
||||||
|
}
|
||||||
|
ws := *list[0].WaitingSince
|
||||||
|
if ws.Before(before) || ws.After(after) {
|
||||||
|
t.Errorf("WaitingSince %v not between %v and %v", ws, before, after)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Placeholder to verify file exists
|
||||||
|
func init() {
|
||||||
|
_ = os.TempDir()
|
||||||
|
}
|
||||||
103
protocol_test.go
Normal file
103
protocol_test.go
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRequestMarshal(t *testing.T) {
|
||||||
|
req := Request{Action: "list"}
|
||||||
|
|
||||||
|
data, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("marshal: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var got Request
|
||||||
|
if err := json.Unmarshal(data, &got); err != nil {
|
||||||
|
t.Fatalf("unmarshal: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if got.Action != "list" {
|
||||||
|
t.Errorf("action = %q, want %q", got.Action, "list")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRequestMarshalWithArgs(t *testing.T) {
|
||||||
|
args, _ := json.Marshal(LabelArgs{SessionID: "abc", Label: "review MR"})
|
||||||
|
req := Request{Action: "label", Args: args}
|
||||||
|
|
||||||
|
data, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("marshal: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var got Request
|
||||||
|
if err := json.Unmarshal(data, &got); err != nil {
|
||||||
|
t.Fatalf("unmarshal: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if got.Action != "label" {
|
||||||
|
t.Errorf("action = %q, want %q", got.Action, "label")
|
||||||
|
}
|
||||||
|
|
||||||
|
var la LabelArgs
|
||||||
|
if err := json.Unmarshal(got.Args, &la); err != nil {
|
||||||
|
t.Fatalf("unmarshal args: %v", err)
|
||||||
|
}
|
||||||
|
if la.SessionID != "abc" || la.Label != "review MR" {
|
||||||
|
t.Errorf("args = %+v, want {abc, review MR}", la)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResponseWithSessions(t *testing.T) {
|
||||||
|
now := time.Now()
|
||||||
|
resp := Response{
|
||||||
|
OK: true,
|
||||||
|
Sessions: []SessionInfo{
|
||||||
|
{
|
||||||
|
PID: 1234,
|
||||||
|
SessionID: "sess-1",
|
||||||
|
Cwd: "/home/user/project",
|
||||||
|
GitBranch: "main",
|
||||||
|
State: "Working",
|
||||||
|
Preview: "Building...",
|
||||||
|
Workspace: "3",
|
||||||
|
Label: "feature-x",
|
||||||
|
WaitingSince: &now,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := json.Marshal(resp)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("marshal: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var got Response
|
||||||
|
if err := json.Unmarshal(data, &got); err != nil {
|
||||||
|
t.Fatalf("unmarshal: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !got.OK {
|
||||||
|
t.Error("ok = false, want true")
|
||||||
|
}
|
||||||
|
if len(got.Sessions) != 1 {
|
||||||
|
t.Fatalf("sessions len = %d, want 1", len(got.Sessions))
|
||||||
|
}
|
||||||
|
|
||||||
|
s := got.Sessions[0]
|
||||||
|
if s.PID != 1234 {
|
||||||
|
t.Errorf("pid = %d, want 1234", s.PID)
|
||||||
|
}
|
||||||
|
if s.Workspace != "3" {
|
||||||
|
t.Errorf("workspace = %q, want %q", s.Workspace, "3")
|
||||||
|
}
|
||||||
|
if s.Label != "feature-x" {
|
||||||
|
t.Errorf("label = %q, want %q", s.Label, "feature-x")
|
||||||
|
}
|
||||||
|
if s.WaitingSince == nil {
|
||||||
|
t.Error("waiting_since = nil, want non-nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user