mirror of https://github.com/lukechilds/node.git
Browse Source
PR-URL: https://github.com/nodejs/node/pull/13559 Fixes: https://github.com/nodejs/node/issues/13527 Reviewed-By: Andreas Madsen <amwebdk@gmail.com>v6
2 changed files with 121 additions and 36 deletions
@ -0,0 +1,21 @@ |
|||||
|
prefix async-hooks |
||||
|
|
||||
|
# To mark a test as flaky, list the test name in the appropriate section |
||||
|
# below, without ".js", followed by ": PASS,FLAKY". Example: |
||||
|
# sample-test : PASS,FLAKY |
||||
|
|
||||
|
[true] # This section applies to all platforms |
||||
|
|
||||
|
[$system==win32] |
||||
|
|
||||
|
[$system==linux] |
||||
|
test-callback-error : PASS,FLAKY |
||||
|
|
||||
|
[$system==macos] |
||||
|
test-callback-error : PASS,FLAKY |
||||
|
|
||||
|
[$arch==arm || $arch==arm64] |
||||
|
|
||||
|
[$system==solaris] # Also applies to SmartOS |
||||
|
|
||||
|
[$system==freebsd] |
@ -1,56 +1,120 @@ |
|||||
'use strict'; |
'use strict'; |
||||
|
|
||||
const common = require('../common'); |
const common = require('../common'); |
||||
const assert = require('assert'); |
const assert = require('assert'); |
||||
const spawnSync = require('child_process').spawnSync; |
const { spawnSync, fork } = require('child_process'); |
||||
const async_hooks = require('async_hooks'); |
const async_hooks = require('async_hooks'); |
||||
const initHooks = require('./init-hooks'); |
const initHooks = require('./init-hooks'); |
||||
|
|
||||
switch (process.argv[2]) { |
const arg = process.argv[2]; |
||||
|
switch (arg) { |
||||
case 'test_init_callback': |
case 'test_init_callback': |
||||
initHooks({ |
initHooks({ |
||||
oninit: common.mustCall(() => { throw new Error('test_init_callback'); }) |
oninit: common.mustCall(() => { throw new Error(arg); }) |
||||
}).enable(); |
}).enable(); |
||||
|
async_hooks.emitInit( |
||||
|
async_hooks.executionAsyncId(), |
||||
|
`${arg}_type`, |
||||
|
async_hooks.triggerAsyncId() |
||||
|
); |
||||
|
return; |
||||
|
|
||||
async_hooks.emitInit(async_hooks.executionAsyncId(), |
|
||||
'test_init_callback_type', |
|
||||
async_hooks.triggerAsyncId()); |
|
||||
break; |
|
||||
case 'test_callback': |
case 'test_callback': |
||||
initHooks({ |
initHooks({ |
||||
onbefore: common.mustCall(() => { throw new Error('test_callback'); }) |
onbefore: common.mustCall(() => { throw new Error(arg); }) |
||||
}).enable(); |
}).enable(); |
||||
|
async_hooks.emitInit( |
||||
async_hooks.emitInit(async_hooks.executionAsyncId(), 'test_callback_type', |
async_hooks.executionAsyncId(), |
||||
async_hooks.triggerAsyncId()); |
`${arg}_type`, |
||||
|
async_hooks.triggerAsyncId() |
||||
|
); |
||||
async_hooks.emitBefore(async_hooks.executionAsyncId()); |
async_hooks.emitBefore(async_hooks.executionAsyncId()); |
||||
break; |
return; |
||||
|
|
||||
case 'test_callback_abort': |
case 'test_callback_abort': |
||||
initHooks({ |
initHooks({ |
||||
oninit: common.mustCall(() => { throw new Error('test_callback_abort'); }) |
oninit: common.mustCall(() => { throw new Error(arg); }) |
||||
}).enable(); |
}).enable(); |
||||
|
async_hooks.emitInit( |
||||
|
async_hooks.executionAsyncId(), |
||||
|
`${arg}_type`, |
||||
|
async_hooks.triggerAsyncId() |
||||
|
); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// this part should run only for the master test
|
||||
|
assert.ok(!arg); |
||||
|
{ |
||||
|
// console.log should stay until this test's flakiness is solved
|
||||
|
console.log('start case 1'); |
||||
|
console.time('end case 1'); |
||||
|
const child = spawnSync(process.execPath, [__filename, 'test_init_callback']); |
||||
|
assert.ifError(child.error); |
||||
|
const test_init_first_line = child.stderr.toString().split(/[\r\n]+/g)[0]; |
||||
|
assert.strictEqual(test_init_first_line, 'Error: test_init_callback'); |
||||
|
assert.strictEqual(child.status, 1); |
||||
|
console.timeEnd('end case 1'); |
||||
|
} |
||||
|
|
||||
async_hooks.emitInit(async_hooks.executionAsyncId(), 'test_callback_abort', |
{ |
||||
async_hooks.triggerAsyncId()); |
console.log('start case 2'); |
||||
break; |
console.time('end case 2'); |
||||
|
const child = spawnSync(process.execPath, [__filename, 'test_callback']); |
||||
|
assert.ifError(child.error); |
||||
|
const test_callback_first_line = child.stderr.toString().split(/[\r\n]+/g)[0]; |
||||
|
assert.strictEqual(test_callback_first_line, 'Error: test_callback'); |
||||
|
assert.strictEqual(child.status, 1); |
||||
|
console.timeEnd('end case 2'); |
||||
} |
} |
||||
|
|
||||
const c1 = spawnSync(`${process.execPath}`, [__filename, 'test_init_callback']); |
{ |
||||
assert.strictEqual(c1.stderr.toString().split('\n')[0], |
console.log('start case 3'); |
||||
'Error: test_init_callback'); |
console.time('end case 3'); |
||||
assert.strictEqual(c1.status, 1); |
// Timeout is set because this case is known to be problematic, so stderr is
|
||||
|
// logged for further analysis.
|
||||
const c2 = spawnSync(`${process.execPath}`, [__filename, 'test_callback']); |
// Ref: https://github.com/nodejs/node/issues/13527
|
||||
assert.strictEqual(c2.stderr.toString().split('\n')[0], 'Error: test_callback'); |
// Ref: https://github.com/nodejs/node/pull/13559
|
||||
assert.strictEqual(c2.status, 1); |
const opts = { |
||||
|
execArgv: ['--abort-on-uncaught-exception'], |
||||
const c3 = spawnSync(`${process.execPath}`, ['--abort-on-uncaught-exception', |
silent: true |
||||
__filename, |
}; |
||||
'test_callback_abort']); |
const child = fork(__filename, ['test_callback_abort'], opts); |
||||
assert.strictEqual(c3.stdout.toString(), ''); |
|
||||
|
let stdout = ''; |
||||
const stderrOutput = c3.stderr.toString() |
child.stdout.on('data', (data) => { |
||||
.trim() |
stdout += data; |
||||
.split('\n') |
}); |
||||
.map((s) => s.trim()); |
|
||||
assert.strictEqual(stderrOutput[0], 'Error: test_callback_abort'); |
let stderr = ''; |
||||
|
child.stderr.on('data', (data) => { |
||||
|
stderr += data; |
||||
|
}); |
||||
|
|
||||
|
const tO = setTimeout(() => { |
||||
|
console.log(stderr); |
||||
|
child.kill('SIGKILL'); |
||||
|
process.exit(1); |
||||
|
}, 15 * 1000); |
||||
|
tO.unref(); |
||||
|
|
||||
|
child.on('close', (code, signal) => { |
||||
|
clearTimeout(tO); |
||||
|
if (common.isWindows) { |
||||
|
assert.strictEqual(code, 3); |
||||
|
assert.strictEqual(signal, null); |
||||
|
} else { |
||||
|
assert.strictEqual(code, null); |
||||
|
// most posix systems will show 'SIGABRT', but alpine34 does not
|
||||
|
if (signal !== 'SIGABRT') { |
||||
|
console.log(`parent recived signal ${signal}\nchild's stderr:`); |
||||
|
console.log(stderr); |
||||
|
process.exit(1); |
||||
|
} |
||||
|
assert.strictEqual(signal, 'SIGABRT'); |
||||
|
} |
||||
|
assert.strictEqual(stdout, ''); |
||||
|
const firstLineStderr = stderr.split(/[\r\n]+/g)[0].trim(); |
||||
|
assert.strictEqual(firstLineStderr, 'Error: test_callback_abort'); |
||||
|
}); |
||||
|
console.timeEnd('end case 3'); |
||||
|
} |
||||
|
Loading…
Reference in new issue