106 lines
2.8 KiB
Go
106 lines
2.8 KiB
Go
package session
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"nub/internal/llm"
|
|
)
|
|
|
|
func textMsg(role llm.Role, text string) llm.Message {
|
|
return llm.Message{Role: role, Content: []llm.Block{{Kind: llm.KindText, Text: text}}}
|
|
}
|
|
|
|
func TestSession_PathToHead_OrdersRootToHead(t *testing.T) {
|
|
s := New("s1")
|
|
n1 := NewNode("", textMsg(llm.RoleUser, "one"), NodeMeta{})
|
|
must(t, s.Append(n1))
|
|
n2 := NewNode(n1.ID, textMsg(llm.RoleAssistant, "two"), NodeMeta{})
|
|
must(t, s.Append(n2))
|
|
n3 := NewNode(n2.ID, textMsg(llm.RoleUser, "three"), NodeMeta{})
|
|
must(t, s.Append(n3))
|
|
|
|
msgs := s.PathToHead()
|
|
if len(msgs) != 3 {
|
|
t.Fatalf("len = %d, want 3", len(msgs))
|
|
}
|
|
want := []string{"one", "two", "three"}
|
|
for i, w := range want {
|
|
if msgs[i].Content[0].Text != w {
|
|
t.Errorf("msgs[%d] = %q, want %q", i, msgs[i].Content[0].Text, w)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSession_PathToHead_StopsAtSummary(t *testing.T) {
|
|
s := New("s1")
|
|
n1 := NewNode("", textMsg(llm.RoleUser, "old-1"), NodeMeta{})
|
|
must(t, s.Append(n1))
|
|
n2 := NewNode(n1.ID, textMsg(llm.RoleAssistant, "old-2"), NodeMeta{})
|
|
must(t, s.Append(n2))
|
|
|
|
summary := &Node{
|
|
ID: "summary-1",
|
|
ParentID: n2.ID,
|
|
Kind: NodeSummary,
|
|
Message: textMsg(llm.RoleUser, "SUMMARY of old-1/old-2"),
|
|
Replaces: []string{n1.ID, n2.ID},
|
|
}
|
|
must(t, s.Append(summary))
|
|
|
|
n3 := NewNode(summary.ID, textMsg(llm.RoleUser, "new"), NodeMeta{})
|
|
must(t, s.Append(n3))
|
|
|
|
msgs := s.PathToHead()
|
|
if len(msgs) != 2 {
|
|
t.Fatalf("len = %d, want 2 (summary + new)", len(msgs))
|
|
}
|
|
if msgs[0].Content[0].Text != "SUMMARY of old-1/old-2" {
|
|
t.Errorf("msgs[0] = %q", msgs[0].Content[0].Text)
|
|
}
|
|
if msgs[1].Content[0].Text != "new" {
|
|
t.Errorf("msgs[1] = %q", msgs[1].Content[0].Text)
|
|
}
|
|
}
|
|
|
|
func TestSession_Branch_CreatesSecondPath(t *testing.T) {
|
|
s := New("s1")
|
|
n1 := NewNode("", textMsg(llm.RoleUser, "root"), NodeMeta{})
|
|
must(t, s.Append(n1))
|
|
n2a := NewNode(n1.ID, textMsg(llm.RoleAssistant, "branch-a"), NodeMeta{})
|
|
must(t, s.Append(n2a))
|
|
|
|
must(t, s.Branch(n1.ID))
|
|
n2b := NewNode(n1.ID, textMsg(llm.RoleAssistant, "branch-b"), NodeMeta{})
|
|
must(t, s.Append(n2b))
|
|
|
|
if s.Head != n2b.ID {
|
|
t.Fatalf("head = %s, want %s", s.Head, n2b.ID)
|
|
}
|
|
|
|
must(t, s.Branch(n2a.ID))
|
|
msgsA := s.PathToHead()
|
|
if msgsA[len(msgsA)-1].Content[0].Text != "branch-a" {
|
|
t.Errorf("branch a tip = %q", msgsA[len(msgsA)-1].Content[0].Text)
|
|
}
|
|
|
|
must(t, s.Branch(n2b.ID))
|
|
msgsB := s.PathToHead()
|
|
if msgsB[len(msgsB)-1].Content[0].Text != "branch-b" {
|
|
t.Errorf("branch b tip = %q", msgsB[len(msgsB)-1].Content[0].Text)
|
|
}
|
|
}
|
|
|
|
func TestSession_Append_RejectsUnknownParent(t *testing.T) {
|
|
s := New("s1")
|
|
n := NewNode("does-not-exist", textMsg(llm.RoleUser, "x"), NodeMeta{})
|
|
if err := s.Append(n); err == nil {
|
|
t.Fatal("expected error for unknown parent")
|
|
}
|
|
}
|
|
|
|
func must(t *testing.T, err error) {
|
|
t.Helper()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|