test: make sudo failure regression independent of host privileges

This commit is contained in:
Ed1s0nZ
2026-09-16 18:34:11 +08:00
parent f7882be546
commit 4d53717cd7
+26 -5
View File
@@ -44,15 +44,27 @@ func TestEinoStreamingShell_StreamsStderrBeforeStdoutEOF(t *testing.T) {
func TestEinoStreamingShell_SudoFailsFast(t *testing.T) { func TestEinoStreamingShell_SudoFailsFast(t *testing.T) {
shell := NewEinoStreamingShell() shell := NewEinoStreamingShell()
cmd := PrepareNonInteractiveShellCommand("sudo whoami && sudo cat /etc/os-release") // Exercise stderr delivery and failure propagation without relying on the
sr, err := shell.ExecuteStreaming(context.Background(), &filesystem.ExecuteRequest{Command: cmd}) // host's sudo policy: CI runners may allow passwordless sudo, even as root.
// A shell function also prevents this test from invoking the real sudo.
cmd := PrepareNonInteractiveShellCommand(`
sudo() {
printf '%s\n' 'sudo: a password is required' >&2
return 1
}
sudo whoami && printf '%s\n' 'unexpected-command-success'
`)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
start := time.Now()
sr, err := shell.ExecuteStreaming(ctx, &filesystem.ExecuteRequest{Command: cmd})
if err != nil { if err != nil {
t.Fatalf("ExecuteStreaming: %v", err) t.Fatalf("ExecuteStreaming: %v", err)
} }
defer sr.Close() defer sr.Close()
start := time.Now()
var got strings.Builder var got strings.Builder
var exitCode *int
for { for {
resp, rerr := sr.Recv() resp, rerr := sr.Recv()
if errors.Is(rerr, io.EOF) { if errors.Is(rerr, io.EOF) {
@@ -65,17 +77,26 @@ func TestEinoStreamingShell_SudoFailsFast(t *testing.T) {
continue continue
} }
got.WriteString(resp.Output) got.WriteString(resp.Output)
if resp.ExitCode != nil {
exitCode = resp.ExitCode
}
} }
if time.Since(start) > 5*time.Second { if ctx.Err() != nil || time.Since(start) > 5*time.Second {
t.Fatalf("sudo should fail quickly, took %v output=%q", time.Since(start), got.String()) t.Fatalf("sudo should fail quickly, took %v output=%q", time.Since(start), got.String())
} }
out := got.String() out := got.String()
if strings.Contains(out, "command exited with non-zero code") { if strings.Contains(out, "command exited with non-zero code") {
t.Fatalf("legacy exit line present: %q", out) t.Fatalf("legacy exit line present: %q", out)
} }
if !strings.Contains(out, "sudo") && !strings.Contains(out, "password") && !strings.Contains(out, "terminal") { if !strings.Contains(out, "sudo: a password is required") {
t.Fatalf("expected sudo error text, got: %q", out) t.Fatalf("expected sudo error text, got: %q", out)
} }
if strings.Contains(out, "unexpected-command-success") {
t.Fatalf("command after failed sudo unexpectedly ran: %q", out)
}
if exitCode == nil || *exitCode != 1 {
t.Fatalf("expected exit code 1, got: %v", exitCode)
}
} }
func TestEinoStreamingShell_StderrWhileStdoutBlocks(t *testing.T) { func TestEinoStreamingShell_StderrWhileStdoutBlocks(t *testing.T) {