From fff3b15fd73cdf2187a28e4dd11b022567da0c94 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sun, 7 Jun 2026 09:01:51 +0200 Subject: [PATCH] fix(e2e): bound kitchen sink failure logs --- .../lib/kitchen-sink-plugin/assertions.mjs | 18 ++++++++++++- .../kitchen-sink-plugin-assertions.test.ts | 27 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/scripts/e2e/lib/kitchen-sink-plugin/assertions.mjs b/scripts/e2e/lib/kitchen-sink-plugin/assertions.mjs index c0315c2e95d1..dfaa2ac2169a 100644 --- a/scripts/e2e/lib/kitchen-sink-plugin/assertions.mjs +++ b/scripts/e2e/lib/kitchen-sink-plugin/assertions.mjs @@ -14,6 +14,10 @@ const LOG_SCAN_MAX_FILES = 5000; const LOG_SCAN_MAX_FINDINGS = 100; const LOG_SCAN_MAX_LINE_CHARS = 16 * 1024; const LOG_SCAN_SEGMENT_OVERLAP_CHARS = 256; +const EXPECT_FAILURE_OUTPUT_MAX_BYTES = readPositiveIntEnv( + "KITCHEN_SINK_EXPECT_FAILURE_OUTPUT_MAX_BYTES", + 1024 * 1024, +); const readJson = (file) => JSON.parse(fs.readFileSync(file, "utf8")); const scratchFile = (name) => path.join(scratchRoot, name); @@ -45,9 +49,21 @@ function resolveHomePath(value) { return value; } +function readTextFileBounded(file, maxBytes, label) { + const stats = fs.statSync(file); + if (stats.size > maxBytes) { + throw new Error(`${label} exceeded ${maxBytes} bytes: ${file} (${stats.size} bytes)`); + } + return fs.readFileSync(file, "utf8"); +} + function expectFailure() { const outputFile = process.argv[3]; - const output = fs.readFileSync(outputFile, "utf8"); + const output = readTextFileBounded( + outputFile, + EXPECT_FAILURE_OUTPUT_MAX_BYTES, + "expected failure output", + ); const source = process.env.KITCHEN_SINK_SOURCE; const spec = process.env.KITCHEN_SINK_SPEC; const displayedSpec = source === "npm" ? spec.replace(/^npm:/u, "") : spec; diff --git a/test/scripts/kitchen-sink-plugin-assertions.test.ts b/test/scripts/kitchen-sink-plugin-assertions.test.ts index 2a40f023f542..c3191dd2ce33 100644 --- a/test/scripts/kitchen-sink-plugin-assertions.test.ts +++ b/test/scripts/kitchen-sink-plugin-assertions.test.ts @@ -222,6 +222,33 @@ function runSweepShell(script: string, env: NodeJS.ProcessEnv = {}) { } describe("kitchen-sink plugin assertions", () => { + it("bounds expected-failure output before matching failure diagnostics", () => { + const scratchRoot = mkdtempSync(path.join(tmpdir(), "openclaw-kitchen-sink-failure-cap-")); + const outputPath = path.join(scratchRoot, "expected-failure.log"); + try { + writeFileSync(outputPath, "x".repeat(128)); + + const result = spawnSync( + process.execPath, + [ASSERTIONS_SCRIPT, "expect-failure", outputPath], + { + encoding: "utf8", + env: { + ...process.env, + KITCHEN_SINK_EXPECT_FAILURE_OUTPUT_MAX_BYTES: "64", + KITCHEN_SINK_SOURCE: "npm", + KITCHEN_SINK_SPEC: "npm:@openclaw/kitchen-sink@0.0.0", + }, + }, + ); + + expect(result.status).not.toBe(0); + expect(result.stderr).toContain("expected failure output exceeded 64 bytes"); + } finally { + rmSync(scratchRoot, { force: true, recursive: true }); + } + }); + it("fails full-surface installs when stable diagnostic canaries disappear", () => { const result = runAssertInstalled();