diff --git a/scripts/e2e/kitchen-sink-plugin-docker.sh b/scripts/e2e/kitchen-sink-plugin-docker.sh index 08c3ceb3777..afd7f983aa8 100644 --- a/scripts/e2e/kitchen-sink-plugin-docker.sh +++ b/scripts/e2e/kitchen-sink-plugin-docker.sh @@ -77,7 +77,7 @@ wait "$docker_pid" run_status="$?" set -e -cat "$RUN_LOG" +docker_e2e_print_log "$RUN_LOG" if [ "$run_status" -eq 0 ]; then node scripts/e2e/lib/docker-stats/assert-resource-ceiling.mjs "$STATS_LOG" "$MAX_MEMORY_MIB" "$MAX_CPU_PERCENT" kitchen-sink diff --git a/scripts/e2e/kitchen-sink-rpc-docker.sh b/scripts/e2e/kitchen-sink-rpc-docker.sh index 244f297699e..70588bdf8e6 100755 --- a/scripts/e2e/kitchen-sink-rpc-docker.sh +++ b/scripts/e2e/kitchen-sink-rpc-docker.sh @@ -66,7 +66,7 @@ wait "$docker_pid" run_status="$?" set -e -cat "$RUN_LOG" +docker_e2e_print_log "$RUN_LOG" if [ "$run_status" -eq 0 ]; then node scripts/e2e/lib/docker-stats/assert-resource-ceiling.mjs "$STATS_LOG" "$MAX_MEMORY_MIB" "$MAX_CPU_PERCENT" kitchen-sink-rpc diff --git a/scripts/e2e/lib/kitchen-sink-plugin/sweep.sh b/scripts/e2e/lib/kitchen-sink-plugin/sweep.sh index 65a078c7acc..53efeca46aa 100644 --- a/scripts/e2e/lib/kitchen-sink-plugin/sweep.sh +++ b/scripts/e2e/lib/kitchen-sink-plugin/sweep.sh @@ -37,16 +37,41 @@ if [[ "$KITCHEN_SINK_SWEEP_SOURCE_ONLY" != "1" ]]; then openclaw_e2e_eval_test_state_from_b64 "${OPENCLAW_TEST_STATE_SCRIPT_B64:?missing OPENCLAW_TEST_STATE_SCRIPT_B64}" fi +print_kitchen_sink_log() { + local log_file="$1" + local max_bytes="${OPENCLAW_DOCKER_E2E_LOG_PRINT_BYTES:-65536}" + if ! [[ "$max_bytes" =~ ^[0-9]+$ ]] || [ "$max_bytes" -lt 1 ]; then + max_bytes="65536" + else + max_bytes="$((10#$max_bytes))" + fi + if [ ! -f "$log_file" ]; then + return 0 + fi + local log_bytes + log_bytes="$(wc -c <"$log_file" 2>/dev/null || echo 0)" + log_bytes="${log_bytes//[[:space:]]/}" + if ! [[ "$log_bytes" =~ ^[0-9]+$ ]]; then + log_bytes="0" + fi + if [ "$log_bytes" -le "$max_bytes" ]; then + cat "$log_file" + return 0 + fi + echo "--- ${log_file} truncated: showing last ${max_bytes} of ${log_bytes} bytes ---" + tail -c "$max_bytes" "$log_file" +} + run_kitchen_sink_openclaw_logged() { local label="$1" shift local safe_label="${label//[^[:alnum:]._-]/_}" local log_file="${KITCHEN_SINK_TMP_DIR}/${safe_label}.log" if ! openclaw_e2e_maybe_timeout "$KITCHEN_SINK_CLI_TIMEOUT" node "$OPENCLAW_ENTRY" "$@" >"$log_file" 2>&1; then - cat "$log_file" + print_kitchen_sink_log "$log_file" return 1 fi - cat "$log_file" + print_kitchen_sink_log "$log_file" } run_kitchen_sink_openclaw_capture() { @@ -64,7 +89,7 @@ run_expect_failure() { "$@" >"$output_file" 2>&1 local status="$?" set -e - cat "$output_file" + print_kitchen_sink_log "$output_file" if [ "$status" -eq 0 ]; then echo "Expected ${label} to fail, but it succeeded." >&2 exit 1 diff --git a/scripts/e2e/onboard-docker.sh b/scripts/e2e/onboard-docker.sh index e170f56debe..379b65558c2 100755 --- a/scripts/e2e/onboard-docker.sh +++ b/scripts/e2e/onboard-docker.sh @@ -43,7 +43,7 @@ wait "$docker_pid" run_status="$?" set -e -cat "$RUN_LOG" +docker_e2e_print_log "$RUN_LOG" if [ "$run_status" -eq 0 ]; then node scripts/e2e/lib/docker-stats/assert-resource-ceiling.mjs "$STATS_LOG" "$MAX_MEMORY_MIB" "$MAX_CPU_PERCENT" onboard diff --git a/test/scripts/docker-build-helper.test.ts b/test/scripts/docker-build-helper.test.ts index 718a1463348..46340d17800 100644 --- a/test/scripts/docker-build-helper.test.ts +++ b/test/scripts/docker-build-helper.test.ts @@ -2126,6 +2126,8 @@ output="$(cat "$sampler_log")" expect(runner, path).toContain("docker_e2e_sample_stats_until_exit \\"); expect(runner, path).toContain('"$STATS_LOG" \\'); expect(runner, path).toContain('"$RUN_LOG" \\'); + expect(runner, path).toContain('docker_e2e_print_log "$RUN_LOG"'); + expect(runner, path).not.toContain('cat "$RUN_LOG"'); expect(runner, path).not.toMatch(/(^|\n)docker run --name "\$CONTAINER_NAME"/u); expect(runner, path).not.toMatch(/(^|\n)docker (?:inspect|stats) /u); expect(runner, path).toMatch(/cleanup\(\) \{[\s\S]*rm -f "\$RUN_LOG" "\$STATS_LOG"/u); diff --git a/test/scripts/kitchen-sink-plugin-assertions.test.ts b/test/scripts/kitchen-sink-plugin-assertions.test.ts index 4a9dbee55c7..2a40f023f54 100644 --- a/test/scripts/kitchen-sink-plugin-assertions.test.ts +++ b/test/scripts/kitchen-sink-plugin-assertions.test.ts @@ -522,6 +522,43 @@ grep -q "cli transcript: plugins install demo" "$SCRATCH_ROOT/install_log.log" } }); + it("bounds printed kitchen-sink CLI command logs without truncating saved logs", () => { + const parent = mkdtempSync(path.join(tmpdir(), "openclaw-kitchen-sink-log-print-")); + const scratchRoot = path.join(parent, "scratch"); + const entry = path.join(parent, "entry.mjs"); + try { + mkdirSync(scratchRoot, { recursive: true }); + writeFileSync( + entry, + 'process.stdout.write(`prefix\\n${"x".repeat(2048)}\\nTAIL_MARKER\\n`);\n', + ); + + const result = runSweepShell( + ` +set -euo pipefail +export KITCHEN_SINK_SWEEP_SOURCE_ONLY=1 +export KITCHEN_SINK_TMP_DIR="$SCRATCH_ROOT" +export OPENCLAW_ENTRY="$ENTRY" +export OPENCLAW_DOCKER_E2E_LOG_PRINT_BYTES=64 +source scripts/e2e/lib/kitchen-sink-plugin/sweep.sh +run_kitchen_sink_openclaw_logged "install/noisy" plugins install demo +grep -q "prefix" "$SCRATCH_ROOT/install_noisy.log" +`, + { + ENTRY: entry, + SCRATCH_ROOT: scratchRoot, + }, + ); + + expect(result.status).toBe(0); + expect(result.stdout).toContain("truncated: showing last 64"); + expect(result.stdout).toContain("TAIL_MARKER"); + expect(result.stdout).not.toContain("prefix"); + } finally { + rmSync(parent, { force: true, recursive: true }); + } + }); + it("includes expected-failure transcripts in the final kitchen-sink log scan", () => { const parent = mkdtempSync(path.join(tmpdir(), "openclaw-kitchen-sink-failure-log-")); const home = path.join(parent, "home");