TerminalProcessInterpretExitCode.test.ts 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. import { TerminalProcess } from "../TerminalProcess"
  2. import { execSync } from "child_process"
  3. describe("TerminalProcess.interpretExitCode", () => {
  4. let terminalProcess: TerminalProcess
  5. beforeEach(() => {
  6. terminalProcess = new TerminalProcess()
  7. })
  8. it("should handle undefined exit code", () => {
  9. const result = terminalProcess.interpretExitCode(undefined)
  10. expect(result).toEqual({ exitCode: undefined })
  11. })
  12. it("should handle normal exit codes (0-127)", () => {
  13. // Test success exit code (0)
  14. let result = terminalProcess.interpretExitCode(0)
  15. expect(result).toEqual({ exitCode: 0 })
  16. // Test error exit code (1)
  17. result = terminalProcess.interpretExitCode(1)
  18. expect(result).toEqual({ exitCode: 1 })
  19. // Test arbitrary exit code within normal range
  20. result = terminalProcess.interpretExitCode(42)
  21. expect(result).toEqual({ exitCode: 42 })
  22. // Test boundary exit code
  23. result = terminalProcess.interpretExitCode(127)
  24. expect(result).toEqual({ exitCode: 127 })
  25. })
  26. it("should handle signal exit codes (128+)", () => {
  27. // Test SIGINT (Ctrl+C) - 128 + 2 = 130
  28. const result = terminalProcess.interpretExitCode(130)
  29. expect(result).toEqual({
  30. exitCode: 130,
  31. signal: 2,
  32. signalName: "SIGINT",
  33. coreDumpPossible: false,
  34. })
  35. // Test SIGTERM - 128 + 15 = 143
  36. const resultTerm = terminalProcess.interpretExitCode(143)
  37. expect(resultTerm).toEqual({
  38. exitCode: 143,
  39. signal: 15,
  40. signalName: "SIGTERM",
  41. coreDumpPossible: false,
  42. })
  43. // Test SIGSEGV (segmentation fault) - 128 + 11 = 139
  44. const resultSegv = terminalProcess.interpretExitCode(139)
  45. expect(resultSegv).toEqual({
  46. exitCode: 139,
  47. signal: 11,
  48. signalName: "SIGSEGV",
  49. coreDumpPossible: true,
  50. })
  51. })
  52. it("should identify signals that can produce core dumps", () => {
  53. // Core dump possible signals: SIGQUIT(3), SIGILL(4), SIGABRT(6), SIGBUS(7), SIGFPE(8), SIGSEGV(11)
  54. const coreDumpSignals = [3, 4, 6, 7, 8, 11]
  55. for (const signal of coreDumpSignals) {
  56. const exitCode = 128 + signal
  57. const result = terminalProcess.interpretExitCode(exitCode)
  58. expect(result.coreDumpPossible).toBe(true)
  59. }
  60. // Test a non-core-dump signal
  61. const nonCoreDumpResult = terminalProcess.interpretExitCode(128 + 1) // SIGHUP
  62. expect(nonCoreDumpResult.coreDumpPossible).toBe(false)
  63. })
  64. it("should handle unknown signals", () => {
  65. // Test an exit code for a signal that's not in our mapping
  66. const result = terminalProcess.interpretExitCode(128 + 99)
  67. expect(result).toEqual({
  68. exitCode: 128 + 99,
  69. signal: 99,
  70. signalName: "Unknown Signal (99)",
  71. coreDumpPossible: false,
  72. })
  73. })
  74. })
  75. describe("TerminalProcess.interpretExitCode with real commands", () => {
  76. let terminalProcess: TerminalProcess
  77. beforeEach(() => {
  78. terminalProcess = new TerminalProcess()
  79. })
  80. it("should correctly interpret exit code 0 from successful command", () => {
  81. try {
  82. // Run a command that should succeed
  83. execSync("echo test", { stdio: "ignore" })
  84. // If we get here, the command succeeded with exit code 0
  85. const result = terminalProcess.interpretExitCode(0)
  86. expect(result).toEqual({ exitCode: 0 })
  87. } catch (error: any) {
  88. // This should not happen for a successful command
  89. fail("Command should have succeeded: " + error.message)
  90. }
  91. })
  92. it("should correctly interpret exit code 1 from failed command", () => {
  93. try {
  94. // Run a command that should fail with exit code 1 or 2
  95. execSync("ls /nonexistent_directory", { stdio: "ignore" })
  96. fail("Command should have failed")
  97. } catch (error: any) {
  98. // Verify the exit code is what we expect (can be 1 or 2 depending on the system)
  99. expect(error.status).toBeGreaterThan(0)
  100. expect(error.status).toBeLessThan(128) // Not a signal
  101. const result = terminalProcess.interpretExitCode(error.status)
  102. expect(result).toEqual({ exitCode: error.status })
  103. }
  104. })
  105. it("should correctly interpret exit code from command with custom exit code", () => {
  106. try {
  107. // Run a command that exits with a specific code
  108. execSync("exit 42", { stdio: "ignore" })
  109. fail("Command should have exited with code 42")
  110. } catch (error: any) {
  111. expect(error.status).toBe(42)
  112. const result = terminalProcess.interpretExitCode(error.status)
  113. expect(result).toEqual({ exitCode: 42 })
  114. }
  115. })
  116. // Test signal interpretation directly without relying on actual process termination
  117. it("should correctly interpret signal termination codes", () => {
  118. // Test SIGTERM (signal 15)
  119. const sigtermExitCode = 128 + 15
  120. const sigtermResult = terminalProcess.interpretExitCode(sigtermExitCode)
  121. expect(sigtermResult.signal).toBe(15)
  122. expect(sigtermResult.signalName).toBe("SIGTERM")
  123. expect(sigtermResult.coreDumpPossible).toBe(false)
  124. // Test SIGSEGV (signal 11)
  125. const sigsegvExitCode = 128 + 11
  126. const sigsegvResult = terminalProcess.interpretExitCode(sigsegvExitCode)
  127. expect(sigsegvResult.signal).toBe(11)
  128. expect(sigsegvResult.signalName).toBe("SIGSEGV")
  129. expect(sigsegvResult.coreDumpPossible).toBe(true)
  130. // Test SIGINT (signal 2)
  131. const sigintExitCode = 128 + 2
  132. const sigintResult = terminalProcess.interpretExitCode(sigintExitCode)
  133. expect(sigintResult.signal).toBe(2)
  134. expect(sigintResult.signalName).toBe("SIGINT")
  135. expect(sigintResult.coreDumpPossible).toBe(false)
  136. })
  137. })