Skip to content

Commit

Permalink
test: add test for kill child processes on error
Browse files Browse the repository at this point in the history
  • Loading branch information
iiroj committed Apr 20, 2022
1 parent 877ab4c commit 8be800f
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 3 deletions.
6 changes: 4 additions & 2 deletions lib/resolveTaskFn.js
Expand Up @@ -62,8 +62,10 @@ const interruptExecutionOnError = (ctx, execaChildProcess) => {
if (ctx.errors.size > 0) {
clearInterval(loopIntervalId)

const ids = await pidTree(execaChildProcess.pid)
ids.forEach((id) => process.kill(id))
const childPids = await pidTree(execaChildProcess.pid)
for (const pid of childPids) {
process.kill(pid)
}

// The execa process is killed separately in order
// to get the `KILLED` status.
Expand Down
53 changes: 52 additions & 1 deletion test/resolveTaskFn.spec.js
@@ -1,14 +1,19 @@
import execa from 'execa'
import pidTree from 'pidtree'

import { resolveTaskFn } from '../lib/resolveTaskFn'
import { getInitialState } from '../lib/state'
import { TaskError } from '../lib/symbols'

import { createExecaReturnValue } from './utils/createExecaReturnValue'

jest.useFakeTimers()

jest.mock('pidtree', () => jest.fn(async () => []))

const defaultOpts = { files: ['test.js'] }

function mockExecaImplementationOnce(value) {
const mockExecaImplementationOnce = (value) => {
execa.mockImplementationOnce(() => createExecaReturnValue(value))
}

Expand Down Expand Up @@ -350,6 +355,52 @@ describe('resolveTaskFn', () => {

context.errors.add({})

jest.runAllTimers()

await expect(taskPromise).rejects.toThrowErrorMatchingInlineSnapshot(`"node [KILLED]"`)
})

it('should also kill child processes of killed execa processes', async () => {
expect.assertions(3)

execa.mockImplementationOnce(() =>
createExecaReturnValue(
{
stdout: 'a-ok',
stderr: '',
code: 0,
cmd: 'mock cmd',
failed: false,
killed: false,
signal: null,
},
1000
)
)

const realKill = process.kill
const mockKill = jest.fn()
Object.defineProperty(process, 'kill', {
value: mockKill,
})

pidTree.mockImplementationOnce(() => ['1234'])

const taskFn = resolveTaskFn({ command: 'node' })

const context = getInitialState()
const taskPromise = taskFn(context)

context.errors.add({})
jest.runAllTimers()

await expect(taskPromise).rejects.toThrowErrorMatchingInlineSnapshot(`"node [KILLED]"`)

expect(mockKill).toHaveBeenCalledTimes(1)
expect(mockKill).toHaveBeenCalledWith('1234')

Object.defineProperty(process, 'kill', {
value: realKill,
})
})
})

0 comments on commit 8be800f

Please sign in to comment.