shell_test.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. package shell
  2. import (
  3. "context"
  4. "path/filepath"
  5. "runtime"
  6. "strings"
  7. "testing"
  8. "time"
  9. )
  10. // Benchmark to measure CPU efficiency
  11. func BenchmarkShellQuickCommands(b *testing.B) {
  12. shell := NewShell(&Options{WorkingDir: b.TempDir()})
  13. b.ReportAllocs()
  14. for b.Loop() {
  15. _, _, err := shell.Exec(b.Context(), "echo test")
  16. exitCode := ExitCode(err)
  17. if err != nil || exitCode != 0 {
  18. b.Fatalf("Command failed: %v, exit code: %d", err, exitCode)
  19. }
  20. }
  21. }
  22. func TestTestTimeout(t *testing.T) {
  23. // XXX(@andreynering): This fails on Windows. Address once possible.
  24. if runtime.GOOS == "windows" {
  25. t.Skip("Skipping test on Windows")
  26. }
  27. ctx, cancel := context.WithTimeout(t.Context(), time.Millisecond)
  28. t.Cleanup(cancel)
  29. shell := NewShell(&Options{WorkingDir: t.TempDir()})
  30. _, _, err := shell.Exec(ctx, "sleep 10")
  31. if status := ExitCode(err); status == 0 {
  32. t.Fatalf("Expected non-zero exit status, got %d", status)
  33. }
  34. if !IsInterrupt(err) {
  35. t.Fatalf("Expected command to be interrupted, but it was not")
  36. }
  37. if err == nil {
  38. t.Fatalf("Expected an error due to timeout, but got none")
  39. }
  40. }
  41. func TestTestCancel(t *testing.T) {
  42. ctx, cancel := context.WithCancel(t.Context())
  43. cancel() // immediately cancel the context
  44. shell := NewShell(&Options{WorkingDir: t.TempDir()})
  45. _, _, err := shell.Exec(ctx, "sleep 10")
  46. if status := ExitCode(err); status == 0 {
  47. t.Fatalf("Expected non-zero exit status, got %d", status)
  48. }
  49. if !IsInterrupt(err) {
  50. t.Fatalf("Expected command to be interrupted, but it was not")
  51. }
  52. if err == nil {
  53. t.Fatalf("Expected an error due to cancel, but got none")
  54. }
  55. }
  56. func TestRunCommandError(t *testing.T) {
  57. shell := NewShell(&Options{WorkingDir: t.TempDir()})
  58. _, _, err := shell.Exec(t.Context(), "nopenopenope")
  59. if status := ExitCode(err); status == 0 {
  60. t.Fatalf("Expected non-zero exit status, got %d", status)
  61. }
  62. if IsInterrupt(err) {
  63. t.Fatalf("Expected command to not be interrupted, but it was")
  64. }
  65. if err == nil {
  66. t.Fatalf("Expected an error, got nil")
  67. }
  68. }
  69. func TestRunContinuity(t *testing.T) {
  70. tempDir1 := t.TempDir()
  71. tempDir2 := t.TempDir()
  72. shell := NewShell(&Options{WorkingDir: tempDir1})
  73. if _, _, err := shell.Exec(t.Context(), "export FOO=bar"); err != nil {
  74. t.Fatalf("failed to set env: %v", err)
  75. }
  76. if _, _, err := shell.Exec(t.Context(), "cd "+filepath.ToSlash(tempDir2)); err != nil {
  77. t.Fatalf("failed to change directory: %v", err)
  78. }
  79. out, _, err := shell.Exec(t.Context(), "echo $FOO ; pwd")
  80. if err != nil {
  81. t.Fatalf("failed to echo: %v", err)
  82. }
  83. expect := "bar\n" + tempDir2 + "\n"
  84. if out != expect {
  85. t.Fatalf("expected output %q, got %q", expect, out)
  86. }
  87. }
  88. func TestCrossPlatformExecution(t *testing.T) {
  89. shell := NewShell(&Options{WorkingDir: "."})
  90. ctx, cancel := context.WithTimeout(t.Context(), 5*time.Second)
  91. defer cancel()
  92. // Test a simple command that should work on all platforms
  93. stdout, stderr, err := shell.Exec(ctx, "echo hello")
  94. if err != nil {
  95. t.Fatalf("Echo command failed: %v, stderr: %s", err, stderr)
  96. }
  97. if stdout == "" {
  98. t.Error("Echo command produced no output")
  99. }
  100. // The output should contain "hello" regardless of platform
  101. if !strings.Contains(strings.ToLower(stdout), "hello") {
  102. t.Errorf("Echo output should contain 'hello', got: %q", stdout)
  103. }
  104. }