























@@ -0,0 +1,97 @@
1+import { spawn, spawnSync, type ChildProcessWithoutNullStreams } from "node:child_process";
2+import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
3+import { tmpdir } from "node:os";
4+import path from "node:path";
5+import { setTimeout as delay } from "node:timers/promises";
6+import { describe, expect, it } from "vitest";
7+8+const DRIVER_SCRIPT = "scripts/e2e/npm-telegram-rtt-driver.mjs";
9+10+async function waitForFile(filePath: string, timeoutMs = 3000): Promise<string> {
11+const startedAt = Date.now();
12+while (Date.now() - startedAt < timeoutMs) {
13+if (existsSync(filePath)) {
14+return readFileSync(filePath, "utf8");
15+}
16+await delay(25);
17+}
18+throw new Error(`timed out waiting for ${filePath}`);
19+}
20+21+async function stopChild(child: ChildProcessWithoutNullStreams): Promise<void> {
22+if (child.exitCode !== null) {
23+return;
24+}
25+child.kill("SIGTERM");
26+const startedAt = Date.now();
27+while (child.exitCode === null && Date.now() - startedAt < 1000) {
28+await delay(25);
29+}
30+if (child.exitCode === null) {
31+child.kill("SIGKILL");
32+}
33+}
34+35+function startStalledJsonServer(portPath: string) {
36+return spawn(
37+process.execPath,
38+[
39+"--input-type=module",
40+"--eval",
41+[
42+'import net from "node:net";',
43+'import fs from "node:fs";',
44+'const server = net.createServer((socket) => socket.write("HTTP/1.1 200 OK\\r\\nContent-Type: application/json\\r\\n\\r\\n"));',
45+'server.listen(0, "127.0.0.1", () => {',
46+" const address = server.address();",
47+" fs.writeFileSync(process.env.PORT_FILE, String(address.port));",
48+"});",
49+"setInterval(() => {}, 1000);",
50+].join("\n"),
51+],
52+{
53+env: { ...process.env, PORT_FILE: portPath },
54+stdio: "pipe",
55+},
56+);
57+}
58+59+describe("npm Telegram RTT driver", () => {
60+it("bounds stalled Telegram Bot API response bodies", async () => {
61+const root = mkdtempSync(path.join(tmpdir(), "openclaw-telegram-rtt-driver-"));
62+const portPath = path.join(root, "port.txt");
63+const outputDir = path.join(root, "out");
64+const server = startStalledJsonServer(portPath);
65+66+try {
67+const port = Number.parseInt((await waitForFile(portPath)).trim(), 10);
68+const startedAt = Date.now();
69+const result = spawnSync(process.execPath, [DRIVER_SCRIPT], {
70+encoding: "utf8",
71+env: {
72+ ...process.env,
73+OPENCLAW_NPM_TELEGRAM_BOT_API_TIMEOUT_MS: "100",
74+OPENCLAW_NPM_TELEGRAM_OUTPUT_DIR: outputDir,
75+OPENCLAW_NPM_TELEGRAM_WARM_SAMPLES: "1",
76+OPENCLAW_QA_TELEGRAM_API_BASE_URL: `http://127.0.0.1:${port}`,
77+OPENCLAW_QA_TELEGRAM_CANARY_TIMEOUT_MS: "1000",
78+OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKEN: "driver-token",
79+OPENCLAW_QA_TELEGRAM_GROUP_ID: "-100123",
80+OPENCLAW_QA_TELEGRAM_SCENARIO_TIMEOUT_MS: "1000",
81+OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN: "sut-token",
82+},
83+killSignal: "SIGKILL",
84+timeout: 2500,
85+});
86+87+expect(result.error).toBeUndefined();
88+expect(result.signal).not.toBe("SIGKILL");
89+expect(result.status).not.toBe(0);
90+expect(result.stderr).toMatch(/abort|timed out|terminated/iu);
91+expect(Date.now() - startedAt).toBeLessThan(2500);
92+} finally {
93+await stopChild(server);
94+rmSync(root, { force: true, recursive: true });
95+}
96+});
97+});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。