返回 DeepSeek-Reasonix
probe_count_test.go
根目录 / internal / remote / bootstrap / probe_count_test.go
1 package bootstrap
2
3 import (
4 "context"
5 "os"
6 "strings"
7 "sync"
8 "testing"
9
10 "reasonix/internal/remote"
11 )
12
13 // probeCounts tallies EnsureServe's remote exec traffic by category. The
14 // Capability commands include their own liveness-shaped shell fragments, so
15 // classify them before the general process-liveness shape.
16 type probeCounts struct {
17 mu sync.Mutex
18 pidAlive int // kill -0 / ps -p pid liveness probes
19 capability int // readlink / serve --help capability probes
20 other int
21 }
22
23 func (c *probeCounts) record(cmd string) {
24 c.mu.Lock()
25 defer c.mu.Unlock()
26 switch {
27 case strings.Contains(cmd, "readlink"), strings.Contains(cmd, "serve --help"):
28 c.capability++
29 case strings.Contains(cmd, "kill -0"), strings.Contains(cmd, "ps -p"):
30 c.pidAlive++
31 default:
32 c.other++
33 }
34 }
35
36 func (c *probeCounts) snapshot() (pidAlive, capability, other int) {
37 c.mu.Lock()
38 defer c.mu.Unlock()
39 return c.pidAlive, c.capability, c.other
40 }
41
42 // TestEnsureServeReuseProbeCount pins the reuse path's exec budget:
43 // EnsureServe's retire and reuse decisions share ONE probe round — one
44 // liveness exec and one capability exec. More means the duplication crept
45 // back and every cold start pays it again.
46 func TestEnsureServeReuseProbeCount(t *testing.T) {
47 skipOnWindows(t)
48 root := t.TempDir()
49 paths := pathsFor(root, root)
50 if err := os.MkdirAll(paths.Dir, 0o755); err != nil {
51 t.Fatal(err)
52 }
53 st := ServeState{PID: 777, Addr: "127.0.0.1:5000", Workspace: root, TokenFile: paths.TokenFile}
54 data, _ := MarshalState(st)
55 if err := os.WriteFile(paths.StateJSON, data, 0o600); err != nil {
56 t.Fatal(err)
57 }
58 if err := os.WriteFile(paths.TokenFile, []byte("existing-token\n"), 0o600); err != nil {
59 t.Fatal(err)
60 }
61
62 var c probeCounts
63 conn := newFakeConn(t, root, func(cmd string) (remote.ExecResult, error) {
64 c.record(cmd)
65 switch {
66 case strings.Contains(cmd, "readlink"), strings.Contains(cmd, "serve --help"):
67 return ok("yes\n")
68 case strings.Contains(cmd, "kill -0 777"), strings.Contains(cmd, "ps -p 777"):
69 return ok("1\n") // alive
70 default:
71 return ok("")
72 }
73 })
74
75 res, err := EnsureServe(context.Background(), conn, Options{Workspace: "~"})
76 if err != nil {
77 t.Fatalf("EnsureServe: %v", err)
78 }
79 if !res.Reused {
80 t.Fatal("expected reuse of live process")
81 }
82 pidAlive, capability, other := c.snapshot()
83 if pidAlive != 1 || capability != 1 || other != 0 {
84 t.Fatalf("reuse-path exec budget regressed: pidAlive=%d capability=%d other=%d, want 1/1/0 (single shared probe round)", pidAlive, capability, other)
85 }
86 }
87
87 lines GO