返回 DeepSeek-Reasonix
tabs_sink_context_test.go
根目录 / desktop / tabs_sink_context_test.go
1 package main
2
3 import (
4 "context"
5 "sync"
6 "testing"
7
8 "reasonix/internal/event"
9 )
10
11 // All tabEventSink context mutations go through the locked setContext /
12 // clearContext accessors (no bare s.ctx = ... writes that data-race the
13 // s.context() reads in emitRuntimeEvent). After clearContext the sink stops
14 // emitting — emitRuntimeEvent sees a nil ctx and no-ops — and the queued
15 // emitter is drained, so a detached/backgrounded session can't flush stale
16 // events onto the now-rebound tab (#5352: stale "AI 不断输出" on the visible
17 // session after rapid session switching).
18 func TestTabEventSinkClearContextStopsEmission(t *testing.T) {
19 var mu sync.Mutex
20 var emitted int
21 s := &tabEventSink{tabID: "t"}
22 s.runtimeEvents.emit = func(context.Context, string, ...interface{}) {
23 mu.Lock()
24 emitted++
25 mu.Unlock()
26 }
27
28 s.setContext(context.Background())
29 if s.context() == nil {
30 t.Fatal("setContext did not install the context")
31 }
32
33 s.clearContext()
34 if s.context() != nil {
35 t.Fatal("clearContext did not clear the context")
36 }
37
38 // An emit after clearContext must not reach the runtime bridge.
39 s.emitRuntimeEvent(eventChannel, toWireTab(event.Event{}, s.tabID))
40
41 mu.Lock()
42 defer mu.Unlock()
43 if emitted != 0 {
44 t.Fatalf("sink emitted %d events after clearContext, want 0", emitted)
45 }
46 }
47
47 lines GO