返回 DeepSeek-Reasonix
turn_liveness_test.go
根目录 / internal / control / turn_liveness_test.go
1 package control
2
3 import (
4 "context"
5 "testing"
6 "time"
7
8 "reasonix/internal/event"
9 )
10
11 // A running turn that produces no events for the stall threshold gets exactly
12 // one warning per silent stretch; any progress re-arms it.
13 func TestStalledTurnWarnsOncePerSilence(t *testing.T) {
14 oldInterval, oldThreshold := midTurnSnapshotInterval.Load(), turnStallThreshold.Load()
15 midTurnSnapshotInterval.Store(int64(10 * time.Millisecond))
16 turnStallThreshold.Store(int64(80 * time.Millisecond))
17 t.Cleanup(func() {
18 midTurnSnapshotInterval.Store(oldInterval)
19 turnStallThreshold.Store(oldThreshold)
20 })
21
22 notices := make(chan event.Event, 8)
23 c := newOwnedTestController(t, Options{Sink: event.FuncSink(func(e event.Event) {
24 if e.Kind == event.Notice && e.Code == event.NoticeCodeTurnStalled {
25 notices <- e
26 }
27 })})
28 t.Cleanup(c.Close)
29
30 started := make(chan struct{})
31 c.runGuarded(func(ctx context.Context) error {
32 close(started)
33 <-ctx.Done()
34 return ctx.Err()
35 })
36 <-started
37
38 select {
39 case n := <-notices:
40 if n.Level != event.LevelWarn || n.Text == "" {
41 t.Fatalf("stall notice = %+v, want a warn-level explanation", n)
42 }
43 case <-time.After(5 * time.Second):
44 t.Fatal("silent running turn never produced a stall notice")
45 }
46 select {
47 case <-notices:
48 t.Fatal("stall notice repeated without any progress")
49 case <-time.After(300 * time.Millisecond):
50 }
51
52 c.sink.Emit(event.Event{Kind: event.Text, Text: "still working"})
53 select {
54 case <-notices:
55 case <-time.After(5 * time.Second):
56 t.Fatal("renewed silence after progress did not warn again")
57 }
58 c.Cancel()
59 }
60
61 func TestIdleControllerNeverWarnsAboutStalls(t *testing.T) {
62 notices := 0
63 c := newOwnedTestController(t, Options{Sink: event.FuncSink(func(e event.Event) {
64 if e.Kind == event.Notice && e.Code == event.NoticeCodeTurnStalled {
65 notices++
66 }
67 })})
68 t.Cleanup(c.Close)
69 c.liveness.reset(time.Now().Add(-time.Hour))
70 c.warnIfTurnStalled(time.Now())
71 if notices != 0 {
72 t.Fatalf("idle controller emitted %d stall notices", notices)
73 }
74 }
75
75 lines GO