From 5c199629305a0b935b4388b7db549f77eae82b5a Mon Sep 17 00:00:00 2001 From: Asher Date: Wed, 21 Jun 2023 22:47:01 -0800 Subject: [PATCH] Set session socket into environment variable (#6282) * Avoid spawning code-server with --reuse-window and --new-window These flags mean the user explicitly wants to open in an existing instance so if the socket is down it should error rather than try to spawn code-server normally. * Set session socket into environment variable While I was at it I added a CLI flag to override the default. I also swapped the default to --user-data-dir. The value is set on an environment variable so it can be used by the extension host similar to VSCODE_IPC_HOOK_CLI. * Add e2e test for opening files externally --- CHANGELOG.md | 10 +++ patches/store-socket.diff | 22 +++--- src/node/app.ts | 4 +- src/node/cli.ts | 38 +++++++--- src/node/entry.ts | 2 +- src/node/vscodeSocket.ts | 5 +- test/e2e/models/CodeServer.ts | 110 ++++++++++++++++++++-------- test/e2e/terminal.test.ts | 10 ++- test/unit/node/cli.test.ts | 51 +++++++------ test/unit/node/plugin.test.ts | 1 + test/unit/node/vscodeSocket.test.ts | 13 +--- 11 files changed, 168 insertions(+), 98 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 231ff31387d2..51ec5674f2a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,16 @@ Code v99.99.999 Code v1.79.2 +### Fixed + +- Fix being unable to launch multiple instances of code-server for different + users. + +### Added + +- `--session-socket` CLI flag to configure the location of the session socket. + By default it will be placed in `--user-data-dir`. + ## [4.14.0](https://github.com/coder/code-server/releases/tag/v4.14.0) - 2023-06-16 Code v1.79.2 diff --git a/patches/store-socket.diff b/patches/store-socket.diff index cdcac74f4cca..66066272ff23 100644 --- a/patches/store-socket.diff +++ b/patches/store-socket.diff @@ -15,18 +15,16 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostExtensionService. =================================================================== --- code-server.orig/lib/vscode/src/vs/workbench/api/node/extHostExtensionService.ts +++ code-server/lib/vscode/src/vs/workbench/api/node/extHostExtensionService.ts -@@ -2,7 +2,9 @@ +@@ -2,7 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ - -+import * as os from 'os'; +import * as _http from 'http'; -+import * as path from 'vs/base/common/path'; import * as performance from 'vs/base/common/performance'; import { createApiFactoryAndRegisterActors } from 'vs/workbench/api/common/extHost.api.impl'; import { RequireInterceptor } from 'vs/workbench/api/common/extHostRequireInterceptor'; -@@ -17,6 +19,7 @@ import { ExtensionRuntime } from 'vs/wor +@@ -17,6 +17,7 @@ import { ExtensionRuntime } from 'vs/wor import { CLIServer } from 'vs/workbench/api/node/extHostCLIServer'; import { realpathSync } from 'vs/base/node/extpath'; import { ExtHostConsoleForwarder } from 'vs/workbench/api/node/extHostConsoleForwarder'; @@ -34,13 +32,14 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostExtensionService. import { ExtHostDiskFileSystemProvider } from 'vs/workbench/api/node/extHostDiskFileSystemProvider'; class NodeModuleRequireInterceptor extends RequireInterceptor { -@@ -83,6 +86,52 @@ export class ExtHostExtensionService ext +@@ -83,6 +84,52 @@ export class ExtHostExtensionService ext await interceptor.install(); performance.mark('code/extHost/didInitAPI'); + (async () => { + const socketPath = process.env['VSCODE_IPC_HOOK_CLI']; -+ if (!socketPath) { ++ const codeServerSocketPath = process.env['CODE_SERVER_SESSION_SOCKET'] ++ if (!socketPath || !codeServerSocketPath) { + return; + } + const workspace = this._instaService.invokeFunction((accessor) => { @@ -52,7 +51,6 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostExtensionService. + socketPath + }; + const message = JSON.stringify({entry}); -+ const codeServerSocketPath = path.join(os.tmpdir(), 'code-server-ipc.sock'); + await new Promise((resolve, reject) => { + const opts: _http.RequestOptions = { + path: '/add-session', @@ -91,17 +89,15 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extensionHostProcess.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/workbench/api/node/extensionHostProcess.ts +++ code-server/lib/vscode/src/vs/workbench/api/node/extensionHostProcess.ts -@@ -3,6 +3,9 @@ +@@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -+import * as os from 'os'; +import * as _http from 'http'; -+import * as path from 'vs/base/common/path'; import * as nativeWatchdog from 'native-watchdog'; import * as net from 'net'; import * as minimist from 'minimist'; -@@ -400,7 +403,28 @@ async function startExtensionHostProcess +@@ -400,7 +401,28 @@ async function startExtensionHostProcess ); // rewrite onTerminate-function to be a proper shutdown @@ -110,11 +106,11 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extensionHostProcess.ts + extensionHostMain.terminate(reason); + + const socketPath = process.env['VSCODE_IPC_HOOK_CLI']; -+ if (!socketPath) { ++ const codeServerSocketPath = process.env['CODE_SERVER_SESSION_SOCKET'] ++ if (!socketPath || !codeServerSocketPath) { + return; + } + const message = JSON.stringify({socketPath}); -+ const codeServerSocketPath = path.join(os.tmpdir(), 'code-server-ipc.sock'); + const opts: _http.RequestOptions = { + path: '/delete-session', + socketPath: codeServerSocketPath, diff --git a/src/node/app.ts b/src/node/app.ts index 2cc858f182a5..2043e3fd4bc0 100644 --- a/src/node/app.ts +++ b/src/node/app.ts @@ -9,7 +9,7 @@ import * as util from "../common/util" import { DefaultedArgs } from "./cli" import { disposer } from "./http" import { isNodeJSErrnoException } from "./util" -import { DEFAULT_SOCKET_PATH, EditorSessionManager, makeEditorSessionManagerServer } from "./vscodeSocket" +import { EditorSessionManager, makeEditorSessionManagerServer } from "./vscodeSocket" import { handleUpgrade } from "./wsRouter" type SocketOptions = { socket: string; "socket-mode"?: string } @@ -88,7 +88,7 @@ export const createApp = async (args: DefaultedArgs): Promise => { handleUpgrade(wsRouter, server) const editorSessionManager = new EditorSessionManager() - const editorSessionManagerServer = await makeEditorSessionManagerServer(DEFAULT_SOCKET_PATH, editorSessionManager) + const editorSessionManagerServer = await makeEditorSessionManagerServer(args["session-socket"], editorSessionManager) const disposeEditorSessionManagerServer = disposer(editorSessionManagerServer) const dispose = async () => { diff --git a/src/node/cli.ts b/src/node/cli.ts index fe7350f548cb..37ff3628b2d8 100644 --- a/src/node/cli.ts +++ b/src/node/cli.ts @@ -4,7 +4,7 @@ import { load } from "js-yaml" import * as os from "os" import * as path from "path" import { generateCertificate, generatePassword, humanPath, paths, splitOnFirstEquals } from "./util" -import { DEFAULT_SOCKET_PATH, EditorSessionManagerClient } from "./vscodeSocket" +import { EditorSessionManagerClient } from "./vscodeSocket" export enum Feature { // No current experimental features! @@ -51,6 +51,7 @@ export interface UserProvidedCodeArgs { "disable-file-downloads"?: boolean "disable-workspace-trust"?: boolean "disable-getting-started-override"?: boolean + "session-socket"?: string } /** @@ -160,6 +161,9 @@ export const options: Options> = { "Disable update check. Without this flag, code-server checks every 6 hours against the latest github release and \n" + "then notifies you once every week that a new release is available.", }, + "session-socket": { + type: "string", + }, "disable-file-downloads": { type: "boolean", description: @@ -459,6 +463,7 @@ export interface DefaultedArgs extends ConfigArgs { usingEnvHashedPassword: boolean "extensions-dir": string "user-data-dir": string + "session-socket": string /* Positional arguments. */ _: string[] } @@ -479,6 +484,11 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config args["extensions-dir"] = path.join(args["user-data-dir"], "extensions") } + if (!args["session-socket"]) { + args["session-socket"] = path.join(args["user-data-dir"], "code-server-ipc.sock") + } + process.env.CODE_SERVER_SESSION_SOCKET = args["session-socket"] + // --verbose takes priority over --log and --log takes priority over the // environment variable. if (args.verbose) { @@ -739,7 +749,10 @@ function bindAddrFromAllSources(...argsConfig: UserProvidedArgs[]): Addr { * existing instance. The arguments here should be the arguments the user * explicitly passed on the command line, *NOT DEFAULTS* or the configuration. */ -export const shouldOpenInExistingInstance = async (args: UserProvidedArgs): Promise => { +export const shouldOpenInExistingInstance = async ( + args: UserProvidedArgs, + sessionSocket: string, +): Promise => { // Always use the existing instance if we're running from VS Code's terminal. if (process.env.VSCODE_IPC_HOOK_CLI) { logger.debug("Found VSCODE_IPC_HOOK_CLI") @@ -747,21 +760,22 @@ export const shouldOpenInExistingInstance = async (args: UserProvidedArgs): Prom } const paths = getResolvedPathsFromArgs(args) - const client = new EditorSessionManagerClient(DEFAULT_SOCKET_PATH) - - // If we can't connect to the socket then there's no existing instance. - if (!(await client.canConnect())) { - return undefined - } + const client = new EditorSessionManagerClient(sessionSocket) // If these flags are set then assume the user is trying to open in an - // existing instance since these flags have no effect otherwise. + // existing instance since these flags have no effect otherwise. That means + // if there is no existing instance we should error rather than falling back + // to spawning code-server normally. const openInFlagCount = ["reuse-window", "new-window"].reduce((prev, cur) => { return args[cur as keyof UserProvidedArgs] ? prev + 1 : prev }, 0) if (openInFlagCount > 0) { logger.debug("Found --reuse-window or --new-window") - return await client.getConnectedSocketPath(paths[0]) + const socketPath = await client.getConnectedSocketPath(paths[0]) + if (!socketPath) { + throw new Error(`No opened code-server instances found to handle ${paths[0]}`) + } + return socketPath } // It's possible the user is trying to spawn another instance of code-server. @@ -769,7 +783,11 @@ export const shouldOpenInExistingInstance = async (args: UserProvidedArgs): Prom // code-server is invoked exactly like this: `code-server my-file`). // 2. That a file or directory was passed. // 3. That the socket is active. + // 4. That an instance exists to handle the path (implied by #3). if (Object.keys(args).length === 1 && typeof args._ !== "undefined" && args._.length > 0) { + if (!(await client.canConnect())) { + return undefined + } const socketPath = await client.getConnectedSocketPath(paths[0]) if (socketPath) { logger.debug("Found existing code-server socket") diff --git a/src/node/entry.ts b/src/node/entry.ts index 2a62ac77a1da..749b6e966cbc 100644 --- a/src/node/entry.ts +++ b/src/node/entry.ts @@ -51,7 +51,7 @@ async function entry(): Promise { return runCodeCli(args) } - const socketPath = await shouldOpenInExistingInstance(cliArgs) + const socketPath = await shouldOpenInExistingInstance(cliArgs, args["session-socket"]) if (socketPath) { logger.debug("Trying to open in existing instance") return openInExistingInstance(args, socketPath) diff --git a/src/node/vscodeSocket.ts b/src/node/vscodeSocket.ts index 8dd75a8407eb..68625028bdb3 100644 --- a/src/node/vscodeSocket.ts +++ b/src/node/vscodeSocket.ts @@ -4,10 +4,7 @@ import * as http from "http" import * as path from "path" import { HttpCode } from "../common/http" import { listen } from "./app" -import { canConnect, paths } from "./util" - -// Socket path of the daemonized code-server instance. -export const DEFAULT_SOCKET_PATH = path.join(paths.data, `code-server-ipc.sock`) +import { canConnect } from "./util" export interface EditorSessionEntry { workspace: { diff --git a/test/e2e/models/CodeServer.ts b/test/e2e/models/CodeServer.ts index 2fb625627451..a7bfaf3ddfe9 100644 --- a/test/e2e/models/CodeServer.ts +++ b/test/e2e/models/CodeServer.ts @@ -117,40 +117,26 @@ export class CodeServer { * directories. */ private async spawn(): Promise { - // This will be used both as the workspace and data directory to ensure - // instances don't bleed into each other. const dir = await this.createWorkspace() - + const args = await this.argsWithDefaults([ + "--auth", + "none", + // The workspace to open. + ...(this.args.includes("--ignore-last-opened") ? [] : [dir]), + ...this.args, + // Using port zero will spawn on a random port. + "--bind-addr", + "127.0.0.1:0", + ]) return new Promise((resolve, reject) => { - const args = [ - this.entry, - "--extensions-dir", - path.join(dir, "extensions"), - "--auth", - "none", - // The workspace to open. - ...(this.args.includes("--ignore-last-opened") ? [] : [dir]), - ...this.args, - // Using port zero will spawn on a random port. - "--bind-addr", - "127.0.0.1:0", - // Setting the XDG variables would be easier and more thorough but the - // modules we import ignores those variables for non-Linux operating - // systems so use these flags instead. - "--config", - path.join(dir, "config.yaml"), - "--user-data-dir", - dir, - ] this.logger.debug("spawning `node " + args.join(" ") + "`") const proc = cp.spawn("node", args, { cwd: path.join(__dirname, "../../.."), env: { ...process.env, ...this.env, - // Set to empty string to prevent code-server from - // using the existing instance when running the e2e tests - // from an integrated terminal. + // Prevent code-server from using the existing instance when running + // the e2e tests from an integrated terminal. VSCODE_IPC_HOOK_CLI: "", PASSWORD, }, @@ -173,11 +159,15 @@ export class CodeServer { reject(error) }) + // Tracks when the HTTP and session servers are ready. + let httpAddress: string | undefined + let sessionAddress: string | undefined + let resolved = false proc.stdout.setEncoding("utf8") onLine(proc, (line) => { // As long as we are actively getting input reset the timer. If we stop - // getting input and still have not found the address the timer will + // getting input and still have not found the addresses the timer will // reject. timer.reset() @@ -186,20 +176,69 @@ export class CodeServer { if (resolved) { return } - const match = line.trim().match(/HTTPS? server listening on (https?:\/\/[.:\d]+)\/?$/) + + let match = line.trim().match(/HTTPS? server listening on (https?:\/\/[.:\d]+)\/?$/) if (match) { - // Cookies don't seem to work on IP address so swap to localhost. + // Cookies don't seem to work on IP addresses so swap to localhost. // TODO: Investigate whether this is a bug with code-server. - const address = match[1].replace("127.0.0.1", "localhost") - this.logger.debug(`spawned on ${address}`) + httpAddress = match[1].replace("127.0.0.1", "localhost") + } + + match = line.trim().match(/Session server listening on (.+)$/) + if (match) { + sessionAddress = match[1] + } + + if (typeof httpAddress !== "undefined" && typeof sessionAddress !== "undefined") { resolved = true timer.dispose() - resolve({ process: proc, address }) + this.logger.debug(`code-server is ready: ${httpAddress} ${sessionAddress}`) + resolve({ process: proc, address: httpAddress }) } }) }) } + /** + * Execute a short-lived command. + */ + async run(args: string[]): Promise { + args = await this.argsWithDefaults(args) + this.logger.debug("executing `node " + args.join(" ") + "`") + await util.promisify(cp.exec)("node " + args.join(" "), { + cwd: path.join(__dirname, "../../.."), + env: { + ...process.env, + ...this.env, + // Prevent code-server from using the existing instance when running + // the e2e tests from an integrated terminal. + VSCODE_IPC_HOOK_CLI: "", + }, + }) + } + + /** + * Combine arguments with defaults. + */ + private async argsWithDefaults(args: string[]): Promise { + // This will be used both as the workspace and data directory to ensure + // instances don't bleed into each other. + const dir = await this.workspaceDir + return [ + this.entry, + "--extensions-dir", + path.join(dir, "extensions"), + ...args, + // Setting the XDG variables would be easier and more thorough but the + // modules we import ignores those variables for non-Linux operating + // systems so use these flags instead. + "--config", + path.join(dir, "config.yaml"), + "--user-data-dir", + dir, + ] + } + /** * Close the code-server process. */ @@ -364,6 +403,13 @@ export class CodeServerPage { await this.waitForTab(file) } + /** + * Open a file through an external command. + */ + async openFileExternally(file: string) { + await this.codeServer.run(["--reuse-window", file]) + } + /** * Wait for a tab to open for the specified file. */ diff --git a/test/e2e/terminal.test.ts b/test/e2e/terminal.test.ts index f4860dcd3641..0de4f222a2a3 100644 --- a/test/e2e/terminal.test.ts +++ b/test/e2e/terminal.test.ts @@ -35,13 +35,19 @@ describe("Integrated Terminal", ["--disable-workspace-trust"], {}, () => { const tmpFolderPath = await tmpdir(testName) const tmpFile = path.join(tmpFolderPath, "test-file") await fs.writeFile(tmpFile, "test") - const fileName = path.basename(tmpFile) await codeServerPage.focusTerminal() await codeServerPage.page.keyboard.type(`code-server ${tmpFile}`) await codeServerPage.page.keyboard.press("Enter") - await codeServerPage.waitForTab(fileName) + await codeServerPage.waitForTab(path.basename(tmpFile)) + + const externalTmpFile = path.join(tmpFolderPath, "test-external-file") + await fs.writeFile(externalTmpFile, "foobar") + + await codeServerPage.openFileExternally(externalTmpFile) + + await codeServerPage.waitForTab(path.basename(externalTmpFile)) }) }) diff --git a/test/unit/node/cli.test.ts b/test/unit/node/cli.test.ts index f8cb5b0c9a0f..e5491aca6abf 100644 --- a/test/unit/node/cli.test.ts +++ b/test/unit/node/cli.test.ts @@ -18,7 +18,6 @@ import { import { shouldSpawnCliProcess } from "../../../src/node/main" import { generatePassword, paths } from "../../../src/node/util" import { - DEFAULT_SOCKET_PATH, EditorSessionManager, EditorSessionManagerClient, makeEditorSessionManagerServer, @@ -37,6 +36,7 @@ const defaults = { usingEnvHashedPassword: false, "extensions-dir": path.join(paths.data, "extensions"), "user-data-dir": paths.data, + "session-socket": path.join(paths.data, "code-server-ipc.sock"), _: [], } @@ -103,6 +103,8 @@ describe("parser", () => { "--disable-getting-started-override", + ["--session-socket", "/tmp/override-code-server-ipc-socket"], + ["--host", "0.0.0.0"], "4", "--", @@ -136,6 +138,7 @@ describe("parser", () => { "welcome-text": "welcome to code", version: true, "bind-addr": "192.169.0.1:8080", + "session-socket": "/tmp/override-code-server-ipc-socket", }) }) @@ -504,22 +507,23 @@ describe("cli", () => { it("should use existing if inside code-server", async () => { process.env.VSCODE_IPC_HOOK_CLI = "test" const args: UserProvidedArgs = {} - expect(await shouldOpenInExistingInstance(args)).toStrictEqual("test") + expect(await shouldOpenInExistingInstance(args, "")).toStrictEqual("test") args.port = 8081 args._ = ["./file"] - expect(await shouldOpenInExistingInstance(args)).toStrictEqual("test") + expect(await shouldOpenInExistingInstance(args, "")).toStrictEqual("test") }) it("should use existing if --reuse-window is set", async () => { - const server = await makeEditorSessionManagerServer(DEFAULT_SOCKET_PATH, new EditorSessionManager()) + const sessionSocket = path.join(tmpDirPath, "session-socket") + const server = await makeEditorSessionManagerServer(sessionSocket, new EditorSessionManager()) const args: UserProvidedArgs = {} args["reuse-window"] = true - await expect(shouldOpenInExistingInstance(args)).resolves.toStrictEqual(undefined) + await expect(shouldOpenInExistingInstance(args, sessionSocket)).rejects.toThrow() const socketPath = path.join(tmpDirPath, "socket") - const client = new EditorSessionManagerClient(DEFAULT_SOCKET_PATH) + const client = new EditorSessionManagerClient(sessionSocket) await client.addSession({ entry: { workspace: { @@ -537,24 +541,25 @@ describe("cli", () => { }) const vscodeSockets = listenOn(socketPath) - await expect(shouldOpenInExistingInstance(args)).resolves.toStrictEqual(socketPath) + await expect(shouldOpenInExistingInstance(args, sessionSocket)).resolves.toStrictEqual(socketPath) args.port = 8081 - await expect(shouldOpenInExistingInstance(args)).resolves.toStrictEqual(socketPath) + await expect(shouldOpenInExistingInstance(args, sessionSocket)).resolves.toStrictEqual(socketPath) server.close() vscodeSockets.close() }) it("should use existing if --new-window is set", async () => { - const server = await makeEditorSessionManagerServer(DEFAULT_SOCKET_PATH, new EditorSessionManager()) + const sessionSocket = path.join(tmpDirPath, "session-socket") + const server = await makeEditorSessionManagerServer(sessionSocket, new EditorSessionManager()) const args: UserProvidedArgs = {} args["new-window"] = true - await expect(shouldOpenInExistingInstance(args)).resolves.toStrictEqual(undefined) + await expect(shouldOpenInExistingInstance(args, sessionSocket)).rejects.toThrow() const socketPath = path.join(tmpDirPath, "socket") - const client = new EditorSessionManagerClient(DEFAULT_SOCKET_PATH) + const client = new EditorSessionManagerClient(sessionSocket) await client.addSession({ entry: { workspace: { @@ -572,25 +577,26 @@ describe("cli", () => { }) const vscodeSockets = listenOn(socketPath) - expect(await shouldOpenInExistingInstance(args)).toStrictEqual(socketPath) + expect(await shouldOpenInExistingInstance(args, sessionSocket)).toStrictEqual(socketPath) args.port = 8081 - expect(await shouldOpenInExistingInstance(args)).toStrictEqual(socketPath) + expect(await shouldOpenInExistingInstance(args, sessionSocket)).toStrictEqual(socketPath) server.close() vscodeSockets.close() }) it("should use existing if no unrelated flags are set, has positional, and socket is active", async () => { - const server = await makeEditorSessionManagerServer(DEFAULT_SOCKET_PATH, new EditorSessionManager()) + const sessionSocket = path.join(tmpDirPath, "session-socket") + const server = await makeEditorSessionManagerServer(sessionSocket, new EditorSessionManager()) const args: UserProvidedArgs = {} - expect(await shouldOpenInExistingInstance(args)).toStrictEqual(undefined) + expect(await shouldOpenInExistingInstance(args, sessionSocket)).toStrictEqual(undefined) args._ = ["./file"] - expect(await shouldOpenInExistingInstance(args)).toStrictEqual(undefined) + expect(await shouldOpenInExistingInstance(args, sessionSocket)).toStrictEqual(undefined) - const client = new EditorSessionManagerClient(DEFAULT_SOCKET_PATH) + const client = new EditorSessionManagerClient(sessionSocket) const socketPath = path.join(tmpDirPath, "socket") await client.addSession({ entry: { @@ -609,18 +615,19 @@ describe("cli", () => { }) const vscodeSockets = listenOn(socketPath) - expect(await shouldOpenInExistingInstance(args)).toStrictEqual(socketPath) + expect(await shouldOpenInExistingInstance(args, sessionSocket)).toStrictEqual(socketPath) args.port = 8081 - expect(await shouldOpenInExistingInstance(args)).toStrictEqual(undefined) + expect(await shouldOpenInExistingInstance(args, sessionSocket)).toStrictEqual(undefined) server.close() vscodeSockets.close() }) it("should prefer matching sessions for only the first path", async () => { - const server = await makeEditorSessionManagerServer(DEFAULT_SOCKET_PATH, new EditorSessionManager()) - const client = new EditorSessionManagerClient(DEFAULT_SOCKET_PATH) + const sessionSocket = path.join(tmpDirPath, "session-socket") + const server = await makeEditorSessionManagerServer(sessionSocket, new EditorSessionManager()) + const client = new EditorSessionManagerClient(sessionSocket) await client.addSession({ entry: { workspace: { @@ -655,7 +662,7 @@ describe("cli", () => { const args: UserProvidedArgs = {} args._ = ["/aaa/file", "/bbb/file"] - expect(await shouldOpenInExistingInstance(args)).toStrictEqual(`${tmpDirPath}/vscode-ipc-aaa.sock`) + expect(await shouldOpenInExistingInstance(args, sessionSocket)).toStrictEqual(`${tmpDirPath}/vscode-ipc-aaa.sock`) server.close() }) diff --git a/test/unit/node/plugin.test.ts b/test/unit/node/plugin.test.ts index 88210fd8594a..8237b1177d53 100644 --- a/test/unit/node/plugin.test.ts +++ b/test/unit/node/plugin.test.ts @@ -43,6 +43,7 @@ describe("plugin", () => { usingEnvHashedPassword: false, "extensions-dir": "", "user-data-dir": "", + "session-socket": "", } next() } diff --git a/test/unit/node/vscodeSocket.test.ts b/test/unit/node/vscodeSocket.test.ts index cd84d6ba22f9..75357c76bf08 100644 --- a/test/unit/node/vscodeSocket.test.ts +++ b/test/unit/node/vscodeSocket.test.ts @@ -1,19 +1,8 @@ import { logger } from "@coder/logger" import * as app from "../../../src/node/app" -import { paths } from "../../../src/node/util" -import { - DEFAULT_SOCKET_PATH, - EditorSessionManager, - makeEditorSessionManagerServer, -} from "../../../src/node/vscodeSocket" +import { EditorSessionManager, makeEditorSessionManagerServer } from "../../../src/node/vscodeSocket" import { clean, tmpdir, listenOn, mockLogger } from "../../utils/helpers" -describe("DEFAULT_SOCKET_PATH", () => { - it("should be a unique path per user", () => { - expect(DEFAULT_SOCKET_PATH.startsWith(paths.data)).toBe(true) - }) -}) - describe("makeEditorSessionManagerServer", () => { let tmpDirPath: string