- 只翻注释/文档字符串:剥离注释后代码行逐字节不变(机械校验只剩 4 条行尾注释的翻译,代码前缀全等) - 交叉引用(design/16 §4.6、D4/B3、0010 迁移文件名)逐字保留 - 保留未译技术词:DDL/rowid/LIKE/LEFT JOIN/DTO/rune/WS/actor 及全部标识符与表名 - 顺带副作用:store.go、session_persona_test.go 由注释文字改变而变得 gofmt 干净(未运行 gofmt -w)
133 lines
4.6 KiB
Go
133 lines
4.6 KiB
Go
package history
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// sessionOf 从 ListSessions 里返回某个会话的 SessionMeta,会话缺失时使测试失败。
|
|
func sessionOf(t *testing.T, st *Store, id string) SessionMeta {
|
|
t.Helper()
|
|
sessions, err := st.ListSessions(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("list sessions: %v", err)
|
|
}
|
|
for _, m := range sessions {
|
|
if m.ID == id {
|
|
return m
|
|
}
|
|
}
|
|
t.Fatalf("session %q not found in %+v", id, sessions)
|
|
return SessionMeta{}
|
|
}
|
|
|
|
func TestListSessionsLastMessagePreview(t *testing.T) {
|
|
t.Parallel()
|
|
st := newStore(t)
|
|
ctx := context.Background()
|
|
|
|
// 空的主会话没有预览。
|
|
if got := sessionOf(t, st, MainSessionID); got.LastMessage != nil {
|
|
t.Fatalf("empty main LastMessage = %+v, want nil", got.LastMessage)
|
|
}
|
|
|
|
sub, err := st.NewSubSession(ctx, "owner")
|
|
if err != nil {
|
|
t.Fatalf("new sub: %v", err)
|
|
}
|
|
if err := st.Append(ctx, Message{SessionID: MainSessionID, Role: RoleUser, Content: "first", CreatedAt: 1000}); err != nil {
|
|
t.Fatalf("append main user: %v", err)
|
|
}
|
|
if err := st.Append(ctx, Message{SessionID: MainSessionID, Role: RoleAssistant, Content: "latest reply", CreatedAt: 2000}); err != nil {
|
|
t.Fatalf("append main assistant: %v", err)
|
|
}
|
|
if err := st.Append(ctx, Message{SessionID: sub, Role: RoleUser, Content: "sub question", CreatedAt: 1500}); err != nil {
|
|
t.Fatalf("append sub: %v", err)
|
|
}
|
|
|
|
// 主会话仍在最前,携带它最新的消息,而不是第一条。
|
|
sessions, err := st.ListSessions(ctx)
|
|
if err != nil {
|
|
t.Fatalf("list sessions: %v", err)
|
|
}
|
|
if len(sessions) != 2 || sessions[0].ID != MainSessionID {
|
|
t.Fatalf("sessions = %+v, want main first", sessions)
|
|
}
|
|
main := sessions[0].LastMessage
|
|
if main == nil || main.Role != RoleAssistant || main.Content != "latest reply" || main.CreatedAt != 2000 {
|
|
t.Fatalf("main LastMessage = %+v, want assistant/latest reply/2000", main)
|
|
}
|
|
subPreview := sessions[1].LastMessage
|
|
if subPreview == nil || subPreview.Role != RoleUser || subPreview.Content != "sub question" || subPreview.CreatedAt != 1500 {
|
|
t.Fatalf("sub LastMessage = %+v, want user/sub question/1500", subPreview)
|
|
}
|
|
|
|
// 在主会话之后创建、但从未写入的子会话没有预览。
|
|
empty, err := st.NewSubSession(ctx, "owner")
|
|
if err != nil {
|
|
t.Fatalf("new empty sub: %v", err)
|
|
}
|
|
if got := sessionOf(t, st, empty); got.LastMessage != nil {
|
|
t.Fatalf("empty sub LastMessage = %+v, want nil", got.LastMessage)
|
|
}
|
|
}
|
|
|
|
func TestListSessionsLastMessageTruncatesAndCollapses(t *testing.T) {
|
|
t.Parallel()
|
|
st := newStore(t)
|
|
ctx := context.Background()
|
|
|
|
long := strings.Repeat("字", lastMessagePreviewRunes+10) + "\n\n尾部"
|
|
if err := st.Append(ctx, Message{SessionID: MainSessionID, Role: RoleUser, Content: long, CreatedAt: 1000}); err != nil {
|
|
t.Fatalf("append long: %v", err)
|
|
}
|
|
want := strings.Repeat("字", lastMessagePreviewRunes) + "…"
|
|
if got := sessionOf(t, st, MainSessionID).LastMessage; got == nil || got.Content != want {
|
|
t.Fatalf("truncated preview = %+v, want %q", got, want)
|
|
}
|
|
|
|
// 连续空白(含换行)折叠为单个空格,短消息原样返回。
|
|
sub, err := st.NewSubSession(ctx, "owner")
|
|
if err != nil {
|
|
t.Fatalf("new sub: %v", err)
|
|
}
|
|
if err := st.Append(ctx, Message{SessionID: sub, Role: RoleUser, Content: " 你好\n\t世界 ", CreatedAt: 1000}); err != nil {
|
|
t.Fatalf("append spaced: %v", err)
|
|
}
|
|
if got := sessionOf(t, st, sub).LastMessage; got == nil || got.Content != "你好 世界" {
|
|
t.Fatalf("collapsed preview = %+v, want %q", got, "你好 世界")
|
|
}
|
|
}
|
|
|
|
func TestListSessionsLastMessageTieBreaksByInsertion(t *testing.T) {
|
|
t.Parallel()
|
|
st := newStore(t)
|
|
ctx := context.Background()
|
|
|
|
// 两条消息共享同一毫秒时间戳:后插入的是最新的。
|
|
for _, content := range []string{"older", "newer"} {
|
|
if err := st.Append(ctx, Message{SessionID: MainSessionID, Role: RoleAssistant, Content: content, CreatedAt: 5000}); err != nil {
|
|
t.Fatalf("append %s: %v", content, err)
|
|
}
|
|
}
|
|
if got := sessionOf(t, st, MainSessionID).LastMessage; got == nil || got.Content != "newer" {
|
|
t.Fatalf("tie-break preview = %+v, want newer", got)
|
|
}
|
|
}
|
|
|
|
func TestPreviewContentBounds(t *testing.T) {
|
|
t.Parallel()
|
|
if got := previewContent(""); got != "" {
|
|
t.Fatalf("empty preview = %q, want empty", got)
|
|
}
|
|
exact := strings.Repeat("a", lastMessagePreviewRunes)
|
|
if got := previewContent(exact); got != exact {
|
|
t.Fatalf("exact-length preview changed: %q", got)
|
|
}
|
|
over := strings.Repeat("a", lastMessagePreviewRunes+1)
|
|
if got := previewContent(over); got != exact+"…" {
|
|
t.Fatalf("over-length preview = %q, want ellipsis", got)
|
|
}
|
|
}
|