fix(FN-5048): address PR feedback on test verification

Fusion-Task-Id: FN-5048
This commit is contained in:
gsxdsm
2026-06-21 10:53:08 -07:00
parent 03af93eb3a
commit 21df96cfbb
3 changed files with 56 additions and 18 deletions

View File

@@ -166,6 +166,26 @@ jobs:
- name: Assert every dashboard test file is gated or skip-listed
run: node scripts/check-test-inventory.mjs --dashboard-curated
line-count-audit:
name: Line-count audit
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js and pnpm
uses: ./.github/actions/setup-node-pnpm
with:
skip-install: "true"
# FNXC:TestInfrastructure 2026-06-21-10:26:
# Keep line-count drift visible in automated post-merge signal without restoring it to the blocking PR gate.
# The guard is intentionally absent from pretest/pr-checks so task verification and merge progress are not blocked by file-size cleanup work.
- name: Run line-count audit
continue-on-error: true
run: pnpm check:line-count
# The engine-slow tier (src/**/*.slow.test.ts) runs here with a non-empty
# execution assertion, so a glob/config drift that silently empties the tier
# fails this workflow instead of passing vacuously. Engine slow tests do real

View File

@@ -9,6 +9,7 @@ import {
detectMarathonVerification,
normalizeVerificationCommand,
runVerificationCommand,
__testOnlyReapVerificationProcessGroup,
type RunVerificationOptions,
} from "../run-verification-tool.js";
@@ -19,19 +20,6 @@ import {
const onPosix = process.platform !== "win32";
const itPosix = onPosix ? it : it.skip;
function isProcessAlive(pid: number): boolean {
try {
process.kill(pid, 0);
return true;
} catch {
return false;
}
}
function sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}
/**
* Tests for runVerificationCommand - the core verification execution logic.
* These tests validate basic command execution, output capture, and error handling.
@@ -404,11 +392,32 @@ describe("runVerificationCommand", { timeout: 30000 }, () => {
expect(result.success).toBe(true);
const leakedPid = Number.parseInt(result.stdout.trim(), 10);
expect(Number.isFinite(leakedPid)).toBe(true);
expect(result.timedOut).toBe(false);
});
for (let i = 0; i < 15 && isProcessAlive(leakedPid); i++) {
await sleep(100);
it("escalates non-timeout process-group reaping with fake timers", () => {
/*
* FNXC:Verification 2026-06-21-10:26:
* Keep timer assertions on a narrow seam with fake timers so the integration test above never polls wall-clock time while still pinning SIGTERM -> SIGKILL escalation.
*/
vi.useFakeTimers();
const kill = vi.fn();
const supervised = { kill } as unknown as Parameters<typeof __testOnlyReapVerificationProcessGroup>[0];
try {
__testOnlyReapVerificationProcessGroup(supervised);
expect(kill).toHaveBeenCalledTimes(1);
expect(kill).toHaveBeenCalledWith("SIGTERM");
vi.advanceTimersByTime(499);
expect(kill).toHaveBeenCalledTimes(1);
vi.advanceTimersByTime(1);
expect(kill).toHaveBeenCalledTimes(2);
expect(kill).toHaveBeenLastCalledWith("SIGKILL");
} finally {
vi.useRealTimers();
}
expect(isProcessAlive(leakedPid)).toBe(false);
});
});

View File

@@ -2,6 +2,8 @@
import { globSync } from "node:fs";
import { spawn } from "node:child_process";
import { resolve } from "node:path";
import { fileURLToPath, URL } from "node:url";
/*
FNXC:TestInfrastructure 2026-06-21-10:00:
@@ -10,12 +12,19 @@ The old package script always expanded scripts/__tests__/*.test.mjs before forwa
*/
const forwarded = process.argv.slice(2).filter((arg) => arg !== "--");
const repoRoot = fileURLToPath(new URL("..", import.meta.url));
const testFiles = forwarded.length > 0
? forwarded
: globSync("scripts/__tests__/*.test.mjs").sort();
? forwarded.map((file) => resolve(repoRoot, file))
: globSync("scripts/__tests__/*.test.mjs", { cwd: repoRoot }).sort().map((file) => resolve(repoRoot, file));
if (testFiles.length === 0) {
console.error("[run-script-tests] no script test files matched");
process.exit(1);
}
const child = spawn(process.execPath, ["--test", ...testFiles], {
stdio: "inherit",
cwd: repoRoot,
});
child.on("exit", (code, signal) => {