mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-21 02:06:43 +00:00
test: accelerate sqlite state cli tests (#107150)
This commit is contained in:
@@ -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-"));
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -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,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user