package session import ( "os" "path/filepath" "strings" "testing" "git.gopher.ink/mirrors2/AutoZero/llm" ) // TestNewNameSkipsExisting:时间戳撞上已有文件时依次加 -2/-3,绝不指向别人的会话。 // 不依赖时钟(直接喂固定 ts),所以不会因跨过一秒而变哑。 func TestNewNameSkipsExisting(t *testing.T) { dir := t.TempDir() ts := "20260101-000000" if got := newName(dir, ts); got != filepath.Join(dir, ts+".jsonl") { t.Fatalf("干净目录里应直接用基础名,得到 %q", got) } writeFile(t, filepath.Join(dir, ts+".jsonl")) if got := newName(dir, ts); got != filepath.Join(dir, ts+"-2.jsonl") { t.Fatalf("基础名被占时应给 -2,得到 %q", got) } writeFile(t, filepath.Join(dir, ts+"-2.jsonl")) if got := newName(dir, ts); got != filepath.Join(dir, ts+"-3.jsonl") { t.Fatalf("前两个都被占时应给 -3,得到 %q", got) } } // TestNewDoesNotRecoverOldSession:连续两次新建必须拿到不同名字,第二份还是空的。 // 撞名的真实后果:/session new 后立刻发消息(文件写下内容),同一秒内再新建, // 前端拿 LoadOrCreate 打开同名文件,"新建"就变成了把旧会话整份恢复回来。 func TestNewDoesNotRecoverOldSession(t *testing.T) { t.Setenv("HOME", t.TempDir()) first, err := New() if err != nil { t.Fatalf("New: %v", err) } if err := first.Append(llm.Message{Role: llm.RoleUser, Content: "history"}); err != nil { t.Fatalf("append: %v", err) } second, err := New() if err != nil { t.Fatalf("New: %v", err) } if second.Path == first.Path { t.Fatalf("两次新建拿到同一个名字 %s", second.Path) } if len(second.Messages) != 0 { t.Fatalf("新会话应为空,得到 %d 条", len(second.Messages)) } if _, err := os.Stat(second.Path); !os.IsNotExist(err) { t.Fatalf("新会话文件不该在这一步出现(err=%v)", err) } // 经渠道/前端实际会走的路径再打开一次,仍然是空的 byName := strings.TrimSuffix(filepath.Base(second.Path), ".jsonl") again, err := LoadOrCreate(byName) if err != nil { t.Fatalf("LoadOrCreate: %v", err) } if len(again.Messages) != 0 { t.Fatalf("按名字打开新会话却拿到 %d 条消息", len(again.Messages)) } // 第一份的历史不受影响 reloaded, err := Load(first.Path) if err != nil { t.Fatalf("load: %v", err) } if len(reloaded.Messages) != 1 || reloaded.Messages[0].Content != "history" { t.Fatalf("旧会话被改动: %+v", reloaded.Messages) } } // TestNewNameSkipsUnwrittenIssued:两份新会话都还没落盘时也不能同名。 // 会话文件要到第一条消息才写出来,所以"盘上没有"不等于"没人用"。 func TestNewNameSkipsUnwrittenIssued(t *testing.T) { dir := t.TempDir() ts := "20260202-120000" first := newName(dir, ts) second := newName(dir, ts) if first == second { t.Fatalf("两次取名拿到同一个名字 %s(第一份还没落盘,Stat 看不见)", first) } if strings.TrimSuffix(filepath.Base(second), ".jsonl") != ts+"-2" { t.Fatalf("第二个名字 = %q,want %s-2.jsonl", second, ts) } // 已发出的名字不许被复用 if got := newName(dir, ts); got == first || got == second { t.Fatalf("复用了已发出的名字: %q", got) } } func writeFile(t *testing.T, path string) { t.Helper() if err := os.WriteFile(path, []byte("{}\n"), 0o644); err != nil { t.Fatalf("write %s: %v", path, err) } }