From 49c44818d926e6c339e008809c4ecac7bb636997 Mon Sep 17 00:00:00 2001 From: Asher Date: Wed, 23 Jun 2021 15:57:16 -0500 Subject: [PATCH] Move onLine to utilities This way it can be used by the tests when spawning code-server on a random port to look for the address. --- ci/dev/watch.ts | 33 +-------------------------------- src/node/util.ts | 32 ++++++++++++++++++++++++++++++++ test/unit/node/util.test.ts | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 32 deletions(-) diff --git a/ci/dev/watch.ts b/ci/dev/watch.ts index 714a12f7e..1503256c0 100644 --- a/ci/dev/watch.ts +++ b/ci/dev/watch.ts @@ -2,6 +2,7 @@ import browserify from "browserify" import * as cp from "child_process" import * as fs from "fs" import * as path from "path" +import { onLine } from "../../src/node/util" async function main(): Promise { try { @@ -97,38 +98,6 @@ class Watcher { path.join(this.rootPath, "out/browser/pages/vscode.js"), ] - // From https://github.com/chalk/ansi-regex - const pattern = [ - "[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[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") - - /** - * Split stdout on newlines and strip ANSI codes. - */ - const onLine = (proc: cp.ChildProcess, callback: (strippedLine: string, originalLine: string) => void): 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] - }) - } - let startingVscode = false let startedVscode = false onLine(vscode, (line, original) => { diff --git a/src/node/util.ts b/src/node/util.ts index 053f2df51..9129c7e84 100644 --- a/src/node/util.ts +++ b/src/node/util.ts @@ -17,6 +17,38 @@ export interface Paths { runtime: string } +// From https://github.com/chalk/ansi-regex +const pattern = [ + "[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[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") + +/** + * Split stdout on newlines and strip ANSI codes. + */ +export const onLine = (proc: cp.ChildProcess, callback: (strippedLine: string, originalLine: string) => void): 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/unit/node/util.test.ts b/test/unit/node/util.test.ts index 6ea6c818c..38534c228 100644 --- a/test/unit/node/util.test.ts +++ b/test/unit/node/util.test.ts @@ -1,3 +1,5 @@ +import * as cp from "child_process" +import { generateUuid } from "../../../src/common/util" import * as util from "../../../src/node/util" describe("getEnvPaths", () => { @@ -397,3 +399,38 @@ describe("sanitizeString", () => { expect(util.sanitizeString(" ")).toBe("") }) }) + +describe("onLine", () => { + // Spawn a process that outputs anything given on stdin. + let proc: cp.ChildProcess | undefined + + beforeAll(() => { + proc = cp.spawn("node", ["-e", 'process.stdin.setEncoding("utf8");process.stdin.on("data", console.log)']) + }) + + afterAll(() => { + proc?.kill() + }) + + it("should call with individual lines", async () => { + const size = 100 + const received = new Promise((resolve) => { + const lines: string[] = [] + util.onLine(proc!, (line) => { + lines.push(line) + if (lines.length === size) { + resolve(lines) + } + }) + }) + + const expected: string[] = [] + for (let i = 0; i < size; ++i) { + expected.push(generateUuid(i)) + } + + proc?.stdin?.write(expected.join("\n")) + + expect(await received).toEqual(expected) + }) +})