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