Files
bun.sh/test/js/node/fs/fs-leak.test.js

129 lines
3.3 KiB
JavaScript

// This file is a .cjs file so you can run it in node+jest to verify node behaves exactly the same.
const { expect, test } = require("bun:test");
const fs = require("fs");
const { tmpdir, devNull } = require("os");
const { fsStreamInternals } = require("bun:internal-for-testing");
function getMaxFd() {
const dev_null = fs.openSync(devNull, "r");
fs.closeSync(dev_null);
return dev_null;
}
test("createWriteStream does not leak file descriptors", async () => {
let start = getMaxFd();
const path = `${tmpdir()}/${Date.now()}.leakTest.txt`;
await new Promise((resolve, reject) => {
const stream = fs.createWriteStream(path, {});
stream.on("error", reject);
stream.on("open", () => {
for (let i = 0; i < 100; i++) {
stream.write("hello world");
}
stream.end();
});
stream.on("close", () => {
resolve();
});
});
// If this is larger than the start value, it means that the file descriptor was not closed
expect(getMaxFd()).toBe(start);
});
test("createReadStream does not leak file descriptors", async () => {
let start = getMaxFd();
const path = `${tmpdir()}/${Date.now()}.leakTest.txt`;
fs.writeFileSync(path, "hello world\n".repeat(1000));
let n_bytes = 0;
await new Promise((resolve, reject) => {
const stream = fs.createReadStream(path, {});
stream.on("error", reject);
stream.on("data", chunk => {
n_bytes += chunk.length;
});
stream.on("close", () => {
resolve();
});
});
// If this is larger than the start value, it means that the file descriptor was not closed
expect(getMaxFd()).toBe(start);
expect(n_bytes).toBe("hello world\n".repeat(1000).length);
});
test("createWriteStream file handle does not leak file descriptors", async () => {
let start = getMaxFd();
const path = `${tmpdir()}/${Date.now()}.leakTest.txt`;
const fd = await fs.promises.open(path, "w");
let closed = false;
fd.on("close", () => {
closed = true;
});
await new Promise((resolve, reject) => {
const stream = fd.createWriteStream();
expect(stream.autoClose).toBe(true);
stream.on("error", reject);
stream.on("open", () => {
reject(new Error("fd is already open. open event should not be called"));
});
stream.on("close", () => {
resolve();
});
for (let i = 0; i < 100; i++) {
stream.write("hello world");
}
stream.end();
});
expect(closed).toBe(true);
// If this is larger than the start value, it means that the file descriptor was not closed
expect(getMaxFd()).toBe(start);
});
test("createReadStream file handle does not leak file descriptors", async () => {
let start = getMaxFd();
const path = `${tmpdir()}/${Date.now()}.leakTest.txt`;
fs.writeFileSync(path, "hello world\n".repeat(1000));
let n_bytes = 0;
const fd = await fs.promises.open(path, "r");
await new Promise((resolve, reject) => {
const stream = fd.createReadStream({});
stream.on("error", reject);
stream.on("data", chunk => {
n_bytes += chunk.length;
});
stream.on("close", () => {
resolve();
});
});
await fd.close();
await fd.close();
// If this is larger than the start value, it means that the file descriptor was not closed
expect(getMaxFd()).toBe(start);
expect(n_bytes).toBe("hello world\n".repeat(1000).length);
});