mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
fix(e2e): clean plugin fixture servers on timeout
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { spawn, spawnSync } from "node:child_process";
|
||||
import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { chmodSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { createServer } from "node:http";
|
||||
import { tmpdir } from "node:os";
|
||||
import path from "node:path";
|
||||
@@ -7,6 +7,10 @@ import { describe, expect, it } from "vitest";
|
||||
|
||||
const ASSERTIONS_SCRIPT = "scripts/e2e/lib/plugins/assertions.mjs";
|
||||
|
||||
function shellQuote(value: string): string {
|
||||
return `'${value.replace(/'/gu, `'\\''`)}'`;
|
||||
}
|
||||
|
||||
function writeJson(filePath: string, value: unknown) {
|
||||
mkdirSync(path.dirname(filePath), { recursive: true });
|
||||
writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`, "utf8");
|
||||
@@ -47,6 +51,43 @@ function runAssertionAsync(args: string[], env: NodeJS.ProcessEnv) {
|
||||
);
|
||||
}
|
||||
|
||||
function writeFixtureServerShims(binDir: string, pidPath: string): void {
|
||||
mkdirSync(binDir, { recursive: true });
|
||||
writeFileSync(
|
||||
path.join(binDir, "node"),
|
||||
[
|
||||
"#!/bin/bash",
|
||||
'printf "%s\\n" "$$" >"$OPENCLAW_TEST_FIXTURE_SERVER_PID"',
|
||||
"trap 'exit 0' TERM",
|
||||
"while true; do /bin/sleep 1; done",
|
||||
"",
|
||||
].join("\n"),
|
||||
);
|
||||
writeFileSync(path.join(binDir, "sleep"), "#!/bin/bash\nexit 0\n");
|
||||
chmodSync(path.join(binDir, "node"), 0o755);
|
||||
chmodSync(path.join(binDir, "sleep"), 0o755);
|
||||
writeFileSync(pidPath, "");
|
||||
}
|
||||
|
||||
function isProcessAlive(pid: number): boolean {
|
||||
try {
|
||||
process.kill(pid, 0);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function waitForDead(pid: number, timeoutMs = 2_000): void {
|
||||
const startedAt = Date.now();
|
||||
while (isProcessAlive(pid)) {
|
||||
if (Date.now() - startedAt > timeoutMs) {
|
||||
throw new Error(`pid ${pid} is still alive`);
|
||||
}
|
||||
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 20);
|
||||
}
|
||||
}
|
||||
|
||||
describe("plugins Docker assertions", () => {
|
||||
it("rejects loose ClawHub preflight limits instead of parsing prefixes", () => {
|
||||
const timeoutResult = spawnSync(process.execPath, [ASSERTIONS_SCRIPT, "clawhub-preflight"], {
|
||||
@@ -92,6 +133,99 @@ describe("plugins Docker assertions", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("cleans npm fixture registry children when readiness times out", () => {
|
||||
const root = mkdtempSync(path.join(tmpdir(), "openclaw-plugin-npm-fixture-cleanup-"));
|
||||
try {
|
||||
const binDir = path.join(root, "bin");
|
||||
const fixtureDir = path.join(root, "fixture");
|
||||
const cleanupPath = path.join(root, "caller-cleanup");
|
||||
const pidPath = path.join(root, "server.pid");
|
||||
mkdirSync(fixtureDir);
|
||||
writeFixtureServerShims(binDir, pidPath);
|
||||
|
||||
const result = spawnSync(
|
||||
"/bin/bash",
|
||||
[
|
||||
"-c",
|
||||
[
|
||||
"set -euo pipefail",
|
||||
"source scripts/e2e/lib/plugins/fixtures.sh",
|
||||
"set +e",
|
||||
`( set -e; trap 'printf caller-cleanup > ${shellQuote(cleanupPath)}' EXIT; start_npm_fixture_registry fixture-pkg 1.0.0 ${shellQuote(path.join(root, "fixture.tgz"))} ${shellQuote(fixtureDir)} )`,
|
||||
'status="$?"',
|
||||
"set -e",
|
||||
'[ "$status" != "0" ]',
|
||||
].join("\n"),
|
||||
],
|
||||
{
|
||||
cwd: process.cwd(),
|
||||
encoding: "utf8",
|
||||
env: {
|
||||
...process.env,
|
||||
OPENCLAW_TEST_FIXTURE_SERVER_PID: pidPath,
|
||||
PATH: `${binDir}${path.delimiter}/usr/bin${path.delimiter}/bin`,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
expect(result.status, result.stderr || result.stdout).toBe(0);
|
||||
const pid = Number(readFileSync(pidPath, "utf8"));
|
||||
expect(Number.isInteger(pid)).toBe(true);
|
||||
waitForDead(pid);
|
||||
expect(readFileSync(cleanupPath, "utf8")).toBe("caller-cleanup");
|
||||
} finally {
|
||||
rmSync(root, { force: true, recursive: true });
|
||||
}
|
||||
});
|
||||
|
||||
it("cleans ClawHub fixture children when readiness times out", () => {
|
||||
const root = mkdtempSync(path.join(tmpdir(), "openclaw-plugin-clawhub-fixture-cleanup-"));
|
||||
try {
|
||||
const binDir = path.join(root, "bin");
|
||||
const cleanupPath = path.join(root, "caller-cleanup");
|
||||
const tmpDir = path.join(root, "scratch");
|
||||
const pidPath = path.join(root, "server.pid");
|
||||
mkdirSync(tmpDir);
|
||||
writeFixtureServerShims(binDir, pidPath);
|
||||
|
||||
const result = spawnSync(
|
||||
"/bin/bash",
|
||||
[
|
||||
"-c",
|
||||
[
|
||||
"set -euo pipefail",
|
||||
"source scripts/e2e/lib/plugins/fixtures.sh",
|
||||
"source scripts/e2e/lib/plugins/clawhub.sh",
|
||||
"set +e",
|
||||
`( set -e; trap 'printf caller-cleanup > ${shellQuote(cleanupPath)}' EXIT; run_plugins_clawhub_scenario )`,
|
||||
'status="$?"',
|
||||
"set -e",
|
||||
'[ "$status" != "0" ]',
|
||||
].join("\n"),
|
||||
],
|
||||
{
|
||||
cwd: process.cwd(),
|
||||
encoding: "utf8",
|
||||
env: {
|
||||
...process.env,
|
||||
OPENCLAW_PLUGINS_E2E_LIVE_CLAWHUB: "0",
|
||||
OPENCLAW_PLUGINS_TMP_DIR: tmpDir,
|
||||
OPENCLAW_TEST_FIXTURE_SERVER_PID: pidPath,
|
||||
PATH: `${binDir}${path.delimiter}/usr/bin${path.delimiter}/bin`,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
expect(result.status, result.stderr || result.stdout).toBe(0);
|
||||
const pid = Number(readFileSync(pidPath, "utf8"));
|
||||
expect(Number.isInteger(pid)).toBe(true);
|
||||
waitForDead(pid);
|
||||
expect(readFileSync(cleanupPath, "utf8")).toBe("caller-cleanup");
|
||||
} finally {
|
||||
rmSync(root, { force: true, recursive: true });
|
||||
}
|
||||
});
|
||||
|
||||
it("uses the configured scratch root and resolves Windows home-relative install paths", () => {
|
||||
const root = mkdtempSync(path.join(tmpdir(), "openclaw-plugins-assertions-"));
|
||||
const home = path.join(root, "home");
|
||||
|
||||
Reference in New Issue
Block a user