-
Notifications
You must be signed in to change notification settings - Fork 29.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
One test per each API, so that additional tests in future are modular. test/common/report.js contain common functions that tests leverage. PR-URL: #22712 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Michael Dawson <Michael_Dawson@ca.ibm.com> Reviewed-By: Vse Mozhet Byt <vsemozhetbyt@gmail.com>
- Loading branch information
1 parent
4f38106
commit 0800f91
Showing
13 changed files
with
484 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
'use strict'; | ||
require('../common'); | ||
const assert = require('assert'); | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
|
||
const REPORT_SECTIONS = [ 'header', | ||
'javascriptStack', | ||
'nativeStack', | ||
'javascriptHeap', | ||
'libuv', | ||
'environmentVariables', | ||
'sharedObjects' ]; | ||
|
||
let tmppath = ''; | ||
|
||
exports.findReports = (pid, path) => { | ||
// Default filenames are of the form | ||
// report.<date>.<time>.<pid>.<seq>.json | ||
tmppath = path; | ||
const format = '^report\\.\\d+\\.\\d+\\.' + pid + '\\.\\d+\\.json$'; | ||
const filePattern = new RegExp(format); | ||
const files = fs.readdirSync(path); | ||
return files.filter((file) => filePattern.test(file)); | ||
}; | ||
|
||
exports.validate = (report, options) => { | ||
const jtmp = path.join(tmppath, report); | ||
fs.readFile(jtmp, (err, data) => { | ||
this.validateContent(data, options); | ||
}); | ||
}; | ||
|
||
|
||
exports.validateContent = function validateContent(data, options) { | ||
const report = JSON.parse(data); | ||
const comp = Object.keys(report); | ||
|
||
// Check all sections are present | ||
REPORT_SECTIONS.forEach((section) => { | ||
assert.ok(comp.includes(section)); | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
'use strict'; | ||
|
||
// Testcase for returning report as a string via API call | ||
const common = require('../common'); | ||
common.skipIfReportDisabled(); | ||
const assert = require('assert'); | ||
if (process.argv[2] === 'child') { | ||
console.log(process.report.getReport()); | ||
} else { | ||
const helper = require('../common/report.js'); | ||
const spawnSync = require('child_process').spawnSync; | ||
const tmpdir = require('../common/tmpdir'); | ||
tmpdir.refresh(); | ||
|
||
const args = ['--experimental-report', __filename, 'child']; | ||
const child = spawnSync(process.execPath, args, { cwd: tmpdir.path }); | ||
const report_msg = 'Found report files'; | ||
const std_msg = 'Found messages on stderr'; | ||
assert.ok(child.stderr.toString().includes( | ||
`(node:${child.pid}) ExperimentalWarning: report is an` + | ||
' experimental feature. This feature could change at any time'), std_msg); | ||
const reportFiles = helper.findReports(child.pid, tmpdir.path); | ||
assert.deepStrictEqual(reportFiles, [], report_msg); | ||
helper.validateContent(child.stdout, { pid: child.pid, | ||
commandline: process.execPath + | ||
' ' + args.join(' ') | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
'use strict'; | ||
|
||
// Testcase to produce report via API call, using the no-hooks/no-signal | ||
// interface - i.e. require('node-report/api') | ||
const common = require('../common'); | ||
common.skipIfReportDisabled(); | ||
if (process.argv[2] === 'child') { | ||
process.report.triggerReport(); | ||
} else { | ||
const helper = require('../common/report.js'); | ||
const spawn = require('child_process').spawn; | ||
const assert = require('assert'); | ||
const tmpdir = require('../common/tmpdir'); | ||
tmpdir.refresh(); | ||
|
||
const child = spawn(process.execPath, ['--experimental-report', | ||
__filename, 'child'], | ||
{ cwd: tmpdir.path }); | ||
child.on('exit', common.mustCall((code) => { | ||
const report_msg = 'No reports found'; | ||
const process_msg = 'Process exited unexpectedly'; | ||
assert.strictEqual(code, 0, process_msg + ':' + code); | ||
const reports = helper.findReports(child.pid, tmpdir.path); | ||
assert.strictEqual(reports.length, 1, report_msg); | ||
const report = reports[0]; | ||
helper.validate(report, { pid: child.pid, | ||
commandline: child.spawnargs.join(' ') | ||
}); | ||
})); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
'use strict'; | ||
|
||
// Testcase for passing an error object to the API call. | ||
const common = require('../common'); | ||
common.skipIfReportDisabled(); | ||
const assert = require('assert'); | ||
if (process.argv[2] === 'child') { | ||
try { | ||
throw new Error('Testing error handling'); | ||
} catch { | ||
process.report.triggerReport(); | ||
} | ||
} else { | ||
const helper = require('../common/report.js'); | ||
const spawn = require('child_process').spawn; | ||
const tmpdir = require('../common/tmpdir'); | ||
tmpdir.refresh(); | ||
const child = spawn(process.execPath, ['--experimental-report', | ||
__filename, 'child'], | ||
{ cwd: tmpdir.path }); | ||
child.on('exit', common.mustCall((code) => { | ||
const report_msg = 'No reports found'; | ||
const process_msg = 'Process exited unexpectedly'; | ||
assert.strictEqual(code, 0, process_msg); | ||
const reports = helper.findReports(child.pid, tmpdir.path); | ||
assert.strictEqual(reports.length, 1, report_msg); | ||
const report = reports[0]; | ||
helper.validate(report, { pid: child.pid, | ||
commandline: child.spawnargs.join(' '), | ||
expectedException: 'Testing error handling', | ||
}); | ||
})); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
'use strict'; | ||
|
||
// Testcase to check reporting of uv handles. | ||
const common = require('../common'); | ||
common.skipIfReportDisabled(); | ||
if (process.argv[2] === 'child') { | ||
// Exit on loss of parent process | ||
const exit = () => process.exit(2); | ||
process.on('disconnect', exit); | ||
|
||
const fs = require('fs'); | ||
const http = require('http'); | ||
const spawn = require('child_process').spawn; | ||
|
||
// Watching files should result in fs_event/fs_poll uv handles. | ||
let watcher; | ||
try { | ||
watcher = fs.watch(__filename); | ||
} catch { | ||
// fs.watch() unavailable | ||
} | ||
fs.watchFile(__filename, () => {}); | ||
|
||
// Child should exist when this returns as child_process.pid must be set. | ||
const child_process = spawn(process.execPath, | ||
['-e', "process.stdin.on('data', (x) => " + | ||
'console.log(x.toString()));']); | ||
|
||
const timeout = setInterval(() => {}, 1000); | ||
// Make sure the timer doesn't keep the test alive and let | ||
// us check we detect unref'd handles correctly. | ||
timeout.unref(); | ||
|
||
// Datagram socket for udp uv handles. | ||
const dgram = require('dgram'); | ||
const udp_socket = dgram.createSocket('udp4'); | ||
udp_socket.bind({}); | ||
|
||
// Simple server/connection to create tcp uv handles. | ||
const server = http.createServer((req, res) => { | ||
req.on('end', () => { | ||
// Generate the report while the connection is active. | ||
console.log(process.report.getReport()); | ||
child_process.kill(); | ||
|
||
res.writeHead(200, { 'Content-Type': 'text/plain' }); | ||
res.end(); | ||
|
||
// Tidy up to allow process to exit cleanly. | ||
server.close(() => { | ||
if (watcher) watcher.close(); | ||
fs.unwatchFile(__filename); | ||
udp_socket.close(); | ||
process.removeListener('disconnect', exit); | ||
}); | ||
}); | ||
req.resume(); | ||
}); | ||
server.listen(() => { | ||
const data = { pid: child_process.pid, | ||
tcp_address: server.address(), | ||
udp_address: udp_socket.address(), | ||
skip_fs_watch: (watcher === undefined ? | ||
'fs.watch() unavailable' : | ||
false) }; | ||
process.send(data); | ||
http.get({ port: server.address().port }); | ||
}); | ||
} else { | ||
const helper = require('../common/report.js'); | ||
const fork = require('child_process').fork; | ||
const assert = require('assert'); | ||
const tmpdir = require('../common/tmpdir'); | ||
tmpdir.refresh(); | ||
const options = { encoding: 'utf8', silent: true, cwd: tmpdir.path }; | ||
const child = fork('--experimental-report', [__filename, 'child'], options); | ||
let stderr = ''; | ||
child.stderr.on('data', (chunk) => { stderr += chunk; }); | ||
let stdout = ''; | ||
const std_msg = 'Found messages in stderr unexpectedly: '; | ||
const report_msg = 'Report files were written: unexpectedly'; | ||
child.stdout.on('data', (chunk) => { stdout += chunk; }); | ||
child.on('exit', common.mustCall((code, signal) => { | ||
assert.deepStrictEqual(code, 0, 'Process exited unexpectedly with code' + | ||
`${code}`); | ||
assert.deepStrictEqual(signal, null, 'Process should have exited cleanly,' + | ||
` but did not: ${signal}`); | ||
assert.ok(stderr.match( | ||
'(node:.*) ExperimentalWarning: report is an experimental' + | ||
' feature. This feature could change at any time'), | ||
std_msg); | ||
|
||
const reports = helper.findReports(child.pid, tmpdir.path); | ||
assert.deepStrictEqual(reports, [], report_msg, reports); | ||
|
||
const report = JSON.parse(stdout); | ||
let fs = 0; | ||
let poll = 0; | ||
let process = 0; | ||
let timer = 0; | ||
let pipe = 0; | ||
let tcp = 0; | ||
let udp = 0; | ||
const fs_msg = 'fs_event not found'; | ||
const poll_msg = 'poll_event not found'; | ||
const process_msg = 'process event not found'; | ||
const timer_msg = 'timer event not found'; | ||
const pipe_msg = 'pipe event not found'; | ||
const tcp_msg = 'tcp event not found'; | ||
const udp_msg = 'udp event not found'; | ||
for (const entry in report.libuv) { | ||
if (report.libuv[entry].type === 'fs_event') fs = 1; | ||
else if (report.libuv[entry].type === 'fs_poll') poll = 1; | ||
else if (report.libuv[entry].type === 'process') process = 1; | ||
else if (report.libuv[entry].type === 'timer') timer = 1; | ||
else if (report.libuv[entry].type === 'pipe') pipe = 1; | ||
else if (report.libuv[entry].type === 'tcp') tcp = 1; | ||
else if (report.libuv[entry].type === 'udp') udp = 1; | ||
} | ||
assert.deepStrictEqual(fs, 1, fs_msg); | ||
assert.deepStrictEqual(poll, 1, poll_msg); | ||
assert.deepStrictEqual(process, 1, process_msg); | ||
assert.deepStrictEqual(timer, 1, timer_msg); | ||
assert.deepStrictEqual(pipe, 1, pipe_msg); | ||
assert.deepStrictEqual(tcp, 1, tcp_msg); | ||
assert.deepStrictEqual(udp, 1, udp_msg); | ||
|
||
// Common report tests. | ||
helper.validateContent(stdout, { pid: child.pid, | ||
commandline: child.spawnargs.join(' ') | ||
}); | ||
})); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
'use strict'; | ||
|
||
// Testcase to produce report via API call | ||
const common = require('../common'); | ||
common.skipIfReportDisabled(); | ||
if (process.argv[2] === 'child') { | ||
process.report.triggerReport(); | ||
} else { | ||
const helper = require('../common/report.js'); | ||
const spawn = require('child_process').spawn; | ||
const assert = require('assert'); | ||
const tmpdir = require('../common/tmpdir'); | ||
tmpdir.refresh(); | ||
|
||
const child = spawn(process.execPath, | ||
['--experimental-report', __filename, 'child'], | ||
{ cwd: tmpdir.path }); | ||
child.on('exit', common.mustCall((code) => { | ||
const report_msg = 'No reports found'; | ||
const process_msg = 'Process exited unexpectedly'; | ||
assert.strictEqual(code, 0, process_msg + ':' + code); | ||
const reports = helper.findReports(child.pid, tmpdir.path); | ||
assert.strictEqual(reports.length, 1, report_msg); | ||
const report = reports[0]; | ||
helper.validate(report, { pid: child.pid, | ||
commandline: child.spawnargs.join(' ') | ||
}); | ||
})); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
'use strict'; | ||
|
||
// Testcase to produce report on uncaught exception | ||
const common = require('../common'); | ||
common.skipIfReportDisabled(); | ||
if (process.argv[2] === 'child') { | ||
function myException(request, response) { | ||
const m = '*** test-exception.js: throwing uncaught Error'; | ||
throw new Error(m); | ||
} | ||
|
||
myException(); | ||
|
||
} else { | ||
const helper = require('../common/report.js'); | ||
const tmpdir = require('../common/tmpdir'); | ||
tmpdir.refresh(); | ||
const spawn = require('child_process').spawn; | ||
const assert = require('assert'); | ||
|
||
const child = spawn(process.execPath, | ||
['--experimental-report', | ||
'--diagnostic-report-uncaught-exception', | ||
__filename, 'child'], | ||
{ cwd: tmpdir.path }); | ||
// Capture stderr output from the child process | ||
let stderr = ''; | ||
child.stderr.on('data', (chunk) => { | ||
stderr += chunk; | ||
}); | ||
child.on('exit', common.mustCall((code) => { | ||
const report_msg = 'No reports found'; | ||
const process_msg = 'Process exited unexpectedly'; | ||
assert.strictEqual(code, 1, process_msg + ':' + code); | ||
assert.ok(new RegExp('myException').test(stderr), | ||
'Check for expected stack trace frame in stderr'); | ||
const reports = helper.findReports(child.pid, tmpdir.path); | ||
assert.strictEqual(reports.length, 1, report_msg); | ||
const report = reports[0]; | ||
helper.validate(report, { pid: child.pid, | ||
commandline: child.spawnargs.join(' ') | ||
}); | ||
})); | ||
} |
Oops, something went wrong.