Skip to content

Commit 701d2e1

Browse files
committed
feat: US-112 - Add concurrent openShell() session test
1 parent a1408f2 commit 701d2e1

1 file changed

Lines changed: 58 additions & 0 deletions

File tree

packages/kernel/test/shell-terminal.test.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,64 @@ describe("shell-terminal", () => {
330330
});
331331
});
332332

333+
// ---------------------------------------------------------------------------
334+
// Concurrent openShell() session isolation
335+
// ---------------------------------------------------------------------------
336+
337+
describe("concurrent openShell sessions", () => {
338+
let harnessA: TerminalHarness;
339+
let harnessB: TerminalHarness;
340+
341+
afterEach(async () => {
342+
await harnessA?.dispose();
343+
await harnessB?.dispose();
344+
});
345+
346+
it("output isolation — data from shell A never appears in shell B", async () => {
347+
const driver = new MockShellDriver();
348+
const { kernel } = await createTestKernel({ drivers: [driver] });
349+
350+
harnessA = new TerminalHarness(kernel);
351+
harnessB = new TerminalHarness(kernel);
352+
353+
await harnessA.waitFor("$");
354+
await harnessB.waitFor("$");
355+
356+
// Send different commands to each shell
357+
await harnessA.type("echo ALPHA\n");
358+
await harnessB.type("echo BRAVO\n");
359+
360+
// Shell A has ALPHA, never BRAVO
361+
const screenA = harnessA.screenshotTrimmed();
362+
expect(screenA).toBe(["$ echo ALPHA", "ALPHA", "$ "].join("\n"));
363+
364+
// Shell B has BRAVO, never ALPHA
365+
const screenB = harnessB.screenshotTrimmed();
366+
expect(screenB).toBe(["$ echo BRAVO", "BRAVO", "$ "].join("\n"));
367+
});
368+
369+
it("exit one shell — surviving shell is unaffected", async () => {
370+
const driver = new MockShellDriver();
371+
const { kernel } = await createTestKernel({ drivers: [driver] });
372+
373+
harnessA = new TerminalHarness(kernel);
374+
harnessB = new TerminalHarness(kernel);
375+
376+
await harnessA.waitFor("$");
377+
await harnessB.waitFor("$");
378+
379+
// Exit shell A
380+
const codeA = await harnessA.exit();
381+
expect(codeA).toBe(0);
382+
383+
// Shell B still works — run a command
384+
await harnessB.type("echo STILL_ALIVE\n");
385+
expect(harnessB.screenshotTrimmed()).toBe(
386+
["$ echo STILL_ALIVE", "STILL_ALIVE", "$ "].join("\n"),
387+
);
388+
});
389+
});
390+
333391
// ---------------------------------------------------------------------------
334392
// readPump lifecycle tests — verify pump is tracked, exits on shell exit,
335393
// errors are propagated, and wait() drains before resolving.

0 commit comments

Comments
 (0)