fix(e2e): reject loose runtime smoke limits

This commit is contained in:
Vincent Koc
2026-05-28 23:56:50 +02:00
parent 80f7e36ddc
commit 3ca1135515
2 changed files with 56 additions and 1 deletions

View File

@@ -42,7 +42,11 @@ const READY_OFFSET_LOG_NEEDLES = [
const FORBIDDEN_POST_READY_DEPS_WORK = [/\b(?:npm|pnpm|yarn|corepack) install\b/iu];
function readPositiveInt(raw, fallback) {
const parsed = Number.parseInt(String(raw || ""), 10);
const text = String(raw ?? "").trim();
if (!/^\d+$/u.test(text)) {
return fallback;
}
const parsed = Number(text);
return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback;
}

View File

@@ -95,6 +95,31 @@ function runRuntimeSmoke(root: string, args: string[]) {
});
}
async function importRuntimeSmokeWithEnv(env: Record<string, string | undefined>) {
const previous = new Map<string, string | undefined>();
for (const [key, value] of Object.entries(env)) {
previous.set(key, process.env[key]);
if (value === undefined) {
delete process.env[key];
} else {
process.env[key] = value;
}
}
try {
return await import(
`${pathToFileURL(runtimeSmokePath).href}?case=${Date.now()}-${Math.random()}`
);
} finally {
for (const [key, value] of previous.entries()) {
if (value === undefined) {
delete process.env[key];
} else {
process.env[key] = value;
}
}
}
}
async function listenOnLoopback(server: HttpServer | NetServer): Promise<number> {
return new Promise((resolve, reject) => {
const onError = (error: Error) => {
@@ -151,6 +176,17 @@ describe("bundled plugin install/uninstall probe", () => {
expect(second).toEqual({ text: "fghij", truncatedChars: 5 });
});
it("rejects loose runtime output limit env values instead of parsing prefixes", async () => {
const runtimeSmoke = await importRuntimeSmokeWithEnv({
OPENCLAW_BUNDLED_PLUGIN_RUNTIME_OUTPUT_CHARS: "5chars",
});
expect(runtimeSmoke.appendBoundedOutput({ text: "", truncatedChars: 0 }, "abcdef")).toEqual({
text: "abcdef",
truncatedChars: 0,
});
});
it("keeps runtime log tail reads bounded", async () => {
const runtimeSmoke = await import(pathToFileURL(runtimeSmokePath).href);
const root = makePackageRoot();
@@ -165,6 +201,21 @@ describe("bundled plugin install/uninstall probe", () => {
expect(fullRead).not.toHaveBeenCalled();
});
it("rejects loose runtime log scan byte env values instead of parsing prefixes", async () => {
const runtimeSmoke = await importRuntimeSmokeWithEnv({
OPENCLAW_BUNDLED_PLUGIN_RUNTIME_LOG_SCAN_BYTES: "64bytes",
});
const root = makePackageRoot();
const logPath = path.join(root, "gateway.log");
fs.writeFileSync(logPath, `${"old log line\n".repeat(20)}[gateway] ready\n`, "utf8");
const tail = runtimeSmoke.readFileTail(logPath);
expect(Buffer.byteLength(tail)).toBeGreaterThan(64);
expect(tail).toContain("old log line");
expect(tail).toContain("[gateway] ready");
});
it("remembers runtime ready logs after they fall outside the tail", async () => {
const runtimeSmoke = await import(pathToFileURL(runtimeSmokePath).href);
const root = makePackageRoot();