From cec0658e86fbf44e61e26dfa420aabdd2145899b Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Tue, 10 May 2022 21:53:34 +0000 Subject: [PATCH 1/4] refactor: delete unused code --- src/common/util.ts | 30 ------------------------------ src/node/app.ts | 23 ----------------------- src/node/constants.ts | 3 --- src/node/util.ts | 9 --------- test/unit/node/constants.test.ts | 4 ---- 5 files changed, 69 deletions(-) diff --git a/src/common/util.ts b/src/common/util.ts index 191c907abf7e..6639beca42b1 100644 --- a/src/common/util.ts +++ b/src/common/util.ts @@ -1,12 +1,3 @@ -/** - * Split a string up to the delimiter. If the delimiter doesn't exist the first - * item will have all the text and the second item will be an empty string. - */ -export const split = (str: string, delimiter: string): [string, string] => { - const index = str.indexOf(delimiter) - return index !== -1 ? [str.substring(0, index).trim(), str.substring(index + 1)] : [str, ""] -} - /** * Appends an 's' to the provided string if count is greater than one; * otherwise the string is returned @@ -34,27 +25,6 @@ export const normalize = (url: string, keepTrailing = false): string => { return url.replace(/\/\/+/g, "/").replace(/\/+$/, keepTrailing ? "/" : "") } -/** - * Remove leading and trailing slashes. - */ -export const trimSlashes = (url: string): string => { - return url.replace(/^\/+|\/+$/g, "") -} - -/** - * Wrap the value in an array if it's not already an array. If the value is - * undefined return an empty array. - */ -export const arrayify = (value?: T | T[]): T[] => { - if (Array.isArray(value)) { - return value - } - if (typeof value === "undefined") { - return [] - } - return [value] -} - // TODO: Might make sense to add Error handling to the logger itself. export function logError(logger: { error: (msg: string) => void }, prefix: string, err: unknown): void { if (err instanceof Error) { diff --git a/src/node/app.ts b/src/node/app.ts index aece0432ca7f..3e6e4bfa0b3a 100644 --- a/src/node/app.ts +++ b/src/node/app.ts @@ -102,29 +102,6 @@ export const ensureAddress = (server: http.Server, protocol: string): URL | stri return addr } -/** - * Handles error events from the server. - * - * If the outlying Promise didn't resolve - * then we reject with the error. - * - * Otherwise, we log the error. - * - * We extracted into a function so that we could - * test this logic more easily. - */ -export const handleServerError = (resolved: boolean, err: Error, reject: (err: Error) => void) => { - // Promise didn't resolve earlier so this means it's an error - // that occurs before the server can successfully listen. - // Possibly triggered by listening on an invalid port or socket. - if (!resolved) { - reject(err) - } else { - // Promise resolved earlier so this is an unrelated error. - util.logError(logger, "http server error", err) - } -} - /** * Handles the error that occurs in the catch block * after we try fs.unlink(args.socket). diff --git a/src/node/constants.ts b/src/node/constants.ts index c85e0a7b0cdf..bb6873dfa113 100644 --- a/src/node/constants.ts +++ b/src/node/constants.ts @@ -3,8 +3,6 @@ import type { JSONSchemaForNPMPackageJsonFiles } from "@schemastore/package" import * as os from "os" import * as path from "path" -export const WORKBENCH_WEB_CONFIG_ID = "vscode-workbench-web-configuration" - export function getPackageJson(relativePath: string): JSONSchemaForNPMPackageJsonFiles { let pkg = {} try { @@ -21,7 +19,6 @@ export const vsRootPath = path.join(rootPath, "lib/vscode") const PACKAGE_JSON = "package.json" const pkg = getPackageJson(`${rootPath}/${PACKAGE_JSON}`) const codePkg = getPackageJson(`${vsRootPath}/${PACKAGE_JSON}`) || { version: "0.0.0" } -export const pkgName = pkg.name || "code-server" export const version = pkg.version || "development" export const commit = pkg.commit || "development" export const codeVersion = codePkg.version || "development" diff --git a/src/node/util.ts b/src/node/util.ts index e33ad95bf24f..1bf43cd8996e 100644 --- a/src/node/util.ts +++ b/src/node/util.ts @@ -426,15 +426,6 @@ export const enumToArray = (t: any): string[] => { return values } -/** - * For displaying all allowed options in an enum. - */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export const buildAllowedMessage = (t: any): string => { - const values = enumToArray(t) - return `Allowed value${values.length === 1 ? " is" : "s are"} ${values.map((t) => `'${t}'`).join(", ")}` -} - /** * Return a promise that resolves with whether the socket path is active. */ diff --git a/test/unit/node/constants.test.ts b/test/unit/node/constants.test.ts index 38affbb874d9..2ed963f87ba3 100644 --- a/test/unit/node/constants.test.ts +++ b/test/unit/node/constants.test.ts @@ -34,10 +34,6 @@ describe("constants", () => { jest.resetModules() }) - it("should provide the package name", () => { - expect(constants.pkgName).toBe(mockPackageJson.name) - }) - it("should provide the commit", () => { expect(constants.commit).toBe(mockPackageJson.commit) }) From 32cc27b21361f88ac7d0457f9e2b3906f2f94fe1 Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Tue, 10 May 2022 21:54:20 +0000 Subject: [PATCH 2/4] refactor: move onLine to test helpers --- src/node/util.ts | 32 -------------------------------- test/e2e/models/CodeServer.ts | 5 ++--- test/unit/node/util.test.ts | 5 +++-- test/utils/helpers.ts | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 39 insertions(+), 37 deletions(-) diff --git a/src/node/util.ts b/src/node/util.ts index 1bf43cd8996e..a13076fe6262 100644 --- a/src/node/util.ts +++ b/src/node/util.ts @@ -17,39 +17,7 @@ export interface Paths { runtime: string } -// From https://github.com/chalk/ansi-regex -const pattern = [ - "[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)", - "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))", -].join("|") -const re = new RegExp(pattern, "g") - export type OnLineCallback = (strippedLine: string, originalLine: string) => void -/** - * Split stdout on newlines and strip ANSI codes. - */ -export const onLine = (proc: cp.ChildProcess, callback: OnLineCallback): void => { - let buffer = "" - if (!proc.stdout) { - throw new Error("no stdout") - } - proc.stdout.setEncoding("utf8") - proc.stdout.on("data", (d) => { - const data = buffer + d - const split = data.split("\n") - const last = split.length - 1 - - for (let i = 0; i < last; ++i) { - callback(split[i].replace(re, ""), split[i]) - } - - // The last item will either be an empty string (the data ended with a - // newline) or a partial line (did not end with a newline) and we must - // wait to parse it until we get a full line. - buffer = split[last] - }) -} - export const paths = getEnvPaths() /** diff --git a/test/e2e/models/CodeServer.ts b/test/e2e/models/CodeServer.ts index 8b3c4a4afd62..23847fe5763e 100644 --- a/test/e2e/models/CodeServer.ts +++ b/test/e2e/models/CodeServer.ts @@ -5,9 +5,8 @@ import * as path from "path" import { Page } from "playwright" import * as util from "util" import { logError, plural } from "../../../src/common/util" -import { onLine } from "../../../src/node/util" import { PASSWORD, workspaceDir } from "../../utils/constants" -import { idleTimer, tmpdir } from "../../utils/helpers" +import { idleTimer, onLine, tmpdir } from "../../utils/helpers" interface CodeServerProcess { process: cp.ChildProcess @@ -147,7 +146,7 @@ export class CodeServer { let resolved = false proc.stdout.setEncoding("utf8") - onLine(proc, (line) => { + onLine(proc, (line: string) => { // 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 // reject. diff --git a/test/unit/node/util.test.ts b/test/unit/node/util.test.ts index 1455a7e07700..0c1376d1a930 100644 --- a/test/unit/node/util.test.ts +++ b/test/unit/node/util.test.ts @@ -4,6 +4,7 @@ import * as path from "path" import { generateUuid } from "../../../src/common/util" import { tmpdir } from "../../../src/node/constants" import * as util from "../../../src/node/util" +import { onLine } from "../../utils/helpers" describe("getEnvPaths", () => { describe("on darwin", () => { @@ -379,7 +380,7 @@ describe("onLine", () => { const size = 100 const received = new Promise((resolve) => { const lines: string[] = [] - util.onLine(proc!, (line) => { + onLine(proc!, (line: string) => { lines.push(line) if (lines.length === size) { resolve(lines) @@ -412,7 +413,7 @@ describe("onLine", () => { }) const mockCallback = jest.fn() - expect(() => util.onLine(proc, mockCallback)).toThrowError(/stdout/) + expect(() => onLine(proc, mockCallback)).toThrowError(/stdout/) // Cleanup proc?.kill() diff --git a/test/utils/helpers.ts b/test/utils/helpers.ts index 3f9399d4b2c2..761bb9c0661d 100644 --- a/test/utils/helpers.ts +++ b/test/utils/helpers.ts @@ -1,5 +1,6 @@ import { logger } from "@coder/logger" import { promises as fs } from "fs" +import * as cp from "child_process" import * as net from "net" import * as os from "os" import * as path from "path" @@ -119,3 +120,36 @@ export function isAddressInfo(address: unknown): address is net.AddressInfo { (address as net.AddressInfo).address !== undefined ) } + +// From https://github.com/chalk/ansi-regex +const pattern = [ + "[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)", + "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))", +].join("|") +const re = new RegExp(pattern, "g") + +type OnLineCallback = (strippedLine: string, originalLine: string) => void +/** + * Split stdout on newlines and strip ANSI codes. + */ +export const onLine = (proc: cp.ChildProcess, callback: OnLineCallback): void => { + let buffer = "" + if (!proc.stdout) { + throw new Error("no stdout") + } + proc.stdout.setEncoding("utf8") + proc.stdout.on("data", (d) => { + const data = buffer + d + const split = data.split("\n") + const last = split.length - 1 + + for (let i = 0; i < last; ++i) { + callback(split[i].replace(re, ""), split[i]) + } + + // The last item will either be an empty string (the data ended with a + // newline) or a partial line (did not end with a newline) and we must + // wait to parse it until we get a full line. + buffer = split[last] + }) +} From 01a42850a7ac7eed8ca468d3c53a499a704c896c Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Tue, 10 May 2022 22:11:55 +0000 Subject: [PATCH 3/4] Revert "refactor: move onLine to test helpers" This reverts commit 32cc27b21361f88ac7d0457f9e2b3906f2f94fe1. --- src/node/util.ts | 32 ++++++++++++++++++++++++++++++++ test/e2e/models/CodeServer.ts | 5 +++-- test/unit/node/util.test.ts | 5 ++--- test/utils/helpers.ts | 34 ---------------------------------- 4 files changed, 37 insertions(+), 39 deletions(-) diff --git a/src/node/util.ts b/src/node/util.ts index a13076fe6262..1bf43cd8996e 100644 --- a/src/node/util.ts +++ b/src/node/util.ts @@ -17,7 +17,39 @@ export interface Paths { runtime: string } +// From https://github.com/chalk/ansi-regex +const pattern = [ + "[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)", + "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))", +].join("|") +const re = new RegExp(pattern, "g") + export type OnLineCallback = (strippedLine: string, originalLine: string) => void +/** + * Split stdout on newlines and strip ANSI codes. + */ +export const onLine = (proc: cp.ChildProcess, callback: OnLineCallback): void => { + let buffer = "" + if (!proc.stdout) { + throw new Error("no stdout") + } + proc.stdout.setEncoding("utf8") + proc.stdout.on("data", (d) => { + const data = buffer + d + const split = data.split("\n") + const last = split.length - 1 + + for (let i = 0; i < last; ++i) { + callback(split[i].replace(re, ""), split[i]) + } + + // The last item will either be an empty string (the data ended with a + // newline) or a partial line (did not end with a newline) and we must + // wait to parse it until we get a full line. + buffer = split[last] + }) +} + export const paths = getEnvPaths() /** diff --git a/test/e2e/models/CodeServer.ts b/test/e2e/models/CodeServer.ts index 23847fe5763e..8b3c4a4afd62 100644 --- a/test/e2e/models/CodeServer.ts +++ b/test/e2e/models/CodeServer.ts @@ -5,8 +5,9 @@ import * as path from "path" import { Page } from "playwright" import * as util from "util" import { logError, plural } from "../../../src/common/util" +import { onLine } from "../../../src/node/util" import { PASSWORD, workspaceDir } from "../../utils/constants" -import { idleTimer, onLine, tmpdir } from "../../utils/helpers" +import { idleTimer, tmpdir } from "../../utils/helpers" interface CodeServerProcess { process: cp.ChildProcess @@ -146,7 +147,7 @@ export class CodeServer { let resolved = false proc.stdout.setEncoding("utf8") - onLine(proc, (line: string) => { + 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 // reject. diff --git a/test/unit/node/util.test.ts b/test/unit/node/util.test.ts index 0c1376d1a930..1455a7e07700 100644 --- a/test/unit/node/util.test.ts +++ b/test/unit/node/util.test.ts @@ -4,7 +4,6 @@ import * as path from "path" import { generateUuid } from "../../../src/common/util" import { tmpdir } from "../../../src/node/constants" import * as util from "../../../src/node/util" -import { onLine } from "../../utils/helpers" describe("getEnvPaths", () => { describe("on darwin", () => { @@ -380,7 +379,7 @@ describe("onLine", () => { const size = 100 const received = new Promise((resolve) => { const lines: string[] = [] - onLine(proc!, (line: string) => { + util.onLine(proc!, (line) => { lines.push(line) if (lines.length === size) { resolve(lines) @@ -413,7 +412,7 @@ describe("onLine", () => { }) const mockCallback = jest.fn() - expect(() => onLine(proc, mockCallback)).toThrowError(/stdout/) + expect(() => util.onLine(proc, mockCallback)).toThrowError(/stdout/) // Cleanup proc?.kill() diff --git a/test/utils/helpers.ts b/test/utils/helpers.ts index 761bb9c0661d..3f9399d4b2c2 100644 --- a/test/utils/helpers.ts +++ b/test/utils/helpers.ts @@ -1,6 +1,5 @@ import { logger } from "@coder/logger" import { promises as fs } from "fs" -import * as cp from "child_process" import * as net from "net" import * as os from "os" import * as path from "path" @@ -120,36 +119,3 @@ export function isAddressInfo(address: unknown): address is net.AddressInfo { (address as net.AddressInfo).address !== undefined ) } - -// From https://github.com/chalk/ansi-regex -const pattern = [ - "[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)", - "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))", -].join("|") -const re = new RegExp(pattern, "g") - -type OnLineCallback = (strippedLine: string, originalLine: string) => void -/** - * Split stdout on newlines and strip ANSI codes. - */ -export const onLine = (proc: cp.ChildProcess, callback: OnLineCallback): void => { - let buffer = "" - if (!proc.stdout) { - throw new Error("no stdout") - } - proc.stdout.setEncoding("utf8") - proc.stdout.on("data", (d) => { - const data = buffer + d - const split = data.split("\n") - const last = split.length - 1 - - for (let i = 0; i < last; ++i) { - callback(split[i].replace(re, ""), split[i]) - } - - // The last item will either be an empty string (the data ended with a - // newline) or a partial line (did not end with a newline) and we must - // wait to parse it until we get a full line. - buffer = split[last] - }) -} From 9aad95b5df961f8291fc9362acbe688cd5f98d77 Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Tue, 10 May 2022 22:22:46 +0000 Subject: [PATCH 4/4] fixup! refactor: delete unused code --- test/unit/common/util.test.ts | 47 ----------------------------------- test/unit/node/app.test.ts | 34 +------------------------ 2 files changed, 1 insertion(+), 80 deletions(-) diff --git a/test/unit/common/util.test.ts b/test/unit/common/util.test.ts index eef219210187..9e17b5734691 100644 --- a/test/unit/common/util.test.ts +++ b/test/unit/common/util.test.ts @@ -24,16 +24,6 @@ describe("util", () => { }) }) - describe("split", () => { - it("should split at a comma", () => { - expect(util.split("Hello,world", ",")).toStrictEqual(["Hello", "world"]) - }) - - it("shouldn't split if the delimiter doesn't exist", () => { - expect(util.split("Hello world", ",")).toStrictEqual(["Hello world", ""]) - }) - }) - describe("plural", () => { it("should add an s if count is greater than 1", () => { expect(util.plural(2, "dog")).toBe("dogs") @@ -57,43 +47,6 @@ describe("util", () => { }) }) - describe("trimSlashes", () => { - it("should remove leading slashes", () => { - expect(util.trimSlashes("/hello-world")).toBe("hello-world") - }) - - it("should remove trailing slashes", () => { - expect(util.trimSlashes("hello-world/")).toBe("hello-world") - }) - - it("should remove both leading and trailing slashes", () => { - expect(util.trimSlashes("/hello-world/")).toBe("hello-world") - }) - - it("should remove multiple leading and trailing slashes", () => { - expect(util.trimSlashes("///hello-world////")).toBe("hello-world") - }) - }) - - describe("arrayify", () => { - it("should return value it's already an array", () => { - expect(util.arrayify(["hello", "world"])).toStrictEqual(["hello", "world"]) - }) - - it("should wrap the value in an array if not an array", () => { - expect( - util.arrayify({ - name: "Coder", - version: "3.8", - }), - ).toStrictEqual([{ name: "Coder", version: "3.8" }]) - }) - - it("should return an empty array if the value is undefined", () => { - expect(util.arrayify(undefined)).toStrictEqual([]) - }) - }) - describe("logError", () => { beforeAll(() => { mockLogger() diff --git a/test/unit/node/app.test.ts b/test/unit/node/app.test.ts index 56c0e70ddc2c..b2c169a2e429 100644 --- a/test/unit/node/app.test.ts +++ b/test/unit/node/app.test.ts @@ -3,7 +3,7 @@ import { promises } from "fs" import * as http from "http" import * as https from "https" import * as path from "path" -import { createApp, ensureAddress, handleArgsSocketCatchError, handleServerError, listen } from "../../../src/node/app" +import { createApp, ensureAddress, handleArgsSocketCatchError, listen } from "../../../src/node/app" import { OptionalString, setDefaults } from "../../../src/node/cli" import { generateCertificate } from "../../../src/node/util" import { clean, mockLogger, getAvailablePort, tmpdir } from "../../utils/helpers" @@ -169,38 +169,6 @@ describe("ensureAddress", () => { }) }) -describe("handleServerError", () => { - beforeAll(() => { - mockLogger() - }) - - afterEach(() => { - jest.clearAllMocks() - }) - - it("should call reject if resolved is false", async () => { - const resolved = false - const reject = jest.fn((err: Error) => undefined) - const error = new Error("handleServerError Error") - - handleServerError(resolved, error, reject) - - expect(reject).toHaveBeenCalledTimes(1) - expect(reject).toHaveBeenCalledWith(error) - }) - - it("should log an error if resolved is true", async () => { - const resolved = true - const reject = jest.fn((err: Error) => undefined) - const error = new Error("handleServerError Error") - - handleServerError(resolved, error, reject) - - expect(logger.error).toHaveBeenCalledTimes(1) - expect(logger.error).toHaveBeenCalledWith(`http server error: ${error.message} ${error.stack}`) - }) -}) - describe("handleArgsSocketCatchError", () => { beforeAll(() => { mockLogger()