


























@@ -1,4 +1,6 @@
11import { execFileSync, spawnSync } from "node:child_process";
2+import fs from "node:fs";
3+import os from "node:os";
24import path from "node:path";
35import { describe, expect, it } from "vitest";
46@@ -51,4 +53,111 @@ describe("scripts/lib/openclaw-e2e-instance.sh", () => {
5153expect(result.stdout).not.toContain("value=");
5254expect(result.stderr).toContain("decoded to an empty script");
5355});
56+57+it("wraps package installs with the configured timeout", () => {
58+const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-e2e-instance-"));
59+try {
60+const timeoutArgsPath = path.join(tempDir, "timeout-args.txt");
61+const npmArgsPath = path.join(tempDir, "npm-args.txt");
62+const logPath = path.join(tempDir, "install.log");
63+const packagePath = path.join(tempDir, "openclaw.tgz");
64+fs.writeFileSync(packagePath, "");
65+fs.writeFileSync(
66+path.join(tempDir, "timeout"),
67+[
68+"#!/usr/bin/env bash",
69+"set -euo pipefail",
70+'printf "%s\\n" "$*" >"$OPENCLAW_TEST_TIMEOUT_ARGS"',
71+'while [ "$#" -gt 0 ] && [ "$1" != "npm" ]; do shift; done',
72+'exec "$@"',
73+"",
74+].join("\n"),
75+);
76+fs.writeFileSync(
77+path.join(tempDir, "npm"),
78+["#!/bin/sh", "set -eu", 'printf "%s\\n" "$*" >"$OPENCLAW_TEST_NPM_ARGS"', ""].join("\n"),
79+);
80+fs.chmodSync(path.join(tempDir, "timeout"), 0o755);
81+fs.chmodSync(path.join(tempDir, "npm"), 0o755);
82+83+const result = spawnSync(
84+"/bin/bash",
85+[
86+"-c",
87+[
88+"set -euo pipefail",
89+`source ${shellQuote(helperPath)}`,
90+`openclaw_e2e_install_package ${shellQuote(logPath)} ${shellQuote("fixture package")}`,
91+].join("; "),
92+],
93+{
94+encoding: "utf8",
95+env: {
96+ ...process.env,
97+PATH: `${tempDir}:${process.env.PATH ?? ""}`,
98+OPENCLAW_CURRENT_PACKAGE_TGZ: packagePath,
99+OPENCLAW_E2E_NPM_INSTALL_TIMEOUT: "42s",
100+OPENCLAW_TEST_TIMEOUT_ARGS: timeoutArgsPath,
101+OPENCLAW_TEST_NPM_ARGS: npmArgsPath,
102+},
103+},
104+);
105+106+expect(result.status).toBe(0);
107+expect(result.stdout).toContain("Installing fixture package...");
108+expect(fs.readFileSync(timeoutArgsPath, "utf8").trim()).toBe(
109+`--foreground --kill-after=30s 42s npm install -g ${packagePath} --no-fund --no-audit`,
110+);
111+expect(fs.readFileSync(npmArgsPath, "utf8").trim()).toBe(
112+`install -g ${packagePath} --no-fund --no-audit`,
113+);
114+} finally {
115+fs.rmSync(tempDir, { force: true, recursive: true });
116+}
117+});
118+119+it("runs package installs without a wrapper when timeout is unavailable", () => {
120+const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-e2e-instance-no-timeout-"));
121+try {
122+const npmArgsPath = path.join(tempDir, "npm-args.txt");
123+const logPath = path.join(tempDir, "install.log");
124+const packagePath = path.join(tempDir, "openclaw.tgz");
125+fs.writeFileSync(packagePath, "");
126+fs.writeFileSync(
127+path.join(tempDir, "npm"),
128+["#!/bin/sh", "set -eu", 'printf "%s\\n" "$*" >"$OPENCLAW_TEST_NPM_ARGS"', ""].join("\n"),
129+);
130+fs.chmodSync(path.join(tempDir, "npm"), 0o755);
131+132+const result = spawnSync(
133+"/bin/bash",
134+[
135+"-c",
136+[
137+"set -euo pipefail",
138+`source ${shellQuote(helperPath)}`,
139+`openclaw_e2e_install_package ${shellQuote(logPath)} ${shellQuote("fixture package")}`,
140+].join("; "),
141+],
142+{
143+encoding: "utf8",
144+env: {
145+ ...process.env,
146+PATH: tempDir,
147+OPENCLAW_CURRENT_PACKAGE_TGZ: packagePath,
148+OPENCLAW_E2E_NPM_INSTALL_TIMEOUT: "42s",
149+OPENCLAW_TEST_NPM_ARGS: npmArgsPath,
150+},
151+},
152+);
153+154+expect(result.status).toBe(0);
155+expect(fs.readFileSync(logPath, "utf8")).toContain("timeout command not found");
156+expect(fs.readFileSync(npmArgsPath, "utf8").trim()).toBe(
157+`install -g ${packagePath} --no-fund --no-audit`,
158+);
159+} finally {
160+fs.rmSync(tempDir, { force: true, recursive: true });
161+}
162+});
54163});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。