Skip to content

Commit 7ffcc1b

Browse files
Harden CLI entrypoint guard tests
1 parent bcec8d7 commit 7ffcc1b

2 files changed

Lines changed: 65 additions & 25 deletions

File tree

scripts/cli-entrypoints.test.ts

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,59 @@
11
import assert from "node:assert/strict";
2+
import { execFile } from "node:child_process";
23
import { readFile } from "node:fs/promises";
34
import path from "node:path";
45
import test from "node:test";
6+
import { promisify } from "node:util";
57

8+
const execFileAsync = promisify(execFile);
69
const repoRoot = process.cwd();
7-
const embeddableCliEntrypoints = [
8-
"apps/gateway/src/index.ts",
9-
"packages/core/scripts/release/check-source.mjs",
10-
"packages/deploy/src/cli.ts",
11-
"packages/sdk/scripts/release/check-source.mjs",
12-
"scripts/benchmark.ts",
13-
"scripts/deploy-storage-preflight.ts",
14-
"scripts/docs-link-check.ts",
15-
"scripts/package-runtime-coverage.ts",
16-
"scripts/test.mjs",
17-
];
18-
19-
test("embeddable CLI entrypoints avoid abrupt process exits", async () => {
20-
for (const relativePath of embeddableCliEntrypoints) {
21-
const contents = await readFile(path.join(repoRoot, relativePath), "utf8");
10+
const sourceRoots = ["apps", "packages", "scripts"] as const;
11+
const sourceExtensions = new Set([".mjs", ".ts"]);
12+
const cliEntrypointGuardPattern =
13+
/import\.meta\.url\s*===\s*pathToFileURL\(process\.argv\[1\]\)\.href/;
14+
15+
async function collectCheckedInSourceFiles(): Promise<string[]> {
16+
const { stdout } = await execFileAsync("git", ["ls-files", "--", ...sourceRoots], {
17+
cwd: repoRoot,
18+
maxBuffer: 1024 * 1024,
19+
});
20+
21+
return stdout
22+
.split(/\r?\n/)
23+
.filter(
24+
(relativePath) =>
25+
sourceExtensions.has(path.extname(relativePath)) && !relativePath.endsWith(".test.ts"),
26+
)
27+
.sort((left, right) => left.localeCompare(right));
28+
}
29+
30+
async function readRelativeSource(relativePath: string): Promise<string> {
31+
return await readFile(path.join(repoRoot, relativePath), "utf8");
32+
}
33+
34+
test("checked-in non-test source files avoid abrupt process exits", async () => {
35+
const sourceFiles = await collectCheckedInSourceFiles();
36+
37+
assert.ok(sourceFiles.length > 0);
38+
for (const relativePath of sourceFiles) {
39+
const contents = await readRelativeSource(relativePath);
2240

2341
assert.doesNotMatch(contents, /\bprocess\.exit\s*\(/, relativePath);
42+
}
43+
});
44+
45+
test("embeddable CLI entrypoints set process.exitCode", async () => {
46+
const entrypoints = [];
47+
48+
for (const relativePath of await collectCheckedInSourceFiles()) {
49+
const contents = await readRelativeSource(relativePath);
50+
if (cliEntrypointGuardPattern.test(contents)) {
51+
entrypoints.push({ contents, relativePath });
52+
}
53+
}
54+
55+
assert.ok(entrypoints.length >= 20);
56+
for (const { contents, relativePath } of entrypoints) {
2457
assert.match(contents, /\bprocess\.exitCode\s*=/, relativePath);
2558
}
2659
});

scripts/gateway-smoke.test.ts

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@ import {
1313

1414
const repoRoot = process.cwd();
1515

16-
function createIoCapture(): {
16+
interface IoCapture {
1717
io: Pick<NodeJS.Process, "stdout" | "stderr">;
1818
stdout: () => string;
1919
stderr: () => string;
20-
} {
20+
}
21+
22+
function createIoCapture(): IoCapture {
2123
let stdout = "";
2224
let stderr = "";
2325

@@ -41,6 +43,15 @@ function createIoCapture(): {
4143
};
4244
}
4345

46+
function assertCliSucceeded(exitCode: number, capture: IoCapture): void {
47+
assert.equal(
48+
exitCode,
49+
0,
50+
`expected gateway smoke CLI to exit 0\nstderr:\n${capture.stderr()}\nstdout:\n${capture.stdout()}`,
51+
);
52+
assert.equal(capture.stderr(), "");
53+
}
54+
4455
test("parseArgs accepts strict gateway smoke options", () => {
4556
const args = parseArgs([
4657
"--cwd",
@@ -383,8 +394,7 @@ test("runGatewaySmokeCli starts the tiny profile and verifies inference", async
383394

384395
const exitCode = await runGatewaySmokeCli(["--cwd", repoRoot, "--json"], capture.io);
385396

386-
assert.equal(exitCode, 0);
387-
assert.equal(capture.stderr(), "");
397+
assertCliSucceeded(exitCode, capture);
388398

389399
const summary = JSON.parse(capture.stdout()) as GatewaySmokeSummary;
390400
assert.equal(summary.ok, true);
@@ -440,8 +450,7 @@ test("runGatewaySmokeCli verifies public auth guards and rate limiting", async (
440450
capture.io,
441451
);
442452

443-
assert.equal(exitCode, 0);
444-
assert.equal(capture.stderr(), "");
453+
assertCliSucceeded(exitCode, capture);
445454

446455
const summary = JSON.parse(capture.stdout()) as GatewaySmokeSummary;
447456
assert.equal(summary.ok, true);
@@ -485,8 +494,7 @@ test("runGatewaySmokeCli verifies async queue submission and completion", async
485494
capture.io,
486495
);
487496

488-
assert.equal(exitCode, 0);
489-
assert.equal(capture.stderr(), "");
497+
assertCliSucceeded(exitCode, capture);
490498

491499
const summary = JSON.parse(capture.stdout()) as GatewaySmokeSummary;
492500
assert.equal(summary.ok, true);
@@ -520,8 +528,7 @@ test("runGatewaySmokeCli verifies authenticated public async queue submission",
520528
capture.io,
521529
);
522530

523-
assert.equal(exitCode, 0);
524-
assert.equal(capture.stderr(), "");
531+
assertCliSucceeded(exitCode, capture);
525532

526533
const summary = JSON.parse(capture.stdout()) as GatewaySmokeSummary;
527534
assert.equal(summary.ok, true);

0 commit comments

Comments
 (0)