test(server): harden worker terminal cleanup on windows
This commit is contained in:
@@ -87,14 +87,45 @@ class FakeTerminalWorker extends EventEmitter {
|
|||||||
|
|
||||||
let manager: TerminalManager | null = null;
|
let manager: TerminalManager | null = null;
|
||||||
const temporaryDirs: string[] = [];
|
const temporaryDirs: string[] = [];
|
||||||
|
const terminalSessions: TerminalSession[] = [];
|
||||||
|
|
||||||
afterEach(() => {
|
function trackTerminal(session: TerminalSession): TerminalSession {
|
||||||
|
terminalSessions.push(session);
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function removeTemporaryDir(dir: string): Promise<void> {
|
||||||
|
let lastError: unknown;
|
||||||
|
for (let attempt = 0; attempt < 5; attempt += 1) {
|
||||||
|
try {
|
||||||
|
rmSync(dir, { recursive: true, force: true });
|
||||||
|
return;
|
||||||
|
} catch (error) {
|
||||||
|
lastError = error;
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw lastError;
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
const sessions = terminalSessions.splice(0);
|
||||||
|
await Promise.all(
|
||||||
|
sessions.map((session) =>
|
||||||
|
session
|
||||||
|
.killAndWait({
|
||||||
|
gracefulTimeoutMs: 1000,
|
||||||
|
forceTimeoutMs: 500,
|
||||||
|
})
|
||||||
|
.catch(() => {}),
|
||||||
|
),
|
||||||
|
);
|
||||||
manager?.killAll();
|
manager?.killAll();
|
||||||
manager = null;
|
manager = null;
|
||||||
while (temporaryDirs.length > 0) {
|
while (temporaryDirs.length > 0) {
|
||||||
const dir = temporaryDirs.pop();
|
const dir = temporaryDirs.pop();
|
||||||
if (dir) {
|
if (dir) {
|
||||||
rmSync(dir, { recursive: true, force: true });
|
await removeTemporaryDir(dir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -103,15 +134,17 @@ it("creates a terminal through the worker and streams output", async () => {
|
|||||||
const cwd = mkdtempSync(join(tmpdir(), "worker-terminal-manager-output-"));
|
const cwd = mkdtempSync(join(tmpdir(), "worker-terminal-manager-output-"));
|
||||||
temporaryDirs.push(cwd);
|
temporaryDirs.push(cwd);
|
||||||
manager = createWorkerTerminalManager();
|
manager = createWorkerTerminalManager();
|
||||||
const session = await manager.createTerminal({
|
const session = trackTerminal(
|
||||||
cwd,
|
await manager.createTerminal({
|
||||||
...nodeTerminalCommand(`
|
cwd,
|
||||||
|
...nodeTerminalCommand(`
|
||||||
process.stdin.on("data", (chunk) => {
|
process.stdin.on("data", (chunk) => {
|
||||||
process.stdout.write("worker-output:" + chunk.toString());
|
process.stdout.write("worker-output:" + chunk.toString());
|
||||||
});
|
});
|
||||||
setInterval(() => {}, 1000);
|
setInterval(() => {}, 1000);
|
||||||
`),
|
`),
|
||||||
});
|
}),
|
||||||
|
);
|
||||||
const messages: string[] = [];
|
const messages: string[] = [];
|
||||||
let snapshots = 0;
|
let snapshots = 0;
|
||||||
const unsubscribe = session.subscribe((message) => {
|
const unsubscribe = session.subscribe((message) => {
|
||||||
@@ -125,7 +158,7 @@ it("creates a terminal through the worker and streams output", async () => {
|
|||||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||||
const snapshotsBeforeOutput = snapshots;
|
const snapshotsBeforeOutput = snapshots;
|
||||||
|
|
||||||
session.send({ type: "input", data: "hello\n" });
|
session.send({ type: "input", data: "hello\r" });
|
||||||
|
|
||||||
await waitForCondition(
|
await waitForCondition(
|
||||||
() =>
|
() =>
|
||||||
@@ -181,16 +214,18 @@ it("keeps registered cwd env inheritance behind the worker manager interface", a
|
|||||||
cwd,
|
cwd,
|
||||||
env: { PASEO_WORKER_TERMINAL_TEST: "worker-env" },
|
env: { PASEO_WORKER_TERMINAL_TEST: "worker-env" },
|
||||||
});
|
});
|
||||||
await manager.createTerminal({
|
trackTerminal(
|
||||||
cwd,
|
await manager.createTerminal({
|
||||||
...nodeTerminalCommand(`
|
cwd,
|
||||||
|
...nodeTerminalCommand(`
|
||||||
require("node:fs").writeFileSync(
|
require("node:fs").writeFileSync(
|
||||||
${JSON.stringify(markerPath)},
|
${JSON.stringify(markerPath)},
|
||||||
process.env.PASEO_WORKER_TERMINAL_TEST ?? "",
|
process.env.PASEO_WORKER_TERMINAL_TEST ?? "",
|
||||||
);
|
);
|
||||||
setInterval(() => {}, 1000);
|
setInterval(() => {}, 1000);
|
||||||
`),
|
`),
|
||||||
});
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
await waitForCondition(() => existsSync(markerPath), 10000);
|
await waitForCondition(() => existsSync(markerPath), 10000);
|
||||||
|
|
||||||
@@ -202,7 +237,7 @@ it("starts the default shell through the worker and accepts quoted commands", as
|
|||||||
const cwd = mkdtempSync(join(tmpdir(), "worker-terminal-manager-shell-"));
|
const cwd = mkdtempSync(join(tmpdir(), "worker-terminal-manager-shell-"));
|
||||||
temporaryDirs.push(cwd);
|
temporaryDirs.push(cwd);
|
||||||
const markerPath = join(cwd, "shell quoted marker.txt");
|
const markerPath = join(cwd, "shell quoted marker.txt");
|
||||||
const session = await manager.createTerminal({ cwd });
|
const session = trackTerminal(await manager.createTerminal({ cwd }));
|
||||||
const command = [
|
const command = [
|
||||||
"node",
|
"node",
|
||||||
"-e",
|
"-e",
|
||||||
@@ -220,15 +255,18 @@ it("removes worker terminals after killAndWait", async () => {
|
|||||||
const cwd = mkdtempSync(join(tmpdir(), "worker-terminal-manager-kill-"));
|
const cwd = mkdtempSync(join(tmpdir(), "worker-terminal-manager-kill-"));
|
||||||
temporaryDirs.push(cwd);
|
temporaryDirs.push(cwd);
|
||||||
manager = createWorkerTerminalManager();
|
manager = createWorkerTerminalManager();
|
||||||
const session = await manager.createTerminal({
|
const session = trackTerminal(
|
||||||
cwd,
|
await manager.createTerminal({
|
||||||
...nodeTerminalCommand("setInterval(() => {}, 1000);"),
|
cwd,
|
||||||
});
|
...nodeTerminalCommand("setInterval(() => {}, 1000);"),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
await manager.killTerminalAndWait(session.id, {
|
await manager.killTerminalAndWait(session.id, {
|
||||||
gracefulTimeoutMs: 1000,
|
gracefulTimeoutMs: 1000,
|
||||||
forceTimeoutMs: 500,
|
forceTimeoutMs: 500,
|
||||||
});
|
});
|
||||||
|
terminalSessions.splice(terminalSessions.indexOf(session), 1);
|
||||||
|
|
||||||
await waitForCondition(() => manager?.getTerminal(session.id) === undefined, 5000);
|
await waitForCondition(() => manager?.getTerminal(session.id) === undefined, 5000);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user