Skip to content

Commit 16ba8c7

Browse files
authored
fix: time out browser coverage collection (#1865)
It seems browser coverage collection can hang in the same way node coverage does.
1 parent 94bda99 commit 16ba8c7

File tree

5 files changed

+64
-52
lines changed

5 files changed

+64
-52
lines changed

src/test/browser.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { fileURLToPath } from 'url'
33
import { execa } from 'execa'
44
import merge from '../utils/merge-options.js'
55
import { fromAegir, findBinary } from '../utils.js'
6+
import { killIfCoverageHangs } from './utils.js'
67

78
const __dirname = path.dirname(fileURLToPath(import.meta.url))
89

@@ -41,7 +42,7 @@ export default async (argv, execaOptions) => {
4142
const beforeEnv = before && before.env ? before.env : {}
4243

4344
// run pw-test
44-
await execa(findBinary('pw-test'),
45+
const proc = execa(findBinary('pw-test'),
4546
[
4647
...files,
4748
'--mode', argv.runner === 'browser' ? 'main' : 'worker',
@@ -69,6 +70,8 @@ export default async (argv, execaOptions) => {
6970
)
7071
)
7172

73+
await killIfCoverageHangs(proc, argv)
74+
7275
// after hook
7376
await argv.fileConfig.test.after(argv, before)
7477
}

src/test/node.js

Lines changed: 2 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import os from 'os'
22
import path from 'path'
33
import { fileURLToPath } from 'url'
44
import { execa } from 'execa'
5-
import kleur from 'kleur'
65
import * as tempy from 'tempy'
76
import merge from '../utils/merge-options.js'
7+
import { killIfCoverageHangs } from './utils.js'
88

99
const __dirname = path.dirname(fileURLToPath(import.meta.url))
1010

@@ -91,52 +91,7 @@ export default async function testNode (argv, execaOptions) {
9191
)
9292
)
9393

94-
let killedWhileCollectingCoverage = false
95-
96-
/** @type {ReturnType<setTimeout> | undefined} */
97-
let timeout
98-
99-
if (argv.cov) {
100-
proc.stderr?.addListener('data', (data) => {
101-
process.stderr.write(data)
102-
})
103-
104-
let lastLine = ''
105-
proc.stdout?.addListener('data', (data) => {
106-
process.stdout.write(data)
107-
108-
lastLine = data.toString()
109-
110-
if (lastLine.trim() !== '') {
111-
// more output has been sent, reset timer
112-
clearTimeout(timeout)
113-
}
114-
115-
if (lastLine.match(/^ {2}\d+ (passing|pending)/m) != null) {
116-
// if we see something that looks like the successful end of a mocha
117-
// run, set a timer - if the process does not exit before the timer
118-
// fires, kill it and log a warning, though don't cause the test run
119-
// to fail
120-
timeout = setTimeout(() => {
121-
console.warn(kleur.red('!!! Collecting coverage has hung, killing process')) // eslint-disable-line no-console
122-
console.warn(kleur.red('!!! See https://github.com/ipfs/aegir/issues/1206 for more information')) // eslint-disable-line no-console
123-
killedWhileCollectingCoverage = true
124-
125-
proc.kill('SIGTERM')
126-
}, argv.covTimeout).unref()
127-
}
128-
})
129-
}
130-
131-
try {
132-
await proc
133-
} catch (err) {
134-
if (!killedWhileCollectingCoverage) {
135-
throw err
136-
}
137-
} finally {
138-
clearTimeout(timeout)
139-
}
94+
await killIfCoverageHangs(proc, argv)
14095

14196
// after hook
14297
await argv.fileConfig.test.after(argv, before)

src/test/utils.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import kleur from 'kleur'
2+
3+
/**
4+
* @param {import('execa').ResultPromise<{}>} proc
5+
* @param {{ cov: boolean, covTimeout: number }} argv
6+
*/
7+
export async function killIfCoverageHangs (proc, argv) {
8+
let killedWhileCollectingCoverage = false
9+
10+
/** @type {ReturnType<setTimeout> | undefined} */
11+
let timeout
12+
13+
if (argv.cov) {
14+
proc.stderr?.addListener('data', (data) => {
15+
process.stderr.write(data)
16+
})
17+
18+
let lastLine = ''
19+
proc.stdout?.addListener('data', (data) => {
20+
process.stdout.write(data)
21+
22+
lastLine = data.toString()
23+
24+
if (lastLine.trim() !== '') {
25+
// more output has been sent, reset timer
26+
clearTimeout(timeout)
27+
}
28+
29+
if (lastLine.match(/^ {2}\d+ (passing|pending)/m) != null) {
30+
// if we see something that looks like the successful end of a mocha
31+
// run, set a timer - if the process does not exit before the timer
32+
// fires, kill it and log a warning, though don't cause the test run
33+
// to fail
34+
timeout = setTimeout(() => {
35+
console.warn(kleur.red('!!! Collecting coverage has hung, killing process')) // eslint-disable-line no-console
36+
console.warn(kleur.red('!!! See https://github.com/ipfs/aegir/issues/1206 for more information')) // eslint-disable-line no-console
37+
killedWhileCollectingCoverage = true
38+
39+
proc.kill('SIGTERM')
40+
}, argv.covTimeout).unref()
41+
}
42+
})
43+
}
44+
45+
try {
46+
await proc
47+
} catch (err) {
48+
if (!killedWhileCollectingCoverage) {
49+
throw err
50+
}
51+
} finally {
52+
clearTimeout(timeout)
53+
}
54+
}

test/fixtures/dependency-check/jsx-fail/src/index.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
// @ts-expect-error - not installed
2-
// eslint-disable-next-line no-unused-vars
2+
33
import React from 'react'
44

55
// @ts-expect-error - not installed
6-
// eslint-disable-next-line no-unused-vars
6+
77
const Component = () => (<div>Hello, world!</div>)
88
const App = () => (<Component />)
99

test/fixtures/dependency-check/jsx-pass/src/index.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
// @ts-expect-error - not installed
2-
// eslint-disable-next-line no-unused-vars
2+
33
import React from 'react'
44

55
// @ts-expect-error - not installed
6-
// eslint-disable-next-line no-unused-vars
6+
77
const Component = () => (<div>Hello, world!</div>)
88
const App = () => (<Component />)
99

0 commit comments

Comments
 (0)