Skip to content

Commit

Permalink
refactor: use IPC to communicate test results
Browse files Browse the repository at this point in the history
  • Loading branch information
adalinesimonian committed Dec 5, 2021
1 parent 8e1f582 commit 0c98677
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 39 deletions.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,14 @@
"@vscode/test-electron": "^1.6.2",
"cosmiconfig": "^7.0.1",
"jest-cli": "^27.2.1",
"jest-environment-node": "^27.2.0"
"jest-environment-node": "^27.2.0",
"node-ipc": "^9.0.0"
},
"devDependencies": {
"@types/fs-extra": "9.0.13",
"@types/jest": "27.0.3",
"@types/node": "14.14.45",
"@types/node-ipc": "^9.2.0",
"@types/vscode": "1.56.0",
"@typescript-eslint/eslint-plugin": "5.5.0",
"@typescript-eslint/parser": "5.5.0",
Expand Down
4 changes: 4 additions & 0 deletions renovate.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
{
"matchPackageNames": ["@types/vscode"],
"allowedVersions": "~1.56.0"
},
{
"matchPackageNames": ["node-ipc", "@types/node-ipc"],
"allowedVersions": "^9.0.0"
}
]
}
41 changes: 33 additions & 8 deletions src/child-process-runner.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import type { RemoteTestOptions, RemoteTestResults } from './types'
import * as jest from '@jest/core'
import console from 'console'
import type { buildArgv as buildArgvType } from 'jest-cli/build/cli/index'
import vscode from 'vscode'
import path from 'path'
import type { buildArgv as buildArgvType } from 'jest-cli/build/cli/index'
import process from 'process'
import { IPC } from 'node-ipc'
import console from 'console'

