mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
fix(e2e): bound plugin update logs
This commit is contained in:
@@ -10,6 +10,9 @@ import {
|
||||
} from "../plugin-index-sqlite.mjs";
|
||||
|
||||
const home = os.homedir();
|
||||
const OUTPUT_TAIL_BYTES = 64 * 1024;
|
||||
const OUTPUT_TAIL_LINES = 120;
|
||||
const OUTPUT_SCAN_WINDOW_BYTES = 8 * 1024;
|
||||
|
||||
const readJson = (file) => {
|
||||
try {
|
||||
@@ -106,15 +109,51 @@ function assertSnapshot(beforePath) {
|
||||
}
|
||||
}
|
||||
|
||||
function assertOutput(logPath) {
|
||||
const output = fs.readFileSync(logPath, "utf8");
|
||||
const failure = output.includes("Downloading @example/lossless-claw")
|
||||
function appendBufferTail(tail, chunk, maxBytes) {
|
||||
if (chunk.length >= maxBytes) {
|
||||
return chunk.subarray(chunk.length - maxBytes);
|
||||
}
|
||||
if (tail.length + chunk.length <= maxBytes) {
|
||||
return Buffer.concat([tail, chunk]);
|
||||
}
|
||||
return Buffer.concat([tail, chunk]).subarray(tail.length + chunk.length - maxBytes);
|
||||
}
|
||||
|
||||
async function readOutputEvidence(logPath) {
|
||||
let outputTail = Buffer.alloc(0);
|
||||
let scanWindow = "";
|
||||
let sawDownload = false;
|
||||
let sawUpToDate = false;
|
||||
for await (const chunk of fs.createReadStream(logPath)) {
|
||||
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
||||
const text = buffer.toString("utf8");
|
||||
const searchable = `${scanWindow}${text}`;
|
||||
outputTail = appendBufferTail(outputTail, buffer, OUTPUT_TAIL_BYTES);
|
||||
sawDownload ||= searchable.includes("Downloading @example/lossless-claw");
|
||||
sawUpToDate ||= searchable.includes("lossless-claw is up to date (0.9.0).");
|
||||
scanWindow = searchable.slice(-OUTPUT_SCAN_WINDOW_BYTES);
|
||||
}
|
||||
return {
|
||||
outputTail: outputTail
|
||||
.toString("utf8")
|
||||
.split(/\r?\n/u)
|
||||
.slice(-OUTPUT_TAIL_LINES)
|
||||
.join("\n")
|
||||
.trimEnd(),
|
||||
sawDownload,
|
||||
sawUpToDate,
|
||||
};
|
||||
}
|
||||
|
||||
async function assertOutput(logPath) {
|
||||
const evidence = await readOutputEvidence(logPath);
|
||||
const failure = evidence.sawDownload
|
||||
? "Unexpected npm download/reinstall path"
|
||||
: !output.includes("lossless-claw is up to date (0.9.0).")
|
||||
: !evidence.sawUpToDate
|
||||
? "Expected up-to-date output missing"
|
||||
: "";
|
||||
if (failure) {
|
||||
throw new Error(`${failure}\n${output}`);
|
||||
throw new Error(`${failure}\nOutput tail:\n${evidence.outputTail}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ trap 'openclaw_e2e_stop_process "${registry_pid:-}"' EXIT
|
||||
|
||||
if ! node "$probe" wait-registry; then
|
||||
echo "Local npm metadata registry failed to start"
|
||||
cat /tmp/openclaw-e2e-registry.log || true
|
||||
openclaw_e2e_print_log /tmp/openclaw-e2e-registry.log
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -42,9 +42,9 @@ set -e
|
||||
if [ "$plugin_update_status" -ne 0 ]; then
|
||||
echo "Plugin update command failed or timed out after ${plugin_update_timeout_seconds}s (status ${plugin_update_status})"
|
||||
echo "--- plugin update output ---"
|
||||
cat /tmp/plugin-update-output.log || true
|
||||
openclaw_e2e_print_log /tmp/plugin-update-output.log
|
||||
echo "--- local registry output ---"
|
||||
cat /tmp/openclaw-e2e-registry.log || true
|
||||
openclaw_e2e_print_log /tmp/openclaw-e2e-registry.log
|
||||
exit "$plugin_update_status"
|
||||
fi
|
||||
|
||||
@@ -52,11 +52,11 @@ if [ -n "$before_config_hash" ]; then
|
||||
after_config_hash="$(sha256sum "$OPENCLAW_CONFIG_PATH" | awk '{print $1}')"
|
||||
if [ "$before_config_hash" != "$after_config_hash" ]; then
|
||||
echo "Config changed unexpectedly for modern package $package_version"
|
||||
cat /tmp/plugin-update-output.log
|
||||
openclaw_e2e_print_log /tmp/plugin-update-output.log
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
node "$probe" assert-snapshot /tmp/plugin-update-before.json
|
||||
node "$probe" assert-output /tmp/plugin-update-output.log
|
||||
cat /tmp/plugin-update-output.log
|
||||
openclaw_e2e_print_log /tmp/plugin-update-output.log
|
||||
|
||||
@@ -47,6 +47,17 @@ function runProbeStatus(
|
||||
}
|
||||
}
|
||||
|
||||
function runProbeFileStatus(
|
||||
command: string,
|
||||
filePath: string,
|
||||
): { status: number | null; stderr: string } {
|
||||
const result = spawnSync("node", [PLUGIN_UPDATE_PROBE_SCRIPT, command, filePath], {
|
||||
encoding: "utf8",
|
||||
stdio: "pipe",
|
||||
});
|
||||
return { status: result.status, stderr: result.stderr };
|
||||
}
|
||||
|
||||
describe("plugin update unchanged Docker E2E", () => {
|
||||
it("seeds current plugin install ledger state before checking config stability", () => {
|
||||
const runner = readFileSync(PLUGIN_UPDATE_DOCKER_SCRIPT, "utf8");
|
||||
@@ -75,6 +86,56 @@ describe("plugin update unchanged Docker E2E", () => {
|
||||
);
|
||||
expect(script).toContain('"--- plugin update output ---"');
|
||||
expect(script).toContain('"--- local registry output ---"');
|
||||
expect(script).toContain("openclaw_e2e_print_log /tmp/plugin-update-output.log");
|
||||
expect(script).toContain("openclaw_e2e_print_log /tmp/openclaw-e2e-registry.log");
|
||||
expect(script).not.toContain("cat /tmp/plugin-update-output.log");
|
||||
expect(script).not.toContain("cat /tmp/openclaw-e2e-registry.log");
|
||||
});
|
||||
|
||||
it("bounds assert-output diagnostics to the saved command log tail", () => {
|
||||
const root = mkdtempSync(path.join(tmpdir(), "openclaw-plugin-update-probe-"));
|
||||
const logPath = path.join(root, "plugin-update-output.log");
|
||||
try {
|
||||
writeFileSync(
|
||||
logPath,
|
||||
`DO_NOT_PRINT_OLD_PLUGIN_UPDATE_LOG\n${"filler line\n".repeat(12 * 1024)}missing marker tail`,
|
||||
"utf8",
|
||||
);
|
||||
|
||||
const result = runProbeFileStatus("assert-output", logPath);
|
||||
|
||||
expect(result.status).toBe(1);
|
||||
expect(result.stderr).toContain("Expected up-to-date output missing");
|
||||
expect(result.stderr).toContain("Output tail:");
|
||||
expect(result.stderr).toContain("missing marker tail");
|
||||
expect(result.stderr).not.toContain("DO_NOT_PRINT_OLD_PLUGIN_UPDATE_LOG");
|
||||
expect(result.stderr.length).toBeLessThan(80 * 1024);
|
||||
} finally {
|
||||
rmSync(root, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
it("detects unexpected download output before a large log tail", () => {
|
||||
const root = mkdtempSync(path.join(tmpdir(), "openclaw-plugin-update-probe-"));
|
||||
const logPath = path.join(root, "plugin-update-output.log");
|
||||
try {
|
||||
writeFileSync(
|
||||
logPath,
|
||||
[
|
||||
"Downloading @example/lossless-claw",
|
||||
"filler line\n".repeat(12 * 1024),
|
||||
"lossless-claw is up to date (0.9.0).",
|
||||
].join("\n"),
|
||||
"utf8",
|
||||
);
|
||||
|
||||
const result = runProbeFileStatus("assert-output", logPath);
|
||||
|
||||
expect(result.status).toBe(1);
|
||||
expect(result.stderr).toContain("Unexpected npm download/reinstall path");
|
||||
} finally {
|
||||
rmSync(root, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
it("waits for the local registry process during cleanup", () => {
|
||||
|
||||
Reference in New Issue
Block a user