























@@ -0,0 +1,108 @@
1+import fs from "node:fs";
2+import path from "node:path";
3+import { afterAll, beforeAll, describe, expect, test } from "vitest";
4+import { GATEWAY_CLIENT_MODES, GATEWAY_CLIENT_NAMES } from "../utils/message-channel.js";
5+import { resolveRuntimeServiceVersion } from "../version.js";
6+import { connectGatewayClient } from "./test-helpers.e2e.js";
7+import { installGatewayTestHooks, startServer } from "./test-helpers.js";
8+9+installGatewayTestHooks({ scope: "suite" });
10+11+const gatewayVersion = resolveRuntimeServiceVersion(process.env);
12+13+const TEST_LOCAL_NODE_ID = "test-local-node-version-mismatch";
14+15+describe("node host version mismatch guard", () => {
16+let port: number;
17+let server: Awaited<ReturnType<typeof startServer>>["server"];
18+19+beforeAll(async () => {
20+// Write a node.json so the gateway's resolveLocalNodeId() finds it in the test state dir.
21+const stateDir = process.env.OPENCLAW_STATE_DIR;
22+if (stateDir) {
23+fs.mkdirSync(stateDir, { recursive: true });
24+fs.writeFileSync(
25+path.join(stateDir, "node.json"),
26+JSON.stringify({ version: 1, nodeId: TEST_LOCAL_NODE_ID }),
27+);
28+}
29+const started = await startServer("secret");
30+port = started.port;
31+server = started.server;
32+});
33+34+afterAll(async () => {
35+await server?.close();
36+});
37+38+test("local node with matching released version connects successfully", async () => {
39+// Use the actual gateway version so versions match
40+const client = await connectGatewayClient({
41+url: `ws://127.0.0.1:${port}`,
42+token: "secret",
43+role: "node",
44+clientName: GATEWAY_CLIENT_NAMES.NODE_HOST,
45+clientDisplayName: "test-node-match",
46+clientVersion: gatewayVersion,
47+instanceId: TEST_LOCAL_NODE_ID,
48+mode: GATEWAY_CLIENT_MODES.NODE,
49+scopes: [],
50+commands: [],
51+});
52+expect(client).toBeDefined();
53+await client.stopAndWait({ timeoutMs: 2_000 });
54+});
55+56+test("local node with mismatched released version is rejected", async () => {
57+const staleVersion = "2020.1.1";
58+await expect(
59+connectGatewayClient({
60+url: `ws://127.0.0.1:${port}`,
61+token: "secret",
62+role: "node",
63+clientName: GATEWAY_CLIENT_NAMES.NODE_HOST,
64+clientDisplayName: "test-node-stale",
65+clientVersion: staleVersion,
66+instanceId: TEST_LOCAL_NODE_ID,
67+mode: GATEWAY_CLIENT_MODES.NODE,
68+scopes: [],
69+commands: [],
70+timeoutMs: 5_000,
71+timeoutMessage: "expected version mismatch rejection",
72+}),
73+).rejects.toThrow(/client version mismatch|version mismatch/i);
74+});
75+76+test("local node with dev/test version is allowed (not a released version)", async () => {
77+// "dev" does not match YYYY.M.D, so the guard skips
78+const client = await connectGatewayClient({
79+url: `ws://127.0.0.1:${port}`,
80+token: "secret",
81+role: "node",
82+clientName: GATEWAY_CLIENT_NAMES.NODE_HOST,
83+clientDisplayName: "test-node-dev",
84+clientVersion: "dev",
85+mode: GATEWAY_CLIENT_MODES.NODE,
86+scopes: [],
87+commands: [],
88+});
89+expect(client).toBeDefined();
90+await client.stopAndWait({ timeoutMs: 2_000 });
91+});
92+93+test("local node with non-date version '1.0.0' is allowed", async () => {
94+const client = await connectGatewayClient({
95+url: `ws://127.0.0.1:${port}`,
96+token: "secret",
97+role: "node",
98+clientName: GATEWAY_CLIENT_NAMES.NODE_HOST,
99+clientDisplayName: "test-node-semver",
100+clientVersion: "1.0.0",
101+mode: GATEWAY_CLIENT_MODES.NODE,
102+scopes: [],
103+commands: [],
104+});
105+expect(client).toBeDefined();
106+await client.stopAndWait({ timeoutMs: 2_000 });
107+});
108+});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。