mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
116 lines
3.4 KiB
JavaScript
116 lines
3.4 KiB
JavaScript
import assert from "node:assert/strict";
|
|||
|
|
import { execFileSync } from "node:child_process";
|
||
|
|
import { existsSync, mkdirSync, mkdtempSync, rmSync } from "node:fs";
|
||
|
|
import { tmpdir } from "node:os";
|
||
|
|
import { join } from "node:path";
|
||
|
|
import test from "node:test";
|
||
|
|
import {
|
||
|
|
acquireFuzzLock,
|
||
|
|
buildFuzzEnvironment,
|
||
|
|
fuzzLockPath,
|
||
|
|
parseFuzzArguments,
|
||
|
|
} from "../../../scripts/run-fuzz-gate.mjs";
|
||
|
|
|
||
|
|
test("parses canonical fuzz runner arguments", () => {
|
||
|
|
assert.deepEqual(parseFuzzArguments(["--runs", "50", "--seed=1234"]), {
|
||
|
|
help: false,
|
||
|
|
runs: 50,
|
||
|
|
seed: 1234,
|
||
|
|
});
|
||
|
|
assert.deepEqual(parseFuzzArguments(["--help"]), {
|
||
|
|
help: true,
|
||
|
|
runs: undefined,
|
||
|
|
seed: undefined,
|
||
|
|
});
|
||
|
|
assert.deepEqual(parseFuzzArguments(["--", "--runs", "25"]), {
|
||
|
|
help: false,
|
||
|
|
runs: 25,
|
||
|
|
seed: undefined,
|
||
|
|
});
|
||
|
|
assert.throws(() => parseFuzzArguments(["--runs", "0"]), /--runs.*between 1 and 10000/i);
|
||
|
|
assert.throws(() => parseFuzzArguments(["--seed", "NaN"]), /--seed.*integer/i);
|
||
|
|
assert.throws(() => parseFuzzArguments(["--unknown"]), /unknown argument/i);
|
||
|
|
});
|
||
|
|
|
||
|
|
test("forces the canonical single-fork fuzz environment", () => {
|
||
|
|
assert.deepEqual(
|
||
|
|
buildFuzzEnvironment(
|
||
|
|
{
|
||
|
|
FC_SEED: "5678",
|
||
|
|
FUZZ: "0",
|
||
|
|
FUZZ_RUNS: "10",
|
||
|
|
FUZZ_SEED: "8765",
|
||
|
|
VITEST_MAX_FORKS: "8",
|
||
|
|
},
|
||
|
|
{ help: false, runs: 50, seed: 1234 },
|
||
|
|
),
|
||
|
|
{
|
||
|
|
FUZZ: "1",
|
||
|
|
FUZZ_RUNS: "50",
|
||
|
|
FUZZ_SEED: "1234",
|
||
|
|
VITEST_MAX_FORKS: "1",
|
||
|
|
},
|
||
|
|
);
|
||
|
|
|
||
|
|
assert.deepEqual(buildFuzzEnvironment({ FC_SEED: "5678" }, { help: false }), {
|
||
|
|
FC_SEED: "5678",
|
||
|
|
FUZZ: "1",
|
||
|
|
VITEST_MAX_FORKS: "1",
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
test("derives a stable repo-scoped lock path", () => {
|
||
|
|
const firstRepo = mkdtempSync(join(tmpdir(), "snapotter-fuzz-repo-a-"));
|
||
|
|
const secondRepo = mkdtempSync(join(tmpdir(), "snapotter-fuzz-repo-b-"));
|
||
|
|
const nested = join(firstRepo, "nested");
|
||
|
|
try {
|
||
|
|
execFileSync("git", ["init", "--quiet"], { cwd: firstRepo });
|
||
|
|
execFileSync("git", ["init", "--quiet"], { cwd: secondRepo });
|
||
|
|
mkdirSync(nested);
|
||
|
|
|
||
|
|
assert.equal(fuzzLockPath(firstRepo), fuzzLockPath(nested));
|
||
|
|
assert.notEqual(fuzzLockPath(firstRepo), fuzzLockPath(secondRepo));
|
||
|
|
assert.match(fuzzLockPath(firstRepo), /snapotter-fuzz-[a-f0-9]{64}\.lock$/);
|
||
|
|
} finally {
|
||
|
|
rmSync(firstRepo, { force: true, recursive: true });
|
||
|
|
rmSync(secondRepo, { force: true, recursive: true });
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
test("refuses a second fuzz campaign and only releases its own lock", () => {
|
||
|
|
const root = mkdtempSync(join(tmpdir(), "snapotter-fuzz-lock-test-"));
|
||
|
|
const lockPath = join(root, "fuzz.lock");
|
||
|
|
|
||
|
|
try {
|
||
|
|
const first = acquireFuzzLock(lockPath, {
|
||
|
|
pid: process.pid,
|
||
|
|
startedAt: "2026-07-25T00:00:00.000Z",
|
||
|
|
token: "first-owner",
|
||
|
|
});
|
||
|
|
assert.equal(existsSync(lockPath), true);
|
||
|
|
assert.throws(
|
||
|
|
() =>
|
||
|
|
acquireFuzzLock(lockPath, {
|
||
|
|
pid: process.pid,
|
||
|
|
startedAt: "2026-07-25T00:00:01.000Z",
|
||
|
|
token: "second-owner",
|
||
|
|
}),
|
||
|
|
/another fuzz campaign is already running/i,
|
||
|
|
);
|
||
|
|
assert.equal(existsSync(lockPath), true);
|
||
|
|
|
||
|
|
first.release();
|
||
|
|
assert.equal(existsSync(lockPath), false);
|
||
|
|
|
||
|
|
const next = acquireFuzzLock(lockPath, {
|
||
|
|
pid: process.pid,
|
||
|
|
startedAt: "2026-07-25T00:00:02.000Z",
|
||
|
|
token: "next-owner",
|
||
|
|
});
|
||
|
|
next.release();
|
||
|
|
assert.equal(existsSync(lockPath), false);
|
||
|
|
} finally {
|
||
|
|
rmSync(root, { force: true, recursive: true });
|
||
|
|
}
|
||
|
|
});
|