aboutsummaryrefslogtreecommitdiff
path: root/test/bun.js
diff options
context:
space:
mode:
Diffstat (limited to 'test/bun.js')
-rw-r--r--test/bun.js/child_process-node.test.js241
-rw-r--r--test/bun.js/child_process.test.ts33
-rw-r--r--test/bun.js/filesink.test.ts133
-rw-r--r--test/bun.js/streams.test.js3
4 files changed, 232 insertions, 178 deletions
diff --git a/test/bun.js/child_process-node.test.js b/test/bun.js/child_process-node.test.js
index 17b2c4cfb..0f04bb2cd 100644
--- a/test/bun.js/child_process-node.test.js
+++ b/test/bun.js/child_process-node.test.js
@@ -8,12 +8,11 @@ import {
createCallCheckCtx,
createDoneDotAll,
} from "node-test-helpers";
+import { tmpdir } from "node:os";
const debug = process.env.DEBUG ? console.log : () => {};
-const platformTmpDir = `${process.platform === "darwin" ? "/private" : ""}${
- process.env.TMPDIR
-}`.slice(0, -1); // remove trailing slash
+const platformTmpDir = tmpdir();
// Copyright Joyent, Inc. and other Node contributors.
//
@@ -131,23 +130,29 @@ describe("ChildProcess.spawn()", () => {
});
describe("ChildProcess.spawn", () => {
- const child = new ChildProcess();
- child.spawn({
- file: "bun",
- // file: process.execPath,
- args: ["--interactive"],
- cwd: process.cwd(),
- stdio: "pipe",
- });
+ function getChild() {
+ const child = new ChildProcess();
+ child.spawn({
+ file: "node",
+ // file: process.execPath,
+ args: ["--interactive"],
+ cwd: process.cwd(),
+ stdio: ["ignore", "ignore", "ignore", "ipc"],
+ });
+ return child;
+ }
it("should spawn a process", () => {
+ const child = getChild();
// Test that we can call spawn
strictEqual(Object.hasOwn(child, "pid"), true);
assert(Number.isInteger(child.pid));
+ child.kill();
});
it("should throw error on invalid signal", () => {
+ const child = getChild();
// Try killing with invalid signal
throws(
() => {
@@ -158,6 +163,7 @@ describe("ChildProcess.spawn", () => {
});
it("should die when killed", () => {
+ const child = getChild();
strictEqual(child.kill(), true);
});
});
@@ -250,6 +256,7 @@ describe("child_process cwd", () => {
let data = "";
child.stdout.on("data", (chunk) => {
data += chunk;
+ console.trace("here");
});
// TODO: Test exit events
@@ -315,7 +322,7 @@ describe("child_process cwd", () => {
// });
it("should work for valid given cwd", (done) => {
- const tmpdir = { path: Bun.env.TMPDIR };
+ const tmpdir = { path: platformTmpDir };
const createDone = createDoneDotAll(done);
// Assume these exist, and 'pwd' gives us the right directory back
@@ -373,115 +380,115 @@ describe("child_process default options", () => {
// because the process can exit before the stream is closed and the data is read
child.stdout.on("close", () => {
assertOk(
- response.includes(`TMPDIR=${process.env.TMPDIR}`),
+ response.includes(`TMPDIR=${platformTmpDir}`),
"spawn did not use process.env as default " +
- `(process.env.TMPDIR = ${process.env.TMPDIR})`,
+ `(process.env.TMPDIR=${platformTmpDir})`,
);
done();
});
});
});
-describe("child_process double pipe", () => {
- it("should allow two pipes to be used at once", (done) => {
- const { mustCallAtLeast, mustCall } = createCallCheckCtx(done);
- let grep, sed, echo;
- grep = spawn("grep", ["o"]);
- sed = spawn("sed", ["s/o/O/"]);
- echo = spawn("echo", ["hello\nnode\nand\nworld\n"]);
-
- // pipe echo | grep
- echo.stdout.on(
- "data",
- mustCallAtLeast((data) => {
- debug(`grep stdin write ${data.length}`);
- if (!grep.stdin.write(data)) {
- echo.stdout.pause();
- }
- }),
- );
-
- // TODO(Derrick): We don't implement the full API for this yet,
- // So stdin has no 'drain' event.
- // // TODO(@jasnell): This does not appear to ever be
- // // emitted. It's not clear if it is necessary.
- // grep.stdin.on("drain", (data) => {
- // echo.stdout.resume();
- // });
-
- // Propagate end from echo to grep
- echo.stdout.on(
- "end",
- mustCall(() => {
- debug("echo stdout end");
- grep.stdin.end();
- }),
- );
-
- echo.on(
- "exit",
- mustCall(() => {
- debug("echo exit");
- }),
- );
-
- grep.on(
- "exit",
- mustCall(() => {
- debug("grep exit");
- }),
- );
-
- sed.on(
- "exit",
- mustCall(() => {
- debug("sed exit");
- }),
- );
-
- // pipe grep | sed
- grep.stdout.on(
- "data",
- mustCallAtLeast((data) => {
- debug(`grep stdout ${data.length}`);
- if (!sed.stdin.write(data)) {
- grep.stdout.pause();
- }
- }),
- );
-
- // // TODO(@jasnell): This does not appear to ever be
- // // emitted. It's not clear if it is necessary.
- // sed.stdin.on("drain", (data) => {
- // grep.stdout.resume();
- // });
-
- // Propagate end from grep to sed
- grep.stdout.on(
- "end",
- mustCall((code) => {
- debug("grep stdout end");
- sed.stdin.end();
- }),
- );
-
- let result = "";
-
- // print sed's output
- sed.stdout.on(
- "data",
- mustCallAtLeast((data) => {
- result += data.toString("utf8");
- debug(data);
- }),
- );
-
- sed.stdout.on(
- "end",
- mustCall(() => {
- debug("result: " + result);
- strictEqual(result, `hellO\nnOde\nwOrld\n`);
- }),
- );
- });
-});
+// describe("child_process double pipe", () => {
+// it("should allow two pipes to be used at once", (done) => {
+// const { mustCallAtLeast, mustCall } = createCallCheckCtx(done);
+// let grep, sed, echo;
+// grep = spawn("grep", ["o"]);
+// sed = spawn("sed", ["s/o/O/"]);
+// echo = spawn("echo", ["hello\nnode\nand\nworld\n"]);
+
+// // pipe echo | grep
+// echo.stdout.on(
+// "data",
+// mustCallAtLeast((data) => {
+// debug(`grep stdin write ${data.length}`);
+// if (!grep.stdin.write(data)) {
+// echo.stdout.pause();
+// }
+// }),
+// );
+
+// // TODO(Derrick): We don't implement the full API for this yet,
+// // So stdin has no 'drain' event.
+// // // TODO(@jasnell): This does not appear to ever be
+// // // emitted. It's not clear if it is necessary.
+// // grep.stdin.on("drain", (data) => {
+// // echo.stdout.resume();
+// // });
+
+// // Propagate end from echo to grep
+// echo.stdout.on(
+// "end",
+// mustCall(() => {
+// debug("echo stdout end");
+// grep.stdin.end();
+// }),
+// );
+
+// echo.on(
+// "exit",
+// mustCall(() => {
+// debug("echo exit");
+// }),
+// );
+
+// grep.on(
+// "exit",
+// mustCall(() => {
+// debug("grep exit");
+// }),
+// );
+
+// sed.on(
+// "exit",
+// mustCall(() => {
+// debug("sed exit");
+// }),
+// );
+
+// // pipe grep | sed
+// grep.stdout.on(
+// "data",
+// mustCallAtLeast((data) => {
+// debug(`grep stdout ${data.length}`);
+// if (!sed.stdin.write(data)) {
+// grep.stdout.pause();
+// }
+// }),
+// );
+
+// // // TODO(@jasnell): This does not appear to ever be
+// // // emitted. It's not clear if it is necessary.
+// // sed.stdin.on("drain", (data) => {
+// // grep.stdout.resume();
+// // });
+
+// // Propagate end from grep to sed
+// grep.stdout.on(
+// "end",
+// mustCall((code) => {
+// debug("grep stdout end");
+// sed.stdin.end();
+// }),
+// );
+
+// let result = "";
+
+// // print sed's output
+// sed.stdout.on(
+// "data",
+// mustCallAtLeast((data) => {
+// result += data.toString("utf8");
+// debug(data);
+// }),
+// );
+
+// sed.stdout.on(
+// "end",
+// mustCall(() => {
+// debug("result: " + result);
+// strictEqual(result, `hellO\nnOde\nwOrld\n`);
+// }),
+// );
+// });
+// });
diff --git a/test/bun.js/child_process.test.ts b/test/bun.js/child_process.test.ts
index f39629169..c862ff1b4 100644
--- a/test/bun.js/child_process.test.ts
+++ b/test/bun.js/child_process.test.ts
@@ -9,12 +9,11 @@ import {
execFileSync,
execSync,
} from "node:child_process";
+import { tmpdir } from "node:os";
const debug = process.env.DEBUG ? console.log : () => {};
-const platformTmpDir = `${process.platform === "darwin" ? "/private" : ""}${
- process.env.TMPDIR
-}`.slice(0, -1); // remove trailing slash
+const platformTmpDir = tmpdir();
// Semver regex: https://gist.github.com/jhorsman/62eeea161a13b80e39f5249281e17c39?permalink_comment_id=2896416#gistcomment-2896416
// Not 100% accurate, but good enough for this test
@@ -122,7 +121,7 @@ describe("spawn()", () => {
});
it("should allow us to set cwd", async () => {
- const child = spawn("pwd", { cwd: process.env.TMPDIR });
+ const child = spawn("pwd", { cwd: platformTmpDir });
const result: string = await new Promise((resolve) => {
child.stdout.on("data", (data) => {
resolve(data.toString());
@@ -261,10 +260,14 @@ describe("execFileSync()", () => {
});
it("should allow us to pass input to the command", () => {
- const result = execFileSync("node", ["spawned-child.js", "STDIN"], {
- input: "hello world!",
- encoding: "utf8",
- });
+ const result = execFileSync(
+ "node",
+ [import.meta.dir + "/spawned-child.js", "STDIN"],
+ {
+ input: "hello world!",
+ encoding: "utf8",
+ },
+ );
expect(result.trim()).toBe("hello world!");
});
});
@@ -278,11 +281,17 @@ describe("execSync()", () => {
describe("Bun.spawn()", () => {
it("should return exit code 0 on successful execution", async () => {
+ const proc = Bun.spawn({
+ cmd: ["echo", "hello"],
+ stdout: "pipe",
+ });
+
+ for await (const chunk of proc.stdout!) {
+ const text = new TextDecoder().decode(chunk);
+ expect(text.trim()).toBe("hello");
+ }
+
const result = await new Promise((resolve) => {
- const proc = Bun.spawn({
- cmd: ["echo", "hello"],
- stdout: "inherit",
- });
const maybeExited = Bun.peek(proc.exited);
if (maybeExited === proc.exited) {
proc.exited.then((code) => resolve(code));
diff --git a/test/bun.js/filesink.test.ts b/test/bun.js/filesink.test.ts
index b3b3a7e74..b4a178613 100644
--- a/test/bun.js/filesink.test.ts
+++ b/test/bun.js/filesink.test.ts
@@ -1,5 +1,6 @@
import { ArrayBufferSink } from "bun";
import { describe, expect, it } from "bun:test";
+import { mkfifo } from "mkfifo";
describe("FileSink", () => {
const fixtures = [
@@ -66,64 +67,100 @@ describe("FileSink", () => {
],
] as const;
- for (const [input, expected, label] of fixtures) {
- it(`${JSON.stringify(label)}`, async () => {
- const path = `/tmp/bun-test-${Bun.hash(label).toString(10)}.txt`;
- try {
- require("fs").unlinkSync(path);
- } catch (e) {}
+ function getPath(label) {
+ const path = `/tmp/bun-test-${Bun.hash(label).toString(10)}.txt`;
+ try {
+ require("fs").unlinkSync(path);
+ } catch (e) {}
+ return path;
+ }
- const sink = Bun.file(path).writer();
- for (let i = 0; i < input.length; i++) {
- sink.write(input[i]);
- }
- await sink.end();
+ var activeFIFO: Promise<string>;
+ var decoder = new TextDecoder();
- const output = new Uint8Array(await Bun.file(path).arrayBuffer());
- for (let i = 0; i < expected.length; i++) {
- expect(output[i]).toBe(expected[i]);
+ function getFd(label) {
+ const path = `/tmp/bun-test-${Bun.hash(label).toString(10)}.txt`;
+ try {
+ require("fs").unlinkSync(path);
+ } catch (e) {}
+ mkfifo(path, 0o666);
+ activeFIFO = (async function (stream: ReadableStream<Uint8Array>) {
+ var chunks = [];
+ for await (const chunk of stream) {
+ chunks.push(chunk);
}
- expect(output.byteLength).toBe(expected.byteLength);
- });
+ return Buffer.concat(chunks).toString();
+ // test it on a small chunk size
+ })(Bun.file(path).stream(4));
+ return path;
+ }
- it(`flushing -> ${JSON.stringify(label)}`, async () => {
- const path = `/tmp/bun-test-${Bun.hash(label).toString(10)}.txt`;
- try {
- require("fs").unlinkSync(path);
- } catch (e) {}
+ for (let isPipe of [true, false] as const) {
+ describe(isPipe ? "pipe" : "file", () => {
+ for (const [input, expected, label] of fixtures) {
+ var getPathOrFd = () => (isPipe ? getFd(label) : getPath(label));
- const sink = Bun.file(path).writer();
- for (let i = 0; i < input.length; i++) {
- sink.write(input[i]);
- await sink.flush();
- }
- await sink.end();
+ it(`${JSON.stringify(label)}`, async () => {
+ const path = getPathOrFd();
+ const sink = Bun.file(path).writer();
+ for (let i = 0; i < input.length; i++) {
+ sink.write(input[i]);
+ }
+ await sink.end();
- const output = new Uint8Array(await Bun.file(path).arrayBuffer());
- for (let i = 0; i < expected.length; i++) {
- expect(output[i]).toBe(expected[i]);
- }
- expect(output.byteLength).toBe(expected.byteLength);
- });
+ if (!isPipe) {
+ const output = new Uint8Array(await Bun.file(path).arrayBuffer());
+ for (let i = 0; i < expected.length; i++) {
+ expect(output[i]).toBe(expected[i]);
+ }
+ expect(output.byteLength).toBe(expected.byteLength);
+ } else {
+ const output = await activeFIFO;
+ expect(output).toBe(decoder.decode(expected));
+ }
+ });
- it(`highWaterMark -> ${JSON.stringify(label)}`, async () => {
- const path = `/tmp/bun-test-${Bun.hash(label).toString(10)}.txt`;
- try {
- require("fs").unlinkSync(path);
- } catch (e) {}
+ it(`flushing -> ${JSON.stringify(label)}`, async () => {
+ const path = getPathOrFd();
+ const sink = Bun.file(path).writer();
+ for (let i = 0; i < input.length; i++) {
+ sink.write(input[i]);
+ await sink.flush();
+ }
+ await sink.end();
+ if (!isPipe) {
+ const output = new Uint8Array(await Bun.file(path).arrayBuffer());
+ for (let i = 0; i < expected.length; i++) {
+ expect(output[i]).toBe(expected[i]);
+ }
+ expect(output.byteLength).toBe(expected.byteLength);
+ } else {
+ const output = await activeFIFO;
+ expect(output).toBe(decoder.decode(expected));
+ }
+ });
- const sink = Bun.file(path).writer({ highWaterMark: 1 });
- for (let i = 0; i < input.length; i++) {
- sink.write(input[i]);
- await sink.flush();
- }
- await sink.end();
+ it(`highWaterMark -> ${JSON.stringify(label)}`, async () => {
+ const path = getPathOrFd();
+ const sink = Bun.file(path).writer({ highWaterMark: 1 });
+ for (let i = 0; i < input.length; i++) {
+ sink.write(input[i]);
+ await sink.flush();
+ }
+ await sink.end();
- const output = new Uint8Array(await Bun.file(path).arrayBuffer());
- for (let i = 0; i < expected.length; i++) {
- expect(output[i]).toBe(expected[i]);
+ if (!isPipe) {
+ const output = new Uint8Array(await Bun.file(path).arrayBuffer());
+ for (let i = 0; i < expected.length; i++) {
+ expect(output[i]).toBe(expected[i]);
+ }
+ expect(output.byteLength).toBe(expected.byteLength);
+ } else {
+ const output = await activeFIFO;
+ expect(output).toBe(decoder.decode(expected));
+ }
+ });
}
- expect(output.byteLength).toBe(expected.byteLength);
});
}
});
diff --git a/test/bun.js/streams.test.js b/test/bun.js/streams.test.js
index c6d69ab08..75ac964ca 100644
--- a/test/bun.js/streams.test.js
+++ b/test/bun.js/streams.test.js
@@ -218,7 +218,8 @@ it("Bun.file() read text from pipe", async () => {
mkfifo("/tmp/fifo", 0o666);
- const large = "HELLO!".repeat((((1024 * 512) / "HELLO!".length) | 0) + 1);
+ // 65k so its less than the max on linux
+ const large = "HELLO!".repeat((((1024 * 65) / "HELLO!".length) | 0) + 1);
const chunks = [];
var out = Bun.file("/tmp/fifo").stream();