TestExecutorHandlerErrorPreservesStderr pins the contract that when a handler returns an error, the diagnostic stderr it captured before failing survives all the way to [Result.Stderr]. aggregate routes that field into the user-visible PreToolUse fail-closed message; if runHook ever drops it on the
(t *testing.T)
| 171 | // HandlerResult-embedding refactor) PreToolUse denials would lose |
| 172 | // their explanatory text. |
| 173 | func TestExecutorHandlerErrorPreservesStderr(t *testing.T) { |
| 174 | t.Parallel() |
| 175 | |
| 176 | const customType HookType = "errors-with-stderr" |
| 177 | const diagnostic = "BOOM: subprocess crashed at line 42" |
| 178 | |
| 179 | registry := NewRegistry() |
| 180 | registry.Register(customType, func(_ HandlerEnv, _ Hook) (Handler, error) { |
| 181 | return handlerFunc(func(context.Context, []byte) (HandlerResult, error) { |
| 182 | // Mirrors what commandHandler does on a spawn failure: it |
| 183 | // captured stderr, then surfaces an exec-level error. |
| 184 | return HandlerResult{Stderr: diagnostic, ExitCode: -1}, errors.New("spawn failed") |
| 185 | }), nil |
| 186 | }) |
| 187 | |
| 188 | config := &Config{ |
| 189 | PreToolUse: []MatcherConfig{ |
| 190 | {Matcher: "*", Hooks: []Hook{{Type: customType, Timeout: 5}}}, |
| 191 | }, |
| 192 | } |
| 193 | |
| 194 | exec := NewExecutorWithRegistry(config, t.TempDir(), nil, registry) |
| 195 | result, err := exec.Dispatch(t.Context(), EventPreToolUse, &Input{ |
| 196 | SessionID: "s", ToolName: "shell", ToolUseID: "t", |
| 197 | }) |
| 198 | require.NoError(t, err) |
| 199 | |
| 200 | assert.False(t, result.Allowed) |
| 201 | assert.Equal(t, -1, result.ExitCode) |
| 202 | assert.Equal(t, diagnostic, result.Stderr, |
| 203 | "handler-captured stderr must survive the err != nil normalization in runHook") |
| 204 | } |
| 205 | |
| 206 | // handlerFunc adapts a function value into a [Handler] for terse tests. |
| 207 | type handlerFunc func(context.Context, []byte) (HandlerResult, error) |
nothing calls this directly
no test coverage detected