Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/src/packages/terminal/lib/remote-pty.test.ts
Views: 687
/*12NOTE: these tests are pretty low level. We don't actually use a websocket at all,3and explicitly shuffle messages around.45---6*/78import { Terminal } from "./terminal";9import {10getOpts,11getPrimusMock,12isPidRunning,13waitForPidToChange,14} from "./support";15import { getRemotePtyChannelName, getChannelName } from "./util";1617describe("tests remotePty connecting and handling data with **simulated** pty and explicitly pushing messages back and forth (for low level tests)", () => {18let terminal;19const { path, options } = getOpts();20const primus = getPrimusMock();21const channel = primus.channel(getChannelName(path));22const ptyChannel = primus.channel(getRemotePtyChannelName(path));2324beforeAll(() => {25terminal = new Terminal(primus, path, options);26});2728afterAll(() => {29terminal.close();30});3132it("initialize the terminal", async () => {33await terminal.init();34expect(typeof terminal.getPid()).toBe("number");35});3637let spark1, spark2;38it("create two clients connection to the terminal", async () => {39spark1 = channel.createSpark("192.168.2.1");40spark2 = channel.createSpark("192.168.2.2");41for (const s of [spark1, spark2]) {42// it initially tells us the current computeServerId, right when we connect.43const mesg1 = await s.waitForMessage();44expect(mesg1).toEqual({ cmd: "computeServerId", id: 0 });45const mesg2 = await s.waitForMessage();46expect(mesg2).toEqual({ cmd: "no-ignore" });47}48});4950let remoteSpark;51it("connect to remote pty channel and observe that local terminal process terminates", async () => {52const pid = terminal.getPid();53remoteSpark = ptyChannel.createSpark("192.168.2.2");54expect(terminal.getPid()).toBe(undefined);55// check that original process is no longer running.56expect(await isPidRunning(pid)).toBe(false);57});5859it("send data from spark1 and see that it is received by the remoteSpark, then respond and see that the client sparks both receive the response", async () => {60// reset client data state61spark1.data = spark2.data = "";62spark1.emit("data", "17+13");63expect(await remoteSpark.waitForData("17+13")).toBe("17+13");64remoteSpark.emit("data", "30");65expect(await spark1.waitForData("30")).toBe("30");66expect(await spark2.waitForData("30")).toBe("30");67});6869it("disconect the remoteSpark and see that a local pty is spawned again", async () => {70remoteSpark.end();71await waitForPidToChange(terminal, 0);72const pid = terminal.getPid();73expect(await isPidRunning(pid)).toBe(true);74});7576it("connect a remote pty again, send a kill command from one of the spark clients, and check that remote pty receives kill command", async () => {77remoteSpark = ptyChannel.createSpark("192.168.2.2");78expect((await remoteSpark.waitForMessage()).cmd).toBe("init");79spark1.emit("data", { cmd: "kill" });80expect(await remoteSpark.waitForMessage()).toEqual({ cmd: "kill" });81});8283it("sends a change of commands and args from client and sees remote pty receives that", async () => {84const command = "/usr/bin/python3";85const args = ["-b"];86spark1.emit("data", {87cmd: "set_command",88command,89args,90});91expect(await remoteSpark.waitForMessage()).toEqual({92cmd: "set_command",93command,94args,95});96});9798it("sends a size message from a client, and observes that remote pty receives a size message", async () => {99const rows = 10;100const cols = 50;101const mesg = { cmd: "size", rows, cols };102spark1.emit("data", mesg);103expect(await remoteSpark.waitForMessage()).toEqual(mesg);104});105106it("sends a cwd message from a client, then responds to that from the remoteSpark, and finally checks that the client gets it", async () => {107spark1.emit("data", { cmd: "cwd" });108spark1.messages = [];109// wait for the message to get sent to our remote spark:110expect(await remoteSpark.waitForMessage()).toEqual({ cmd: "cwd" });111// send back a cwd112remoteSpark.emit("data", { cmd: "cwd", payload: "/home/user" });113expect(await spark1.waitForMessage()).toEqual({114cmd: "cwd",115payload: "/home/user",116});117});118});119120// I disabled all of these for now. They are too difficult to maintain since they are so "fake".121122// describe("test remotePty using actual pty", () => {123// let terminal, remote;124// const { path, options } = getOpts();125// const primus = getPrimusMock();126// const channel = primus.channel(getChannelName(path));127// const ptyChannel = primus.channel(getRemotePtyChannelName(path));128129// beforeAll(async () => {130// await delay(1000);131// terminal = new Terminal(primus, path, options);132// });133134// afterAll(() => {135// terminal.close();136// if (remote != null) {137// remote.close();138// }139// });140141// it("initialize the terminal", async () => {142// await terminal.init();143// expect(typeof terminal.getPid()).toBe("number");144// });145146// let spark;147// it("create a normal client connected to the terminal", async () => {148// spark = channel.createSpark("192.168.2.1");149// const mesg = await spark.waitForMessage();150// expect(mesg).toEqual({ cmd: "no-ignore" });151// });152153// let remoteSpark;154// it("create remote terminal, and observe that local terminal process terminates", async () => {155// const pid = terminal.getPid();156// remoteSpark = ptyChannel.createSpark("192.168.2.2");157// remote = new RemoteTerminal(remoteSpark);158// expect(terminal.getPid()).toBe(undefined);159// // check that original process is no longer running.160// expect(await isPidRunning(pid)).toBe(false);161// });162163// it("observe that remote terminal process gets created", async () => {164// // NOTE: we have to explicitly shuffle the messages along,165// // since our spark mock is VERY minimal and is the same object166// // for both the client and the server.167168// const mesg = await remoteSpark.waitForMessage();169// remote.handleData(mesg);170171// expect(remote.localPty).not.toEqual(undefined);172// const pid = remote.localPty.pid;173// expect(await isPidRunning(pid)).toBe(true);174// });175176// it("use bash to compute something", async () => {177// const input = "expr 5077 \\* 389\n";178// const output = `${5077 * 389}`;179// spark.emit("data", input);180181// // shuttle the data along:182// const data = await remoteSpark.waitForData(input);183// remote.handleData(data);184// const out = await remoteSpark.waitForData(output);185// remoteSpark.emit("data", out);186187// const out2 = await spark.waitForData(output);188// expect(out2).toContain("5077");189// expect(out2).toContain(output);190// });191192// it("have client send a size, and see the remote terminal gets that size", async () => {193// spark.emit("data", { cmd: "size", rows: 10, cols: 69 });194// const mesg = await remoteSpark.waitForMessage();195// remote.handleData(mesg);196// expect(mesg).toEqual({ cmd: "size", rows: 10, cols: 69 });197// // now ask the terminal for its size198// spark.emit("data", "stty size\n");199200// const data = await remoteSpark.waitForData("stty size\n");201// remote.handleData(data);202// const out = await remoteSpark.waitForData("10 69");203// remoteSpark.emit("data", out);204205// const out2 = await spark.waitForData("10 69");206// expect(out2.trim().slice(-5)).toBe("10 69");207// });208209// it("tests the cwd command", async () => {210// spark.messages = [];211// // first from browser client to project:212// spark.emit("data", { cmd: "cwd" });213// const mesg = await remoteSpark.waitForMessage();214// remote.handleData(mesg);215// const mesg2 = await remoteSpark.waitForMessage();216// expect(mesg2.payload).toContain("terminal");217// remoteSpark.emit("data", mesg2);218// const mesg3 = await spark.waitForMessage();219// expect(mesg3).toEqual(mesg2);220// });221222// // do this last!223// it("close the RemoteTerminal, and see that a local pty is spawned again", async () => {224// remote.close();225// await waitForPidToChange(terminal, 0);226// const pid = terminal.getPid();227// expect(await isPidRunning(pid)).toBe(true);228// });229// });230231232