Skip to content

Commit

Permalink
fix: unable to cancel in-progress test runs
Browse files Browse the repository at this point in the history
  • Loading branch information
IGx89 committed Dec 29, 2022
1 parent b4ebe9c commit 7ca7f4a
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 13 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@
"mocha": "^9.2.1",
"prettier": "^2.5.1",
"semver": "^7.3.5",
"tree-kill": "^1.2.2",
"tsup": "^5.12.7",
"typescript": "^4.5.5",
"vite": "^2.8.6",
Expand Down
21 changes: 20 additions & 1 deletion src/pure/ApiProcess.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type { ChildProcess, SpawnOptionsWithStdioTuple, StdioNull, StdioPipe } from 'child_process'
import getPort from 'get-port'
import type { File, WebSocketEvents } from 'vitest'
import type { CancellationToken } from 'vscode'
import kill from 'tree-kill'
import { getConfig } from '../config'
import { log } from '../log'
import { execWithLog, filterColorFormatOutput, sanitizeFilePath } from './utils'
Expand Down Expand Up @@ -132,6 +134,14 @@ export class ApiProcess {
}, 50)
}

kill() {
// Kill using tree-kill to ensure all child processes are killed.
// Especially necessary on Windows, due to shell: true being passed to spawn.
if (this.process)
kill(this.process?.pid)
this.handlers.onFinished?.()
}

private _start(debouncedLog: (line: string) => void, port: number, cwd: string) {
this.process = execWithLog(
this.vitest.cmd,
Expand All @@ -149,6 +159,9 @@ export class ApiProcess {
})

this.process.on('exit', (code) => {
if (this.disposed)
return

if (code !== 0) {
this.dispose()
log.error(`Process exited with code ${code}`)
Expand All @@ -168,7 +181,8 @@ export class ApiProcess {
dispose() {
this.disposed = true
this.vitestState?.client.dispose()
this.process?.kill()
if (this.process)
kill(this.process?.pid)
this.vitestState = undefined
this.process = undefined
}
Expand All @@ -179,6 +193,7 @@ export function runVitestWithApi(
workspace: string,
handlers: Handlers,
customStartProcess?: (config: StartConfig) => void,
cancellationToken?: CancellationToken,
): Promise<string> {
log.info('[Execute Vitest]', vitest.cmd, vitest.args.join(' '))
return new Promise<string>((resolve) => {
Expand All @@ -196,5 +211,9 @@ export function runVitestWithApi(
},
}, true, customStartProcess)
process.start()

cancellationToken?.onCancellationRequested(() => {
process.kill()
})
})
}
7 changes: 5 additions & 2 deletions src/pure/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { spawn } from 'child_process'

import { chunksToLinesAsync } from '@rauschma/stringio'
import type { File } from 'vitest'
import type { CancellationToken } from 'vscode'
import {
filterColorFormatOutput,
sanitizeFilePath,
Expand Down Expand Up @@ -68,6 +69,7 @@ export class TestRunner {
updateSnapshot = false,
onUpdate?: (files: File[]) => void,
customStartProcess?: (config: StartConfig) => void,
cancellation?: CancellationToken,
): Promise<{ testResultFiles: File[]; output: string }> {
const command = vitestCommand.cmd
const args = [
Expand All @@ -91,7 +93,8 @@ export class TestRunner {
},
onFinished: (files) => {
if (files == null) {
handleError()
if (!cancellation?.isCancellationRequested)
handleError()
return
}

Expand All @@ -101,7 +104,7 @@ export class TestRunner {
files && onUpdate && onUpdate(files)
},
onUpdate,
}, customStartProcess)
}, customStartProcess, cancellation)

return { testResultFiles, output }

Expand Down
14 changes: 5 additions & 9 deletions src/runHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,6 @@ export async function runHandler(

log.info('Tests run start')
const run = ctrl.createTestRun(request)
cancellation.onCancellationRequested(() => {
run.end()
})

await Promise.allSettled(workspaces.map(async (folder) => {
const runner = new TestRunner(
Expand All @@ -63,7 +60,7 @@ export async function runHandler(

log.info(`[Workspace "${folder.name}] Run tests from workspace`)
try {
await runTest(ctrl, runner, run, testForThisWorkspace, 'run', discover)
await runTest(ctrl, runner, run, testForThisWorkspace, 'run', discover, cancellation)
log.info(`[Workspace "${folder.name}] Test run finished`)
}
catch (e) {
Expand Down Expand Up @@ -116,9 +113,6 @@ export async function debugHandler(
return

const run = ctrl.createTestRun(request)
cancellation.onCancellationRequested(() => {
run.end()
})

for (const folder of workspaces) {
const items = request.include ?? ctrl.items
Expand All @@ -127,7 +121,7 @@ export async function debugHandler(
continue
try {
const runner = new TestRunner(folder.uri.fsPath, getVitestCommand(folder.uri.fsPath))
await runTest(ctrl, runner, run, testsInThisWorkspace, 'debug', discover)
await runTest(ctrl, runner, run, testsInThisWorkspace, 'debug', discover, cancellation)
}
catch (e) {
if (e instanceof Error) {
Expand Down Expand Up @@ -192,6 +186,7 @@ async function runTest(
items: readonly vscode.TestItem[],
mode: Mode,
discover: TestFileDiscoverer,
cancellation?: vscode.CancellationToken,
) {
if (mode !== 'debug' && runner === undefined)
throw new Error('should provide runner if not debug')
Expand Down Expand Up @@ -326,10 +321,11 @@ async function runTest(
syncFilesTestStatus(files, discover, ctrl, run, false, false, finishedTests)
},
mode === 'debug' ? startDebugProcess : undefined,
cancellation,
)

syncFilesTestStatus(testResultFiles, discover, ctrl, run, true, false, finishedTests)
if (mode !== 'debug') {
if (mode !== 'debug' && !cancellation?.isCancellationRequested) {
for (const item of testCaseSet) {
if (!finishedTests.has(item)) {
run.errored(item, new vscode.TestMessage(`${TEST_NOT_FOUND_MESSAGE}\r\n\r\nVitest output:\r\n${filterColorFormatOutput(output)}`))
Expand Down
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2990,7 +2990,7 @@ tr46@^1.0.1:

tree-kill@^1.2.2:
version "1.2.2"
resolved "https://registry.npmmirror.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==

ts-interface-checker@^0.1.9:
Expand Down

0 comments on commit 7ca7f4a

Please sign in to comment.