fix(test): guard model resolution profiler args

This commit is contained in:
Vincent Koc
2026-06-20 02:22:59 +02:00
parent e02bee6aab
commit 87358d7a7c
2 changed files with 94 additions and 5 deletions

View File

@@ -26,6 +26,23 @@ type Options = {
warmup: number;
};
const BOOLEAN_FLAGS = new Set(["--help", "-h", "--json", "--keep-temp", "--runtime-hooks"]);
const VALUE_FLAGS = new Set([
"--agents",
"--cpu-prof-dir",
"--cpu-prof-output",
"--lookups",
"--models-per-provider",
"--output",
"--providers",
"--runs",
"--warmup",
]);
class CliArgumentError extends Error {
override name = "CliArgumentError";
}
type PhaseSample = {
ensureMs: number;
resolveMs: number;
@@ -73,7 +90,11 @@ function parseFlagValue(flag: string): string | undefined {
if (index === -1) {
return undefined;
}
return process.argv[index + 1];
const value = process.argv[index + 1];
if (!value || value.startsWith("--")) {
throw new CliArgumentError(`${flag} requires a value`);
}
return value;
}
function hasFlag(flag: string): boolean {
@@ -85,9 +106,12 @@ function parsePositiveInt(flag: string, fallback: number): number {
if (!raw) {
return fallback;
}
const value = Number.parseInt(raw, 10);
const value = Number(raw);
if (!Number.isFinite(value) || value <= 0) {
throw new Error(`${flag} must be a positive integer`);
throw new CliArgumentError(`${flag} must be a positive integer`);
}
if (!Number.isInteger(value)) {
throw new CliArgumentError(`${flag} must be a positive integer`);
}
return value;
}
@@ -97,14 +121,32 @@ function parseNonNegativeInt(flag: string, fallback: number): number {
if (!raw) {
return fallback;
}
const value = Number.parseInt(raw, 10);
const value = Number(raw);
if (!Number.isFinite(value) || value < 0) {
throw new Error(`${flag} must be a non-negative integer`);
throw new CliArgumentError(`${flag} must be a non-negative integer`);
}
if (!Number.isInteger(value)) {
throw new CliArgumentError(`${flag} must be a non-negative integer`);
}
return value;
}
function validateCliArgs(args = process.argv.slice(2)): void {
for (let index = 0; index < args.length; index += 1) {
const arg = args[index] ?? "";
if (BOOLEAN_FLAGS.has(arg)) {
continue;
}
if (VALUE_FLAGS.has(arg)) {
index += 1;
continue;
}
throw new CliArgumentError(`Unknown argument: ${arg}`);
}
}
function parseOptions(): Options {
validateCliArgs();
return {
agentCount: parsePositiveInt("--agents", 8),
cpuProfDir: parseFlagValue("--cpu-prof-dir"),
@@ -494,6 +536,10 @@ async function main(): Promise<void> {
}
main().catch((error: unknown) => {
if (error instanceof CliArgumentError) {
process.stderr.write(`${error.message}\n`);
process.exit(1);
}
const message = error instanceof Error ? (error.stack ?? error.message) : String(error);
process.stderr.write(`${message}\n`);
process.exit(1);

View File

@@ -0,0 +1,43 @@
// Issue 78851 profiler CLI tests cover argument handling before work starts.
import { spawnSync } from "node:child_process";
import { describe, expect, it } from "vitest";
function runProfiler(...args: string[]) {
return spawnSync(
process.execPath,
["--import", "tsx", "scripts/perf/issue-78851-model-resolution.ts", ...args],
{
cwd: process.cwd(),
encoding: "utf8",
},
);
}
describe("issue 78851 model resolution profiler CLI", () => {
it("prints help without starting the profiler", () => {
const result = runProfiler("--help");
expect(result.status).toBe(0);
expect(result.stdout).toContain("OpenClaw issue #78851 model-resolution profiler");
expect(result.stdout).toContain(
"node --import tsx scripts/perf/issue-78851-model-resolution.ts [options]",
);
expect(result.stderr).toBe("");
});
it("rejects unknown arguments before starting the profiler", () => {
const result = runProfiler("--wat");
expect(result.status).toBe(1);
expect(result.stdout).toBe("");
expect(result.stderr.trim()).toBe("Unknown argument: --wat");
});
it("rejects partial numeric arguments before starting the profiler", () => {
const result = runProfiler("--providers", "48junk");
expect(result.status).toBe(1);
expect(result.stdout).toBe("");
expect(result.stderr.trim()).toBe("--providers must be a positive integer");
});
});