mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
Fixes test\regression\issue\23316-long-path-spawn.test.ts
The problem was ``await Bun.write(join(deepPath, "test.js"),
`console.log("hello");`);`` was failing because the name was too long,
but it failed before refConcurrently was called and it called
unrefConcurrently after failing. so then when the subprocess spawned it
didn't ref.
---------
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
99 lines
2.7 KiB
TypeScript
99 lines
2.7 KiB
TypeScript
import { expect, test } from "bun:test";
|
|
import { bunExe, isWindows, tempDir } from "harness";
|
|
import { join } from "path";
|
|
|
|
test("spawn should handle cwd paths >= MAX_PATH on Windows", async () => {
|
|
if (!isWindows) {
|
|
return;
|
|
}
|
|
|
|
using dir = tempDir("long-path-spawn", {});
|
|
|
|
// Create a deeply nested directory structure that exceeds MAX_PATH (260 chars)
|
|
// Windows MAX_PATH is 260, so we'll create a path > 260 characters
|
|
const segments: string[] = [];
|
|
let currentPath = String(dir);
|
|
let totalLength = currentPath.length;
|
|
|
|
// Keep adding directory segments until we exceed MAX_PATH
|
|
let i = 0;
|
|
while (totalLength < 280) {
|
|
const segment = `dir${i.toString().padStart(3, "0")}`;
|
|
segments.push(segment);
|
|
totalLength += segment.length + 1; // +1 for the path separator
|
|
i++;
|
|
}
|
|
|
|
// Create the nested directory structure
|
|
let deepPath = String(dir);
|
|
for (const segment of segments) {
|
|
deepPath = join(deepPath, segment);
|
|
await Bun.write(join(deepPath, ".keep"), "");
|
|
}
|
|
|
|
console.log(`Created deep path (length: ${deepPath.length}): ${deepPath}`);
|
|
expect(deepPath.length).toBeGreaterThanOrEqual(260);
|
|
|
|
// This should either:
|
|
// 1. Succeed and spawn the process
|
|
// 2. Fail gracefully with an error (not panic with UV_ENOTCONN)
|
|
let err;
|
|
try {
|
|
await Bun.spawn({
|
|
cmd: [bunExe(), "--version"],
|
|
cwd: deepPath,
|
|
stdout: "pipe",
|
|
stderr: "pipe",
|
|
}).exited;
|
|
} catch (e) {
|
|
err = e;
|
|
}
|
|
expect(err).toBeInstanceOf(Error);
|
|
});
|
|
|
|
test("spawn should handle cwd paths with disabled 8.3 names on Windows", async () => {
|
|
if (!isWindows) {
|
|
return;
|
|
}
|
|
|
|
using dir = tempDir("8-3-disabled-spawn", {
|
|
"test.js": `console.log("hello");`,
|
|
});
|
|
|
|
// Create a moderately long path that would trigger GetShortPathNameW
|
|
// but might fail if 8.3 names are disabled
|
|
const segments = Array.from({ length: 20 }, (_, i) => `directory_with_long_name_${i}`);
|
|
let deepPath = String(dir);
|
|
for (const segment of segments) {
|
|
deepPath = join(deepPath, segment);
|
|
await Bun.write(join(deepPath, ".keep"), "");
|
|
}
|
|
|
|
console.log(`Created path for 8.3 test (length: ${deepPath.length}): ${deepPath}`);
|
|
|
|
// Attempt to copy test.js to the deep path
|
|
let err;
|
|
try {
|
|
await Bun.write(join(deepPath, "test.js"), `console.log("hello");`);
|
|
} catch (e) {
|
|
err = e;
|
|
}
|
|
expect(err).toBeInstanceOf(Error);
|
|
|
|
// This should not panic, even if GetShortPathNameW fails
|
|
err = undefined;
|
|
try {
|
|
const proc = Bun.spawn({
|
|
cmd: [bunExe(), "test.js"],
|
|
cwd: deepPath,
|
|
stdout: "inherit",
|
|
stderr: "inherit",
|
|
});
|
|
const exitCode = await proc.exited;
|
|
if (exitCode !== 0) throw new Error("process exited");
|
|
} catch (e) {
|
|
err = e;
|
|
}
|
|
expect(err).toBeInstanceOf(Error);
|
|
});
|