package shell_test import ( "bytes" "strings" "testing" "time" "apigo.cc/go/shell" ) func TestRunTimeout(t *testing.T) { // 测试超时功能 _, err := shell.Run("sleep", []string{"2"}, &shell.Options{ Timeout: 100 * time.Millisecond, }) if err == nil || !strings.Contains(err.Error(), "timed out") { t.Errorf("Expected timeout error, got: %v", err) } } func TestRunEnv(t *testing.T) { // 测试环境变量传递 // 使用 printenv 检查是否设置了自定义变量 res, err := shell.Run("printenv", []string{"TEST_VAR"}, &shell.Options{ Env: []string{"TEST_VAR=hello_env"}, }) if err != nil { t.Errorf("Run with env failed: %v", err) } if strings.TrimSpace(string(res.Stdout)) != "hello_env" { t.Errorf("Expected 'hello_env', got: %s", res.Stdout) } } func TestRunCallbacks(t *testing.T) { // 测试 OnStdout 回调 var stdoutCaptured bytes.Buffer _, err := shell.Run("echo", []string{"test_callback"}, &shell.Options{ OnStdout: func(data []byte) { stdoutCaptured.Write(data) }, }) if err != nil { t.Errorf("Run with callback failed: %v", err) } if strings.TrimSpace(stdoutCaptured.String()) != "test_callback" { t.Errorf("Callback didn't capture expected output, got: %s", stdoutCaptured.String()) } } func TestRunStderr(t *testing.T) { // 测试标准错误捕获 // 使用 sh -c 显式输出到 stderr res, _ := shell.Run("sh", []string{"-c", "echo error_msg >&2; exit 1"}, nil) // 因为返回错误,所以检查 res if res.ProcessErr == nil { t.Error("Expected error, but got nil") } if strings.TrimSpace(string(res.Stderr)) != "error_msg" { t.Errorf("Expected 'error_msg', got: %s", res.Stderr) } } func TestPipeline(t *testing.T) { res, err := shell.Pipeline([][]string{{"echo", "hello", "world"}, {"grep", "hello"}}, nil) if err != nil { t.Errorf("Pipeline failed: %v", err) } if strings.TrimSpace(string(res.Stdout)) != "hello world" { t.Errorf("Expected 'hello world', got %s", res.Stdout) } } func TestRun(t *testing.T) { // 测试直接 Run res, err := shell.Run("echo", []string{"hello"}, nil) if err != nil { t.Errorf("Run failed: %v", err) } if strings.TrimSpace(string(res.Stdout)) != "hello" { t.Errorf("Expected 'hello', got %s", res.Stdout) } } func TestRunAdvanced(t *testing.T) { // 测试 Timeout, Dir, Verbose _, err := shell.Run("sleep", []string{"0.1"}, &shell.Options{ Timeout: 1 * time.Second, Verbose: true, }) if err != nil { t.Errorf("Run failed: %v", err) } } func TestRunCommand(t *testing.T) { // 测试完整命令字符串 RunCommand res, err := shell.RunCommand("echo hello world", nil) if err != nil { t.Errorf("RunCommand failed: %v", err) } if strings.TrimSpace(string(res.Stdout)) != "hello world" { t.Errorf("Expected 'hello world', got %s", res.Stdout) } } func TestRunCommandWithPipe(t *testing.T) { // 测试包含管道的 RunCommand res, err := shell.RunCommand("echo hello world | grep hello", nil) if err != nil { t.Errorf("RunCommand with pipe failed: %v", err) } if strings.TrimSpace(string(res.Stdout)) != "hello world" { t.Errorf("Expected 'hello world', got %s", res.Stdout) } } func TestRunCommandMixedPipeAndChain(t *testing.T) { // 测试 | 和 && 混合使用 // 期望:(echo hello | grep h) && (echo world | grep w) res, err := shell.RunCommand("echo hello | grep h && echo world | grep w", nil) if err != nil { t.Errorf("RunCommand with mixed operators failed: %v", err) } output := strings.TrimSpace(string(res.Stdout)) if !strings.Contains(output, "hello") || !strings.Contains(output, "world") { t.Errorf("Expected 'hello' and 'world' in output, got: %s", output) } }