Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ test("(multi-file test) my feature", async () => {
- Use `tempDir` from `"harness"` to create a temporary directory. **Do not** use `tmpdirSync` or `fs.mkdtempSync` to create temporary directories.
- When spawning processes, tests should expect(stdout).toBe(...) BEFORE expect(exitCode).toBe(0). This gives you a more useful error message on test failure.
- Keep tests fast: budget roughly 1s per test and 10s per file. Debug+ASAN builds run 10-100x slower than release, so a 1s local test can take a minute in CI. Use `test.concurrent` for independent subprocess-spawning tests.
- Never contact the public internet (registry.npmjs.org, github.com, CDNs). Use `VerdaccioRegistry` from `"harness"` for package installs and a local `Bun.serve({ port: 0 })` for HTTP.
- Never contact the public internet (registry.npmjs.org, github.com, CDNs). Use `TestRegistry` from `"registry"` (`test/packages/registry`) for package installs and a local `Bun.serve({ port: 0 })` for HTTP.
- `setDefaultTimeout` is a ceiling, not a target. Leave the default and pass a per-test timeout only for the rare outlier; a 5-minute file default multiplies across retries when one test hangs.
- Leak tests branch their RSS threshold on `isASAN`/`isDebug` and keep the bound well below what the unfixed leak produces. An un-branched absolute delta flakes under ASAN quarantine and GC jitter.
- **CRITICAL**: Do not write flaky tests. Do not use `setTimeout` or `await sleep(N)` to wait for a condition; poll with a deadline or `await` the event itself. You are not testing the TIME PASSING, you are testing the CONDITION.
Expand Down
578 changes: 1 addition & 577 deletions test/bun.lock

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions test/bundler/bundler_bytecode_portable.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -511,10 +511,10 @@ describe("bytecode cache portability", () => {
},
},
"bun build --bytecode libraries.js": {
"js": "493bab674ff49b287f26be3f356a3ad6681afb0c7eeffaa590f10cdcd8b58724",
"js": "cb63dc7b9a0d57183c02aac96e13182312fdefd64d89da2ad4a60a35d63ff2af",
"jsc": {
"bytes": 21206912,
"sha256": "49e423d3252b0e1ed7e9529d6475026ccb9fb8af73e746cad15d8420e07fae54",
"bytes": 21174272,
"sha256": "7ae6cdd7092d140bfbad79e7f304b14e24f8ece485df9f779092ffde1351e21f",
},
},
"bun build --bytecode lodash/lodash.js": {
Expand Down
4 changes: 1 addition & 3 deletions test/bunfig.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,5 @@ preload = "./preload.ts"

[install]
linker = "isolated"
# See ../bunfig.toml — CI deletes the install cache between steps, and
# verdaccio's internal packages have phantom dependencies that the global
# store's stricter isolation catches.
# See ../bunfig.toml: CI deletes the install cache between steps.
globalStore = false
5 changes: 3 additions & 2 deletions test/cli/install/bun-add-catalog.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import { file, write } from "bun";
import { readTarball } from "bun:internal-for-testing";
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
import { existsSync } from "fs";
import { VerdaccioRegistry, bunEnv, bunExe, readdirSorted, runBunInstall } from "harness";
import { bunEnv, bunExe, readdirSorted, runBunInstall } from "harness";
import { join } from "path";
import { TestRegistry } from "registry";

const registry = new VerdaccioRegistry();
const registry = new TestRegistry();

beforeAll(async () => {
await registry.start();
Expand Down
5 changes: 3 additions & 2 deletions test/cli/install/bun-add-filter.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { file, write } from "bun";
import { afterAll, beforeAll, expect, test } from "bun:test";
import { chmod, exists, mkdir, rm } from "fs/promises";
import { VerdaccioRegistry, bunEnv, bunExe, isWindows, normalizeBunSnapshot } from "harness";
import { bunEnv, bunExe, isWindows, normalizeBunSnapshot } from "harness";
import { join } from "path";
import { TestRegistry } from "registry";

const registry = new VerdaccioRegistry();
const registry = new TestRegistry();

beforeAll(async () => {
await registry.start();
Expand Down
6 changes: 3 additions & 3 deletions test/cli/install/bun-audit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { afterAll, beforeAll, describe, expect, test } from "bun:test";
import { exists, readlink } from "fs/promises";
import {
DirectoryTree,
VerdaccioRegistry,
bunEnv,
bunExe,
gunzipJsonRequest,
Expand All @@ -12,6 +11,7 @@ import {
tempDir,
} from "harness";
import { join } from "node:path";
import { TestRegistry } from "registry";
import { resolveBulkAdvisoryFixture } from "./registry/fixtures/audit/audit-fixtures";

function fixture(
Expand All @@ -25,7 +25,7 @@ function fixture(
}

let server: Bun.Server;
const verdaccio = new VerdaccioRegistry();
const verdaccio = new TestRegistry();

beforeAll(async () => {
server = Bun.serve({
Expand Down Expand Up @@ -125,7 +125,7 @@ type RegistryOptions = {
rewriteTime?: Record<string, Record<string, string>>;
};

// Answers the bulk-advisory endpoint itself and proxies everything else to verdaccio, pointing manifest tarball URLs back at itself.
// Answers the bulk-advisory endpoint itself and proxies everything else to the fixture registry, pointing manifest tarball URLs back at itself.
function startRegistry(advisories: Record<string, Advisory[]>, options: RegistryOptions = {}) {
let bulkRequests = 0;
return Bun.serve({
Expand Down
5 changes: 3 additions & 2 deletions test/cli/install/bun-dedupe.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { file, write } from "bun";
import { afterAll, beforeAll, expect, test } from "bun:test";
import { copyFile, exists, mkdir, realpath, rm } from "fs/promises";
import { VerdaccioRegistry, bunEnv, bunExe, normalizeBunSnapshot, readdirSorted, runBunInstall } from "harness";
import { bunEnv, bunExe, normalizeBunSnapshot, readdirSorted, runBunInstall } from "harness";
import { dirname, join } from "path";
import { TestRegistry } from "registry";

const registry = new VerdaccioRegistry();
const registry = new TestRegistry();

beforeAll(async () => {
await registry.start();
Expand Down
4 changes: 2 additions & 2 deletions test/cli/install/bun-install-lifecycle-scripts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { file, spawn, write } from "bun";
import { afterAll, beforeAll, describe, expect, setDefaultTimeout, test } from "bun:test";
import { exists, mkdir, rm, writeFile } from "fs/promises";
import {
VerdaccioRegistry,
assertManifestsPopulated,
bunEnv as baseEnv,
bunExe,
Expand All @@ -13,8 +12,9 @@ import {
} from "harness";
import { constants as osConstants } from "os";
import { join, sep } from "path";
import { TestRegistry } from "registry";

var verdaccio = new VerdaccioRegistry();
var verdaccio = new TestRegistry();

setDefaultTimeout(1000 * 60 * 5);

Expand Down
7 changes: 4 additions & 3 deletions test/cli/install/bun-install-native-binlink.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ import { spawn } from "bun";
import { afterAll, beforeAll, describe, expect, setDefaultTimeout, test } from "bun:test";
import { chmodSync, existsSync, readFileSync, realpathSync, statSync, symlinkSync } from "fs";
import { rm, writeFile } from "fs/promises";
import { bunEnv, bunExe, isWindows, tempDir, VerdaccioRegistry } from "harness";
import { bunEnv, bunExe, isWindows, tempDir } from "harness";
import { join, sep } from "path";
import { TestRegistry } from "registry";

let verdaccio: VerdaccioRegistry;
let verdaccio: TestRegistry;

setDefaultTimeout(1000 * 60 * 5);

beforeAll(async () => {
verdaccio = new VerdaccioRegistry();
verdaccio = new TestRegistry();
await verdaccio.start();
});

Expand Down
12 changes: 3 additions & 9 deletions test/cli/install/bun-install-patch.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
import { $ } from "bun";
import { afterAll, beforeAll, describe, expect, it, setDefaultTimeout, test } from "bun:test";
import { rmSync } from "fs";
import {
bunEnv,
bunExe,
normalizeBunSnapshot as normalizeBunSnapshot_,
runBunInstall,
tempDir,
VerdaccioRegistry,
} from "harness";
import { bunEnv, bunExe, normalizeBunSnapshot as normalizeBunSnapshot_, runBunInstall, tempDir } from "harness";
import { join } from "path";
import { TestRegistry } from "registry";
import { pathToFileURL } from "url";

const normalizeBunSnapshot = (str: string) => {
Expand Down Expand Up @@ -1136,7 +1130,7 @@ describe("patchedDependencies contents_hash", () => {
// install failed with "Couldn't find patch file" because the dependency's patch
// path was resolved against the consumer's root (#13531).
describe("patchedDependencies declared by a dependency", () => {
const registry = new VerdaccioRegistry();
const registry = new TestRegistry();

beforeAll(async () => {
await registry.start();
Expand Down
82 changes: 35 additions & 47 deletions test/cli/install/bun-install-registry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ import {
toBeValidBin,
toHaveBins,
toMatchNodeModulesAt,
VerdaccioRegistry,
writeShebangScript,
} from "harness";
import { createServer as createTcpServer, connect as tcpConnect, type Socket } from "net";
import { join, resolve } from "path";
import { TestRegistry } from "registry";
import { createServer as createTlsServer } from "tls";
const { parseLockfile } = install_test_helpers;

Expand All @@ -37,31 +37,24 @@ expect.extend({
toMatchNodeModulesAt,
});

var registry: VerdaccioRegistry;
var registry: TestRegistry;
var port: number;
var packageDir: string;
/** packageJson = join(packageDir, "package.json"); */
var packageJson: string;

let users: Record<string, string> = {};

setDefaultTimeout(1000 * 60 * 5);
registry = new VerdaccioRegistry();
registry = new TestRegistry().start();
port = registry.port;
await registry.start();

afterAll(async () => {
await Bun.$`rm -f ${import.meta.dir}/htpasswd`.throws(false);
afterAll(() => {
registry.stop();
});

beforeEach(async () => {
({ packageDir, packageJson } = await registry.createTestDir({
bunfigOpts: { saveTextLockfile: false, linker: "hoisted" },
}));
await Bun.$`rm -f ${import.meta.dir}/htpasswd`.throws(false);
await Bun.$`rm -rf ${import.meta.dir}/packages/private-pkg-dont-touch`.throws(false);
users = {};
env.BUN_INSTALL_CACHE_DIR = join(packageDir, ".bun-cache");
env.BUN_TMPDIR = env.TMPDIR = env.TEMP = join(packageDir, ".bun-tmp");
});
Expand All @@ -70,37 +63,6 @@ function registryUrl() {
return registry.registryUrl();
}

/**
* Returns auth token
*/
async function generateRegistryUser(username: string, password: string): Promise<string> {
if (users[username]) {
throw new Error("that user already exists");
} else users[username] = password;

const url = `http://localhost:${port}/-/user/org.couchdb.user:${username}`;
const user = {
name: username,
password: password,
email: `${username}@example.com`,
};

const response = await fetch(url, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(user),
});

if (response.ok) {
const data = await response.json();
return data.token;
} else {
throw new Error("Failed to create user:", response.statusText);
}
}

describe("auto-install", () => {
test("symlinks (and junctions) are created correctly in the install cache", async () => {
const { stdout, stderr, exited } = spawn({
Expand Down Expand Up @@ -605,7 +567,7 @@ describe("whoami", async () => {
expect(await exited).toBe(0);
});
test("only .npmrc", async () => {
const token = await generateRegistryUser("whoami-npmrc", "whoami-npmrc");
const token = await registry.generateUser("whoami-npmrc", "whoami-npmrc");
const npmrc = `
//localhost:${port}/:_authToken=${token}
registry=http://localhost:${port}`;
Expand All @@ -627,7 +589,7 @@ describe("whoami", async () => {
expect(await exited).toBe(0);
});
test("two .npmrc", async () => {
const token = await generateRegistryUser("whoami-two-npmrc", "whoami-two-npmrc");
const token = await registry.generateUser("whoami-two-npmrc", "whoami-two-npmrc");
const packageNpmrc = `registry=http://localhost:${port}/`;
const homeNpmrc = `//localhost:${port}/:_authToken=${token}`;
const homeDir = `${packageDir}/home_dir`;
Expand Down Expand Up @@ -670,7 +632,7 @@ describe("whoami", async () => {
});
test("invalid token", async () => {
// create the user and provide an invalid token
const token = await generateRegistryUser("invalid-token", "invalid-token");
await registry.generateUser("invalid-token", "invalid-token");
const bunfig = Bun.TOML.stringify({
install: {
cache: false,
Expand All @@ -692,7 +654,33 @@ describe("whoami", async () => {
const out = await stdout.text();
expect(out).toBeEmpty();
const err = await stderr.text();
expect(err).toBe(`error: failed to authenticate with registry 'http://localhost:${port}/'\n`);
expect(err).toBe(`\n401 Unauthorized: http://localhost:${port}/-/whoami\n`);
expect(await exited).toBe(1);
});
test("a registry that answers 200 without a username", async () => {
// Some registries do not reject a token they do not know. They answer with an empty object.
using anonymous = Bun.serve({ port: 0, fetch: () => Response.json({}) });
const bunfig = Bun.TOML.stringify({
install: {
cache: false,
registry: { url: `http://localhost:${anonymous.port}/`, token: "1234567" },
},
});
await Promise.all([
write(packageJson, JSON.stringify({ name: "whoami-pkg", version: "1.1.1" })),
write(join(packageDir, "bunfig.toml"), bunfig),
]);
const { stdout, stderr, exited } = spawn({
cmd: [bunExe(), "pm", "whoami"],
cwd: packageDir,
env,
stdout: "pipe",
stderr: "pipe",
});
const out = await stdout.text();
expect(out).toBeEmpty();
const err = await stderr.text();
expect(err).toBe(`error: failed to authenticate with registry 'http://localhost:${anonymous.port}/'\n`);
expect(await exited).toBe(1);
});
});
Expand Down Expand Up @@ -10048,7 +10036,7 @@ test("rejects npm aliases whose manifest URL resolves to a different host than t
},
});

const token = await generateRegistryUser("manifest-host-pinning", "manifest-host-pinning");
const token = await registry.generateUser("manifest-host-pinning", "manifest-host-pinning");
await Promise.all([
write(
join(packageDir, "bunfig.toml"),
Expand Down
4 changes: 2 additions & 2 deletions test/cli/install/bun-lock.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ import {
runBunInstall,
tempDir,
toBeValidBin,
VerdaccioRegistry,
} from "harness";
import { join } from "path";
import { TestRegistry } from "registry";

expect.extend({
toBeValidBin,
});

var registry = new VerdaccioRegistry();
var registry = new TestRegistry();

beforeAll(async () => {
await registry.start();
Expand Down
5 changes: 3 additions & 2 deletions test/cli/install/bun-lockb.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { file, spawn, write } from "bun";
import { afterAll, beforeAll, expect, it } from "bun:test";
import { copyFile, exists, open, rm, writeFile } from "fs/promises";
import { bunExe, bunEnv as env, isWindows, runBunInstall, VerdaccioRegistry } from "harness";
import { bunExe, bunEnv as env, isWindows, runBunInstall } from "harness";
import { join } from "path";
import { TestRegistry } from "registry";

const registry = new VerdaccioRegistry();
const registry = new TestRegistry();

beforeAll(async () => {
await registry.start();
Expand Down
5 changes: 3 additions & 2 deletions test/cli/install/bun-patch.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { $, ShellOutput } from "bun";
import { afterAll, beforeAll, describe, expect, setDefaultTimeout, test } from "bun:test";
import { lstatSync, readFileSync } from "fs";
import { bunEnv, bunExe, isASAN, tempDir, VerdaccioRegistry } from "harness";
import { bunEnv, bunExe, isASAN, tempDir } from "harness";
import { isAbsolute, join, sep } from "path";
import { TestRegistry } from "registry";

const expectNoError = (o: ShellOutput) => expect(o.stderr.toString()).not.toContain("error");
// const platformPath = (path: string) => (process.platform === "win32" ? path.replaceAll("/", sep) : path);
Expand Down Expand Up @@ -71,7 +72,7 @@ describe("error messages", () => {
// stack buffers (512 bytes in the installer itself), so a long enough spec crashed
// every command that formatted it.
describe("packages whose label is longer than 1024 bytes", () => {
const registry = new VerdaccioRegistry();
const registry = new TestRegistry();

beforeAll(async () => {
await registry.start();
Expand Down
Loading
Loading