返回 DeepSeek-Reasonix
frameSessionPool.test.ts
根目录 / desktop / electron / src / main / browser / frameSessionPool.test.ts
1 import assert from "node:assert/strict";
2 import { test } from "node:test";
3 import { FrameSessionPool } from "./frameSessionPool.js";
4 import { acquireDebugger, disposeDebugger, DEBUGGER_IDLE_MS } from "./debuggerLease.js";
5 import { FakeDebugger } from "./fakeGuestViews.js";
6
7 test("concurrent initialization is shared and one cancellation cannot detach another borrower", async () => {
8 const debuggerAPI = new FakeDebugger(); debuggerAPI.attached = true;
9 let enter!: () => void, finish!: () => void, nextSession = 0;
10 const entered = new Promise<void>(resolve => { enter = resolve; });
11 debuggerAPI.respond = method => {
12 if (method === "Target.attachToTarget") return { sessionId: `child-${++nextSession}` };
13 if (method === "Page.enable") { enter(); return new Promise<void>(resolve => { finish = resolve; }); }
14 return {};
15 };
16 const first = acquireDebugger(debuggerAPI), second = acquireDebugger(debuggerAPI);
17 const pool = FrameSessionPool.for(debuggerAPI, first);
18 assert.equal(FrameSessionPool.for(debuggerAPI, second), pool);
19 const a = pool.borrow("target"), b = pool.borrow("target");
20 await entered;
21 a.release(true); first();
22 assert.equal(debuggerAPI.commands.some(row => row.method === "Target.detachFromTarget"), false);
23 finish(); assert.equal(await b.ready, "child-1");
24 assert.equal(debuggerAPI.commands.filter(row => row.method === "Page.enable").length, 1);
25 b.release(false); second();
26 assert.deepEqual(debuggerAPI.commands.filter(row => row.method === "Target.detachFromTarget").map(row => row.params), [{ sessionId: "child-1" }]);
27 disposeDebugger(debuggerAPI);
28 assert.equal(debuggerAPI.attached, true, "external debugger stays attached");
29 });
30
31 test("an abandoned late attachment cleans only itself and cannot replace a fresh target session", async () => {
32 const debuggerAPI = new FakeDebugger(); debuggerAPI.attached = true;
33 let finish!: (value: unknown) => void, firstAttach = true;
34 debuggerAPI.respond = method => {
35 if (method === "Target.attachToTarget") {
36 if (firstAttach) { firstAttach = false; return new Promise(resolve => { finish = resolve; }); }
37 return { sessionId: "replacement" };
38 }
39 return {};
40 };
41 const connection = acquireDebugger(debuggerAPI), pool = FrameSessionPool.for(debuggerAPI, connection);
42 const old = pool.borrow("target"), rejected = assert.rejects(old.ready, /invalidated/);
43 old.release(true);
44 const current = pool.borrow("target");
45 assert.equal(await current.ready, "replacement");
46 finish({ sessionId: "late" }); await rejected;
47 debuggerAPI.emit("Target.detachedFromTarget", { sessionId: "late" });
48 const adjacent = pool.borrow("target");
49 assert.equal(await adjacent.ready, "replacement");
50 assert.equal(debuggerAPI.commands.filter(row => row.method === "Target.attachToTarget").length, 2);
51 assert.deepEqual(debuggerAPI.commands.filter(row => row.method === "Target.detachFromTarget").map(row => row.params), [{ sessionId: "late" }]);
52 current.release(false); adjacent.release(false); connection(); disposeDebugger(debuggerAPI);
53 });
54
55 test("idle cleanup removes only owned sessions and a detached target is initialized afresh", async t => {
56 t.mock.timers.enable({ apis: ["setTimeout"] });
57 const debuggerAPI = new FakeDebugger(); debuggerAPI.attached = true;
58 let index = 0;
59 debuggerAPI.respond = method => method === "Target.attachToTarget" ? { sessionId: `session-${++index}` } : {};
60 const connection = acquireDebugger(debuggerAPI), pool = FrameSessionPool.for(debuggerAPI, connection);
61 const first = pool.borrow("target"); await first.ready; first.release(false);
62 debuggerAPI.emit("Target.detachedFromTarget", { sessionId: "session-1" });
63 const second = pool.borrow("target"); assert.equal(await second.ready, "session-2"); second.release(false);
64 connection(); t.mock.timers.tick(DEBUGGER_IDLE_MS);
65 assert.deepEqual(debuggerAPI.commands.filter(row => row.method === "Target.detachFromTarget").map(row => row.params), [{ sessionId: "session-2" }]);
66 assert.equal(debuggerAPI.attached, true);
67 assert.throws(() => pool.borrow("target"), /closed/);
68 });
69
69 lines TYPESCRIPT