// eslint-disable-next-line @typescript-eslint/no-var-requires
const buildArgv: typeof buildArgvType = require(path.resolve(
Expand All @@ -16,14 +18,36 @@ const vscodeModulePath = require.resolve('./jest-vscode-module')
const moduleNameMapper = JSON.stringify({ '^vscode$': vscodeModulePath })

export async function run(): Promise<void> {
const { IPC_CHANNEL, PARENT_JEST_OPTIONS } = process.env

if (!IPC_CHANNEL) {
throw new Error('IPC_CHANNEL is not defined')
}

const ipc = new IPC()

ipc.config.silent = true
ipc.config.id = `jest-runner-vscode-client-${process.pid}`

await new Promise<void>(resolve =>
ipc.connectTo(IPC_CHANNEL, () => {
ipc.of[IPC_CHANNEL].on('connect', () => {
console.log(`Connected to ${IPC_CHANNEL}`)
resolve()
})
})
)

const disconnected = new Promise<void>(resolve =>
ipc.of[IPC_CHANNEL].on('disconnect', resolve)
)

let response: RemoteTestResults
try {
if (!process.env.PARENT_JEST_OPTIONS) {
if (!PARENT_JEST_OPTIONS) {
throw new Error('PARENT_JEST_OPTIONS is not defined')
}
const options: RemoteTestOptions = JSON.parse(
process.env.PARENT_JEST_OPTIONS
)
const options: RemoteTestOptions = JSON.parse(PARENT_JEST_OPTIONS)

const jestOptions = buildArgv([
'-i',
Expand Down Expand Up @@ -53,7 +77,8 @@ export async function run(): Promise<void> {
}
}

console.log(`[jest-runner-vscode] ${JSON.stringify(response)}\n`)

ipc.of[IPC_CHANNEL].emit('test-results', response)
ipc.disconnect(IPC_CHANNEL)
await disconnected
await vscode.commands.executeCommand('workbench.action.closeWindow')
}
47 changes: 18 additions & 29 deletions src/run-vscode.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import type { RemoteTestOptions, RemoteTestResults } from './types'
import cp from 'child_process'
import console from 'console'
import readline from 'readline'
import type { IPC } from 'node-ipc'

export default function runVSCode(
export default async function runVSCode(
vscodePath: string,
args: string[],
env: Record<string, string> | undefined,
options: RemoteTestOptions
options: RemoteTestOptions,
ipc: InstanceType<typeof IPC>
): Promise<RemoteTestResults | undefined> {
return new Promise<RemoteTestResults | undefined>(resolve => {
return await new Promise<RemoteTestResults | undefined>(resolve => {
let results: RemoteTestResults | undefined = undefined

const useStdErr =
Expand All @@ -21,24 +22,19 @@ export default function runVSCode(
...process.env,
...env,
PARENT_JEST_OPTIONS: JSON.stringify(options),
IPC_CHANNEL: ipc.config.id,
}

const vscode = cp.spawn(vscodePath, args, { env: environment })
const onTestResults = (response: RemoteTestResults) => {
results = response
}

const stdoutReader = readline.createInterface({
input: vscode.stdout,
terminal: true,
})
ipc.server.on('test-results', onTestResults)

stdoutReader.on('line', line => {
const output = line.replace(/^\[jest-runner-vscode\] .+$/, match => {
results = JSON.parse(match.slice(21))
return ''
})
silent || log(output)
})
const vscode = cp.spawn(vscodePath, args, { env: environment })

if (!silent) {
vscode.stdout.pipe(process.stdout)
vscode.stderr.pipe(process.stderr)
}

Expand All @@ -47,23 +43,12 @@ export default function runVSCode(
})

let exited = false
let streamClosed = false

stdoutReader.on('close', () => {
streamClosed = true
if (exited) {
resolve(results)
}
})

const onExit = (
const onExit = async (
code: number | null,
signal: NodeJS.Signals | null
): void => {
): Promise<void> => {
if (exited) {
if (streamClosed) {
resolve(results)
}
return
}
exited = true
Expand All @@ -81,6 +66,10 @@ export default function runVSCode(
} else {
silent || log(message)
}

ipc.server.off('test-results', onTestResults)

resolve(results)
}

vscode.on('exit', onExit)
Expand Down
19 changes: 18 additions & 1 deletion src/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import type { Config } from '@jest/types'
import type * as JestRunner from 'jest-runner'
import type { TestResult as JestTestResult } from '@jest/types'
import type { TestResult } from '@jest/test-result'
import { IPC } from 'node-ipc'
import type { RunnerOptions } from './types'
import path from 'path'
import process from 'process'
import { cosmiconfig } from 'cosmiconfig'
import downloadVSCode from './download-vscode'
import runVSCode from './run-vscode'
Expand Down Expand Up @@ -64,9 +66,21 @@ export default class VSCodeTestRunner {
}
}

// Start IPC server.
const ipc = new IPC()

ipc.config.silent = true
ipc.config.id = `jest-runner-vscode-server-${process.pid}`

await new Promise<void>(resolve => {
ipc.serve(resolve)
ipc.server.start()
})

// Run each group of tests in its own VS Code process.
for (const [testDir, testGroup] of testsByDir.entries()) {
if (watcher.isInterrupted()) {
ipc.server.stop()
throw Object.assign(new Error(), { name: 'CancelRun' })
}

Expand Down Expand Up @@ -113,7 +127,8 @@ export default class VSCodeTestRunner {
workspacePath: this._globalConfig.rootDir,
options,
testPaths: testGroup.map(test => test.path),
}
},
ipc
)

if (!testResults) {
Expand Down Expand Up @@ -164,5 +179,7 @@ export default class VSCodeTestRunner {
}
}
}

ipc.server.stop()
}
}
52 changes: 52 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1057,6 +1057,15 @@ __metadata:
languageName: node
linkType: hard

"@types/node-ipc@npm:^9.2.0":
version: 9.2.0
resolution: "@types/node-ipc@npm:9.2.0"
dependencies:
"@types/node": "*"
checksum: 05954414de9e3c1e5022338774b02ffd91d2be391157c0d2d9a3de5ffd5cbe0e2d1b9e0f1979232331e7338b2e089a7ea6b6dd2a188b9796614829f7b27cedcc
languageName: node
linkType: hard

"@types/node@npm:*":
version: 16.9.1
resolution: "@types/node@npm:16.9.1"
Expand Down Expand Up @@ -2122,6 +2131,13 @@ __metadata:
languageName: node
linkType: hard

"easy-stack@npm:^1.0.1":
version: 1.0.1
resolution: "easy-stack@npm:1.0.1"
checksum: 161a99e497b3857b0be4ec9e1ebbe90b241ea9d84702f9881b8e5b3f6822065b8c4e33436996935103e191bffba3607de70712a792f4d406a050def48c6bc381
languageName: node
linkType: hard

"electron-to-chromium@npm:^1.3.830":
version: 1.3.840
resolution: "electron-to-chromium@npm:1.3.840"
Expand Down Expand Up @@ -2439,6 +2455,13 @@ __metadata:
languageName: node
linkType: hard

"event-pubsub@npm:4.3.0":
version: 4.3.0
resolution: "event-pubsub@npm:4.3.0"
checksum: 6940f57790c01a967b7c637f1c9fd000ee968a1d5894186ffb3356ffbe174c70e22e62adbbcfcee3f305482d99b6abe7613c1c27c909b07adc9127dc16c8cf73
languageName: node
linkType: hard

"execa@npm:5.1.1, execa@npm:^5.0.0":
version: 5.1.1
resolution: "execa@npm:5.1.1"
Expand Down Expand Up @@ -3925,6 +3948,7 @@ fsevents@^2.3.2:
"@types/fs-extra": 9.0.13
"@types/jest": 27.0.3
"@types/node": 14.14.45
"@types/node-ipc": ^9.2.0
"@types/vscode": 1.56.0
"@typescript-eslint/eslint-plugin": 5.5.0
"@typescript-eslint/parser": 5.5.0
Expand All @@ -3938,6 +3962,7 @@ fsevents@^2.3.2:
jest: 27.4.3
jest-cli: ^27.2.1
jest-environment-node: ^27.2.0
node-ipc: ^9.0.0
npm-run-all: 4.1.5
prettier: 2.5.1
ts-jest: 27.0.7
Expand Down Expand Up @@ -4284,6 +4309,22 @@ fsevents@^2.3.2:
languageName: node
linkType: hard

"js-message@npm:1.0.7":
version: 1.0.7
resolution: "js-message@npm:1.0.7"
checksum: 18dcc4d80356e8b5be978ca7838d96d4e350a1cb8adc5741c229dec6df09f53bfed7c75c1f360171d2d791a14e2f077d6c2b1013ba899ded7a27d7dfcd4f3784
languageName: node
linkType: hard

"js-queue@npm:2.0.2":
version: 2.0.2
resolution: "js-queue@npm:2.0.2"
dependencies:
easy-stack: ^1.0.1
checksum: 5049c3f648315ed13e46755704ff5453df70f7e8e1812acf1f98d6700efbec32421f76294a0e63fd2a9f8aabaf124233bbb308f9a2caec9d9f3d833ab5a73079
languageName: node
linkType: hard

"js-tokens@npm:^4.0.0":
version: 4.0.0
resolution: "js-tokens@npm:4.0.0"
Expand Down Expand Up @@ -4777,6 +4818,17 @@ fsevents@^2.3.2:
languageName: node
linkType: hard

"node-ipc@npm:^9.0.0":
version: 9.2.1
resolution: "node-ipc@npm:9.2.1"
dependencies:
event-pubsub: 4.3.0
js-message: 1.0.7
js-queue: 2.0.2
checksum: a38aa4c8ca4317b293e0ce21f0a3a4941fc51c054800b35e263fcfe3e0feeb60e7d2c497f015054b28783316c6e7d9cc3837af9d9958bcbd8c577d0cdf6964b7
languageName: node
linkType: hard

"node-modules-regexp@npm:^1.0.0":
version: 1.0.0
resolution: "node-modules-regexp@npm:1.0.0"
Expand Down

0 comments on commit 0c98677

Please sign in to comment.