返回 DeepSeek-Reasonix
lifecycle_cleanup_test.go
根目录 / internal / serve / lifecycle_cleanup_test.go
1 package serve
2
3 import (
4 "context"
5 "errors"
6 "testing"
7 "time"
8
9 "reasonix/internal/config"
10 "reasonix/internal/control"
11 "reasonix/internal/session"
12 )
13
14 // Close the host rather than its initial controller: resume and model changes
15 // can install a replacement that owns a different session writer.
16 func newLifecycleTestServer(t *testing.T, ctrl control.SessionAPI, bc *Broadcaster, cfg config.ServeConfig) *Server {
17 t.Helper()
18 server := New(ctrl, bc, cfg)
19 t.Cleanup(func() {
20 var service *session.Service
21 var runtime *session.Runtime
22 if owner, ok := server.ctl().(interface {
23 SessionBinding() (*session.Service, *session.Runtime, bool)
24 }); ok {
25 service, runtime, _ = owner.SessionBinding()
26 }
27 server.Close()
28 if service == nil || runtime == nil {
29 return
30 }
31 // The controller releases its client binding synchronously; the host
32 // retires the idle runtime on a TTL. Force it so a leaked binding
33 // (ErrRuntimeBound) still fails while normal closes settle at once.
34 deadline := time.Now().Add(5 * time.Second)
35 for time.Now().Before(deadline) {
36 err := service.Close(context.Background(), runtime.Ref())
37 if err == nil || errors.Is(err, session.ErrSessionNotRunning) {
38 return
39 }
40 if !errors.Is(err, session.ErrRuntimeBound) && !errors.Is(err, session.ErrRuntimeBusy) {
41 t.Errorf("server session writer did not release after close: %v", err)
42 return
43 }
44 time.Sleep(time.Millisecond)
45 }
46 t.Error("server session writer did not retire after close")
47 })
48 return server
49 }
50
50 lines GO