返回 DeepSeek-Reasonix
synchronous_turn_context_test.go
根目录 / internal / control / synchronous_turn_context_test.go
1 package control
2
3 import (
4 "context"
5 "sync"
6 "testing"
7 "time"
8
9 "reasonix/internal/event"
10 "reasonix/internal/session"
11 )
12
13 type synchronousContextKey struct{}
14
15 func TestSynchronousTurnPreservesCallerContext(t *testing.T) {
16 c := newOwnedTestController(t, Options{Sink: event.Discard})
17 t.Cleanup(c.Close)
18 deadline := time.Now().Add(time.Minute).Round(0)
19 parent, cancel := context.WithDeadline(context.WithValue(t.Context(), synchronousContextKey{}, "caller-value"), deadline)
20 defer cancel()
21
22 err := c.runSynchronousTurn(parent, nil, func(ctx context.Context) error {
23 if got := ctx.Value(synchronousContextKey{}); got != "caller-value" {
24 t.Fatalf("caller context value = %v, want caller-value", got)
25 }
26 gotDeadline, ok := ctx.Deadline()
27 if !ok || !gotDeadline.Equal(deadline) {
28 t.Fatalf("caller deadline = %v, %v; want %v, true", gotDeadline, ok, deadline)
29 }
30 return nil
31 })
32 if err != nil {
33 t.Fatal(err)
34 }
35 }
36
37 func TestSynchronousCloseKeepsExecutionBoundUntilTerminalCommit(t *testing.T) {
38 entered := make(chan struct{}, 1)
39 release := make(chan struct{})
40 c, service, runtime := exclusiveTestController(t, holdFinishingWindow(release, entered, nil))
41 done := make(chan error, 1)
42 finished := make(chan struct{})
43 releaseTerminal := sync.OnceFunc(func() { close(release) })
44 t.Cleanup(func() {
45 releaseTerminal()
46 <-finished
47 })
48 go func() {
49 defer close(finished)
50 done <- c.runSynchronousTurn(t.Context(), nil, func(context.Context) error { return nil })
51 }()
52 select {
53 case <-entered:
54 case <-t.Context().Done():
55 t.Fatal("synchronous terminal publication did not start")
56 }
57 c.Close()
58 if phase := runtime.StateSnapshot().Phase; phase != session.RuntimeFinalizing {
59 t.Fatalf("runtime phase during terminal barrier = %s, want finalizing", phase)
60 }
61 if !runtime.OwnsExecution(c.ExecutionGeneration()) {
62 t.Fatal("close released synchronous execution owner before terminal commit")
63 }
64 if _, ok := service.Runtime(runtime.Ref()); !ok {
65 t.Fatal("close retired synchronous runtime before terminal commit")
66 }
67 releaseTerminal()
68 // The barrier proves execution ownership ordering. Real session teardown
69 // flushes and closes its writer; its speed is not a one-second contract.
70 select {
71 case err := <-done:
72 if err != nil {
73 t.Fatalf("synchronous turn: %v", err)
74 }
75 case <-t.Context().Done():
76 t.Fatal("synchronous turn did not finish")
77 }
78 if runtime.OwnsExecution(c.ExecutionGeneration()) {
79 t.Fatal("closed synchronous controller retained execution owner")
80 }
81 }
82
82 lines GO