Files
harness-tools/extensions/fast-browser/profiles.test.ts
T
jb fd63b0ccec
fast-browser scenarios / Offline scenario contract tests (push) Failing after 44s
fast-browser scenarios / Local Chromium headless scenarios (push) Failing after 23s
fast-browser-with-jev
2026-09-20 12:24:08 -04:00

117 lines
5.0 KiB
TypeScript

import assert from "node:assert/strict";
import { existsSync, mkdirSync, mkdtempSync, readlinkSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
import { hostname, tmpdir } from "node:os";
import { join } from "node:path";
import test from "node:test";
import {
acquireProfileLease,
captureOwnedSingletonLock,
profileDirectory,
releaseProfileLease,
removeOwnedSingletonLock,
removeStaleDevToolsActivePort,
profileStorageRoot,
} from "./profiles.ts";
test("uses private named profile storage and validates basenames", () => {
const root = mkdtempSync(join(tmpdir(), "fast-browser-profiles-test-"));
try {
assert.equal(profileStorageRoot({ XDG_DATA_HOME: root }), join(root, "fast-browser", "profiles"));
assert.equal(profileDirectory("evebot", { profileRoot: join(root, "profiles") }), join(root, "profiles", "evebot"));
for (const value of ["../escape", "/tmp/profile", "", ".", "a".repeat(65), "bad/name"]) {
assert.throws(() => profileDirectory(value, { profileRoot: join(root, "profiles") }), /profile|basename|directory/i);
}
} finally {
rmSync(root, { recursive: true, force: true });
}
});
test("profile lease is exclusive and safely releases", () => {
const root = mkdtempSync(join(tmpdir(), "fast-browser-profiles-test-"));
const profileRoot = join(root, "profiles");
try {
const first = acquireProfileLease("evebot", { profileRoot });
assert.throws(() => acquireProfileLease("evebot", { profileRoot }), /active or stale lease/i);
releaseProfileLease(first);
const second = acquireProfileLease("evebot", { profileRoot });
releaseProfileLease(second);
const changed = acquireProfileLease("evebot", { profileRoot });
rmSync(changed.lockPath);
writeFileSync(changed.lockPath, "foreign-lock", { mode: 0o600 });
assert.throws(() => releaseProfileLease(changed), /changed unexpectedly/);
assert.throws(() => releaseProfileLease(changed), /changed unexpectedly/);
rmSync(changed.lockPath);
} finally {
rmSync(root, { recursive: true, force: true });
}
});
test("SingletonLock is never deleted and stale DevTools metadata is removed only under lease", () => {
const root = mkdtempSync(join(tmpdir(), "fast-browser-profiles-test-"));
const profileRoot = join(root, "profiles");
try {
const directory = profileDirectory("evebot", { profileRoot });
const singleton = join(directory, "SingletonLock");
writeFileSync(singleton, "manual-owner", { mode: 0o600 });
assert.throws(() => acquireProfileLease("evebot", { profileRoot }), /SingletonLock.*manually/i);
assert.equal(existsSync(singleton), true);
rmSync(singleton);
const lease = acquireProfileLease("evebot", { profileRoot });
const activePort = join(directory, "DevToolsActivePort");
writeFileSync(activePort, "9222\n/devtools/browser/test\n", { mode: 0o600 });
removeStaleDevToolsActivePort(lease);
assert.equal(existsSync(activePort), false);
releaseProfileLease(lease);
} finally {
rmSync(root, { recursive: true, force: true });
}
});
test("foreign SingletonLock markers are never removed or mistaken for stale", () => {
const root = mkdtempSync(join(tmpdir(), "fast-browser-profiles-test-"));
const profileRoot = join(root, "profiles");
try {
const directory = profileDirectory("evebot", { profileRoot });
const singleton = join(directory, "SingletonLock");
const target = `${hostname()}-39991`;
symlinkSync(target, singleton);
assert.throws(() => acquireProfileLease("evebot", { profileRoot }), /SingletonLock.*manually/i);
assert.equal(readlinkSync(singleton), target);
} finally {
rmSync(root, { recursive: true, force: true });
}
});
test("owned SingletonLock can be removed only after process-gone proof", () => {
const root = mkdtempSync(join(tmpdir(), "fast-browser-profiles-test-"));
const profileRoot = join(root, "profiles");
try {
const lease = acquireProfileLease("evebot", { profileRoot });
const singleton = join(lease.profileDirectory, "SingletonLock");
symlinkSync(`${hostname()}-39992`, singleton);
captureOwnedSingletonLock(lease, 39992, "start-token");
assert.throws(() => removeOwnedSingletonLock(lease, () => false), /not been proven gone/i);
assert.equal(readlinkSync(singleton), `${hostname()}-39992`);
removeOwnedSingletonLock(lease, (ownership) => ownership.processStartTime === "start-token");
assert.equal(existsSync(singleton), false);
releaseProfileLease(lease);
} finally {
rmSync(root, { recursive: true, force: true });
}
});
test("symlinked named profiles are rejected", () => {
const root = mkdtempSync(join(tmpdir(), "fast-browser-profiles-test-"));
const profileRoot = join(root, "profiles");
const outside = join(root, "outside");
mkdirSync(outside);
mkdirSync(profileRoot, { mode: 0o700 });
symlinkSync(outside, join(profileRoot, "evebot"));
try {
assert.throws(() => acquireProfileLease("evebot", { profileRoot }), /real directory|symlink/i);
} finally {
rmSync(root, { recursive: true, force: true });
}
});