test: accelerate sqlite state cli tests (#107150)

This commit is contained in:
Peter Steinberger
2026-07-13 22:12:21 -07:00
committed by GitHub
parent 25bc6df8cd
commit 069915f173
3 changed files with 100 additions and 99 deletions
+8 -78
View File
@@ -14,8 +14,11 @@ import {
openOpenClawStateDatabase,
} from "../src/state/openclaw-state-db.js";
import { parseStrictIntegerOption } from "./lib/dev-tooling-safety.ts";
type ProfileId = "smoke" | "default" | "large";
import {
CliUsageError,
parseSqliteStateBenchmarkCli,
type ProfileId,
} from "./lib/sqlite-state-benchmark-cli.js";
type ProfileConfig = {
agentCacheEntries: number;
@@ -105,79 +108,6 @@ const PROFILES: Record<ProfileId, ProfileConfig> = {
},
};
type CliOptions = {
output: string | null;
profile: ProfileId;
stateDir: string | null;
};
const BOOLEAN_FLAGS = new Set(["--help"]);
const VALUE_FLAGS = new Set(["--output", "--profile", "--state-dir"]);
class CliUsageError extends Error {
override name = "CliUsageError";
}
function parseFlagValue(flag: string, argv: string[]): string | undefined {
const index = argv.indexOf(flag);
if (index === -1) {
return undefined;
}
const value = argv[index + 1];
if (!value || value.startsWith("-")) {
throw new CliUsageError(`${flag} requires a value`);
}
return value;
}
function hasFlag(flag: string, argv = process.argv.slice(2)): boolean {
return argv.includes(flag);
}
function validateArgs(argv: string[]): void {
const seenValueFlags = new Set<string>();
for (let index = 0; index < argv.length; index += 1) {
const arg = argv[index] ?? "";
if (BOOLEAN_FLAGS.has(arg)) {
continue;
}
if (VALUE_FLAGS.has(arg)) {
if (seenValueFlags.has(arg)) {
throw new CliUsageError(`${arg} was provided more than once`);
}
seenValueFlags.add(arg);
const value = argv[index + 1];
if (!value || value.startsWith("-")) {
throw new CliUsageError(`${arg} requires a value`);
}
index += 1;
continue;
}
throw new CliUsageError(`Unknown argument: ${arg}`);
}
}
function parseProfile(raw: string | undefined): ProfileId {
if (!raw) {
return "default";
}
if (raw === "smoke" || raw === "default" || raw === "large") {
return raw;
}
throw new CliUsageError(
`--profile must be one of smoke, default, large; got ${JSON.stringify(raw)}`,
);
}
function parseOptions(argv = process.argv.slice(2)): CliOptions {
validateArgs(argv);
return {
output: parseFlagValue("--output", argv) ?? null,
profile: parseProfile(parseFlagValue("--profile", argv)),
stateDir: parseFlagValue("--state-dir", argv) ?? null,
};
}
function applyScale(config: ProfileConfig): ProfileConfig {
const scale = parseStrictIntegerOption({
fallback: 1,
@@ -570,12 +500,12 @@ function printProofLines(report: BenchmarkReport): void {
function main(): void {
const argv = process.argv.slice(2);
validateArgs(argv);
if (hasFlag("--help", argv)) {
const cli = parseSqliteStateBenchmarkCli(argv);
if (cli.help) {
printUsage();
return;
}
const options = parseOptions(argv);
const { options } = cli;
const config = applyScale(PROFILES[options.profile]);
const stateDir =
options.stateDir ?? fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-sqlite-perf-"));
+77
View File
@@ -0,0 +1,77 @@
export type ProfileId = "smoke" | "default" | "large";
type CliOptions = {
output: string | null;
profile: ProfileId;
stateDir: string | null;
};
const BOOLEAN_FLAGS = new Set(["--help"]);
const VALUE_FLAGS = new Set(["--output", "--profile", "--state-dir"]);
export class CliUsageError extends Error {
override name = "CliUsageError";
}
function parseFlagValue(flag: string, argv: string[]): string | undefined {
const index = argv.indexOf(flag);
if (index === -1) {
return undefined;
}
const value = argv[index + 1];
if (!value || value.startsWith("-")) {
throw new CliUsageError(`${flag} requires a value`);
}
return value;
}
function validateArgs(argv: string[]): void {
const seenValueFlags = new Set<string>();
for (let index = 0; index < argv.length; index += 1) {
const arg = argv[index] ?? "";
if (BOOLEAN_FLAGS.has(arg)) {
continue;
}
if (!VALUE_FLAGS.has(arg)) {
throw new CliUsageError(`Unknown argument: ${arg}`);
}
if (seenValueFlags.has(arg)) {
throw new CliUsageError(`${arg} was provided more than once`);
}
seenValueFlags.add(arg);
const value = argv[index + 1];
if (!value || value.startsWith("-")) {
throw new CliUsageError(`${arg} requires a value`);
}
index += 1;
}
}
function parseProfile(raw: string | undefined): ProfileId {
if (!raw) {
return "default";
}
if (raw === "smoke" || raw === "default" || raw === "large") {
return raw;
}
throw new CliUsageError(
`--profile must be one of smoke, default, large; got ${JSON.stringify(raw)}`,
);
}
export function parseSqliteStateBenchmarkCli(
argv: string[],
): { help: true } | { help: false; options: CliOptions } {
validateArgs(argv);
if (argv.includes("--help")) {
return { help: true };
}
return {
help: false,
options: {
output: parseFlagValue("--output", argv) ?? null,
profile: parseProfile(parseFlagValue("--profile", argv)),
stateDir: parseFlagValue("--state-dir", argv) ?? null,
},
};
}
+15 -21
View File
@@ -1,6 +1,7 @@
// Bench SQLite State tests cover benchmark CLI argument safety.
import { spawnSync } from "node:child_process";
import { describe, expect, it } from "vitest";
import { parseSqliteStateBenchmarkCli } from "../../scripts/lib/sqlite-state-benchmark-cli.js";
function runBench(args: string[]) {
return spawnSync(
@@ -23,36 +24,29 @@ describe("scripts/bench-sqlite-state", () => {
});
it("rejects missing output values before seeding benchmark databases", () => {
const result = runBench(["--output", "--profile", "smoke"]);
expect(result.status).toBe(2);
expect(result.stdout).toBe("");
expect(result.stderr.trim()).toBe("error: --output requires a value");
expect(() => parseSqliteStateBenchmarkCli(["--output", "--profile", "smoke"])).toThrow(
"--output requires a value",
);
});
it("rejects short flag output values before seeding benchmark databases", () => {
const result = runBench(["--output", "-h"]);
expect(result.status).toBe(2);
expect(result.stdout).toBe("");
expect(result.stderr.trim()).toBe("error: --output requires a value");
expect(() => parseSqliteStateBenchmarkCli(["--output", "-h"])).toThrow(
"--output requires a value",
);
});
it("rejects invalid profiles without printing a stack trace", () => {
const result = runBench(["--profile", "huge"]);
expect(result.status).toBe(2);
expect(result.stdout).toBe("");
expect(result.stderr.trim()).toBe(
'error: --profile must be one of smoke, default, large; got "huge"',
expect(() => parseSqliteStateBenchmarkCli(["--profile", "huge"])).toThrow(
'--profile must be one of smoke, default, large; got "huge"',
);
});
it("rejects duplicate single-value controls before seeding benchmark databases", () => {
const result = runBench(["--profile", "smoke", "--profile", "large"]);
expect(result.status).toBe(2);
expect(result.stdout).toBe("");
expect(result.stderr.trim()).toBe("error: --profile was provided more than once");
expect(() =>
parseSqliteStateBenchmarkCli(["--profile", "smoke", "--profile", "large"]),
).toThrow("--profile was provided more than once");
expect(parseSqliteStateBenchmarkCli(["--help", "--profile", "huge"])).toEqual({
help: true,
});
});
});