Skip to content

Commit 61b116d

Browse files
committed
fix(e2e): validate plugin update timeout seconds
1 parent 033162f commit 61b116d

5 files changed

Lines changed: 59 additions & 2 deletions

File tree

scripts/e2e/lib/plugin-update/corrupt-update-scenario.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export OPENCLAW_NO_ONBOARD=1
1818
export OPENCLAW_NO_PROMPT=1
1919

2020
baseline="${OPENCLAW_UPDATE_CORRUPT_PLUGIN_BASELINE:-openclaw@latest}"
21-
update_timeout_seconds="${OPENCLAW_UPDATE_CORRUPT_PLUGIN_TIMEOUT_SECONDS:-900}"
21+
update_timeout_seconds="$(openclaw_e2e_read_positive_int_env OPENCLAW_UPDATE_CORRUPT_PLUGIN_TIMEOUT_SECONDS 900)"
2222
echo "Installing baseline OpenClaw package: $baseline"
2323
if ! openclaw_e2e_maybe_timeout "${OPENCLAW_E2E_NPM_INSTALL_TIMEOUT:-600s}" npm install -g --prefix /tmp/npm-prefix --omit=optional "$baseline" >/tmp/openclaw-update-corrupt-baseline-install.log 2>&1; then
2424
openclaw_e2e_print_log /tmp/openclaw-update-corrupt-baseline-install.log >&2

scripts/e2e/lib/plugin-update/unchanged-scenario.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ before_config_hash=""
3131
if [ "$OPENCLAW_PACKAGE_ACCEPTANCE_LEGACY_COMPAT" != "1" ]; then
3232
before_config_hash="$(sha256sum "$OPENCLAW_CONFIG_PATH" | awk '{print $1}')"
3333
fi
34-
plugin_update_timeout_seconds="${OPENCLAW_PLUGIN_UPDATE_TIMEOUT_SECONDS:-180}"
34+
plugin_update_timeout_seconds="$(openclaw_e2e_read_positive_int_env OPENCLAW_PLUGIN_UPDATE_TIMEOUT_SECONDS 180)"
3535

3636
node "$probe" snapshot > /tmp/plugin-update-before.json
3737

scripts/lib/openclaw-e2e-instance.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,19 @@ openclaw_e2e_eval_test_state_from_b64() {
1313
fi
1414
eval "$decoded"
1515
}
16+
openclaw_e2e_read_positive_int_env() {
17+
local name="${1:?missing environment variable name}"
18+
local fallback="${2:?missing fallback value}"
19+
local value="${!name-}"
20+
if [ -z "${!name+x}" ]; then
21+
value="$fallback"
22+
fi
23+
if [[ ! "$value" =~ ^[0-9]+$ ]] || (( 10#$value < 1 )); then
24+
echo "invalid $name: $value" >&2
25+
return 2
26+
fi
27+
printf '%s\n' "$value"
28+
}
1629
openclaw_e2e_resolve_entrypoint() {
1730
local entry
1831
for entry in dist/index.mjs dist/index.js; do

test/scripts/openclaw-e2e-instance.test.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,17 @@ function shellTestEnv(overrides: Record<string, string | undefined>): NodeJS.Pro
5353
return env;
5454
}
5555

56+
function runSourcedHelper(
57+
script: string,
58+
overrides: Record<string, string | undefined> = {},
59+
): ReturnType<typeof spawnSync> {
60+
return spawnSync(
61+
"bash",
62+
["-lc", ["set -euo pipefail", `source ${shellQuote(helperPath)}`, script].join("; ")],
63+
{ encoding: "utf8", env: shellTestEnv(overrides) },
64+
);
65+
}
66+
5667
function expectShellSuccess(result: ReturnType<typeof spawnSync>) {
5768
expect(result.status, result.stderr || result.stdout || result.error?.message).toBe(0);
5869
}
@@ -149,6 +160,27 @@ describe("scripts/lib/openclaw-e2e-instance.sh", () => {
149160
expect(result.stderr).toContain("decoded to an empty script");
150161
});
151162

163+
it("reads positive integer env values without treating decimal input as durations", () => {
164+
const fallback = runSourcedHelper(
165+
'printf "%s" "$(openclaw_e2e_read_positive_int_env OPENCLAW_E2E_SAMPLE_SECONDS 180)"',
166+
);
167+
const leadingZero = runSourcedHelper(
168+
'printf "%s" "$(openclaw_e2e_read_positive_int_env OPENCLAW_E2E_SAMPLE_SECONDS 180)"',
169+
{ OPENCLAW_E2E_SAMPLE_SECONDS: "008" },
170+
);
171+
const duration = runSourcedHelper(
172+
"openclaw_e2e_read_positive_int_env OPENCLAW_E2E_SAMPLE_SECONDS 180",
173+
{ OPENCLAW_E2E_SAMPLE_SECONDS: "30s" },
174+
);
175+
176+
expectShellSuccess(fallback);
177+
expect(fallback.stdout).toBe("180");
178+
expectShellSuccess(leadingZero);
179+
expect(leadingZero.stdout).toBe("008");
180+
expect(duration.status).toBe(2);
181+
expect(duration.stderr).toContain("invalid OPENCLAW_E2E_SAMPLE_SECONDS: 30s");
182+
});
183+
152184
it("requires /readyz after the gateway ready log", () => {
153185
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-e2e-readyz-required-"));
154186
try {

test/scripts/plugin-update-unchanged-docker.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,15 @@ describe("plugin update unchanged Docker E2E", () => {
7878
const script = readFileSync(PLUGIN_UPDATE_SCENARIO_SCRIPT, "utf8");
7979

8080
expect(script).toContain("OPENCLAW_PLUGIN_UPDATE_TIMEOUT_SECONDS");
81+
expect(script).toContain(
82+
"openclaw_e2e_read_positive_int_env OPENCLAW_PLUGIN_UPDATE_TIMEOUT_SECONDS 180",
83+
);
8184
expect(script).toContain(
8285
'openclaw_e2e_maybe_timeout "${plugin_update_timeout_seconds}s" node "$entry" plugins update',
8386
);
87+
expect(script).not.toContain(
88+
'plugin_update_timeout_seconds="${OPENCLAW_PLUGIN_UPDATE_TIMEOUT_SECONDS:-180}"',
89+
);
8490
expect(script).not.toMatch(
8591
/^\s*timeout "\$\{plugin_update_timeout_seconds\}s" node "\$entry"/mu,
8692
);
@@ -149,6 +155,12 @@ describe("plugin update unchanged Docker E2E", () => {
149155
const script = readFileSync(CORRUPT_UPDATE_SCENARIO_SCRIPT, "utf8");
150156

151157
expect(script).toContain("OPENCLAW_UPDATE_CORRUPT_PLUGIN_TIMEOUT_SECONDS");
158+
expect(script).toContain(
159+
"openclaw_e2e_read_positive_int_env OPENCLAW_UPDATE_CORRUPT_PLUGIN_TIMEOUT_SECONDS 900",
160+
);
161+
expect(script).not.toContain(
162+
'update_timeout_seconds="${OPENCLAW_UPDATE_CORRUPT_PLUGIN_TIMEOUT_SECONDS:-900}"',
163+
);
152164
expect(
153165
script.match(/openclaw_e2e_maybe_timeout "\$\{update_timeout_seconds\}s" \\/gu)?.length,
154166
).toBe(2);

0 commit comments

Comments
 (0)