test(agent): satisfy goal concurrency lint
- commit
- 5e914f4feba01e31227f4edf5083235010eead28
- author
- brice · · 2026-08-09 21:22 UTC
- parent
- 8cf6b9a
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
1 file · +11 -1
M packages/agent/modes/goal_test.go +11 -1
| @@ -153,6 +153,7 @@ func TestReplacementGoalContinuesAfterStaleTurn(t *testing.T) { | |||
| 153 | 153 | ||
| 154 | 154 | func TestToolResultPersistenceRunsOutsideTUILock(t *testing.T) { | |
| 155 | 155 | var transitionMu sync.RWMutex | |
| 156 | + | transitionCompleted := false | |
| 156 | 157 | callbackStarted := make(chan struct{}) | |
| 157 | 158 | allowPersistence := make(chan struct{}) | |
| 158 | 159 | transitionHeld := make(chan struct{}) | |
| @@ -163,13 +164,18 @@ func TestToolResultPersistenceRunsOutsideTUILock(t *testing.T) { | |||
| 163 | 164 | close(callbackStarted) | |
| 164 | 165 | <-allowPersistence | |
| 165 | 166 | transitionMu.RLock() | |
| 167 | + | completed := transitionCompleted | |
| 166 | 168 | transitionMu.RUnlock() | |
| 169 | + | if !completed { | |
| 170 | + | return errors.New("session transition did not complete") | |
| 171 | + | } | |
| 167 | 172 | return nil | |
| 168 | 173 | } | |
| 169 | 174 | interactive := NewInteractive(InteractiveConfig{Agent: agent}) | |
| 175 | + | commitErr := make(chan error, 1) | |
| 170 | 176 | ||
| 171 | 177 | go func() { | |
| 172 | - | _ = agent.CommitToolResult("tool", core.ToolResult{}) | |
| 178 | + | commitErr <- agent.CommitToolResult("tool", core.ToolResult{}) | |
| 173 | 179 | interactive.handleEvent(core.EvToolResult{ID: "tool", Result: core.ToolResult{}}) | |
| 174 | 180 | close(handled) | |
| 175 | 181 | }() | |
| @@ -182,6 +188,7 @@ func TestToolResultPersistenceRunsOutsideTUILock(t *testing.T) { | |||
| 182 | 188 | transitionMu.Lock() | |
| 183 | 189 | close(transitionHeld) | |
| 184 | 190 | interactive.ApplySessionAgent(core.NewAgent(nil, "model", "system", goalToolRegistry()), "provider", "model") | |
| 191 | + | transitionCompleted = true | |
| 185 | 192 | transitionMu.Unlock() | |
| 186 | 193 | close(transitionDone) | |
| 187 | 194 | }() | |
| @@ -202,6 +209,9 @@ func TestToolResultPersistenceRunsOutsideTUILock(t *testing.T) { | |||
| 202 | 209 | case <-time.After(2 * time.Second): | |
| 203 | 210 | t.Fatal("tool-result callback did not finish") | |
| 204 | 211 | } | |
| 212 | + | if err := <-commitErr; err != nil { | |
| 213 | + | t.Fatalf("commit tool result: %v", err) | |
| 214 | + | } | |
| 205 | 215 | } | |
| 206 | 216 | ||
| 207 | 217 | func TestGoalBadgeUsesDurableStatusAfterPersistenceFailure(t *testing.T) { | |
| @@ -153,6 +153,7 @@ func TestReplacementGoalContinuesAfterStaleTurn(t *testing.T) { | |||||
| 153 | 153 | ||||
| 154 | func TestToolResultPersistenceRunsOutsideTUILock(t *testing.T) { | 154 | func TestToolResultPersistenceRunsOutsideTUILock(t *testing.T) { | ||
| 155 | var transitionMu sync.RWMutex | 155 | var transitionMu sync.RWMutex | ||
| 156 | + | transitionCompleted := false | |||
| 156 | callbackStarted := make(chan struct{}) | 157 | callbackStarted := make(chan struct{}) | ||
| 157 | allowPersistence := make(chan struct{}) | 158 | allowPersistence := make(chan struct{}) | ||
| 158 | transitionHeld := make(chan struct{}) | 159 | transitionHeld := make(chan struct{}) | ||
| @@ -163,13 +164,18 @@ func TestToolResultPersistenceRunsOutsideTUILock(t *testing.T) { | |||||
| 163 | close(callbackStarted) | 164 | close(callbackStarted) | ||
| 164 | <-allowPersistence | 165 | <-allowPersistence | ||
| 165 | transitionMu.RLock() | 166 | transitionMu.RLock() | ||
| 167 | + | completed := transitionCompleted | |||
| 166 | transitionMu.RUnlock() | 168 | transitionMu.RUnlock() | ||
| 169 | + | if !completed { | |||
| 170 | + | return errors.New("session transition did not complete") | |||
| 171 | + | } | |||
| 167 | return nil | 172 | return nil | ||
| 168 | } | 173 | } | ||
| 169 | interactive := NewInteractive(InteractiveConfig{Agent: agent}) | 174 | interactive := NewInteractive(InteractiveConfig{Agent: agent}) | ||
| 175 | + | commitErr := make(chan error, 1) | |||
| 170 | 176 | ||||
| 171 | go func() { | 177 | go func() { | ||
| 172 | - | _ = agent.CommitToolResult("tool", core.ToolResult{}) | 178 | + | commitErr <- agent.CommitToolResult("tool", core.ToolResult{}) |
| 173 | interactive.handleEvent(core.EvToolResult{ID: "tool", Result: core.ToolResult{}}) | 179 | interactive.handleEvent(core.EvToolResult{ID: "tool", Result: core.ToolResult{}}) | ||
| 174 | close(handled) | 180 | close(handled) | ||
| 175 | }() | 181 | }() | ||
| @@ -182,6 +188,7 @@ func TestToolResultPersistenceRunsOutsideTUILock(t *testing.T) { | |||||
| 182 | transitionMu.Lock() | 188 | transitionMu.Lock() | ||
| 183 | close(transitionHeld) | 189 | close(transitionHeld) | ||
| 184 | interactive.ApplySessionAgent(core.NewAgent(nil, "model", "system", goalToolRegistry()), "provider", "model") | 190 | interactive.ApplySessionAgent(core.NewAgent(nil, "model", "system", goalToolRegistry()), "provider", "model") | ||
| 191 | + | transitionCompleted = true | |||
| 185 | transitionMu.Unlock() | 192 | transitionMu.Unlock() | ||
| 186 | close(transitionDone) | 193 | close(transitionDone) | ||
| 187 | }() | 194 | }() | ||
| @@ -202,6 +209,9 @@ func TestToolResultPersistenceRunsOutsideTUILock(t *testing.T) { | |||||
| 202 | case <-time.After(2 * time.Second): | 209 | case <-time.After(2 * time.Second): | ||
| 203 | t.Fatal("tool-result callback did not finish") | 210 | t.Fatal("tool-result callback did not finish") | ||
| 204 | } | 211 | } | ||
| 212 | + | if err := <-commitErr; err != nil { | |||
| 213 | + | t.Fatalf("commit tool result: %v", err) | |||
| 214 | + | } | |||
| 205 | } | 215 | } | ||
| 206 | 216 | ||||
| 207 | func TestGoalBadgeUsesDurableStatusAfterPersistenceFailure(t *testing.T) { | 217 | func TestGoalBadgeUsesDurableStatusAfterPersistenceFailure(t *testing.T) { | ||