fix multi-run.test.ts on windows (#26590)

### What does this PR do?

fixes https://github.com/oven-sh/bun/issues/26597

### How did you verify your code works?

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Dylan Conway
2026-01-29 23:35:53 -08:00
committed by GitHub
parent 3feea91087
commit b4b7cc6d78
2 changed files with 26 additions and 14 deletions

View File

@@ -487,10 +487,13 @@ fn addScriptConfigs(
} else {
// Not a package.json script - run as a raw command
// If it looks like a file path, prefix with bun executable
const is_file = raw_name.len > 0 and (raw_name[0] == '.' or raw_name[0] == '/' or hasRunnableExtension(raw_name));
const is_file = raw_name.len > 0 and (raw_name[0] == '.' or raw_name[0] == '/' or
(Environment.isWindows and raw_name[0] == '\\') or hasRunnableExtension(raw_name));
const command_z = if (is_file) brk: {
const bun_path = bun.selfExePath() catch "bun";
const cmd_str = try std.fmt.allocPrint(allocator, "{s} {s}" ++ "\x00", .{ bun_path, raw_name });
// Quote the bun path so that backslashes on Windows are not
// interpreted as escape characters by `bun exec` (Bun's shell).
const cmd_str = try std.fmt.allocPrint(allocator, "\"{s}\" {s}" ++ "\x00", .{ bun_path, raw_name });
break :brk cmd_str[0 .. cmd_str.len - 1 :0];
} else try allocator.dupeZ(u8, raw_name);
try configs.append(.{

View File

@@ -1,5 +1,7 @@
import { describe, expect, test } from "bun:test";
import { bunEnv, bunExe, tempDir } from "harness";
import { realpathSync } from "fs";
import { bunEnv, bunExe, isWindows, tempDir } from "harness";
import path from "path";
// Helper: spawn bun with multi-run flags, returns { stdout, stderr, exitCode }
async function runMulti(
@@ -339,7 +341,7 @@ describe("parallel: output formatting", () => {
using dir = tempDir("mr-par-empty", {
"package.json": JSON.stringify({
scripts: {
silent: `${bunExe()} -e ""`,
silent: `${bunExe()} -e "0"`,
},
}),
});
@@ -364,7 +366,7 @@ describe("parallel: output formatting", () => {
test("shows 'Done in Xms' for successful scripts", async () => {
using dir = tempDir("mr-par-done", {
"package.json": JSON.stringify({
scripts: { fast: `${bunExe()} -e ""` },
scripts: { fast: `${bunExe()} -e "0"` },
}),
});
const r = await runMulti(["run", "--parallel", "fast"], String(dir));
@@ -922,9 +924,9 @@ describe("timing edge cases", () => {
using dir = tempDir("mr-instant", {
"package.json": JSON.stringify({
scripts: {
a: `${bunExe()} -e ""`,
b: `${bunExe()} -e ""`,
c: `${bunExe()} -e ""`,
a: `${bunExe()} -e "0"`,
b: `${bunExe()} -e "0"`,
c: `${bunExe()} -e "0"`,
},
}),
});
@@ -1019,8 +1021,12 @@ describe("working directory", () => {
}),
});
const r = await runMulti(["run", "--parallel", "pwd"], String(dir));
const realDir = await Bun.$`realpath ${String(dir)}`.text();
expectPrefixed(r.stdout, "pwd", realDir.trim());
const realDir = realpathSync(String(dir));
// On Windows, process.cwd() returns backslash paths; normalize for comparison
const lines = r.stdout.split("\n").filter(l => /pwd\s+\|/.test(l));
expect(lines.length).toBeGreaterThan(0);
const cwdOutput = lines[0].split(" | ").slice(1).join(" | ").trim();
expect(path.normalize(cwdOutput)).toBe(path.normalize(realDir));
expect(r.exitCode).toBe(0);
});
});
@@ -1175,7 +1181,7 @@ describe("abort: failure kills long-running processes", () => {
expect(elapsed).toBeLessThan(15000);
});
test("parallel: signaled process shows Signaled message", async () => {
test.skipIf(isWindows)("parallel: signaled process shows Signaled message", async () => {
using dir = tempDir("mr-abort-signal", {
"package.json": JSON.stringify({
scripts: {
@@ -1897,14 +1903,17 @@ describe("workspace integration", () => {
});
const r = await runMulti(["run", "--parallel", "--filter", "*", "pwd"], String(dir));
// Each package should report its own directory, not the root
const realDir = (await Bun.$`realpath ${String(dir)}`.text()).trim();
const realDir = realpathSync(String(dir));
const lines = r.stdout.split("\n").filter(l => l.includes(" | "));
const pkgALines = lines.filter(l => /pkg-a:pwd/.test(l));
const pkgBLines = lines.filter(l => /pkg-b:pwd/.test(l));
expect(pkgALines.length).toBeGreaterThan(0);
expect(pkgBLines.length).toBeGreaterThan(0);
expect(pkgALines.some(l => l.includes(`${realDir}/packages/pkg-a`))).toBe(true);
expect(pkgBLines.some(l => l.includes(`${realDir}/packages/pkg-b`))).toBe(true);
// Normalize paths for cross-platform comparison (Windows uses backslashes)
const normPkgA = path.normalize(path.join(realDir, "packages", "pkg-a"));
const normPkgB = path.normalize(path.join(realDir, "packages", "pkg-b"));
expect(pkgALines.some(l => l.includes(normPkgA))).toBe(true);
expect(pkgBLines.some(l => l.includes(normPkgB))).toBe(true);
expect(r.exitCode).toBe(0);
});