返回 DeepSeek-Reasonix
new_after_resume_test.go
根目录 / internal / serve / new_after_resume_test.go
1 package serve
2
3 import (
4 "bytes"
5 "encoding/json"
6 "net/http"
7 "net/http/httptest"
8 "path/filepath"
9 "testing"
10
11 "reasonix/internal/agent"
12 "reasonix/internal/config"
13 "reasonix/internal/control"
14 )
15
16 // TestNewSessionAfterResumeKeepsWritePath reproduces the field report: after
17 // an in-place /resume onto a listed session, POST /new must still rotate.
18 // Rebind's releaseLocked used to strip the controller's transition handler
19 // while Resume left the session authority-required, so the next /new failed
20 // with "bind new session: session write authority missing".
21 func TestNewSessionAfterResumeKeepsWritePath(t *testing.T) {
22 dir := t.TempDir()
23 aPath := filepath.Join(dir, "a.jsonl")
24 bPath := filepath.Join(dir, "b.jsonl")
25 saveServeTestSession(t, aPath)
26 saveServeTestSession(t, bPath)
27
28 bc := NewBroadcaster()
29 exec := agent.New(nil, nil, agent.NewSession("sys"), agent.Options{}, bc)
30 ctrl := control.New(control.Options{Executor: exec, Sink: bc, SessionDir: dir, SessionPath: aPath})
31 t.Cleanup(ctrl.Close)
32 server := New(ctrl, bc, config.ServeConfig{})
33 leases := control.NewSessionLeaseKeeper()
34 defer leases.Release()
35 if err := leases.Rebind(aPath); err != nil {
36 t.Fatal(err)
37 }
38 if err := server.SetSessionLeases(leases); err != nil {
39 t.Fatal(err)
40 }
41 srv := httptest.NewServer(server.Handler())
42 defer srv.Close()
43
44 resumeBody, _ := json.Marshal(map[string]string{"path": bPath})
45 resp, err := http.Post(srv.URL+"/resume", "application/json", bytes.NewReader(resumeBody))
46 if err != nil {
47 t.Fatal(err)
48 }
49 resumeRespBody, _ := readAll(resp)
50 if resp.StatusCode != http.StatusNoContent {
51 t.Fatalf("/resume status = %d body %q, want 204", resp.StatusCode, resumeRespBody)
52 }
53
54 newResp, err := http.Post(srv.URL+"/new", "application/json", bytes.NewReader([]byte(`{}`)))
55 if err != nil {
56 t.Fatal(err)
57 }
58 newRespBody, _ := readAll(newResp)
59 if newResp.StatusCode != http.StatusNoContent {
60 t.Fatalf("/new after resume status = %d body %q, want 204", newResp.StatusCode, newRespBody)
61 }
62 }
63
63 lines GO