| import { describe, expect, it } from "vitest"; |
| import { runCommandBuffersWithTimeout, runCommandWithTimeout } from "./exec-runner.js"; |
|
|
| describe("owned command output bytes", () => { |
| it("retains binary stdout/stderr and the actual exit result", async () => { |
| const result = await runCommandBuffersWithTimeout( |
| [ |
| process.execPath, |
| "-e", |
| "process.stdout.write(Buffer.from([0,128,255,65]));process.stderr.write(Buffer.from([255,0,66]));process.exitCode=7;", |
| ], |
| { timeoutMs: 10_000 }, |
| ); |
| expect(result.stdout).toEqual(Buffer.from([0, 128, 255, 65])); |
| expect(result.stderr).toEqual(Buffer.from([255, 0, 66])); |
| expect(result).toMatchObject({ code: 7, signal: null, termination: "exit" }); |
| }); |
|
|
| it.each(["text", "bytes"] as const)( |
| "keeps the existing bounded tail contract for %s output", |
| async (mode) => { |
| const command = [ |
| process.execPath, |
| "-e", |
| "process.stdout.write('0123456789');process.stderr.write('abcdef');", |
| ]; |
| const options = { timeoutMs: 10_000, maxOutputBytes: { stdout: 4, stderr: 3 } }; |
| const result = |
| mode === "bytes" |
| ? await runCommandBuffersWithTimeout(command, options) |
| : await runCommandWithTimeout(command, options); |
| expect(result.stdout.toString()).toBe("6789"); |
| expect(result.stderr.toString()).toBe("def"); |
| expect(result).toMatchObject({ |
| code: 0, |
| termination: "exit", |
| stdoutTruncatedBytes: 6, |
| stderrTruncatedBytes: 3, |
| }); |
| }, |
| ); |
|
|
| it("does not start an already canceled byte consumer", async () => { |
| const controller = new AbortController(); |
| controller.abort(); |
| const result = await runCommandBuffersWithTimeout( |
| [process.execPath, "-e", "throw new Error('must not execute');"], |
| { timeoutMs: 10_000, signal: controller.signal }, |
| ); |
| expect(result).toMatchObject({ |
| code: null, |
| termination: "signal", |
| stdout: Buffer.alloc(0), |
| stderr: Buffer.alloc(0), |
| }); |
| expect(result.pid).toBeUndefined(); |
| }); |
| }); |
|
|