feat(tests): enhance bash script validation in platform tests

- Added assertions to ensure the presence and order of `set -e` and `set +e` in the generated bash script when a system prompt is included.
- Updated the test for the scenario without a prompt to confirm that `set -e` is not present, ensuring correct script behavior.
- Improved documentation in the `buildBashScript` function to clarify the use of `set -e` for error handling during script execution.
This commit is contained in:
Max 2026-03-21 11:04:18 +08:00
parent 610e6b3506
commit 4f7989d796
3 changed files with 39 additions and 1 deletions

View file

@ -68,6 +68,11 @@ func (b *posixBase) ListDirCmd(dir string) []string {
}
// buildBashScript is the shared bash script builder for macOS/Linux.
//
// When a system prompt is present, the script uses `set -e` to ensure that
// any failure in directory creation or prompt file writing aborts the entire
// script before Claude CLI is launched. This prevents silent fallback to
// running without a system prompt.
func (b *posixBase) buildBashScript(in scriptInput, xauthCmd string) string {
var s strings.Builder
@ -76,10 +81,12 @@ func (b *posixBase) buildBashScript(in scriptInput, xauthCmd string) string {
}
if in.systemPrompt != "" {
s.WriteString("set -e\n")
s.WriteString(fmt.Sprintf("mkdir -p \"$(dirname %q)\"\n", in.promptFile))
s.WriteString(fmt.Sprintf("cat << 'PROMPTEOF' > %s\n", in.promptFile))
s.WriteString(in.systemPrompt)
s.WriteString("\nPROMPTEOF\n")
s.WriteString("set +e\n")
in.args = append(in.args, "--append-system-prompt-file", in.promptFile)
}

View file

@ -82,6 +82,7 @@ func TestPosixBase_BuildBashScript_NoPrompt(t *testing.T) {
assert.Contains(t, script, "--verbose")
assert.Contains(t, script, "INPUTEOF")
assert.NotContains(t, script, "PROMPTEOF")
assert.NotContains(t, script, "set -e", "set -e should not be present when no prompt is written")
}
func TestPosixBase_BuildBashScript_WithPrompt(t *testing.T) {
@ -98,6 +99,16 @@ func TestPosixBase_BuildBashScript_WithPrompt(t *testing.T) {
assert.Contains(t, script, "PROMPTEOF")
assert.Contains(t, script, "You are a helpful assistant.")
assert.Contains(t, script, "--append-system-prompt-file")
promptIdx := strings.Index(script, "PROMPTEOF")
claudeIdx := strings.Index(script, "claude -p")
assert.True(t, strings.Contains(script, "set -e"), "script should enable set -e before prompt write")
assert.True(t, strings.Contains(script, "set +e"), "script should disable set -e before claude command")
setEIdx := strings.Index(script, "set -e")
setNoEIdx := strings.Index(script, "set +e")
assert.Less(t, setEIdx, promptIdx, "set -e should come before PROMPTEOF")
assert.Less(t, promptIdx, setNoEIdx, "set +e should come after PROMPTEOF")
assert.Less(t, setNoEIdx, claudeIdx, "set +e should come before claude -p")
}
func TestPosixBase_BuildBashScript_WithXauth(t *testing.T) {

View file

@ -64,7 +64,27 @@ func (s *session) runStream(handler message.StreamFunc) (completed bool, err err
return true, nil
}
return false, s.waitForExit(parseErr)
exitErr := s.waitForExit(parseErr)
if exitErr != nil {
if handler != nil {
handler(message.ChunkError, []byte(exitErr.Error()))
}
return false, exitErr
}
s.stderrMu.Lock()
stderrStr := strings.TrimSpace(s.stderr.String())
s.stderrMu.Unlock()
if stderrStr != "" {
s.logger.Warn("claude exited with code 0 but stream incomplete and stderr present: %s", stderrStr)
errMsg := fmt.Errorf("claude CLI setup failed: %s", stderrStr)
if handler != nil {
handler(message.ChunkError, []byte(errMsg.Error()))
}
return false, errMsg
}
return false, nil
}
// collectStderr reads stderr in a background goroutine.