新增 chat_summaries 迁移。数据库写失败会返回错误并标明仅本进程可见。test_manager 血缘改用文档版本,不再写死 1。 Co-authored-by: Cursor <cursoragent@cursor.com>
80 lines
2.6 KiB
Go
80 lines
2.6 KiB
Go
package ctxmgr
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
)
|
|
|
|
func TestSaveChatSummary_MemoryStoreCountsAsPersisted(t *testing.T) {
|
|
mgr := NewContextManager(nil, nil, DefaultTimeDecayConfig())
|
|
sum := &ChatSummary{SessionID: "sess_mem", Narrative: "仅内存", Facts: map[string]string{}, OpenQuestions: []string{}}
|
|
if err := mgr.SaveChatSummary(context.Background(), sum); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !sum.Persisted {
|
|
t.Fatal("nil pool is the configured store and must report persisted")
|
|
}
|
|
}
|
|
|
|
func TestSaveChatSummary_DatabaseFailureIsNotSuccess(t *testing.T) {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
defer cancel()
|
|
pool, err := pgxpool.New(ctx, "postgres://summary:summary@127.0.0.1:1/none?sslmode=disable&connect_timeout=1")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Cleanup(pool.Close)
|
|
|
|
mgr := NewContextManager(pool, nil, DefaultTimeDecayConfig())
|
|
sum := &ChatSummary{
|
|
SessionID: "sess_db_down", Narrative: "不应伪装成功",
|
|
Facts: map[string]string{}, OpenQuestions: []string{},
|
|
}
|
|
err = mgr.SaveChatSummary(ctx, sum)
|
|
if err == nil {
|
|
t.Fatal("database write failure must be returned")
|
|
}
|
|
if sum.Persisted {
|
|
t.Fatal("failed write must not be marked persisted")
|
|
}
|
|
if !strings.Contains(sum.FreshnessNote, summaryNotDurableNote) {
|
|
t.Fatalf("freshness note = %q", sum.FreshnessNote)
|
|
}
|
|
got, getErr := mgr.GetChatSummary(context.Background(), sum.SessionID)
|
|
if getErr != nil || got == nil {
|
|
t.Fatalf("current process should still serve the summary, err=%v", getErr)
|
|
}
|
|
if got.Persisted || !strings.Contains(got.FreshnessNote, summaryNotDurableNote) {
|
|
t.Fatalf("served fallback must stay non-durable: %+v", got)
|
|
}
|
|
}
|
|
|
|
func TestGenerateRollingSummary_RecordsRevisionAndMessageSpan(t *testing.T) {
|
|
mgr := NewContextManager(nil, nil, DefaultTimeDecayConfig())
|
|
ctx := context.Background()
|
|
first := []ChatMessageRecord{{
|
|
ID: 10, Role: "user", Content: "临床评价路径该怎么走?", CreatedAt: time.Now(),
|
|
}}
|
|
sum, err := mgr.GenerateRollingSummary(ctx, "sess_rev", nil, first)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !sum.Persisted || sum.Revision != 1 || sum.FromMessageID != 10 || sum.ToMessageID != 10 || sum.ProtocolVersion != "deterministic-v1" {
|
|
t.Fatalf("first summary = %+v", sum)
|
|
}
|
|
second := []ChatMessageRecord{{
|
|
ID: 11, Role: "user", Content: "预算大约在200万左右", CreatedAt: time.Now(),
|
|
}}
|
|
next, err := mgr.GenerateRollingSummary(ctx, "sess_rev", sum, second)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if next.Revision != 2 || next.PreviousRevision != 1 || next.FromMessageID != 11 || next.Facts["budget"] != "200万元" {
|
|
t.Fatalf("rolled summary = %+v", next)
|
|
}
|
|
}
|