diff --git a/test/bundler/bun-build-api.test.ts b/test/bundler/bun-build-api.test.ts
index c7ca18450820..015646fb4a13 100644
--- a/test/bundler/bun-build-api.test.ts
+++ b/test/bundler/bun-build-api.test.ts
@@ -1061,14 +1061,12 @@ describe("Bun.build", () => {
// descriptor in the resolver. A second in-process Bun.build() used to reuse a
// descriptor the first build had already closed, failing with EBADF. The test
// host must also import the package so its fd is cached before the builds run.
- test.concurrent.skipIf(isWindows)(
- "repeated in-process builds of a symlinked package do not reuse a closed fd",
- async () => {
- using dir = tempDir("build-symlink-fd-cache", {
- "vendor/pkg/package.json": `{"name":"pkg","version":"1.0.0","type":"module","exports":"./index.js"}`,
- "vendor/pkg/index.js": `export const value = 1;\n`,
- "entry.ts": `import { value } from "pkg";\nconsole.log(value);\n`,
- "repro.test.ts": `
+ test.concurrent("repeated in-process builds of a symlinked package do not reuse a closed fd", async () => {
+ using dir = tempDir("build-symlink-fd-cache", {
+ "vendor/pkg/package.json": `{"name":"pkg","version":"1.0.0","type":"module","exports":"./index.js"}`,
+ "vendor/pkg/index.js": `export const value = 1;\n`,
+ "entry.ts": `import { value } from "pkg";\nconsole.log(value);\n`,
+ "repro.test.ts": `
import { it } from "bun:test";
import { value } from "pkg";
void value;
@@ -1082,22 +1080,21 @@ describe("Bun.build", () => {
console.log("ALL_BUILDS_OK");
});
`,
- });
- mkdirSync(join(String(dir), "node_modules"), { recursive: true });
- symlinkSync("../vendor/pkg", join(String(dir), "node_modules", "pkg"));
+ });
+ mkdirSync(join(String(dir), "node_modules"), { recursive: true });
+ symlinkSync("../vendor/pkg", join(String(dir), "node_modules", "pkg"));
- await using proc = Bun.spawn({
- cmd: [bunExe(), "test", "repro.test.ts"],
- env: bunEnv,
- cwd: String(dir),
- stdout: "pipe",
- stderr: "pipe",
- });
- const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
- expect(stdout + stderr).toContain("ALL_BUILDS_OK");
- expect(exitCode).toBe(0);
- },
- );
+ await using proc = Bun.spawn({
+ cmd: [bunExe(), "test", "repro.test.ts"],
+ env: bunEnv,
+ cwd: String(dir),
+ stdout: "pipe",
+ stderr: "pipe",
+ });
+ const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
+ expect(stdout + stderr).toContain("ALL_BUILDS_OK");
+ expect(exitCode).toBe(0);
+ });
test.concurrent("errors are returned as an array", async () => {
const x = await buildNoThrow({
diff --git a/test/cli/bake/bake.test.ts b/test/cli/bake/bake.test.ts
index 734d25ce2cc3..83bee919ada6 100644
--- a/test/cli/bake/bake.test.ts
+++ b/test/cli/bake/bake.test.ts
@@ -464,8 +464,7 @@ test.concurrent.each([
expect(response).toBe("200 1");
});
-// Creating a symlink on Windows needs a privilege that CI does not have.
-test.concurrent.skipIf(isWindows)("bun bake serves pages that are symlinks or in a symlinked folder", async () => {
+test.concurrent("bun bake serves pages that are symlinks or in a symlinked folder", async () => {
using dir = tempDir("bake-command-symlink", {
"shared/page.html": `
Shared
`,
"shared/docs/intro.html": `Intro
`,
@@ -792,9 +791,8 @@ test.concurrent("bun bake runs the SIGTERM handlers before it starts again for b
await output.waitFor(/SIGTERM before restart/);
});
-// On a terminal, `bun bake` adds its own SIGTERM listener, which exits. Bun.spawn's `terminal` is
-// POSIX only.
-test.concurrent.skipIf(isWindows)(
+// On a terminal, `bun bake` adds its own SIGTERM listener, which exits.
+test.concurrent(
"on a terminal, bun bake runs every SIGTERM listener before it starts again for bake.config.ts",
async () => {
const server = (version: string) => `
diff --git a/test/cli/check/check.test.ts b/test/cli/check/check.test.ts
index 57ca2153d3a0..9aa861824a1d 100644
--- a/test/cli/check/check.test.ts
+++ b/test/cli/check/check.test.ts
@@ -2911,7 +2911,7 @@ export const a: number[] = [file, one, two];
});
// Opening such a pipe blocks until a writer opens it. package.json is opened to look for a "check" script.
- test.skipIf(isWindows)("doesn't hang when package.json is a symlink to a named pipe with no writer", async () => {
+ test("doesn't hang when package.json is a symlink to a named pipe with no writer", async () => {
using dir = project({ "a.ts": `export {};\n` });
expect(Bun.spawnSync(["mkfifo", join(String(dir), "pipe")]).exitCode).toBe(0);
symlinkSync("pipe", join(String(dir), "package.json"));
@@ -3035,7 +3035,7 @@ export const a: number[] = [file, one, two];
expect(exitCode).toBe(1);
});
- test.skipIf(process.platform === "win32")("ignores a named pipe in the project directory", async () => {
+ test("ignores a named pipe in the project directory", async () => {
using dir = project({ "a.ts": `export const a: string = 1;\n` });
// Reading a pipe without a writer blocks forever.
expect(Bun.spawnSync(["mkfifo", join(String(dir), "pipe.ts")]).exitCode).toBe(0);
@@ -24276,28 +24276,25 @@ describe.concurrent("--check", () => {
});
// The path is compared as `bun run` spells it.
- test.skipIf(isWindows)(
- "`bun check` type checks in a `check` script started by a Bun that sets only BUN_INTERNAL_CHECK_SCRIPTS",
- async () => {
- using dir = project({
- "package.json": JSON.stringify({ scripts: { check: "echo the script ran" } }),
- "tsconfig.json": tsconfig,
- "a.ts": `export const a: number = "1";\n`,
- });
- const cwd = String(dir);
- const results = await Promise.all([
- run(cwd, ["check", "--pretty", "false"], { BUN_INTERNAL_CHECK_SCRIPTS: `${Buffer.byteLength(cwd)}:${cwd}` }),
- // Another package's path.
- run(cwd, ["check", "--pretty", "false"], { BUN_INTERNAL_CHECK_SCRIPTS: `2:/x` }),
- ]);
- expect(
- results.map(it => [it.stdout.includes("TS2322"), it.stdout.includes("the script ran"), it.exitCode]),
- ).toEqual([
- [true, false, 1],
- [false, true, 0],
- ]);
- },
- );
+ test("`bun check` type checks in a `check` script started by a Bun that sets only BUN_INTERNAL_CHECK_SCRIPTS", async () => {
+ using dir = project({
+ "package.json": JSON.stringify({ scripts: { check: "echo the script ran" } }),
+ "tsconfig.json": tsconfig,
+ "a.ts": `export const a: number = "1";\n`,
+ });
+ const cwd = String(dir);
+ const results = await Promise.all([
+ run(cwd, ["check", "--pretty", "false"], { BUN_INTERNAL_CHECK_SCRIPTS: `${Buffer.byteLength(cwd)}:${cwd}` }),
+ // Another package's path.
+ run(cwd, ["check", "--pretty", "false"], { BUN_INTERNAL_CHECK_SCRIPTS: `2:/x` }),
+ ]);
+ expect(
+ results.map(it => [it.stdout.includes("TS2322"), it.stdout.includes("the script ran"), it.exitCode]),
+ ).toEqual([
+ [true, false, 1],
+ [false, true, 0],
+ ]);
+ });
test("--check with --filter, --parallel or --sequential checks the project before the scripts", async () => {
using dir = project({
diff --git a/test/cli/create/create-jsx.test.ts b/test/cli/create/create-jsx.test.ts
index b9883c9ac35a..60944d07edb6 100644
--- a/test/cli/create/create-jsx.test.ts
+++ b/test/cli/create/create-jsx.test.ts
@@ -126,7 +126,7 @@ for (const development of [true, false]) {
});
});
- test.todoIf(isCI || isWindows)("dev server", async () => {
+ test.todoIf(isCI)("dev server", async () => {
console.log({ dir });
await using process = Bun.spawn([bunExe(), "create", "./index.jsx"], {
cwd: dir,
@@ -193,7 +193,7 @@ for (const development of [true, false]) {
});
});
- test.todoIf(isCI || isWindows)("dev server", async () => {
+ test.todoIf(isCI)("dev server", async () => {
const process = Bun.spawn([bunExe(), "create", "./index.tsx"], {
cwd: dir,
env: env,
@@ -259,7 +259,7 @@ for (const development of [true, false]) {
});
});
- test.todoIf(isCI || isWindows)("dev server", async () => {
+ test.todoIf(isCI)("dev server", async () => {
const process = Bun.spawn([bunExe(), "create", "./index.tsx"], {
cwd: dir,
env: env,
diff --git a/test/cli/format/format.test.ts b/test/cli/format/format.test.ts
index bf602778695e..a61b8cf2b154 100644
--- a/test/cli/format/format.test.ts
+++ b/test/cli/format/format.test.ts
@@ -521,20 +521,17 @@ describe.concurrent("bun fmt", () => {
expect(result.exitCode).toBe(0);
});
- // A file name can have at most 255 bytes. On Windows the path would also be too long.
- test.skipIf(isWindows)(
- "can have the longest possible name, and is still replaced rather than written in place",
- async () => {
- const name = `${Buffer.alloc(252, "a")}.ts`;
- using dir = tempDir("bun-format", { [name]: ugly });
- const before = statSync(join(String(dir), name)).ino;
- const { exitCode } = await write(String(dir), []);
- expect(read(String(dir), name)).toBe(formatted);
- expect(statSync(join(String(dir), name)).ino).not.toBe(before);
- expect(readdirSync(String(dir))).toEqual([name]);
- expect(exitCode).toBe(0);
- },
- );
+ // A file name can have at most 255 bytes.
+ test("can have the longest possible name, and is still replaced rather than written in place", async () => {
+ const name = `${Buffer.alloc(252, "a")}.ts`;
+ using dir = tempDir("bun-format", { [name]: ugly });
+ const before = statSync(join(String(dir), name)).ino;
+ const { exitCode } = await write(String(dir), []);
+ expect(read(String(dir), name)).toBe(formatted);
+ expect(statSync(join(String(dir), name)).ino).not.toBe(before);
+ expect(readdirSync(String(dir))).toEqual([name]);
+ expect(exitCode).toBe(0);
+ });
// For example in a container with a user's project mounted into it.
test.skipIf(!isRoot)("keeps its owner if root formats it", async () => {
@@ -552,7 +549,7 @@ describe.concurrent("bun fmt", () => {
});
// Prettier doesn't need write access to the directory.
- test.skipIf(isWindows || isRoot)("can be in a read-only directory", async () => {
+ test.skipIf(isRoot)("can be in a read-only directory", async () => {
using dir = tempDir("bun-format", { "src/a.js": ugly });
chmodSync(join(String(dir), "src"), 0o555);
try {
@@ -5731,15 +5728,12 @@ exports.format = async text => "by Prettier";
expect(result.exitCode).toBe(2);
});
- test.skipIf(isWindows)(
- "/dev/null works as an ignore file without patterns and as a configuration without options",
- async () => {
- const files = { ".prettierignore": "a.js\n", ".prettierrc": `{ "semi": false }\n`, "a.js": formatted };
- expect(await different(files, ["."])).toEqual([]);
- expect(await different(files, ["--ignore-path", "/dev/null", "."])).toEqual(["a.js"]);
- expect(await different(files, ["--ignore-path", "/dev/null", "--config", "/dev/null", "."])).toEqual([]);
- },
- );
+ test("/dev/null works as an ignore file without patterns and as a configuration without options", async () => {
+ const files = { ".prettierignore": "a.js\n", ".prettierrc": `{ "semi": false }\n`, "a.js": formatted };
+ expect(await different(files, ["."])).toEqual([]);
+ expect(await different(files, ["--ignore-path", "/dev/null", "."])).toEqual(["a.js"]);
+ expect(await different(files, ["--ignore-path", "/dev/null", "--config", "/dev/null", "."])).toEqual([]);
+ });
// This means "never break a line". Prettier accepts every integer from 0 up, and Infinity.
test.each([
@@ -6162,7 +6156,7 @@ exports.format = async text => "by Prettier";
expect(result.exitCode).toBe(0);
});
- test.skipIf(isWindows)("a named pipe whose name ends in .js is skipped, like in Prettier", async () => {
+ test("a named pipe whose name ends in .js is skipped, like in Prettier", async () => {
const before = (dir: string) => expect(Bun.spawnSync(["mkfifo", join(dir, "pipe.js")]).exitCode).toBe(0);
expect(await different({ "a.js": ugly }, [], { before })).toEqual(["a.js"]);
});
@@ -6634,7 +6628,7 @@ exports.format = async text => "by Prettier";
// A case's guard used to be printed without a stack check, so the stack overflowed at depths between the printer's
// limit and the parser's. The threads that format files have stack to spare, so this uses the main thread with half
// of its usual stack.
- test.skipIf(isWindows || isDebug || isASAN).concurrent.each([4_500, 4_612, 4_728, 4_846, 4_967, 5_091])(
+ test.skipIf(isDebug || isASAN).concurrent.each([4_500, 4_612, 4_728, 4_846, 4_967, 5_091])(
"Flow's match with %d nested guards, on a 4 MB stack",
async depth => {
using dir = tempDir("bun-format-small-stack", {});
diff --git a/test/cli/format/oxfmt-cli/oxfmt-cli.test.ts b/test/cli/format/oxfmt-cli/oxfmt-cli.test.ts
index e4e58c346444..eab664bb18f1 100644
--- a/test/cli/format/oxfmt-cli/oxfmt-cli.test.ts
+++ b/test/cli/format/oxfmt-cli/oxfmt-cli.test.ts
@@ -3,7 +3,7 @@
// `--list-different` list.
// `cases.json` is written by `test/cli/lint/oracle/driver/oxfmt-fixtures.mjs --record`.
import { afterAll, describe, expect, test } from "bun:test";
-import { bunEnv, bunExe, isWindows, tempDir } from "harness";
+import { bunEnv, bunExe, tempDir } from "harness";
import { readFileSync, symlinkSync } from "node:fs";
import { join } from "node:path";
import { endChildren, spawn } from "../../children";
@@ -21,7 +21,7 @@ describe.concurrent("bun fmt behaves like oxfmt", () => {
for (const it of cases) {
const files = { ...(fixtures as Record)[it.name], ...it.gitignore } as Files;
const links = Object.entries(files).filter(([, file]) => typeof file !== "string") as [string, { link: string }][];
- test.skipIf(isWindows && links.length > 0)(`${it.name}/${it.index}: ${it.args.join(" ")}`, async () => {
+ test(`${it.name}/${it.index}: ${it.args.join(" ")}`, async () => {
const texts = Object.entries(files).filter(([, file]) => typeof file === "string") as [string, string][];
// Without a configuration file, `bun fmt` behaves like Prettier. An empty one above the fixtures makes it behave
// like oxfmt.
diff --git a/test/cli/format/prettier-cli/prettier-cli.test.ts b/test/cli/format/prettier-cli/prettier-cli.test.ts
index 68df7a389d7e..84b1c5495e21 100644
--- a/test/cli/format/prettier-cli/prettier-cli.test.ts
+++ b/test/cli/format/prettier-cli/prettier-cli.test.ts
@@ -4,7 +4,7 @@
// input. `bun fmt` writes unless told otherwise, so Prettier was given `--write` where the command line only prints.
// `cases.json` is written by `test/cli/lint/oracle/driver/prettier-fixtures.mjs --record`.
import { afterAll, describe, expect, test } from "bun:test";
-import { bunEnv, bunExe, isWindows, tempDir } from "harness";
+import { bunEnv, bunExe, tempDir } from "harness";
import { readFileSync, symlinkSync } from "node:fs";
import { join } from "node:path";
import { endChildren, spawn } from "../../children";
@@ -25,7 +25,7 @@ describe.concurrent("bun fmt behaves like Prettier", () => {
const links = Object.entries(files).filter(([, file]) => typeof file !== "string") as [string, { link: string }][];
// Links, or a name that Windows doesn't allow.
const needsPosix = links.length > 0 || Object.keys(files).some(name => /[<>:"|?*\\]/.test(name));
- test.skipIf(isWindows && needsPosix)(`${it.test}: ${it.directory} $ ${it.args.join(" ")}`, async () => {
+ test(`${it.test}: ${it.directory} $ ${it.args.join(" ")}`, async () => {
const texts = Object.entries(files).filter(([, file]) => typeof file === "string") as [string, string][];
using dir = tempDir("prettier-cli", Object.fromEntries(texts.map(([name, text]) => [`${top}/${name}`, text])));
for (const [name, { link }] of links) symlinkSync(link, join(String(dir), top, name));
diff --git a/test/cli/format/tailwind/tailwind.test.ts b/test/cli/format/tailwind/tailwind.test.ts
index 7c167152d3c3..126d0815f026 100644
--- a/test/cli/format/tailwind/tailwind.test.ts
+++ b/test/cli/format/tailwind/tailwind.test.ts
@@ -5,7 +5,7 @@
//
// The order comes from the project's `tailwindcss` package. Here that's a stub that knows the classes in order.json.
import { afterAll, describe, expect, test } from "bun:test";
-import { bunEnv, bunExe, isLinux, isWindows, tempDir } from "harness";
+import { bunEnv, bunExe, isLinux, tempDir } from "harness";
import { chmodSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
import { join } from "node:path";
import { endChildren, spawn } from "../../children";
@@ -163,7 +163,7 @@ if (now.join() !== before.join()) throw new Error("There is " + now.filter(it =>
});
// As with Nix, an image layer owned by root, or a sandbox. Skipped as root, which can write anywhere.
- test.skipIf(isWindows || process.getuid?.() === 0)("works with read-only packages", async () => {
+ test.skipIf(process.getuid?.() === 0)("works with read-only packages", async () => {
using dir = tempDir("bun-format-tailwind", {
...version4,
".oxfmtrc.json": '{ "sortTailwindcss": {} }\n',
diff --git a/test/cli/hot/watch.test.ts b/test/cli/hot/watch.test.ts
index 4a6a5c2908b7..aeb08fd0a7ca 100644
--- a/test/cli/hot/watch.test.ts
+++ b/test/cli/hot/watch.test.ts
@@ -1,10 +1,10 @@
import { spawn } from "bun";
import { describe, expect, test } from "bun:test";
-import { bunEnv, bunExe, forEachLine, isBroken, isWindows, tempDir } from "harness";
+import { bunEnv, bunExe, forEachLine, tempDir } from "harness";
import { writeFile } from "node:fs/promises";
import { join } from "node:path";
-describe.todoIf(isBroken && isWindows)("--watch works", async () => {
+describe("--watch works", async () => {
for (const watchedFile of ["entry.js", "tmp.js"]) {
test(`with ${watchedFile}`, async () => {
await using tmpdir_ = tempDir("watch-fixture", {
diff --git a/test/cli/inspect/BunFrontendDevServer.test.ts b/test/cli/inspect/BunFrontendDevServer.test.ts
index a5301cac32e9..f72b0ab3f142 100644
--- a/test/cli/inspect/BunFrontendDevServer.test.ts
+++ b/test/cli/inspect/BunFrontendDevServer.test.ts
@@ -3,7 +3,7 @@ import { decodeSerializedError } from "bake/error-serialization.ts";
import { Subprocess, spawn } from "bun";
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
import fs from "fs";
-import { bunExe, bunEnv as env, isPosix, tempDir, tmpdirSync } from "harness";
+import { bunExe, bunEnv as env, tempDir, tmpdirSync } from "harness";
import path, { join } from "node:path";
import { InspectorSession, connect } from "./junit-reporter";
import { SocketFramer } from "./socket-framer";
@@ -72,7 +72,7 @@ class BunFrontendDevServerSession extends InspectorSession {
}
}
-describe.if(isPosix)("BunFrontendDevServer inspector protocol", () => {
+describe("BunFrontendDevServer inspector protocol", () => {
let devServerProcess: Subprocess<"ignore", "pipe", "pipe">;
let serverUrl: URL;
let session: BunFrontendDevServerSession;
diff --git a/test/cli/inspect/test-reporter.test.ts b/test/cli/inspect/test-reporter.test.ts
index 607d04a5ea37..5b898a46739f 100644
--- a/test/cli/inspect/test-reporter.test.ts
+++ b/test/cli/inspect/test-reporter.test.ts
@@ -1,6 +1,6 @@
import { Subprocess, spawn, write } from "bun";
import { afterEach, describe, expect, test } from "bun:test";
-import { bunEnv, bunExe, isPosix, tempDir } from "harness";
+import { bunEnv, bunExe, tempDir } from "harness";
import { join } from "node:path";
import { InspectorSession, connect } from "./junit-reporter";
import { SocketFramer } from "./socket-framer";
@@ -165,7 +165,7 @@ class TestReporterSession extends InspectorSession {
}
}
-describe.if(isPosix)("TestReporter inspector protocol", () => {
+describe("TestReporter inspector protocol", () => {
let proc: Subprocess<"ignore", "pipe", "pipe"> | undefined;
let socket: ReturnType extends Promise ? T : never;
diff --git a/test/cli/install/bun-add-filter.test.ts b/test/cli/install/bun-add-filter.test.ts
index e3b8a3a9289a..aca9546b44d1 100644
--- a/test/cli/install/bun-add-filter.test.ts
+++ b/test/cli/install/bun-add-filter.test.ts
@@ -2408,7 +2408,7 @@ test.concurrent("remove --filter --dry-run touches nothing", async () => {
expect(await exists(join(dir, "node_modules", "no-deps", "package.json"))).toBeTrue();
});
-test.concurrent.skipIf(isWindows || isRoot)(
+test.concurrent.skipIf(isRoot)(
"an unwritable target is reported by name, the rest is still written, exit code 1",
async () => {
const dir = await makeMonorepo();
diff --git a/test/cli/install/bun-install-git-deps.test.ts b/test/cli/install/bun-install-git-deps.test.ts
index 47c5ebc990a4..9b07689f74f8 100644
--- a/test/cli/install/bun-install-git-deps.test.ts
+++ b/test/cli/install/bun-install-git-deps.test.ts
@@ -675,7 +675,7 @@ function expectOneStoreEntry(project: string, aliases: string[]) {
// folder taken moves it away (`move_to_cache_directory` in extract_tarball.rs) while another one is still reading its
// package.json. Occasionally that one creates a package with no name and no dependencies.
for (const linker of ["isolated", "hoisted"] as const) {
- test.concurrent.skipIf(isWindows)(
+ test.concurrent(
`${linker} linker installs github: refs that point to one commit as one package`,
async () => {
using dir = tempDir(`github-one-commit-${linker}`, {});
@@ -739,7 +739,7 @@ for (const linker of ["isolated", "hoisted"] as const) {
// The same for a repository whose package.json has no name, or that has no package.json. The package is named after the
// repository, for every ref.
-test.concurrent.skipIf(isWindows).each([
+test.concurrent.each([
["a package.json without a name", { "package.json": JSON.stringify({ version: "1.0.0" }) }],
["no package.json", {}],
])(
@@ -2826,7 +2826,7 @@ test.concurrent.each([
});
// It's neither a URL nor an scp-style path, so git would read it as a directory in the project and clone that.
-test.concurrent.skipIf(isWindows)("does not hand a bare word to git clone", async () => {
+test.concurrent("does not hand a bare word to git clone", async () => {
const { calls, stderr, exitCode } = await failingGitCalls("git+:latest");
expect(calls).toEqual([]);
// It's a git dependency, so the registry wasn't asked for a `git+:latest` tag.
@@ -3495,7 +3495,7 @@ test.concurrent("bun update moves a git dependency without a committish to the n
});
// Ubuntu 22.04 has git 2.34, Debian 11 has 2.30.
-test.concurrent.skipIf(isWindows)("clones with a git older than 2.39, which refuses --bare with --origin", async () => {
+test.concurrent("clones with a git older than 2.39, which refuses --bare with --origin", async () => {
using dir = tempDir("git-dep-old-git", {
"bin/git": `#!/bin/sh
for arg in "$@"; do
@@ -3932,7 +3932,7 @@ test.concurrent("a git dependency with a submodule, under the user's own setting
});
// How git fails when it can't use the clone depends on its version.
-test.concurrent.skipIf(isWindows)("clones again after a git fetch that did not fail at the remote", async () => {
+test.concurrent("clones again after a git fetch that did not fail at the remote", async () => {
using dir = tempDir("git-dep-fetch-exit-code", {});
const root = String(dir);
const bare = await makeSharedRepo(root, [{ name: "dep", branch: "main" }]);
diff --git a/test/cli/install/bun-install-lifecycle-scripts.test.ts b/test/cli/install/bun-install-lifecycle-scripts.test.ts
index b2b134c55469..4c1b624a7eb8 100644
--- a/test/cli/install/bun-install-lifecycle-scripts.test.ts
+++ b/test/cli/install/bun-install-lifecycle-scripts.test.ts
@@ -3073,7 +3073,7 @@ describe.concurrent.each(["hoisted", "isolated"] as const)("the install after a
// One at a time, so that the third script to start is the one that fails. Two have finished and aren't run again, and
// one hasn't started.
- test.skipIf(isWindows).each([
+ test.each([
{ title: "preinstall", script: "preinstall", args: [] },
{ title: "install", script: "install", args: [] },
{ title: "postinstall", script: "postinstall", args: [] },
@@ -3103,7 +3103,7 @@ describe.concurrent.each(["hoisted", "isolated"] as const)("the install after a
expect(await install("third.txt", 100, ...args)).toEqual({ errors: [], ran: [], exitCode: 0 });
});
- test.skipIf(isWindows)("all at the same time: every script runs in the end", async () => {
+ test("all at the same time: every script runs in the end", async () => {
const { ctx, install } = await setup("postinstall");
using _ = ctx;
@@ -3166,7 +3166,7 @@ describe.concurrent.each(["hoisted", "isolated"] as const)("the install after a
// The root's `dep` is a different package. With the hoisted linker, each parent has its own copy, and the first one
// fails before the walk reaches the last.
- test.skipIf(isWindows)("copies that the failed install hadn't reached", async () => {
+ test("copies that the failed install hadn't reached", async () => {
const parents = Array.from({ length: 40 }, (_, i) => `parent-${i}`);
using ctx = await setupScriptPackages(linker, {
scripted: { scripts: { postinstall: `echo ran >> "$RUNS" && test -z "$FAIL"` } },
diff --git a/test/cli/install/bun-install-native-binlink.test.ts b/test/cli/install/bun-install-native-binlink.test.ts
index edbe55172151..f114c3f36762 100644
--- a/test/cli/install/bun-install-native-binlink.test.ts
+++ b/test/cli/install/bun-install-native-binlink.test.ts
@@ -120,7 +120,7 @@ describe.concurrent("native binlink optimization", () => {
// bunx takes the bin of a package from that package's own package.json. Here the entry in `.bin` leads into
// the platform package, and the file of the main package keeps the mode of its tarball.
- test.skipIf(isWindows).each(["a folder", "a link to another folder"])(
+ test.each(["a folder", "a link to another folder"])(
`bunx runs the platform-specific bin with linker ${linker} and node_modules %s`,
async nodeModules => {
let env = { ...bunEnv };
@@ -294,7 +294,7 @@ describe.concurrent("native binlink optimization", () => {
}
// The link leaves node_modules, so its text depends on where node_modules really is.
- test.skipIf(isWindows)("in a workspace whose node_modules is a link to another folder", async () => {
+ test("in a workspace whose node_modules is a link to another folder", async () => {
const { packageDir, packageJson } = await verdaccio.createTestDir();
const env = { ...bunEnv, BUN_INSTALL_CACHE_DIR: join(packageDir, ".bun-cache") };
const app = join(packageDir, "packages", "app");
diff --git a/test/cli/install/bun-install-patch.test.ts b/test/cli/install/bun-install-patch.test.ts
index b396c5f6645e..af11dc683469 100644
--- a/test/cli/install/bun-install-patch.test.ts
+++ b/test/cli/install/bun-install-patch.test.ts
@@ -6,7 +6,6 @@ import {
bunExe,
DirectoryTree,
isRoot,
- isWindows,
normalizeBunSnapshot as normalizeBunSnapshot_,
runBunInstall,
tempDir,
@@ -470,7 +469,7 @@ diff --git a/package.json b/package.json
// The new directories used to get the file's mode (0644), which only root can enter
// (CAP_DAC_OVERRIDE), so as root the install runs without that capability.
const setpriv = isRoot ? Bun.which("setpriv") : null;
- test.skipIf(isWindows || (isRoot && !setpriv))(
+ test.skipIf(isRoot && !setpriv)(
"should apply a patch that adds a file in a directory the package does not have",
async () => {
await using project = createProject("patch-new-dir", {
@@ -1313,11 +1312,7 @@ describe("patchedDependencies path longer than the path buffer", () => {
});
const [, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
- // The path is handed to the OS as is. POSIX rejects anything longer than
- // PATH_MAX with ENAMETOOLONG; Windows may report it as missing instead.
- if (!isWindows) {
- expect(stderr).toContain("error: failed to read patch file: ENAMETOOLONG: ");
- }
+ expect(stderr).toContain("error: failed to read patch file: ENAMETOOLONG: ");
expect(stderr).toContain(`${longName}.patch`);
expect(exitCode).toBe(1);
});
diff --git a/test/cli/install/bun-install-registry.test.ts b/test/cli/install/bun-install-registry.test.ts
index 67ffcbc8e71d..dc281d7c93bf 100644
--- a/test/cli/install/bun-install-registry.test.ts
+++ b/test/cli/install/bun-install-registry.test.ts
@@ -20,7 +20,6 @@ import {
bunEnv,
bunExe,
isDebug,
- isFlaky,
isLinux,
isMacOS,
isRoot,
@@ -4005,7 +4004,7 @@ describe.concurrent("binaries", () => {
expect(exitCode).toBe(0);
});
- test.skipIf(isWindows)("a stale link, a file and a directory in .bin are replaced", async () => {
+ test("a stale link, a file and a directory in .bin are replaced", async () => {
const { packageDir, packageJson, env } = await setupTest();
const binDir = join(packageDir, "node_modules", ".bin");
await Promise.all([
@@ -7862,7 +7861,7 @@ describe.concurrent("hoisting", async () => {
});
});
- test.serial.todoIf(isFlaky && isWindows)("text lockfile is hoisted", async () => {
+ test.serial("text lockfile is hoisted", async () => {
const { packageDir, packageJson, env } = await setupTest();
// Each dependency depends on 'hoist-lockfile-shared'.
// 1 - "*"
diff --git a/test/cli/install/bun-install-staging.test.ts b/test/cli/install/bun-install-staging.test.ts
index 983d49e458cc..6d6900373d12 100644
--- a/test/cli/install/bun-install-staging.test.ts
+++ b/test/cli/install/bun-install-staging.test.ts
@@ -792,29 +792,26 @@ for (const linker of ["hoisted", "isolated"]) {
// It replaces a link at node_modules/@scope by a directory now, and the isolated
// linker moves a node_modules it did not make aside first.
for (const linker of ["hoisted", "isolated"]) {
- test.concurrent.skipIf(isWindows)(
- `${linker} linker: a dangling node_modules/@scope symlink does not hang the install`,
- async () => {
- const depTarball = await new Bun.Archive(
- { "package/package.json": JSON.stringify({ name: "@scope/dep", version: "1.0.0" }) },
- { compress: "gzip" },
- ).bytes();
- using dir = tempDir(`staging-dangling-scope-${linker}`, {
- "package.json": JSON.stringify({ name: "app", dependencies: { "@scope/dep": "file:./dep-1.0.0.tgz" } }),
- "dep-1.0.0.tgz": Buffer.from(depTarball),
- "node_modules": {},
- "bunfig.toml": ({ root }) => Bun.TOML.stringify({ install: { cache: join(root, ".bun-cache"), linker } }),
- });
- const root = String(dir);
- symlinkSync(join(root, "does-not-exist"), join(root, "node_modules", "@scope"));
+ test.concurrent(`${linker} linker: a dangling node_modules/@scope symlink does not hang the install`, async () => {
+ const depTarball = await new Bun.Archive(
+ { "package/package.json": JSON.stringify({ name: "@scope/dep", version: "1.0.0" }) },
+ { compress: "gzip" },
+ ).bytes();
+ using dir = tempDir(`staging-dangling-scope-${linker}`, {
+ "package.json": JSON.stringify({ name: "app", dependencies: { "@scope/dep": "file:./dep-1.0.0.tgz" } }),
+ "dep-1.0.0.tgz": Buffer.from(depTarball),
+ "node_modules": {},
+ "bunfig.toml": ({ root }) => Bun.TOML.stringify({ install: { cache: join(root, ".bun-cache"), linker } }),
+ });
+ const root = String(dir);
+ symlinkSync(join(root, "does-not-exist"), join(root, "node_modules", "@scope"));
- const { stderr, exitCode } = await install(root);
- expect(stderr).not.toContain("error");
- expect(readdirSync(join(root, "node_modules", "@scope"))).toEqual(["dep"]);
- expect(lstatSync(join(root, "node_modules", "@scope")).isDirectory()).toBe(true);
- expect(exitCode).toBe(0);
- },
- );
+ const { stderr, exitCode } = await install(root);
+ expect(stderr).not.toContain("error");
+ expect(readdirSync(join(root, "node_modules", "@scope"))).toEqual(["dep"]);
+ expect(lstatSync(join(root, "node_modules", "@scope")).isDirectory()).toBe(true);
+ expect(exitCode).toBe(0);
+ });
}
// When linking fails midway, bun sees the error itself instead of being killed,
@@ -1152,7 +1149,7 @@ describe("hoisted linker: packages linked by the thread pool", () => {
});
// The pool keeps the node_modules of a batch open. Each `host-N` has one, for its `inner`.
- test.concurrent.skipIf(isWindows)("a low limit on open files does not fail the install", async () => {
+ test.concurrent("a low limit on open files does not fail the install", async () => {
const hosts = Array.from({ length: 60 }, (_, i) => `host-${i}`);
const files = ["index.js"];
using registry = serveRegistry({
diff --git a/test/cli/install/bun-install.test.ts b/test/cli/install/bun-install.test.ts
index 011399d13c7a..f49622a93d86 100644
--- a/test/cli/install/bun-install.test.ts
+++ b/test/cli/install/bun-install.test.ts
@@ -2146,7 +2146,7 @@ describe.concurrent("bun-install", () => {
// buffer (4096 bytes on Linux, 1024 on macOS), so aliases a few bytes short of it used to crash
// the install right there. A name over 255 bytes no longer gets that far: it is refused when it is read.
// On Windows the buffer is far larger than any path the OS accepts.
- describe.concurrent.skipIf(isWindows)("dependency alias that fills the path buffer", () => {
+ describe.concurrent("dependency alias that fills the path buffer", () => {
const alias = Buffer.alloc((isLinux ? 4096 : 1024) - 6, "a").toString();
async function installIntoExistingNodeModules(cwd: string) {
@@ -16065,7 +16065,7 @@ it.concurrent(doesNotCreateCacheEntryOutside, async () => {
// collide under the seed-0 std.Wyhash that keys the folder-resolution dedupe
// map must each resolve to their own package, not share one identity.
// https://github.com/oven-sh/bun/issues/32741
-it.concurrent.skipIf(isWindows)("file: deps with colliding abs-path hashes resolve to distinct packages", async () => {
+it.concurrent("file: deps with colliding abs-path hashes resolve to distinct packages", async () => {
using dir = tempDir("folder-resolution-collision", {
"package.json": JSON.stringify({ name: "victim", version: "0.0.0" }),
});
@@ -16119,7 +16119,7 @@ it.concurrent.skipIf(isWindows)("file: deps with colliding abs-path hashes resol
});
// The lockfile interns every string over 8 bytes in a pool keyed by Wyhash11(0, bytes).
-it.concurrent.skipIf(isWindows)("two specifiers whose hashes collide stay two strings", async () => {
+it.concurrent("two specifiers whose hashes collide stay two strings", async () => {
const specA = "./t/m3daaaaaaaaaaaaaaaaaaaaaaaaa.7aQs_ePaaaaaaaaw9Aaaaaaaaaaaaaa.tgz";
const specB = "./t/m3daaaaaaaaaaaaaaaaaaaaaaaaa.7aQs_ePbaaaaaaaw9Aaaaaaaaaaaaaa.tgz";
expect(specA).not.toBe(specB);
diff --git a/test/cli/install/bun-link.test.ts b/test/cli/install/bun-link.test.ts
index 0f98bb499114..30fcb1383c8a 100644
--- a/test/cli/install/bun-link.test.ts
+++ b/test/cli/install/bun-link.test.ts
@@ -1026,7 +1026,7 @@ describe("global bin dir", () => {
"elsewhere.txt": "",
});
const binDir = join(String(bunInstall), "bin");
- if (!isWindows) await symlink(join(String(bunInstall), "elsewhere.txt"), join(binDir, "foreign"));
+ await symlink(join(String(bunInstall), "elsewhere.txt"), join(binDir, "foreign"));
// Bins are linked in map order: the taken names first, then the free one.
using pkg = tempDir(
"link-pkg",
@@ -1040,7 +1040,7 @@ describe("global bin dir", () => {
expect(await readFile(join(binDir, binEntry("bun")), "utf8")).toBe("the bun binary");
if (isWindows) expect(await exists(join(binDir, "bun.bunx"))).toBeFalse();
expect(await readFile(join(binDir, binEntry("adir"), "inner.txt"), "utf8")).toBe("keep");
- if (!isWindows) expect(await readlink(join(binDir, "foreign"))).toBe(join(String(bunInstall), "elsewhere.txt"));
+ expect(await readlink(join(binDir, "foreign"))).toBe(join(String(bunInstall), "elsewhere.txt"));
expect(exitCode).toBe(1);
});
@@ -1126,7 +1126,7 @@ describe("global bin dir", () => {
await writeFile(join(binDir, binEntry("bun")), "the bun binary");
await mkdir(join(binDir, binEntry("adir")));
await writeFile(join(binDir, binEntry("adir"), "inner.txt"), "keep");
- if (!isWindows) await symlink(join(String(bunInstall), "elsewhere.txt"), join(binDir, "foreign"));
+ await symlink(join(String(bunInstall), "elsewhere.txt"), join(binDir, "foreign"));
await writeFile(
join(String(pkg), "package.json"),
pkgFiles("own-bin", { "own-bin": "cli.js", bun: "cli.js", adir: "cli.js", foreign: "cli.js" })["package.json"],
@@ -1139,7 +1139,7 @@ describe("global bin dir", () => {
if (isWindows) expect(await exists(join(binDir, "own-bin.bunx"))).toBeFalse();
expect(await readFile(join(binDir, binEntry("bun")), "utf8")).toBe("the bun binary");
expect(await readFile(join(binDir, binEntry("adir"), "inner.txt"), "utf8")).toBe("keep");
- if (!isWindows) expect(await readlink(join(binDir, "foreign"))).toBe(join(String(bunInstall), "elsewhere.txt"));
+ expect(await readlink(join(binDir, "foreign"))).toBe(join(String(bunInstall), "elsewhere.txt"));
expect(result.exitCode).toBe(0);
});
});
diff --git a/test/cli/install/bun-pack.test.ts b/test/cli/install/bun-pack.test.ts
index 81778503351c..86085e4bcd4d 100644
--- a/test/cli/install/bun-pack.test.ts
+++ b/test/cli/install/bun-pack.test.ts
@@ -127,7 +127,7 @@ test.concurrent("the archive is not padded to a full tar record", async () => {
// pack only reads package.json, so a file that is readable but not writable (a read-only
// checkout, a file owned by another user) must not stop it.
-test.concurrent.skipIf(isWindows)("read-only package.json", async () => {
+test.concurrent("read-only package.json", async () => {
using dir = tempDir("pack-read-only", {
"package.json": JSON.stringify({ name: "pack-read-only", version: "1.2.3" }),
"index.js": "console.log('hello ./index.js')",
@@ -1243,7 +1243,7 @@ describe.concurrent("something already exists at the tarball's destination", ()
});
// Serial: `unprivilegedSpawnOptions` may change and restore the modes of directories above the test's own.
- test.serial.skipIf(isWindows)("a writable file in a read-only folder", async () => {
+ test.serial("a writable file in a read-only folder", async () => {
using dir = tempDir("pack-over-locked", { ...files, "pkg/out/pack-over-1.0.0.tgz": "an earlier tarball" });
using unprivileged = unprivilegedSpawnOptions(String(dir));
await chmod(join(dir, "pkg", "out"), 0o555);
@@ -2984,7 +2984,7 @@ describe.concurrent("bundledDependencies", () => {
// The isolated linker's layout: node_modules has links into a store, where a package's dependencies are links next to
// it. `y` goes next to `x`, unless the packed package has its own `y` that it doesn't bundle.
- test.skipIf(isWindows).each([
+ test.each([
{ name: "x", own: {}, y: "node_modules/y" },
{ name: "@s/x", own: {}, y: "node_modules/y" },
{ name: "x", own: { y: "2.0.0" }, y: "node_modules/x/node_modules/y" },
@@ -3028,7 +3028,7 @@ describe.concurrent("bundledDependencies", () => {
});
// Like npm: a link to a folder that is no installed copy is packed by that folder's own rules.
- test.skipIf(isWindows).each([
+ test.each([
["", "project"],
[", also below a folder named node_modules", "node_modules/project"],
])("a bundled workspace is packed with its own files and .npmignore%s", async (_, project) => {
@@ -3416,7 +3416,7 @@ describe.concurrent("bundledDependencies", () => {
});
// The layout of pnpm and of the isolated linker: each package is next to links to its dependencies.
- describe.skipIf(isWindows)("two versions of two packages that depend on each other", () => {
+ describe("two versions of two packages that depend on each other", () => {
async function packLinked(graph: Record>) {
const tree: Record = {
"package.json": JSON.stringify({
@@ -3501,7 +3501,7 @@ describe.concurrent("bundledDependencies", () => {
]);
});
- test.skipIf(isWindows)("bundled dependencies that link to each other end the lookup", async () => {
+ test("bundled dependencies that link to each other end the lookup", async () => {
using dir = tempDir("pack-bundled-dep-cycle", {
"package.json": JSON.stringify({
name: "pack-bundled-dep-cycle",
@@ -3537,7 +3537,7 @@ describe.concurrent("bundledDependencies", () => {
});
// This is what `bun install` creates for a workspace that's a dependency.
- test.skipIf(isWindows)("a scoped bundled dependency that is a link is followed", async () => {
+ test("a scoped bundled dependency that is a link is followed", async () => {
using dir = tempDir("pack-bundled-dep-scoped-link", {
"package.json": JSON.stringify({
name: "pack-bundled-dep-scoped-link",
@@ -3561,7 +3561,7 @@ describe.concurrent("bundledDependencies", () => {
});
// The lookup used to keep every directory it found open.
- test.skipIf(isWindows)("more dependencies than file descriptors", async () => {
+ test("more dependencies than file descriptors", async () => {
const names = Array.from({ length: 299 }, (_, i) => `d${i}`);
using dir = tempDir("pack-bundled-dep-emfile", {
"package.json": JSON.stringify({
diff --git a/test/cli/install/bun-patch.test.ts b/test/cli/install/bun-patch.test.ts
index 3602b698aecb..c839540d90a3 100644
--- a/test/cli/install/bun-patch.test.ts
+++ b/test/cli/install/bun-patch.test.ts
@@ -1070,10 +1070,9 @@ describe.concurrent.each([
const repo = join(String(dir), "gitrepo");
// The checkout in the cache has the symlinks, and the copies in node_modules don't. That used to end up in the
// patch as `deleted file mode 120000`, which no install can apply.
- if (!isWindows) {
- symlinkSync("index.js", join(repo, "main.js"));
- symlinkSync("v2", join(repo, "docs", "latest"));
- }
+
+ symlinkSync("index.js", join(repo, "main.js"));
+ symlinkSync("v2", join(repo, "docs", "latest"));
// keep git away from the machine's global/system config (autocrlf, gpgsign)
const gitEnv = { ...bunEnv, GIT_CONFIG_NOSYSTEM: "1", GIT_CONFIG_GLOBAL: join(String(dir), "no-gitconfig") };
diff --git a/test/cli/install/bun-pm.test.ts b/test/cli/install/bun-pm.test.ts
index 20dd76928c8c..3ae7ed6b8902 100644
--- a/test/cli/install/bun-pm.test.ts
+++ b/test/cli/install/bun-pm.test.ts
@@ -1900,7 +1900,7 @@ describe.concurrent("bun pm cache rm", () => {
});
// Serial: `unprivilegedSpawnOptions` may change and restore the modes of directories above the test's own.
- test.serial.skipIf(isWindows)("a cache directory in a read-only parent is emptied", async () => {
+ test.serial("a cache directory in a read-only parent is emptied", async () => {
using dir = tempDir("pm-cache-rm-read-only-parent", {
...sideFiles,
...projectFiles,
diff --git a/test/cli/install/bun-prune.test.ts b/test/cli/install/bun-prune.test.ts
index e92cc053d564..53c21973d5a2 100644
--- a/test/cli/install/bun-prune.test.ts
+++ b/test/cli/install/bun-prune.test.ts
@@ -1156,7 +1156,7 @@ test.concurrent(
},
);
-test.concurrent.skipIf(isWindows)("a symlinked .bin directory is never cleaned through", async () => {
+test.concurrent("a symlinked .bin directory is never cleaned through", async () => {
const dir = await setup({ name: "foo", dependencies: { "no-deps": "1.0.0" } });
const nm = join(dir, "node_modules");
expect(existsSync(join(nm, ".bin"))).toBeFalse();
diff --git a/test/cli/install/bun-publish.test.ts b/test/cli/install/bun-publish.test.ts
index c39f7786d8ba..79ae7bb8d636 100644
--- a/test/cli/install/bun-publish.test.ts
+++ b/test/cli/install/bun-publish.test.ts
@@ -1568,7 +1568,7 @@ describe.concurrent("--dry-run", () => {
// publish only reads package.json, so a file that is readable but not writable (a
// read-only checkout, a file owned by another user) must not stop it.
- test.skipIf(isWindows)("read-only package.json", async () => {
+ test("read-only package.json", async () => {
using dir = tempDir("publish-read-only", {
"package.json": JSON.stringify({ name: "dry-run-read-only", version: "4.4.4" }),
"index.js": "",
diff --git a/test/cli/install/bun-run-bunfig.test.ts b/test/cli/install/bun-run-bunfig.test.ts
index f8aecb74304c..093114ea31a5 100644
--- a/test/cli/install/bun-run-bunfig.test.ts
+++ b/test/cli/install/bun-run-bunfig.test.ts
@@ -55,7 +55,6 @@ describe.each(["bun run", "bun"])(`%s`, cmd => {
});
describe.each(["bun", "system", "default"])(`run.shell = "%s"`, shellStr => {
- if (isWindows && shellStr === "system") return; // windows always uses the bun shell now
const shell = shellStr === "default" ? (isWindows ? "bun" : "system") : shellStr;
const command_not_found =
isWindows && shell === "system" ? "is not recognized as an internal or external command" : "command not found";
diff --git a/test/cli/install/bun-run.test.ts b/test/cli/install/bun-run.test.ts
index 1c8918227511..0a90692c8661 100644
--- a/test/cli/install/bun-run.test.ts
+++ b/test/cli/install/bun-run.test.ts
@@ -378,8 +378,7 @@ describe.concurrent("bun run", () => {
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
expect(stderr).toContain(`Could not change directory to "${cwdArg}"`);
- // Windows leaves the verdict on a path this long to SetCurrentDirectoryW.
- if (!isWindows) expect(stderr).toContain("ENAMETOOLONG");
+ expect(stderr).toContain("ENAMETOOLONG");
expect(stdout).toBe("");
expect(proc.signalCode).toBeNull();
expect(exitCode).toBe(1);
@@ -772,7 +771,7 @@ describe.concurrent("bun run", () => {
expect(exitCode).toBe(0);
});
- it.skipIf(isWindows)("doesn't change an `npm run` that's only quoted text", async () => {
+ it("doesn't change an `npm run` that's only quoted text", async () => {
const { dir, stdout, exitCode } = await runStart("echo 'step: npm run build -w app' && echo 'ok; done'");
using _ = dir;
expect(stdout).toContain("-w app");
diff --git a/test/cli/install/bun-workspaces-self-contained.test.ts b/test/cli/install/bun-workspaces-self-contained.test.ts
index a8c2d56d16d8..6fbecd607fdc 100644
--- a/test/cli/install/bun-workspaces-self-contained.test.ts
+++ b/test/cli/install/bun-workspaces-self-contained.test.ts
@@ -129,13 +129,13 @@ describe.each([
expect(existsSync(join(desktopNm, "@barn", "moo", "package.json"))).toBeTrue();
expect(readlinkSync(join(desktopNm, "shared"))).toContain("shared");
// … as real files, not hardlinks into the cache
- if (!isWindows) {
- expect(lstatSync(join(desktopNm, "bar")).isSymbolicLink()).toBeFalse();
- expect(lstatSync(join(desktopNm, "bar", "package.json")).isSymbolicLink()).toBeFalse();
- expect(statSync(join(desktopNm, "bar", "package.json")).nlink).toBe(1);
- // control: the root's copy of the same package *is* hardlinked from the cache
- expect(statSync(join(package_dir, "node_modules", "bar", "package.json")).nlink).toBeGreaterThan(1);
- }
+
+ expect(lstatSync(join(desktopNm, "bar")).isSymbolicLink()).toBeFalse();
+ expect(lstatSync(join(desktopNm, "bar", "package.json")).isSymbolicLink()).toBeFalse();
+ expect(statSync(join(desktopNm, "bar", "package.json")).nlink).toBe(1);
+ // control: the root's copy of the same package *is* hardlinked from the cache
+ expect(statSync(join(package_dir, "node_modules", "bar", "package.json")).nlink).toBeGreaterThan(1);
+
// even though `bar` also exists at the root for the root package / other workspaces
expect(existsSync(join(package_dir, "node_modules", "bar", "package.json"))).toBeTrue();
// the other workspace hoists as usual
@@ -155,9 +155,8 @@ describe.each([
expect(again.err).not.toContain("error:");
expect(again.code).toBe(0);
expect(await readdirSorted(desktopNm)).toEqual(["@barn", "bar", "baz", "shared"]);
- if (!isWindows) {
- expect(statSync(join(desktopNm, "bar", "package.json")).nlink).toBe(1);
- }
+
+ expect(statSync(join(desktopNm, "bar", "package.json")).nlink).toBe(1);
});
});
diff --git a/test/cli/install/bun-workspaces.test.ts b/test/cli/install/bun-workspaces.test.ts
index 4a2a612072b0..00d9ceaecaeb 100644
--- a/test/cli/install/bun-workspaces.test.ts
+++ b/test/cli/install/bun-workspaces.test.ts
@@ -4299,9 +4299,8 @@ test.concurrent("a copyfile install over a workspace's hardlinked files does not
const nestedPkgJson = join(packageDir, "packages", "pkg1", "node_modules", "no-deps", "package.json");
await install("hardlink");
expect(readJson(nestedPkgJson)).toEqual({ name: "no-deps", version: "2.0.0" });
- if (!isWindows) {
- expect(statSync(nestedPkgJson).nlink).toBeGreaterThan(1);
- }
+
+ expect(statSync(nestedPkgJson).nlink).toBeGreaterThan(1);
await rm(join(packageDir, "node_modules"), { recursive: true, force: true });
await install("copyfile");
@@ -4311,10 +4310,9 @@ test.concurrent("a copyfile install over a workspace's hardlinked files does not
name: "no-deps",
version: "1.0.0",
});
- if (!isWindows) {
- // a new file, not the cache file's inode
- expect(statSync(nestedPkgJson).nlink).toBe(1);
- }
+
+ // a new file, not the cache file's inode
+ expect(statSync(nestedPkgJson).nlink).toBe(1);
const cacheDir = join(packageDir, ".bun-cache");
const cached = (await readdirSorted(cacheDir)).filter(name => name.startsWith("no-deps@2.0.0@"));
@@ -4324,8 +4322,7 @@ test.concurrent("a copyfile install over a workspace's hardlinked files does not
});
for (const linker of ["hoisted", "isolated"]) {
- // symlinkSync to a directory needs Developer Mode or elevation on Windows.
- test.concurrent.skipIf(isWindows)(`workspace globs match a symlinked member directory (${linker})`, async () => {
+ test.concurrent(`workspace globs match a symlinked member directory (${linker})`, async () => {
using ctx = await setupTest();
const { packageDir, env } = ctx;
// Its own version of no-deps is installed in its own node_modules, behind the link.
@@ -4378,7 +4375,7 @@ for (const [link, target] of [
["packages/s", "real/deeper/s"],
["packages", "real/deeper"],
]) {
- test.concurrent.skipIf(isWindows)(`isolated: a member finds its dependencies when ${link} is a symlink`, async () => {
+ test.concurrent(`isolated: a member finds its dependencies when ${link} is a symlink`, async () => {
using ctx = await setupTest();
const { packageDir, env } = ctx;
await Promise.all([
@@ -4572,7 +4569,7 @@ describe("a workspace outside the project", () => {
});
});
-describe.skipIf(isWindows)("in a workspace that's a link to a folder somewhere else", () => {
+describe("in a workspace that's a link to a folder somewhere else", () => {
/** `cwd` and `pwd` are relative to the directory that holds `repo` and `other`. */
async function install(cwd: string, pwd: string) {
using ctx = await setupTest();
@@ -4747,7 +4744,7 @@ describe.skipIf(isWindows)("in a workspace that's a link to a folder somewhere e
});
});
-test.concurrent.skipIf(isWindows)("`**` in a workspace glob does not go through a symlinked directory", async () => {
+test.concurrent("`**` in a workspace glob does not go through a symlinked directory", async () => {
using ctx = await setupTest();
const { packageDir, env } = ctx;
await Promise.all([
@@ -5034,7 +5031,7 @@ describe("links of a renamed or removed workspace", () => {
// the isolated linker looped forever. On POSIX a symlinked root package.json
// made workspace discovery run in the symlink target's directory.
describe("aliased project root", () => {
- test.concurrent.skipIf(isWindows)("workspaces install when the root package.json is a symlink", async () => {
+ test.concurrent("workspaces install when the root package.json is a symlink", async () => {
using ctx = await setupTest();
const { packageDir, env } = ctx;
await Promise.all([
diff --git a/test/cli/install/bunx-directories-bin.test.ts b/test/cli/install/bunx-directories-bin.test.ts
index fd2702b6d456..1a991000eeec 100644
--- a/test/cli/install/bunx-directories-bin.test.ts
+++ b/test/cli/install/bunx-directories-bin.test.ts
@@ -49,7 +49,7 @@ const rejected: [label: string, value: (dir: string) => string, picked: string][
];
for (const [label, value, picked] of rejected) {
- test.concurrent.skipIf(isWindows)(`bunx ignores a directories.bin that is ${label}`, async () => {
+ test.concurrent(`bunx ignores a directories.bin that is ${label}`, async () => {
using dir = tempDir("bunx-directories-bin-rejected", {
"package.json": JSON.stringify({ name: "app", dependencies: { tool: "file:./tool" } }),
"tool/package.json": "",
diff --git a/test/cli/install/bunx.test.ts b/test/cli/install/bunx.test.ts
index 5c7841e88ab7..58267d695c53 100644
--- a/test/cli/install/bunx.test.ts
+++ b/test/cli/install/bunx.test.ts
@@ -3033,8 +3033,7 @@ describe("a package in node_modules", () => {
});
});
- // On Windows the entry is no link, so it does not say whose it is.
- it.concurrent.skipIf(isWindows).each([[["@corp/tool"]], [["-p", "@corp/tool", "tool"]]])(
+ it.concurrent.each([[["@corp/tool"]], [["-p", "@corp/tool", "tool"]]])(
"bunx %j runs the bin of that package where another one has the entry in .bin",
async args => {
using box = sandbox();
@@ -3126,7 +3125,7 @@ describe("flags", () => {
const expected = { stdout: `local ${flags}\n`, stderr: "", exitCode: 0, requests: [] };
expect(await box.run([...flags.split(" "), "local-tool", ...flags.split(" ")])).toEqual(expected);
- if (isWindows) return;
+
symlinkSync(bunExe(), join(box.dir, isDebug ? "bun-debug" : "bun"));
const env = { ...box.env, PATH: box.dir + delimiter + box.env.PATH };
expect(await box.run(["run", "--silent", "tool"], { env, bunx: [bunExe()] })).toEqual(expected);
diff --git a/test/cli/install/npmrc.test.ts b/test/cli/install/npmrc.test.ts
index 9ec486cdaaa5..c0878e93e061 100644
--- a/test/cli/install/npmrc.test.ts
+++ b/test/cli/install/npmrc.test.ts
@@ -300,7 +300,7 @@ registry = http://localhost:${registry.port}/
expect(result.exitCode).toBe(0);
});
- it.skipIf(isWindows)("bun install prints nothing when $NPM_CONFIG_USERCONFIG is a directory", async () => {
+ it("bun install prints nothing when $NPM_CONFIG_USERCONFIG is a directory", async () => {
using dir = tempDir("npmrc-userconfig-directory", { ...pkg, "home/.keep": "", "elsewhere/ci.npmrc/.keep": "" });
const directory = join(String(dir), "elsewhere", "ci.npmrc");
const result = await bun(String(dir), { NPM_CONFIG_USERCONFIG: directory }, "install");
@@ -5235,7 +5235,7 @@ describe.concurrent("`ca` and `cafile` are one setting: a layer that sets either
// Like npm, Bun skips a config file that it can't read, e.g. a root-owned ~/.npmrc in a Docker image that runs as another
// user. Not concurrent: `unprivilegedSpawnOptions` may change and restore the modes of directories above the test's own.
-describe.skipIf(isWindows)("unreadable config files are skipped", () => {
+describe("unreadable config files are skipped", () => {
/** Runs bun in `/project` with `/home` as the home directory, as a user that file modes apply to. */
async function run(
cmd: string[],
diff --git a/test/cli/install/redacted-config-logs.test.ts b/test/cli/install/redacted-config-logs.test.ts
index a5f631a9cd34..f3058563f1b7 100644
--- a/test/cli/install/redacted-config-logs.test.ts
+++ b/test/cli/install/redacted-config-logs.test.ts
@@ -1,6 +1,6 @@
import { iniInternals } from "bun:internal-for-testing";
import { describe, expect, test } from "bun:test";
-import { bunEnv, bunExe, hostedGitRepository, isWindows, tempDir } from "harness";
+import { bunEnv, bunExe, hostedGitRepository, tempDir } from "harness";
import { join } from "path";
test("registry url password is sent as Basic auth and left out of request error output", async () => {
@@ -1221,7 +1221,7 @@ describe.concurrent("the userinfo of a git URL is masked as a whole", () => {
});
// git names the URL it wants a password for, and bun passes on what git says.
- test.skipIf(isWindows)("git's own output", async () => {
+ test("git's own output", async () => {
await using server = Bun.serve({
port: 0,
hostname: "127.0.0.1",
@@ -1242,7 +1242,7 @@ describe.concurrent("the userinfo of a git URL is masked as a whole", () => {
});
// When no form of the URL can be cloned, each is named above what git said of it.
- test.skipIf(isWindows)("every form of a URL that cannot be cloned", async () => {
+ test("every form of a URL that cannot be cloned", async () => {
const url = (scheme: string, userinfo: string) => `${scheme}://${userinfo}@example.com/org/lib.git`;
await using server = Bun.serve({
port: 0,
diff --git a/test/cli/install/symlink-path-traversal.test.ts b/test/cli/install/symlink-path-traversal.test.ts
index 744a3b289d6e..2971b69c29a8 100644
--- a/test/cli/install/symlink-path-traversal.test.ts
+++ b/test/cli/install/symlink-path-traversal.test.ts
@@ -770,108 +770,104 @@ describe.concurrent.skipIf(isWindows)("symlink path traversal protection", () =>
}
});
-it.skipIf(isWindows)(
- "rejects symlink targets that climb through other symlinks from the same archive (.bun-tag write stays inside the package)",
- async () => {
- // A tarball can ship symlinks whose targets each normalize to a path
- // inside the package (`l1 -> .`, `l2 -> l1/..`, `l3 -> l2/..`, ...).
- // Lexically every hop is "safe", but the kernel resolves each link before
- // applying `..`, so each hop climbs one directory until it clamps at `/`.
- // A final `.bun-tag -> lN/` entry then
- // makes the post-extraction `.bun-tag` marker write (O_CREAT|O_TRUNC) land
- // on an arbitrary file. The extractor must reject symlink targets with a
- // `..` component that follows a named component, and must not follow a
- // pre-existing `.bun-tag` when writing the marker.
- const victimPath = join(systemTmpDir, `bun-tag-victim-${Math.random().toString(36).slice(2, 10)}.txt`);
- await writeFile(victimPath, "original-content");
-
- const chainLength = 30;
- const entries: Parameters[0] = [
- { name: "test-package/", type: "dir" },
- {
- name: "test-package/package.json",
- type: "file",
- content: JSON.stringify({ name: "test-package", version: "1.0.0" }),
- },
- { name: "test-package/l1", type: "symlink", linkname: "." },
- ];
- for (let i = 2; i <= chainLength; i++) {
- // Normalizes to "" (inside the package), but resolves one directory
- // above wherever l(i-1) resolves to.
- entries.push({ name: `test-package/l${i}`, type: "symlink", linkname: `l${i - 1}/..` });
- }
- // After `chainLength` hops the chain is clamped at `/`, so this resolves to
- // the absolute victim path while still normalizing to a path inside the
- // package directory.
- entries.push({
- name: "test-package/.bun-tag",
- type: "symlink",
- linkname: `l${chainLength}/${victimPath.replace(/^\/+/, "")}`,
- });
- const tarball = createTarball(entries);
-
- const server = Bun.serve({
- port: 0,
- fetch(req) {
- const url = new URL(req.url);
- if (url.pathname.includes("/tarball/") || url.pathname.endsWith(".tar.gz")) {
- return new Response(tarball, { headers: { "Content-Type": "application/gzip" } });
- }
- if (url.pathname.includes("/repos/")) {
- return Response.json({ default_branch: "main" });
- }
- return new Response("Not Found", { status: 404 });
- },
- });
+it("rejects symlink targets that climb through other symlinks from the same archive (.bun-tag write stays inside the package)", async () => {
+ // A tarball can ship symlinks whose targets each normalize to a path
+ // inside the package (`l1 -> .`, `l2 -> l1/..`, `l3 -> l2/..`, ...).
+ // Lexically every hop is "safe", but the kernel resolves each link before
+ // applying `..`, so each hop climbs one directory until it clamps at `/`.
+ // A final `.bun-tag -> lN/` entry then
+ // makes the post-extraction `.bun-tag` marker write (O_CREAT|O_TRUNC) land
+ // on an arbitrary file. The extractor must reject symlink targets with a
+ // `..` component that follows a named component, and must not follow a
+ // pre-existing `.bun-tag` when writing the marker.
+ const victimPath = join(systemTmpDir, `bun-tag-victim-${Math.random().toString(36).slice(2, 10)}.txt`);
+ await writeFile(victimPath, "original-content");
+
+ const chainLength = 30;
+ const entries: Parameters[0] = [
+ { name: "test-package/", type: "dir" },
+ {
+ name: "test-package/package.json",
+ type: "file",
+ content: JSON.stringify({ name: "test-package", version: "1.0.0" }),
+ },
+ { name: "test-package/l1", type: "symlink", linkname: "." },
+ ];
+ for (let i = 2; i <= chainLength; i++) {
+ // Normalizes to "" (inside the package), but resolves one directory
+ // above wherever l(i-1) resolves to.
+ entries.push({ name: `test-package/l${i}`, type: "symlink", linkname: `l${i - 1}/..` });
+ }
+ // After `chainLength` hops the chain is clamped at `/`, so this resolves to
+ // the absolute victim path while still normalizing to a path inside the
+ // package directory.
+ entries.push({
+ name: "test-package/.bun-tag",
+ type: "symlink",
+ linkname: `l${chainLength}/${victimPath.replace(/^\/+/, "")}`,
+ });
+ const tarball = createTarball(entries);
+
+ const server = Bun.serve({
+ port: 0,
+ fetch(req) {
+ const url = new URL(req.url);
+ if (url.pathname.includes("/tarball/") || url.pathname.endsWith(".tar.gz")) {
+ return new Response(tarball, { headers: { "Content-Type": "application/gzip" } });
+ }
+ if (url.pathname.includes("/repos/")) {
+ return Response.json({ default_branch: "main" });
+ }
+ return new Response("Not Found", { status: 404 });
+ },
+ });
- try {
- using dir = tempDir("bun-tag-symlink-chain-test", {});
- const installDir = String(dir);
+ try {
+ using dir = tempDir("bun-tag-symlink-chain-test", {});
+ const installDir = String(dir);
- await writeFile(
- join(installDir, "package.json"),
- JSON.stringify({
- name: "test-app",
- version: "1.0.0",
- dependencies: { "test-package": "github:user/repo#main" },
- }),
- );
+ await writeFile(
+ join(installDir, "package.json"),
+ JSON.stringify({
+ name: "test-app",
+ version: "1.0.0",
+ dependencies: { "test-package": "github:user/repo#main" },
+ }),
+ );
- const proc = spawn({
- cmd: [bunExe(), "install"],
- cwd: installDir,
- stdout: "pipe",
- stderr: "pipe",
- env: {
- ...env,
- GITHUB_API_URL: `http://localhost:${server.port}`,
- BUN_INSTALL_CACHE_DIR: join(installDir, ".bun-cache"),
- },
- });
+ const proc = spawn({
+ cmd: [bunExe(), "install"],
+ cwd: installDir,
+ stdout: "pipe",
+ stderr: "pipe",
+ env: {
+ ...env,
+ GITHUB_API_URL: `http://localhost:${server.port}`,
+ BUN_INSTALL_CACHE_DIR: join(installDir, ".bun-cache"),
+ },
+ });
- const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
+ const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
- // The file outside the extraction directory must be untouched: same
- // content, not truncated, not replaced with the github tag string.
- expect(await Bun.file(victimPath).text()).toBe("original-content");
+ // The file outside the extraction directory must be untouched: same
+ // content, not truncated, not replaced with the github tag string.
+ expect(await Bun.file(victimPath).text()).toBe("original-content");
- // The legitimate package contents are still installed.
- const pkgDir = join(installDir, "node_modules", "test-package");
- await access(join(pkgDir, "package.json"));
+ // The legitimate package contents are still installed.
+ const pkgDir = join(installDir, "node_modules", "test-package");
+ await access(join(pkgDir, "package.json"));
- if (exitCode !== 0) {
- console.error("Install failed with exit code:", exitCode);
- console.error("stdout:", stdout);
- console.error("stderr:", stderr);
- }
- expect(exitCode).toBe(0);
- } finally {
- server.stop();
- await rm(victimPath, { force: true });
+ if (exitCode !== 0) {
+ console.error("Install failed with exit code:", exitCode);
+ console.error("stdout:", stdout);
+ console.error("stderr:", stderr);
}
- },
- 60000,
-);
+ expect(exitCode).toBe(0);
+ } finally {
+ server.stop();
+ await rm(victimPath, { force: true });
+ }
+}, 60000);
it.skipIf(isWindows)(
"does not change permissions of a file reached through a symlinked bin target",
@@ -1076,7 +1072,7 @@ it.skipIf(isWindows)(
// The cache folder and the bun.lock entry of a `github:` package are named after the root
// directory of its tarball: the first component of the first entry's path, whatever that
// entry is. A tarball with a Content-Length and a chunked one go through different readers.
-describe.concurrent.skipIf(isWindows)("the root directory of a GitHub tarball", () => {
+describe.concurrent("the root directory of a GitHub tarball", () => {
const readers = ["buffered", "streaming"] as const;
async function install(reader: (typeof readers)[number], root: string, first: string[] = []) {
@@ -1305,7 +1301,7 @@ describe.concurrent("links below node_modules with the hoisted linker", () => {
});
// People do link the project's own `node_modules` (a Docker volume, Nix, Bazel).
- it.skipIf(isWindows)("still installs through a link at the project's own node_modules", async () => {
+ it("still installs through a link at the project's own node_modules", async () => {
using root = tempDir("nm-root", {});
const volume = join(String(root), "volume");
const repo = join(String(root), "repo");
@@ -1367,7 +1363,7 @@ describe.concurrent("links below node_modules with the hoisted linker", () => {
});
// `lodash` is found installed through the link before `zod` is written.
- it.skipIf(isWindows)("keeps what's behind a workspace's link when one package changes", async () => {
+ it("keeps what's behind a workspace's link when one package changes", async () => {
using root = tempDir("nm-member-change", {});
const repo = await workspaceWithNestedDep(String(root));
for (const major of [1, 2, 3]) {
@@ -1399,7 +1395,7 @@ describe.concurrent("links below node_modules with the hoisted linker", () => {
expect(exitCode).toBe(0);
});
- it.skipIf(isWindows)("keeps a workspace member's link when it replaces the isolated linker's tree", async () => {
+ it("keeps a workspace member's link when it replaces the isolated linker's tree", async () => {
using root = tempDir("nm-member-switch", {});
const repo = await workspaceWithNestedDep(String(root));
expect((await runBun(repo, ["install", "--ignore-scripts", "--linker", "isolated"])).exitCode).toBe(0);
@@ -1512,7 +1508,7 @@ describe.concurrent("links below node_modules with the hoisted linker", () => {
// The links are planted after the install, so only `bun remove` itself is between its deletes and the victim. It
// deletes the leftover `@scope/` and the dangling links in `.bin`.
- it.skipIf(isWindows)("bun remove does not delete through node_modules/@scope or .bin", async () => {
+ it("bun remove does not delete through node_modules/@scope or .bin", async () => {
using dir = tempDir("nm-remove-planted", {
"package.json": JSON.stringify({
name: "remove-scope-symlink-app",
@@ -1792,7 +1788,7 @@ describe.concurrent("links below node_modules with the isolated linker", () => {
}
// People do link the project's own `node_modules` (a Docker volume, Nix, Bazel).
- it.skipIf(isWindows)("still installs through a link at the project's own node_modules", async () => {
+ it("still installs through a link at the project's own node_modules", async () => {
using root = tempDir("nm-root", {});
const volume = join(String(root), "volume");
await mkdir(volume);
diff --git a/test/cli/lint/config-files.test.ts b/test/cli/lint/config-files.test.ts
index fd4e36209e43..027407209285 100644
--- a/test/cli/lint/config-files.test.ts
+++ b/test/cli/lint/config-files.test.ts
@@ -6597,7 +6597,7 @@ describe.skipIf(!hasRunner)("Windows paths, on every platform", () => {
// This is what ESLint 10.12.0, ESLint 8.57.1 and oxlint 1.87.0 do with the same files. Without a config file, bun lint
// behaves like oxlint.
-describe.skipIf(isWindows).concurrent("a symlink that's dangling or points to itself or a parent directory", () => {
+describe.concurrent("a symlink that's dangling or points to itself or a parent directory", () => {
const flavors: Record> = {
"eslint.config.js": { "eslint.config.js": `export default [${JSON.stringify(noVar)}];` },
".eslintrc.json": { ".eslintrc.json": rc(noVar) },
diff --git a/test/cli/lint/git.test.ts b/test/cli/lint/git.test.ts
index eb0e7fe36196..e3fdbebd08ea 100644
--- a/test/cli/lint/git.test.ts
+++ b/test/cli/lint/git.test.ts
@@ -290,7 +290,7 @@ describe.concurrent.each(commands)("bun %s", command => {
await commit(join(root, "inner"));
write(root, "inner/a.js", before);
await git(join(root, "inner"), "add", "-A");
- if (!isWindows) symlinkSync("a.js", join(root, "link.js"));
+ symlinkSync("a.js", join(root, "link.js"));
write(root, "b.js", before);
await git(root, "add", "-A");
@@ -444,7 +444,7 @@ describe.concurrent.each(commands)("bun %s", command => {
expect(await git(root, "show", ":sub/bad.js")).toBe("\n" + before);
});
- test.skipIf(isWindows)("works in a pre-commit hook, on the index of that commit", async () => {
+ test("works in a pre-commit hook, on the index of that commit", async () => {
using repo = await repository({ "a.js": tidy, "b.js": tidy });
const { root } = repo;
const hook = join(root, ".git/hooks/pre-commit");
@@ -463,7 +463,7 @@ describe.concurrent.each(commands)("bun %s", command => {
expect(await git(root, "status", "--porcelain")).toBe("");
});
- test.skipIf(isWindows)("git never runs programs named in the repository's config", async () => {
+ test("git never runs programs named in the repository's config", async () => {
using repo = await repository({ "a.js": tidy, "b.js": tidy, ".gitattributes": "*.js diff=mine\n" });
const { root } = repo;
const program = join(root, "program.sh");
@@ -643,33 +643,25 @@ describe.concurrent("bun lint --staged reads the staged version of a partly stag
expect(exitCode).toBe(1);
});
- test.skipIf(isWindows)(
- "for a file passed through a symlinked path, and a package.json with a byte order mark",
- async () => {
- const module = {
- "package.json": '\uFEFF{ "type": "module" }',
- "tsconfig.json": '{ "compilerOptions": { "module": "nodenext", "lib": ["es2015"], "types": [] } }',
- };
- using repo = await repository({ ...module, "a.ts": tidy });
- const { root } = repo;
- write(root, "a.ts", "export async function f(a: number) {\n await a;\n return import.meta;\n}\n");
- write(root, "package.json", module["package.json"] + "\n");
- await git(root, "add", "-A");
- write(root, "a.ts", tidy);
- write(root, "package.json", module["package.json"]);
- using links = tempDir("bun-lint-git-link", {});
- symlinkSync(root, join(String(links), "link"));
- const { stdout, exitCode } = await bun(root, [
- "lint",
- "--staged",
- ...flags,
- join(String(links), "link", "a.ts"),
- ]);
- expect(stdout).toContain("a.ts:2:3: ");
- expect(stdout).toMatch(/^1 problem$/m);
- expect(exitCode).toBe(1);
- },
- );
+ test("for a file passed through a symlinked path, and a package.json with a byte order mark", async () => {
+ const module = {
+ "package.json": '\uFEFF{ "type": "module" }',
+ "tsconfig.json": '{ "compilerOptions": { "module": "nodenext", "lib": ["es2015"], "types": [] } }',
+ };
+ using repo = await repository({ ...module, "a.ts": tidy });
+ const { root } = repo;
+ write(root, "a.ts", "export async function f(a: number) {\n await a;\n return import.meta;\n}\n");
+ write(root, "package.json", module["package.json"] + "\n");
+ await git(root, "add", "-A");
+ write(root, "a.ts", tidy);
+ write(root, "package.json", module["package.json"]);
+ using links = tempDir("bun-lint-git-link", {});
+ symlinkSync(root, join(String(links), "link"));
+ const { stdout, exitCode } = await bun(root, ["lint", "--staged", ...flags, join(String(links), "link", "a.ts")]);
+ expect(stdout).toContain("a.ts:2:3: ");
+ expect(stdout).toMatch(/^1 problem$/m);
+ expect(exitCode).toBe(1);
+ });
});
test("for a file that no tsconfig.json includes", async () => {
@@ -797,7 +789,7 @@ describe.concurrent("bun lint --staged lints what will be committed", () => {
expect(await git(repo.root, "show", ":gone.js")).toBe(before);
});
- test.skipIf(isWindows)("a staged file that was replaced by a symlink on disk is linted", async () => {
+ test("a staged file that was replaced by a symlink on disk is linted", async () => {
using repo = await repository({ "target.js": clean });
write(repo.root, "f.js", broken);
await git(repo.root, "add", "-A");
@@ -946,20 +938,17 @@ test.concurrent("bun lint --staged reads a conflicted file from disk", async ()
expect(exitCode).toBe(0);
});
-test.skipIf(isWindows).concurrent.each(commands)(
- "bun %s --staged skips a file that is staged as a symlink",
- async command => {
- using repo = await repository({ "target.js": tidy, "a.js": tidy, "b.js": tidy });
- const { root } = repo;
- rmSync(join(root, "a.js"));
- symlinkSync("target.js", join(root, "a.js"));
- write(root, "b.js", before);
- await git(root, "add", "-A");
- rmSync(join(root, "a.js"));
- write(root, "a.js", tidy);
- expect(await selected(root, root, [command, "--staged"])).toEqual(["b.js"]);
- },
-);
+test.concurrent.each(commands)("bun %s --staged skips a file that is staged as a symlink", async command => {
+ using repo = await repository({ "target.js": tidy, "a.js": tidy, "b.js": tidy });
+ const { root } = repo;
+ rmSync(join(root, "a.js"));
+ symlinkSync("target.js", join(root, "a.js"));
+ write(root, "b.js", before);
+ await git(root, "add", "-A");
+ rmSync(join(root, "a.js"));
+ write(root, "a.js", tidy);
+ expect(await selected(root, root, [command, "--staged"])).toEqual(["b.js"]);
+});
test.concurrent("bun fmt --staged doesn't count a file it skips", async () => {
using repo = await repository({ "partly.js": tidy, "whole.js": tidy, "tidy.js": tidy });
diff --git a/test/cli/lint/help.test.ts b/test/cli/lint/help.test.ts
index f8958ff7a439..7b98ec5c22eb 100644
--- a/test/cli/lint/help.test.ts
+++ b/test/cli/lint/help.test.ts
@@ -491,7 +491,7 @@ note: package.json has a "${command}" script, so bun ${command} runs that script
},
);
- test.skipIf(isWindows)("`..` after a symlink resolves to the directory that contains the symlink", async () => {
+ test("`..` after a symlink resolves to the directory that contains the symlink", async () => {
const files = { "project/package.json": script["package.json"], "else/where/deep/b.ts": source };
const before = (dir: string) => symlinkSync("../else/where/deep", join(dir, "project/link"));
expect(await whatRan(files, ["--cwd=link/..", command], "project", { before })).toBe("the script");
@@ -685,7 +685,7 @@ STARTED=1 exec "${bunExe()}" ${again.join(" ")}
});
});
- test.skipIf(isWindows)("a backslash in a directory name isn't a separator", async () => {
+ test("a backslash in a directory name isn't a separator", async () => {
const { stdout, exitCode } = await bun(
{ "a\\b/package.json": script["package.json"] },
[command, "--help"],
@@ -697,7 +697,7 @@ STARTED=1 exec "${bunExe()}" ${again.join(" ")}
// Skipped for `bun check`. Like TypeScript, it treats a backslash as a separator everywhere, so it can't find files
// in a directory like this.
- describe.skipIf(isWindows || command === "check")("a backslash in a directory name with --cwd", () => {
+ describe.skipIf(command === "check")("a backslash in a directory name with --cwd", () => {
// The directory that `a\b` would resolve to if the backslash were a separator.
const other = { "a/b/other.ts": source, "a/b/sub/other.ts": source };
diff --git a/test/cli/lint/init.test.ts b/test/cli/lint/init.test.ts
index 75fb5519a009..abec9786575f 100644
--- a/test/cli/lint/init.test.ts
+++ b/test/cli/lint/init.test.ts
@@ -203,7 +203,7 @@ describe.concurrent.each(["lint", "fmt"] as const)("bun %s --init", command => {
}
});
- describe.skipIf(isWindows)("a bunfig.toml that is a symlink", () => {
+ describe("a bunfig.toml that is a symlink", () => {
const project = { "project/.git/HEAD": "ref: refs/heads/main\n", "project/a.js": "a;\n" };
test("isn't written if it points outside the repository", async () => {
diff --git a/test/cli/lint/lint.test.ts b/test/cli/lint/lint.test.ts
index f3c250536739..c5edb068b019 100644
--- a/test/cli/lint/lint.test.ts
+++ b/test/cli/lint/lint.test.ts
@@ -1419,7 +1419,7 @@ describe.concurrent("bun lint", () => {
});
});
- test.skipIf(isWindows)("a named pipe whose name ends in .js is skipped", async () => {
+ test("a named pipe whose name ends in .js is skipped", async () => {
const { stdout, exitCode } = await lint({ "eslint.config.js": basic, "a.js": bad }, ["-f", "unix", "."], {
before: dir => expect(Bun.spawnSync(["mkfifo", join(dir, "pipe.js")]).exitCode).toBe(0),
});
@@ -1429,7 +1429,7 @@ describe.concurrent("bun lint", () => {
});
// Opening a pipe like this blocks until a writer opens it.
- test.skipIf(isWindows).each([".gitignore", ".git/info/exclude", ".eslintignore", "package.json"])(
+ test.each([".gitignore", ".git/info/exclude", ".eslintignore", "package.json"])(
"doesn't hang when %s is a link to a named pipe without a writer",
async name => {
const { raw } = await lint({ "project/a.js": bad, "project/.git/info/a": "" }, ["-f", "json", "."], {
@@ -7256,18 +7256,15 @@ export default { meta: { name: "q" }, rules: { marks, marked } };\n`,
});
// ESLint doesn't print a report in that case.
- test.skipIf(process.getuid?.() === 0 || isWindows)(
- "still prints the report if a file can't be written",
- async () => {
- const files = { "eslint.config.js": basic, "a.js": "var a = 1;\nexport { a };\n", "b.js": "debugger;\n" };
- const before = (dir: string) => chmodSync(join(dir, "a.js"), 0o444);
- const result = await lint(files, ["--fix", "-f", "unix", "a.js", "b.js"], { reads: ["a.js"], before });
- expect(result.files["a.js"]).toBe(files["a.js"]);
- expect(result.stdout).toContain("[Error/no-debugger]");
- expect(result.stderr).toMatch(/Cannot write .*a\.js: (EACCES|EPERM)/);
- expect(result.exitCode).toBe(2);
- },
- );
+ test.skipIf(process.getuid?.() === 0)("still prints the report if a file can't be written", async () => {
+ const files = { "eslint.config.js": basic, "a.js": "var a = 1;\nexport { a };\n", "b.js": "debugger;\n" };
+ const before = (dir: string) => chmodSync(join(dir, "a.js"), 0o444);
+ const result = await lint(files, ["--fix", "-f", "unix", "a.js", "b.js"], { reads: ["a.js"], before });
+ expect(result.files["a.js"]).toBe(files["a.js"]);
+ expect(result.stdout).toContain("[Error/no-debugger]");
+ expect(result.stderr).toMatch(/Cannot write .*a\.js: (EACCES|EPERM)/);
+ expect(result.exitCode).toBe(2);
+ });
const files = { "eslint.config.js": basic, "a.js": bad, "b.js": "export const b = 1;\n" };
@@ -7989,7 +7986,7 @@ export default { meta: { name: "q" }, rules: { marks, marked } };\n`,
expect(result.files).toEqual({ "a.js": `\uFEFF${bad}` });
});
- test.skipIf(isWindows)("writes through a symlink instead of replacing it", async () => {
+ test("writes through a symlink instead of replacing it", async () => {
const result = await lint(files, ["--fix", "link.js"], {
reads: ["a.js", "link.js"],
before: dir => symlinkSync("a.js", join(dir, "link.js")),
@@ -8098,7 +8095,7 @@ export default { meta: { name: "q" }, rules: { marks, marked } };\n`,
});
// ESLint doesn't need write access to the directory.
- test.skipIf(isWindows || isRoot)("fixes a file in a read-only directory", async () => {
+ test.skipIf(isRoot)("fixes a file in a read-only directory", async () => {
using dir = tempDir("bun-lint", { "eslint.config.js": files["eslint.config.js"], "src/a.js": files["a.js"] });
chmodSync(join(String(dir), "src"), 0o555);
try {
@@ -8582,7 +8579,7 @@ export default { meta: { name: "q" }, rules: { marks, marked } };\n`,
const prunes = flag === "--prune-suppressions";
const missingFileError = prunes ? "The suppressions file does not exist" : symlinkError;
- test.skipIf(isWindows)("refuses to write through a symlink that points outside the repository", async () => {
+ test("refuses to write through a symlink that points outside the repository", async () => {
const options = { cwd: "project", before: link("project/f", "outside/f"), reads: ["outside/f"], mayFail: true };
const [toFile, toNothing] = await Promise.all([
lint({ ...tree, "outside/f": before }, flags("f"), options),
@@ -8632,7 +8629,7 @@ export default { meta: { name: "q" }, rules: { marks, marked } };\n`,
expect(result.exitCode).toBe(exitCode);
});
- test.skipIf(isWindows)("writes through a symlink that points inside the repository and keeps it", async () => {
+ test("writes through a symlink that points inside the repository and keeps it", async () => {
using dir = tempDir("bun-lint", { ...tree, [prunes ? "project/real/f" : "project/real/other"]: before });
link("project/f", "project/real/f")(String(dir));
const result = await run(join(String(dir), "project"), flags("f"));
@@ -8642,7 +8639,7 @@ export default { meta: { name: "q" }, rules: { marks, marked } };\n`,
});
});
- test.skipIf(isWindows)("refuses the default suppressions file if it links outside the repository", async () => {
+ test("refuses the default suppressions file if it links outside the repository", async () => {
const name = "eslint-suppressions.json";
const options = {
cwd: "project",
diff --git a/test/cli/run/as-node.test.ts b/test/cli/run/as-node.test.ts
index 4d291b398033..245aef980d51 100644
--- a/test/cli/run/as-node.test.ts
+++ b/test/cli/run/as-node.test.ts
@@ -1,6 +1,6 @@
import { describe, expect, test } from "bun:test";
import { join } from "path";
-import { bunEnv, bunExe, fakeNodeRun, isMacOS, isWindows, tempDir } from "../../harness";
+import { bunEnv, bunExe, fakeNodeRun, isMacOS, tempDir } from "../../harness";
describe("fake node cli", () => {
test("the node cli actually works", () => {
@@ -31,8 +31,7 @@ describe("fake node cli", () => {
});
expect(fakeNodeRun(temp, "run").stdout).toBe("pass");
});
- // A Windows command line is too short for a path longer than the path buffer.
- test.skipIf(isWindows)("reports module not found for a relative script path longer than PATH_MAX", () => {
+ test("reports module not found for a relative script path longer than PATH_MAX", () => {
const long = Array(21).fill(Buffer.alloc(200, "a").toString()).join("/") + ".js";
using temp = tempDir("fake-node-long", {});
const { exitCode, stdout, stderr } = Bun.spawnSync({
diff --git a/test/cli/run/env.test.ts b/test/cli/run/env.test.ts
index 4b0f401c9d90..9a393b148dc5 100644
--- a/test/cli/run/env.test.ts
+++ b/test/cli/run/env.test.ts
@@ -796,7 +796,7 @@ describe.concurrent(".env that is not a regular file", () => {
expect(script.exitCode).toBe(0);
});
- test.skipIf(isWindows)("unix socket behind a symlink", async () => {
+ test("unix socket behind a symlink", async () => {
using dir = tempDir("dotenv-sock", files);
using listener = Bun.listen({
unix: path.join(String(dir), "sock"),
diff --git a/test/cli/run/filter-workspace.test.ts b/test/cli/run/filter-workspace.test.ts
index 031bd4ee5686..3d177c7f66fc 100644
--- a/test/cli/run/filter-workspace.test.ts
+++ b/test/cli/run/filter-workspace.test.ts
@@ -1572,7 +1572,7 @@ describe("auto-discovered bunfig.toml [run] section", () => {
expect(r.exitCode).toBe(0);
});
- test.skipIf(isWindows)("--elide-lines on the CLI wins over [run] elide-lines", () => {
+ test("--elide-lines on the CLI wins over [run] elide-lines", () => {
using dir = workspace("filter-bunfig-cli-elide", "[run]\nelide-lines = 15\n");
const r = run(String(dir), ["run", "--elide-lines", "0", "--filter", "dep0", "lines"], {
FORCE_COLOR: "1",
diff --git a/test/cli/run/no-orphans.test.ts b/test/cli/run/no-orphans.test.ts
index 8f0606f8b32c..0e322243184d 100644
--- a/test/cli/run/no-orphans.test.ts
+++ b/test/cli/run/no-orphans.test.ts
@@ -266,7 +266,7 @@ describe.concurrent.each([
{ via: "--no-orphans", argv: ["--no-orphans"], bunfig: false, env: {} },
{ via: "bunfig [run] noOrphans = true", argv: [], bunfig: true, env: {} },
])("clean exit reaps descendants", ({ via, argv, bunfig, env: extraEnv }) => {
- test.concurrent.skipIf(!isPosix)(via, async () => {
+ test.concurrent(via, async () => {
using dir = tempDir("no-orphans-clean-exit", {
...(bunfig && { "bunfig.toml": "[run]\nnoOrphans = true\n" }),
"grandchild.js": `process.stdout.write("r"); setInterval(()=>{}, 1000);`,
diff --git a/test/cli/run/run-autoinstall.test.ts b/test/cli/run/run-autoinstall.test.ts
index 95ee83d0ac08..786477e3b4b8 100644
--- a/test/cli/run/run-autoinstall.test.ts
+++ b/test/cli/run/run-autoinstall.test.ts
@@ -2555,7 +2555,7 @@ describe.concurrent("auto-install is off when a security scanner is configured",
expect(await run(files, { cwd: "elsewhere", args: ["../app/src/deep/index.js"] })).toEqual(refused(configured));
});
- test.serial.skipIf(isWindows).each([
+ test.serial.each([
[".npmrc", "a folder of the project", { cwd: "app/src" }],
[".npmrc", "outside the project", { cwd: "elsewhere", args: ["../app/src/index.js"] }],
["bunfig.toml", "outside the project", { cwd: "elsewhere", args: ["../app/src/index.js"] }],
@@ -2578,7 +2578,7 @@ describe.concurrent("auto-install is off when a security scanner is configured",
expect(await run(files)).toEqual(refused(unreadable));
});
- test.serial.skipIf(isWindows).each([
+ test.serial.each([
["the user's bunfig", "home/.bunfig.toml"],
["the user's .npmrc", "home/.npmrc"],
["the project's .npmrc", "app/.npmrc"],
diff --git a/test/cli/run/run-crash-handler.test.ts b/test/cli/run/run-crash-handler.test.ts
index 74764bc4bb5c..9828e826b46e 100644
--- a/test/cli/run/run-crash-handler.test.ts
+++ b/test/cli/run/run-crash-handler.test.ts
@@ -61,44 +61,40 @@ test.if(isDebug && isLinux && hasSymbolizer)(
// JS listener's backing sigaction enqueues to the JS thread and returns;
// without the reset the process would survive the raise and fall through to
// the trap fallback, which on aarch64 (brk → SIGTRAP) used to spin forever.
-test.if(isPosix)(
- "panic terminates the process even when JS registered trap-signal listeners",
- async () => {
- await using proc = Bun.spawn({
- cmd: [
- bunExe(),
- "-e",
- `process.on("SIGTRAP", () => {});
+test("panic terminates the process even when JS registered trap-signal listeners", async () => {
+ await using proc = Bun.spawn({
+ cmd: [
+ bunExe(),
+ "-e",
+ `process.on("SIGTRAP", () => {});
process.on("SIGILL", () => {});
process.on("SIGABRT", () => {});
require("bun:internal-for-testing").crash_handler.panic();`,
- // Make debug builds take the fast trace-string path instead of
- // spawning llvm-symbolizer, which can take tens of seconds.
- "--debug-crash-handler-use-trace-string",
- ],
- env: noReportEnv,
- stdio: ["ignore", "pipe", "pipe"],
- });
+ // Make debug builds take the fast trace-string path instead of
+ // spawning llvm-symbolizer, which can take tens of seconds.
+ "--debug-crash-handler-use-trace-string",
+ ],
+ env: noReportEnv,
+ stdio: ["ignore", "pipe", "pipe"],
+ });
- // Without the fix the child never exits — it loops SIGTRAP delivery on the
- // trap instruction. Bound the wait and fail explicitly rather than hanging
- // the test runner and leaking a core-pinning process.
- const exited = await Promise.race([proc.exited, Bun.sleep(8_000).then(() => "spinning" as const)]);
- if (exited === "spinning") {
- proc.kill("SIGKILL");
- }
+ // Without the fix the child never exits — it loops SIGTRAP delivery on the
+ // trap instruction. Bound the wait and fail explicitly rather than hanging
+ // the test runner and leaking a core-pinning process.
+ const exited = await Promise.race([proc.exited, Bun.sleep(8_000).then(() => "spinning" as const)]);
+ if (exited === "spinning") {
+ proc.kill("SIGKILL");
+ }
- const stderr = await proc.stderr.text();
- expect(exited, `process should have died from the trap, stderr:\n${stderr}`).not.toBe("spinning");
+ const stderr = await proc.stderr.text();
+ expect(exited, `process should have died from the trap, stderr:\n${stderr}`).not.toBe("spinning");
- // It went through the crash handler...
- expect(stderr).toContain("invoked crashByPanic() handler");
- // ...and died from the trap's default action, not a clean exit, and not a
- // JS-observed SIGTRAP (the JS listener must never swallow the crash).
- expect(proc.signalCode === null ? proc.exitCode : proc.signalCode).not.toBe(0);
- },
- 20_000,
-);
+ // It went through the crash handler...
+ expect(stderr).toContain("invoked crashByPanic() handler");
+ // ...and died from the trap's default action, not a clean exit, and not a
+ // JS-observed SIGTRAP (the JS listener must never swallow the crash).
+ expect(proc.signalCode === null ? proc.exitCode : proc.signalCode).not.toBe(0);
+}, 20_000);
// After printing the crash report the handler must terminate with a signal
// that reflects the crash cause: panics abort (SIGABRT), a caught fault is
diff --git a/test/cli/run/run-shell.test.ts b/test/cli/run/run-shell.test.ts
index 4d2778abb7cd..4e5da1f2f955 100644
--- a/test/cli/run/run-shell.test.ts
+++ b/test/cli/run/run-shell.test.ts
@@ -1,6 +1,6 @@
import { describe, expect, test } from "bun:test";
import { chmodSync, mkdirSync } from "fs";
-import { bunEnv, bunExe, isWindows, tempDir, tmpdirSync } from "harness";
+import { bunEnv, bunExe, tempDir, tmpdirSync } from "harness";
import { join } from "path";
describe.concurrent("run-shell", () => {
@@ -39,44 +39,41 @@ describe.concurrent("run-shell", () => {
});
});
-test.skipIf(isWindows)(
- "package script shell interpreter is resolved from the original PATH, not node_modules/.bin",
- async () => {
- // A dependency can place arbitrary executables named "bash"/"sh"/"zsh" into
- // node_modules/.bin via its "bin" field. The interpreter that runs
- // package.json scripts must never be picked up from there.
- const fakeShell = "#!/bin/sh\necho FAKE_SHELL_USED\n";
- using dir = tempDir("run-shell-interpreter", {
- "package.json": JSON.stringify({
- name: "shell-interpreter-fixture",
- version: "1.0.0",
- scripts: {
- "say-hi": "echo real-shell-ran",
- },
- }),
- "node_modules/.bin/bash": fakeShell,
- "node_modules/.bin/sh": fakeShell,
- "node_modules/.bin/zsh": fakeShell,
- });
- for (const name of ["bash", "sh", "zsh"]) {
- chmodSync(join(String(dir), "node_modules", ".bin", name), 0o755);
- }
+test("package script shell interpreter is resolved from the original PATH, not node_modules/.bin", async () => {
+ // A dependency can place arbitrary executables named "bash"/"sh"/"zsh" into
+ // node_modules/.bin via its "bin" field. The interpreter that runs
+ // package.json scripts must never be picked up from there.
+ const fakeShell = "#!/bin/sh\necho FAKE_SHELL_USED\n";
+ using dir = tempDir("run-shell-interpreter", {
+ "package.json": JSON.stringify({
+ name: "shell-interpreter-fixture",
+ version: "1.0.0",
+ scripts: {
+ "say-hi": "echo real-shell-ran",
+ },
+ }),
+ "node_modules/.bin/bash": fakeShell,
+ "node_modules/.bin/sh": fakeShell,
+ "node_modules/.bin/zsh": fakeShell,
+ });
+ for (const name of ["bash", "sh", "zsh"]) {
+ chmodSync(join(String(dir), "node_modules", ".bin", name), 0o755);
+ }
- await using proc = Bun.spawn({
- cmd: [bunExe(), "run", "say-hi"],
- cwd: String(dir),
- env: bunEnv,
- stdout: "pipe",
- stderr: "pipe",
- });
+ await using proc = Bun.spawn({
+ cmd: [bunExe(), "run", "say-hi"],
+ cwd: String(dir),
+ env: bunEnv,
+ stdout: "pipe",
+ stderr: "pipe",
+ });
- const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
+ const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
- // The script must run under a real system shell, not the executables a
- // dependency dropped into node_modules/.bin.
- expect(stdout).not.toContain("FAKE_SHELL_USED");
- expect(stderr).not.toContain("FAKE_SHELL_USED");
- expect(stdout).toContain("real-shell-ran");
- expect(exitCode).toBe(0);
- },
-);
+ // The script must run under a real system shell, not the executables a
+ // dependency dropped into node_modules/.bin.
+ expect(stdout).not.toContain("FAKE_SHELL_USED");
+ expect(stderr).not.toContain("FAKE_SHELL_USED");
+ expect(stdout).toContain("real-shell-ran");
+ expect(exitCode).toBe(0);
+});
diff --git a/test/cli/test/bun-test.test.ts b/test/cli/test/bun-test.test.ts
index 4d9e5e8f75b7..bdb6adc238af 100644
--- a/test/cli/test/bun-test.test.ts
+++ b/test/cli/test/bun-test.test.ts
@@ -2093,24 +2093,21 @@ describe.concurrent("test file discovery (scanner)", () => {
);
}
- test.skipIf(isWindows)(
- "a path argument longer than MAX_PATH_BYTES is skipped like a missing path when other arguments match",
- async () => {
- using dir = tempDir("scanner-long-arg-mixed", { "exists.test.ts": existsTest });
- const longArg = "/" + Buffer.alloc(5000, "a").toString() + ".test.ts";
+ test("a path argument longer than MAX_PATH_BYTES is skipped like a missing path when other arguments match", async () => {
+ using dir = tempDir("scanner-long-arg-mixed", { "exists.test.ts": existsTest });
+ const longArg = "/" + Buffer.alloc(5000, "a").toString() + ".test.ts";
- await using proc = Bun.spawn({
- cmd: [bunExe(), "test", "./exists.test.ts", longArg],
- env: bunEnv,
- cwd: String(dir),
- stderr: "pipe",
- });
- const [stderr, exitCode] = await Promise.all([proc.stderr.text(), proc.exited]);
+ await using proc = Bun.spawn({
+ cmd: [bunExe(), "test", "./exists.test.ts", longArg],
+ env: bunEnv,
+ cwd: String(dir),
+ stderr: "pipe",
+ });
+ const [stderr, exitCode] = await Promise.all([proc.stderr.text(), proc.exited]);
- expect(stderr).toContain("Ran 1 test across 1 file.");
- expect(exitCode).toBe(0);
- },
- );
+ expect(stderr).toContain("Ran 1 test across 1 file.");
+ expect(exitCode).toBe(0);
+ });
// The directory walk joins parent + entry name for every directory it
// descends into and every candidate test file. With pathIgnorePatterns
diff --git a/test/cli/watch/watch.test.ts b/test/cli/watch/watch.test.ts
index bc2982d84f66..6802f91386f6 100644
--- a/test/cli/watch/watch.test.ts
+++ b/test/cli/watch/watch.test.ts
@@ -1,7 +1,7 @@
import type { Subprocess } from "bun";
import { spawn } from "bun";
import { afterEach, expect, it } from "bun:test";
-import { bunEnv, bunExe, isBroken, isLinux, isMacOS, isWindows, tempDir, tmpdirSync } from "harness";
+import { bunEnv, bunExe, isLinux, isMacOS, isWindows, tempDir, tmpdirSync } from "harness";
import {
copyFileSync,
readdirSync,
@@ -34,39 +34,35 @@ function stdoutWaiter(proc: Subprocess<"ignore", "pipe", any>) {
}
for (const dir of ["dir", "©️"]) {
- it.todoIf(isBroken && isWindows)(
- `should watch files${dir === "dir" ? "" : " (non-ascii path)"}`,
- async () => {
- const cwd = join(tmpdirSync(), dir);
- const path = join(cwd, "watchee.js");
+ it(`should watch files${dir === "dir" ? "" : " (non-ascii path)"}`, async () => {
+ const cwd = join(tmpdirSync(), dir);
+ const path = join(cwd, "watchee.js");
- const updateFile = async (i: number) => {
- await Bun.write(path, `console.log(${i}, __dirname);`);
- };
+ const updateFile = async (i: number) => {
+ await Bun.write(path, `console.log(${i}, __dirname);`);
+ };
- let i = 0;
- await updateFile(i);
- await Bun.sleep(1000);
- watchee = spawn({
- cwd,
- cmd: [bunExe(), "--watch", "watchee.js"],
- env: bunEnv,
- stdout: "pipe",
- stderr: "inherit",
- stdin: "ignore",
- });
+ let i = 0;
+ await updateFile(i);
+ await Bun.sleep(1000);
+ watchee = spawn({
+ cwd,
+ cmd: [bunExe(), "--watch", "watchee.js"],
+ env: bunEnv,
+ stdout: "pipe",
+ stderr: "inherit",
+ stdin: "ignore",
+ });
- for await (const line of watchee.stdout as ReadableStream) {
- if (i == 10) break;
- var str = new TextDecoder().decode(line);
- expect(str).toContain(`${i} ${cwd}`);
- i++;
- await updateFile(i);
- }
- rmSync(path);
- },
- 10000,
- );
+ for await (const line of watchee.stdout as ReadableStream) {
+ if (i == 10) break;
+ var str = new TextDecoder().decode(line);
+ expect(str).toContain(`${i} ${cwd}`);
+ i++;
+ await updateFile(i);
+ }
+ rmSync(path);
+ }, 10000);
}
afterEach(async () => {
@@ -81,11 +77,9 @@ afterEach(async () => {
}
});
-it.skipIf(isWindows)(
- "process.exit() in a watch kill-signal handler never returns to JS",
- async () => {
- using dir = tempDir("watch-exit-in-sigterm", {
- "exiter.js": `process.on("SIGTERM", () => {
+it("process.exit() in a watch kill-signal handler never returns to JS", async () => {
+ using dir = tempDir("watch-exit-in-sigterm", {
+ "exiter.js": `process.on("SIGTERM", () => {
process.exit(0);
require("fs").writeFileSync("should-not-write.txt", "hello");
});
@@ -95,48 +89,46 @@ process.on("SIGTERM", () => {
console.log("started");
setInterval(() => {}, 1000);
`,
- });
- const cwd = String(dir);
- const path = join(cwd, "exiter.js");
- watchee = spawn({
- cwd,
- cmd: [bunExe(), "--watch", "exiter.js"],
- env: bunEnv,
- stdout: "pipe",
- stderr: "inherit",
- stdin: "ignore",
- });
- let starts = 0;
- let touched = false;
- const decoder = new TextDecoder();
- await (async () => {
- // Output written before this reader attaches waits in the kernel pipe
- // buffer, so no start can be missed. Lines are reassembled across chunk
- // boundaries before matching.
- let buffered = "";
- for await (const chunk of watchee.stdout as ReadableStream) {
- buffered += decoder.decode(chunk);
- let newline;
- while ((newline = buffered.indexOf("\n")) !== -1) {
- const line = buffered.slice(0, newline);
- buffered = buffered.slice(newline + 1);
- if (line.includes("started") && ++starts === 2) return;
- if (starts === 1 && !touched) {
- touched = true;
- // First boot seen: touch the file to trigger the kill-signal reload.
- await Bun.write(path, (await Bun.file(path).text()) + "\n// touched");
- }
+ });
+ const cwd = String(dir);
+ const path = join(cwd, "exiter.js");
+ watchee = spawn({
+ cwd,
+ cmd: [bunExe(), "--watch", "exiter.js"],
+ env: bunEnv,
+ stdout: "pipe",
+ stderr: "inherit",
+ stdin: "ignore",
+ });
+ let starts = 0;
+ let touched = false;
+ const decoder = new TextDecoder();
+ await (async () => {
+ // Output written before this reader attaches waits in the kernel pipe
+ // buffer, so no start can be missed. Lines are reassembled across chunk
+ // boundaries before matching.
+ let buffered = "";
+ for await (const chunk of watchee.stdout as ReadableStream) {
+ buffered += decoder.decode(chunk);
+ let newline;
+ while ((newline = buffered.indexOf("\n")) !== -1) {
+ const line = buffered.slice(0, newline);
+ buffered = buffered.slice(newline + 1);
+ if (line.includes("started") && ++starts === 2) return;
+ if (starts === 1 && !touched) {
+ touched = true;
+ // First boot seen: touch the file to trigger the kill-signal reload.
+ await Bun.write(path, (await Bun.file(path).text()) + "\n// touched");
}
}
- // The child exiting before the reload start is a failure of the watch
- // path itself; without this the absent-file expects below pass vacuously.
- throw new Error(`watchee stdout ended after ${starts} start(s); expected 2`);
- })();
- expect(await Bun.file(join(cwd, "should-not-write.txt")).exists()).toBe(false);
- expect(await Bun.file(join(cwd, "second-listener-ran.txt")).exists()).toBe(false);
- },
- 10000,
-);
+ }
+ // The child exiting before the reload start is a failure of the watch
+ // path itself; without this the absent-file expects below pass vacuously.
+ throw new Error(`watchee stdout ended after ${starts} start(s); expected 2`);
+ })();
+ expect(await Bun.file(join(cwd, "should-not-write.txt")).exists()).toBe(false);
+ expect(await Bun.file(join(cwd, "second-listener-ran.txt")).exists()).toBe(false);
+}, 10000);
// While one thread is inside execve(2), Linux fails every clone(CLONE_FS) in
// the process with EAGAIN until the exec has killed the other threads
diff --git a/test/integration/pprof/pprof.test.ts b/test/integration/pprof/pprof.test.ts
index 64ce4ead58e9..32f689cf278d 100644
--- a/test/integration/pprof/pprof.test.ts
+++ b/test/integration/pprof/pprof.test.ts
@@ -1,14 +1,13 @@
import { describe, expect, test } from "bun:test";
-import { bunEnv, bunExe, canBuildNodeAddons, isBroken, isMusl, isWindows, tempDir } from "harness";
+import { bunEnv, bunExe, canBuildNodeAddons, isBroken, isMusl, tempDir } from "harness";
import { join } from "node:path";
// pprof (google/pprof-nodejs) ships no prebuilds: its nan addon is compiled
// from source with node-gyp, the same way test/v8 builds its module. Unlike
// @datadog/pprof, it drives v8::CpuProfiler through the title-keyed
// StartProfiling()/StopProfiling() overloads and CpuProfile::GetTitle()
-// (#19678). The source build is skipped on Windows; test/v8 covers those
-// overloads on every platform.
-describe.skipIf(!canBuildNodeAddons() || isWindows).todoIf(isBroken && isMusl)("pprof", () => {
+// (#19678).
+describe.skipIf(!canBuildNodeAddons()).todoIf(isBroken && isMusl)("pprof", () => {
test("time.profile() returns a profile with samples", async () => {
using dir = tempDir("pprof", {
"package.json": JSON.stringify({
diff --git a/test/internal/source-lints/windows-cross-config.test.ts b/test/internal/source-lints/windows-cross-config.test.ts
index c11356e91550..3fe9bffa44d2 100644
--- a/test/internal/source-lints/windows-cross-config.test.ts
+++ b/test/internal/source-lints/windows-cross-config.test.ts
@@ -11,7 +11,6 @@
* native toolchain instead.
*/
import { describe, expect, test } from "bun:test";
-import { isWindows } from "harness";
import { resolveConfig, type Config, type PartialConfig, type Toolchain } from "../../../scripts/build/config.ts";
import { webkit } from "../../../scripts/build/deps/webkit.ts";
@@ -76,7 +75,7 @@ function resolveWindowsCross(partial: PartialConfig = {}, toolchain = mockToolch
);
}
-describe.skipIf(isWindows)("Windows cross-compile LTO config (non-windows host)", () => {
+describe("Windows cross-compile LTO config (non-windows host)", () => {
test("ci release x64 cross builds default to ThinLTO with cross-language LTO", () => {
const cfg = resolveWindowsCross();
expect(cfg.windows).toBe(true);
diff --git a/test/js/bun/console/console-write.test.ts b/test/js/bun/console/console-write.test.ts
index 66d6f79fc3c6..f3ca11f2c554 100644
--- a/test/js/bun/console/console-write.test.ts
+++ b/test/js/bun/console/console-write.test.ts
@@ -126,7 +126,7 @@ console.error(JSON.stringify({ wrote }));
// The Promise a backed-up console.write() returns is where its write error arrives: a script that
// awaits it can handle a reader that hung up, instead of dying with an unhandled rejection.
-test.skipIf(isWindows)("an awaited console.write rejects with EPIPE when the reader has hung up", async () => {
+test("an awaited console.write rejects with EPIPE when the reader has hung up", async () => {
await using proc = Bun.spawn({
cmd: [
bunExe(),
diff --git a/test/js/bun/http/bun-listen-connect-args.test.ts b/test/js/bun/http/bun-listen-connect-args.test.ts
index 7c582dc5f094..a89d041fca75 100644
--- a/test/js/bun/http/bun-listen-connect-args.test.ts
+++ b/test/js/bun/http/bun-listen-connect-args.test.ts
@@ -1,7 +1,7 @@
import { describe, test } from "bun:test";
-import { cwdScope, isWindows, tempDir } from "harness";
+import { cwdScope, tempDir } from "harness";
-describe.if(!isWindows)("unix socket", () => {
+describe("unix socket", () => {
test("valid", () => {
using server = Bun.listen({
unix: Math.random().toString(32).slice(2, 15) + ".sock",
diff --git a/test/js/bun/http/fetch-file-upload.test.ts b/test/js/bun/http/fetch-file-upload.test.ts
index f077df18d360..451f74d51bd7 100644
--- a/test/js/bun/http/fetch-file-upload.test.ts
+++ b/test/js/bun/http/fetch-file-upload.test.ts
@@ -1,5 +1,5 @@
import { describe, expect, test } from "bun:test";
-import { isBroken, isWindows, tempDir, withoutAggressiveGC } from "harness";
+import { tempDir, withoutAggressiveGC } from "harness";
import { tmpdir } from "os";
import { join } from "path";
@@ -126,38 +126,34 @@ test("formData uploads roundtrip, without a call to .body", async () => {
expect(await (resData.get("file") as Blob).arrayBuffer()).toEqual(await file.arrayBuffer());
});
-test.todoIf(isBroken && isWindows)(
- "uploads roundtrip with sendfile()",
- async () => {
- const hugeTxt = Buffer.allocUnsafe(1024 * 1024 * 32 * "huge".length);
- hugeTxt.fill("huge");
- const hash = Bun.CryptoHasher.hash("sha256", hugeTxt, "hex");
+test("uploads roundtrip with sendfile()", async () => {
+ const hugeTxt = Buffer.allocUnsafe(1024 * 1024 * 32 * "huge".length);
+ hugeTxt.fill("huge");
+ const hash = Bun.CryptoHasher.hash("sha256", hugeTxt, "hex");
- const path = join(tmpdir(), "huge.txt");
- require("fs").writeFileSync(path, hugeTxt);
- using server = Bun.serve({
- port: 0,
- development: false,
- maxRequestBodySize: hugeTxt.byteLength * 2,
- async fetch(req) {
- const hasher = new Bun.CryptoHasher("sha256");
- for await (let chunk of req.body!) {
- hasher.update(chunk);
- }
- return new Response(hasher.digest("hex"));
- },
- });
+ const path = join(tmpdir(), "huge.txt");
+ require("fs").writeFileSync(path, hugeTxt);
+ using server = Bun.serve({
+ port: 0,
+ development: false,
+ maxRequestBodySize: hugeTxt.byteLength * 2,
+ async fetch(req) {
+ const hasher = new Bun.CryptoHasher("sha256");
+ for await (let chunk of req.body!) {
+ hasher.update(chunk);
+ }
+ return new Response(hasher.digest("hex"));
+ },
+ });
- const resp = await fetch(server.url, {
- body: Bun.file(path),
- method: "PUT",
- });
+ const resp = await fetch(server.url, {
+ body: Bun.file(path),
+ method: "PUT",
+ });
- expect(resp.status).toBe(200);
- expect(await resp.text()).toBe(hash);
- },
- 10_000,
-);
+ expect(resp.status).toBe(200);
+ expect(await resp.text()).toBe(hash);
+}, 10_000);
describe("Bun.file().slice() upload sends the slice's Content-Length", () => {
// The sendfile fast path is entered when the backing file is >= 32 KiB.
diff --git a/test/js/bun/http/http-server-chunking.test.ts b/test/js/bun/http/http-server-chunking.test.ts
index 6f3dc38b1566..6c03a0e9631d 100644
--- a/test/js/bun/http/http-server-chunking.test.ts
+++ b/test/js/bun/http/http-server-chunking.test.ts
@@ -1,9 +1,9 @@
import type { Socket } from "bun";
import { setSocketOptions } from "bun:internal-for-testing";
import { describe, expect, test } from "bun:test";
-import { bunEnv, bunExe, isASAN, isPosix } from "harness";
+import { bunEnv, bunExe, isASAN } from "harness";
-describe.if(isPosix)("HTTP server handles chunked transfer encoding", () => {
+describe("HTTP server handles chunked transfer encoding", () => {
test.concurrentIf(!isASAN)("handles fragmented chunk terminators", async () => {
const script = `
const server = Bun.serve({
@@ -108,7 +108,7 @@ describe.if(isPosix)("HTTP server handles chunked transfer encoding", () => {
});
});
-describe.if(isPosix)("HTTP server handles split chunk-size CRLF", () => {
+describe("HTTP server handles split chunk-size CRLF", () => {
test.concurrentIf(!isASAN)("handles lone CR at end of chunk-size line across TCP segments", async () => {
// Regression test: when a TCP segment boundary falls between the \r and \n
// of a chunk-size line (e.g. "5\r" in one segment, "\n..." in the next),
@@ -530,7 +530,7 @@ describe.if(isPosix)("HTTP server handles split chunk-size CRLF", () => {
});
});
-describe.if(isPosix)("HTTP server handles fragmented requests", () => {
+describe("HTTP server handles fragmented requests", () => {
test.concurrentIf(!isASAN)("handles requests with tiny send buffer (regression test)", async () => {
using server = Bun.serve({
hostname: "127.0.0.1",
diff --git a/test/js/bun/http/serve.test.ts b/test/js/bun/http/serve.test.ts
index 5c0da1622716..9b9fdcafe1c6 100644
--- a/test/js/bun/http/serve.test.ts
+++ b/test/js/bun/http/serve.test.ts
@@ -15,7 +15,6 @@ import {
isIPv4,
isIPv6,
isLinux,
- isPosix,
isWindows,
libcPathForDlopen,
MAX_PATH_BYTES,
@@ -2948,7 +2947,7 @@ describe("server.requestIP", () => {
});
});
- it.if(isPosix)("server.requestIP (unix)", async () => {
+ it("server.requestIP (unix)", async () => {
const unix = join(tmpdirSync(), "serve.sock");
using server = Bun.serve({
unix,
@@ -3962,7 +3961,7 @@ it("only serves /bun:info to loopback clients in development mode", async () =>
expect(externalRes.status).toBe(200);
});
-it.if(isPosix)("serves /bun:info over a unix socket in development mode", async () => {
+it("serves /bun:info over a unix socket in development mode", async () => {
using dir = tempDir("info", {});
const unix = join(String(dir), "bun-info.sock");
using server = Bun.serve({
diff --git a/test/js/bun/image/image.test.ts b/test/js/bun/image/image.test.ts
index 805aa81a0f03..032160f8360e 100644
--- a/test/js/bun/image/image.test.ts
+++ b/test/js/bun/image/image.test.ts
@@ -1679,7 +1679,7 @@ describe("decode-only formats (BMP / TIFF / GIF)", () => {
expect(Buffer.compare(got, ref)).toBe(0);
});
- if (!isMacOS && !isWindows) {
+ if (!isMacOS) {
test("TIFF on Linux throws UnsupportedOnPlatform", async () => {
const tiff = Buffer.from("II*\x00\x08\x00\x00\x00", "binary");
await expect(new Bun.Image(tiff).png().bytes()).rejects.toMatchObject({ code: "ERR_IMAGE_FORMAT_UNSUPPORTED" });
diff --git a/test/js/bun/io/bun-write.test.js b/test/js/bun/io/bun-write.test.js
index bcbd9deef142..fe0e2208cb70 100644
--- a/test/js/bun/io/bun-write.test.js
+++ b/test/js/bun/io/bun-write.test.js
@@ -544,7 +544,7 @@ const IS_UV_FS_COPYFILE_DISABLED =
// must terminate on EOF, not on the stat-derived budget.
// Bun.spawn({stdin:"pipe"}) hands the child a socketpair, not a FIFO, so
// run the pipeline under sh to get real kernel pipes on fd 0/1.
- it.skipIf(isWindows)("Bun.write(Bun.stdout, Bun.stdin) copies the whole pipe (> 4096 bytes)", async () => {
+ it("Bun.write(Bun.stdout, Bun.stdin) copies the whole pipe (> 4096 bytes)", async () => {
const size = 1024 * 1024;
const script = `process.stderr.write(String(await Bun.write(Bun.stdout, Bun.stdin)))`;
diff --git a/test/js/bun/jsc/bun-jsc.test.ts b/test/js/bun/jsc/bun-jsc.test.ts
index a8ec60ca32d4..e23197a3b4b9 100644
--- a/test/js/bun/jsc/bun-jsc.test.ts
+++ b/test/js/bun/jsc/bun-jsc.test.ts
@@ -26,7 +26,7 @@ import {
totalCompileTime,
} from "bun:jsc";
import { describe, expect, it } from "bun:test";
-import { bunEnv, bunExe, isBuildKite, isWindows, tempDir } from "harness";
+import { bunEnv, bunExe, tempDir } from "harness";
import { createHash, type webcrypto } from "node:crypto";
import { existsSync, readdirSync, readFileSync } from "node:fs";
import { join } from "node:path";
@@ -245,7 +245,7 @@ describe("bun:jsc", () => {
Bun.gc(true);
});
- it.todoIf(isBuildKite && isWindows)("profile async", async () => {
+ it("profile async", async () => {
const { promise, resolve } = Promise.withResolvers