返回 DeepSeek-Reasonix
host_stream_test.go
根目录 / internal / extension / host_stream_test.go
1 package extension
2
3 import (
4 "context"
5 "testing"
6 "time"
7 )
8
9 func TestHostStreamRegistryCancelGeneration(t *testing.T) {
10 r := NewHostStreamRegistry()
11 ctx, cancel := context.WithCancel(context.Background())
12 untrack := r.Track(5, cancel)
13 if r.Count(5) != 1 {
14 t.Fatalf("count = %d", r.Count(5))
15 }
16 r.CancelGeneration(5)
17 select {
18 case <-ctx.Done():
19 case <-time.After(time.Second):
20 t.Fatal("cancel not fired")
21 }
22 if r.Count(5) != 0 {
23 t.Fatal("expected cleared")
24 }
25 untrack() // idempotent
26 }
27
28 func TestHostStreamUntrack(t *testing.T) {
29 r := NewHostStreamRegistry()
30 _, cancel := context.WithCancel(context.Background())
31 untrack := r.Track(3, cancel)
32 untrack()
33 if r.Count(3) != 0 {
34 t.Fatal("untrack should remove")
35 }
36 r.CancelGeneration(3) // no-op
37 }
38
39 func TestHostStreamDrainHook(t *testing.T) {
40 g := NewPublishGate().WithDrainTTL(time.Millisecond)
41 r := NewHostStreamRegistry(g)
42 ctx, cancel := context.WithCancel(context.Background())
43 _ = r.Track(42, cancel)
44 // Simulate drain timeout path.
45 g.FireDrainCancels(42)
46 select {
47 case <-ctx.Done():
48 default:
49 t.Fatal("FireDrainCancels should cancel host stream")
50 }
51 }
52
53 func TestHostStreamTrackAfterExpiredGenerationCancelsImmediately(t *testing.T) {
54 g := NewPublishGate()
55 g.Publish(41)
56 g.Publish(42)
57 g.ForceExpireDrain(41)
58 r := NewHostStreamRegistry(g)
59 ctx, cancel := context.WithCancel(context.Background())
60 _ = r.Track(41, cancel)
61 select {
62 case <-ctx.Done():
63 default:
64 t.Fatal("stream registered after generation expiry must cancel immediately")
65 }
66 if got := r.Count(41); got != 0 {
67 t.Fatalf("expired generation retained %d streams", got)
68 }
69 }
70
70 lines GO