




















@@ -180,17 +180,30 @@ describe("scripts/lib/openclaw-e2e-instance.sh", () => {
180180}
181181});
182182183-it("runs package installs without a wrapper when timeout is unavailable", () => {
184-const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-e2e-instance-no-timeout-"));
183+it("uses gtimeout when GNU timeout is not on PATH", () => {
184+const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-e2e-instance-gtimeout-"));
185185try {
186+const timeoutArgsPath = path.join(tempDir, "timeout-args.txt");
186187const npmArgsPath = path.join(tempDir, "npm-args.txt");
187188const logPath = path.join(tempDir, "install.log");
188189const packagePath = path.join(tempDir, "openclaw.tgz");
189190fs.writeFileSync(packagePath, "");
191+fs.writeFileSync(
192+path.join(tempDir, "gtimeout"),
193+[
194+"#!/bin/bash",
195+"set -euo pipefail",
196+'printf "%s\\n" "$*" >"$OPENCLAW_TEST_TIMEOUT_ARGS"',
197+'while [ "$#" -gt 0 ] && [ "$1" != "npm" ]; do shift; done',
198+'exec "$@"',
199+"",
200+].join("\n"),
201+);
190202fs.writeFileSync(
191203path.join(tempDir, "npm"),
192204["#!/bin/sh", "set -eu", 'printf "%s\\n" "$*" >"$OPENCLAW_TEST_NPM_ARGS"', ""].join("\n"),
193205);
206+fs.chmodSync(path.join(tempDir, "gtimeout"), 0o755);
194207fs.chmodSync(path.join(tempDir, "npm"), 0o755);
195208196209const result = spawnSync(
@@ -210,18 +223,71 @@ describe("scripts/lib/openclaw-e2e-instance.sh", () => {
210223PATH: tempDir,
211224OPENCLAW_CURRENT_PACKAGE_TGZ: packagePath,
212225OPENCLAW_E2E_NPM_INSTALL_TIMEOUT: "42s",
226+OPENCLAW_TEST_TIMEOUT_ARGS: timeoutArgsPath,
213227OPENCLAW_TEST_NPM_ARGS: npmArgsPath,
214228},
215229},
216230);
217231218232expect(result.status).toBe(0);
219-expect(fs.readFileSync(logPath, "utf8")).toContain("timeout command not found");
233+expect(fs.readFileSync(timeoutArgsPath, "utf8").trim()).toBe(
234+`--kill-after=30s 42s npm install -g ${packagePath} --no-fund --no-audit`,
235+);
220236expect(fs.readFileSync(npmArgsPath, "utf8").trim()).toBe(
221237`install -g ${packagePath} --no-fund --no-audit`,
222238);
223239} finally {
224240fs.rmSync(tempDir, { force: true, recursive: true });
225241}
226242});
243+244+it("fails package installs when no timeout binary is available", () => {
245+const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-e2e-instance-no-timeout-"));
246+try {
247+const npmArgsPath = path.join(tempDir, "npm-args.txt");
248+const logPath = path.join(tempDir, "install.log");
249+const packagePath = path.join(tempDir, "openclaw.tgz");
250+fs.writeFileSync(packagePath, "");
251+fs.writeFileSync(
252+path.join(tempDir, "npm"),
253+["#!/bin/sh", "set -eu", 'printf "%s\\n" "$*" >"$OPENCLAW_TEST_NPM_ARGS"', ""].join("\n"),
254+);
255+fs.symlinkSync("/bin/cat", path.join(tempDir, "cat"));
256+fs.chmodSync(path.join(tempDir, "npm"), 0o755);
257+258+const result = spawnSync(
259+"/bin/bash",
260+[
261+"-c",
262+[
263+"set -euo pipefail",
264+`source ${shellQuote(helperPath)}`,
265+`openclaw_e2e_install_package ${shellQuote(logPath)} ${shellQuote("fixture package")}`,
266+].join("; "),
267+],
268+{
269+encoding: "utf8",
270+env: {
271+ ...process.env,
272+PATH: tempDir,
273+OPENCLAW_CURRENT_PACKAGE_TGZ: packagePath,
274+OPENCLAW_E2E_NPM_INSTALL_TIMEOUT: "42s",
275+OPENCLAW_TEST_NPM_ARGS: npmArgsPath,
276+},
277+},
278+);
279+280+expect(result.status).not.toBe(0);
281+expect(result.stderr).toContain(
282+"timeout or gtimeout is required for OpenClaw E2E command timeout 42s",
283+);
284+expect(result.stderr).toContain("npm install failed for fixture package");
285+expect(fs.readFileSync(logPath, "utf8")).toContain(
286+"timeout or gtimeout is required for OpenClaw E2E command timeout 42s",
287+);
288+expect(fs.existsSync(npmArgsPath)).toBe(false);
289+} finally {
290+fs.rmSync(tempDir, { force: true, recursive: true });
291+}
292+});
227293});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。