fix: handle missing tailscale binary · openclaw/openclaw@05fbdd4
steipete
·
2026-04-25
·
via Recent Commits to openclaw:main
File tree
extensions/voice-call/src/webhook
| Original file line number | Diff line number | Diff line change |
|---|
@@ -40,6 +40,19 @@ function createProc(params?: { code?: number; stdout?: string }) {
|
40 | 40 | return proc; |
41 | 41 | } |
42 | 42 | |
| 43 | +function createErrorProc() { |
| 44 | +const proc = new EventEmitter() as EventEmitter & { |
| 45 | +stdout: EventEmitter; |
| 46 | +kill: ReturnType<typeof vi.fn>; |
| 47 | +}; |
| 48 | +proc.stdout = new EventEmitter(); |
| 49 | +proc.kill = vi.fn(); |
| 50 | +setTimeout(() => { |
| 51 | +proc.emit("error", Object.assign(new Error("spawn tailscale ENOENT"), { code: "ENOENT" })); |
| 52 | +}, 0); |
| 53 | +return proc; |
| 54 | +} |
| 55 | + |
43 | 56 | describe("voice-call tailscale helpers", () => { |
44 | 57 | beforeEach(() => { |
45 | 58 | vi.clearAllMocks(); |
@@ -83,6 +96,12 @@ describe("voice-call tailscale helpers", () => {
|
83 | 96 | await expect(getTailscaleSelfInfo()).resolves.toBeNull(); |
84 | 97 | }); |
85 | 98 | |
| 99 | +it("treats missing tailscale binary as unavailable instead of leaking spawn errors", async () => { |
| 100 | +spawnMock.mockReturnValueOnce(createErrorProc()); |
| 101 | + |
| 102 | +await expect(getTailscaleSelfInfo()).resolves.toBeNull(); |
| 103 | +}); |
| 104 | + |
86 | 105 | it("sets up and cleans up exposure routes with the selected mode", async () => { |
87 | 106 | spawnMock |
88 | 107 | .mockReturnValueOnce( |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -16,18 +16,32 @@ function runTailscaleCommand(
|
16 | 16 | }); |
17 | 17 | |
18 | 18 | let stdout = ""; |
| 19 | +let settled = false; |
| 20 | +let timer: ReturnType<typeof setTimeout>; |
| 21 | +const finish = (result: { code: number; stdout: string }) => { |
| 22 | +if (settled) { |
| 23 | +return; |
| 24 | +} |
| 25 | +settled = true; |
| 26 | +clearTimeout(timer); |
| 27 | +resolve(result); |
| 28 | +}; |
| 29 | + |
19 | 30 | proc.stdout.on("data", (data) => { |
20 | 31 | stdout += data; |
21 | 32 | }); |
22 | 33 | |
23 | | -const timer = setTimeout(() => { |
| 34 | +timer = setTimeout(() => { |
24 | 35 | proc.kill("SIGKILL"); |
25 | | -resolve({ code: -1, stdout: "" }); |
| 36 | +finish({ code: -1, stdout: "" }); |
26 | 37 | }, timeoutMs); |
27 | 38 | |
| 39 | +proc.on("error", () => { |
| 40 | +finish({ code: -1, stdout: "" }); |
| 41 | +}); |
| 42 | + |
28 | 43 | proc.on("close", (code) => { |
29 | | -clearTimeout(timer); |
30 | | -resolve({ code: code ?? -1, stdout }); |
| 44 | +finish({ code: code ?? -1, stdout }); |
31 | 45 | }); |
32 | 46 | }); |
33 | 47 | } |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。