Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 7ccffcb

Browse filesBrowse files
cjihrigBridgeAR
authored andcommitted
test: improve validation of report output
This commit improves the validation of generated diagnostic reports. PR-URL: #26289 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Richard Lau <riclau@uk.ibm.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent a70bafb commit 7ccffcb
Copy full SHA for 7ccffcb

File tree

Expand file treeCollapse file tree

1 file changed

+184
-5
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

1 file changed

+184
-5
lines changed
Open diff view settings
Collapse file

‎test/common/report.js‎

Copy file name to clipboardExpand all lines: test/common/report.js
+184-5Lines changed: 184 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
'use strict';
33
const assert = require('assert');
44
const fs = require('fs');
5+
const os = require('os');
56
const path = require('path');
67

78
function findReports(pid, dir) {
@@ -27,16 +28,194 @@ function validate(report) {
2728
}
2829

2930
function validateContent(data) {
31+
try {
32+
_validateContent(data);
33+
} catch (err) {
34+
err.stack += `\n------\nFailing Report:\n${data}`;
35+
throw err;
36+
}
37+
}
38+
39+
function _validateContent(data) {
40+
const isWindows = process.platform === 'win32';
3041
const report = JSON.parse(data);
3142

32-
// Verify that all sections are present.
33-
['header', 'javascriptStack', 'nativeStack', 'javascriptHeap',
34-
'libuv', 'environmentVariables', 'sharedObjects'].forEach((section) => {
43+
// Verify that all sections are present as own properties of the report.
44+
const sections = ['header', 'javascriptStack', 'nativeStack',
45+
'javascriptHeap', 'libuv', 'environmentVariables',
46+
'sharedObjects'];
47+
if (!isWindows)
48+
sections.push('resourceUsage', 'userLimits');
49+
50+
if (report.uvthreadResourceUsage)
51+
sections.push('uvthreadResourceUsage');
52+
53+
checkForUnknownFields(report, sections);
54+
sections.forEach((section) => {
3555
assert(report.hasOwnProperty(section));
56+
assert(typeof report[section] === 'object' && report[section] !== null);
57+
});
58+
59+
// Verify the format of the header section.
60+
const header = report.header;
61+
const headerFields = ['event', 'location', 'filename', 'dumpEventTime',
62+
'dumpEventTimeStamp', 'processId', 'commandLine',
63+
'nodejsVersion', 'wordSize', 'arch', 'platform',
64+
'componentVersions', 'release', 'osName', 'osRelease',
65+
'osVersion', 'osMachine', 'host', 'glibcVersionRuntime',
66+
'glibcVersionCompiler'];
67+
checkForUnknownFields(header, headerFields);
68+
assert.strictEqual(typeof header.event, 'string');
69+
assert.strictEqual(typeof header.location, 'string');
70+
assert(typeof header.filename === 'string' || header.filename === null);
71+
assert.notStrictEqual(new Date(header.dumpEventTime).toString(),
72+
'Invalid Date');
73+
if (isWindows)
74+
assert.strictEqual(header.dumpEventTimeStamp, undefined);
75+
else
76+
assert(String(+header.dumpEventTimeStamp), header.dumpEventTimeStamp);
77+
78+
assert(Number.isSafeInteger(header.processId));
79+
assert(Array.isArray(header.commandLine));
80+
header.commandLine.forEach((arg) => {
81+
assert.strictEqual(typeof arg, 'string');
82+
});
83+
assert.strictEqual(header.nodejsVersion, process.version);
84+
assert(Number.isSafeInteger(header.wordSize));
85+
assert.strictEqual(header.arch, os.arch());
86+
assert.strictEqual(header.platform, os.platform());
87+
assert.deepStrictEqual(header.componentVersions, process.versions);
88+
assert.deepStrictEqual(header.release, process.release);
89+
assert.strictEqual(header.osName, os.type());
90+
assert.strictEqual(header.osRelease, os.release());
91+
assert.strictEqual(typeof header.osVersion, 'string');
92+
assert.strictEqual(typeof header.osMachine, 'string');
93+
assert.strictEqual(header.host, os.hostname());
94+
95+
// Verify the format of the javascriptStack section.
96+
checkForUnknownFields(report.javascriptStack, ['message', 'stack']);
97+
assert.strictEqual(typeof report.javascriptStack.message, 'string');
98+
if (report.javascriptStack.stack !== undefined) {
99+
assert(Array.isArray(report.javascriptStack.stack));
100+
report.javascriptStack.stack.forEach((frame) => {
101+
assert.strictEqual(typeof frame, 'string');
102+
});
103+
}
104+
105+
// Verify the format of the nativeStack section.
106+
assert(Array.isArray(report.nativeStack));
107+
report.nativeStack.forEach((frame) => {
108+
assert(typeof frame === 'object' && frame !== null);
109+
checkForUnknownFields(frame, ['pc', 'symbol']);
110+
assert.strictEqual(typeof frame.pc, 'string');
111+
assert(/^0x[0-9a-f]+$/.test(frame.pc));
112+
assert.strictEqual(typeof frame.symbol, 'string');
113+
});
114+
115+
// Verify the format of the javascriptHeap section.
116+
const heap = report.javascriptHeap;
117+
const jsHeapFields = ['totalMemory', 'totalCommittedMemory', 'usedMemory',
118+
'availableMemory', 'memoryLimit', 'heapSpaces'];
119+
checkForUnknownFields(heap, jsHeapFields);
120+
assert(Number.isSafeInteger(heap.totalMemory));
121+
assert(Number.isSafeInteger(heap.totalCommittedMemory));
122+
assert(Number.isSafeInteger(heap.usedMemory));
123+
assert(Number.isSafeInteger(heap.availableMemory));
124+
assert(Number.isSafeInteger(heap.memoryLimit));
125+
assert(typeof heap.heapSpaces === 'object' && heap.heapSpaces !== null);
126+
const heapSpaceFields = ['memorySize', 'committedMemory', 'capacity', 'used',
127+
'available'];
128+
Object.keys(heap.heapSpaces).forEach((spaceName) => {
129+
const space = heap.heapSpaces[spaceName];
130+
checkForUnknownFields(space, heapSpaceFields);
131+
heapSpaceFields.forEach((field) => {
132+
assert(Number.isSafeInteger(space[field]));
133+
});
134+
});
135+
136+
// Verify the format of the resourceUsage section on non-Windows platforms.
137+
if (!isWindows) {
138+
const usage = report.resourceUsage;
139+
const resourceUsageFields = ['userCpuSeconds', 'kernelCpuSeconds',
140+
'cpuConsumptionPercent', 'maxRss',
141+
'pageFaults', 'fsActivity'];
142+
checkForUnknownFields(usage, resourceUsageFields);
143+
assert.strictEqual(typeof usage.userCpuSeconds, 'number');
144+
assert.strictEqual(typeof usage.kernelCpuSeconds, 'number');
145+
assert.strictEqual(typeof usage.cpuConsumptionPercent, 'number');
146+
assert(Number.isSafeInteger(usage.maxRss));
147+
assert(typeof usage.pageFaults === 'object' && usage.pageFaults !== null);
148+
checkForUnknownFields(usage.pageFaults, ['IORequired', 'IONotRequired']);
149+
assert(Number.isSafeInteger(usage.pageFaults.IORequired));
150+
assert(Number.isSafeInteger(usage.pageFaults.IONotRequired));
151+
assert(typeof usage.fsActivity === 'object' && usage.fsActivity !== null);
152+
checkForUnknownFields(usage.fsActivity, ['reads', 'writes']);
153+
assert(Number.isSafeInteger(usage.fsActivity.reads));
154+
assert(Number.isSafeInteger(usage.fsActivity.writes));
155+
}
156+
157+
// Verify the format of the uvthreadResourceUsage section, if present.
158+
if (report.uvthreadResourceUsage) {
159+
const usage = report.uvthreadResourceUsage;
160+
const threadUsageFields = ['userCpuSeconds', 'kernelCpuSeconds',
161+
'cpuConsumptionPercent', 'fsActivity'];
162+
checkForUnknownFields(usage, threadUsageFields);
163+
assert.strictEqual(typeof usage.userCpuSeconds, 'number');
164+
assert.strictEqual(typeof usage.kernelCpuSeconds, 'number');
165+
assert.strictEqual(typeof usage.cpuConsumptionPercent, 'number');
166+
assert(typeof usage.fsActivity === 'object' && usage.fsActivity !== null);
167+
checkForUnknownFields(usage.fsActivity, ['reads', 'writes']);
168+
assert(Number.isSafeInteger(usage.fsActivity.reads));
169+
assert(Number.isSafeInteger(usage.fsActivity.writes));
170+
}
171+
172+
// Verify the format of the libuv section.
173+
assert(Array.isArray(report.libuv));
174+
report.libuv.forEach((resource) => {
175+
assert.strictEqual(typeof resource.type, 'string');
176+
assert.strictEqual(typeof resource.address, 'string');
177+
assert(/^0x[0-9a-f]+$/.test(resource.address));
178+
assert.strictEqual(typeof resource.is_active, 'boolean');
179+
assert.strictEqual(typeof resource.is_referenced,
180+
resource.type === 'loop' ? 'undefined' : 'boolean');
36181
});
37182

38-
assert.deepStrictEqual(report.header.componentVersions, process.versions);
39-
assert.deepStrictEqual(report.header.release, process.release);
183+
// Verify the format of the environmentVariables section.
184+
for (const [key, value] of Object.entries(report.environmentVariables)) {
185+
assert.strictEqual(typeof key, 'string');
186+
assert.strictEqual(typeof value, 'string');
187+
}
188+
189+
// Verify the format of the userLimits section on non-Windows platforms.
190+
if (!isWindows) {
191+
const userLimitsFields = ['core_file_size_blocks', 'data_seg_size_kbytes',
192+
'file_size_blocks', 'max_locked_memory_bytes',
193+
'max_memory_size_kbytes', 'open_files',
194+
'stack_size_bytes', 'cpu_time_seconds',
195+
'max_user_processes', 'virtual_memory_kbytes'];
196+
checkForUnknownFields(report.userLimits, userLimitsFields);
197+
for (const [type, limits] of Object.entries(report.userLimits)) {
198+
assert.strictEqual(typeof type, 'string');
199+
assert(typeof limits === 'object' && limits !== null);
200+
checkForUnknownFields(limits, ['soft', 'hard']);
201+
assert(typeof limits.soft === 'number' || limits.soft === 'unlimited',
202+
`Invalid ${type} soft limit of ${limits.soft}`);
203+
assert(typeof limits.hard === 'number' || limits.hard === 'unlimited',
204+
`Invalid ${type} hard limit of ${limits.hard}`);
205+
}
206+
}
207+
208+
// Verify the format of the sharedObjects section.
209+
assert(Array.isArray(report.sharedObjects));
210+
report.sharedObjects.forEach((sharedObject) => {
211+
assert.strictEqual(typeof sharedObject, 'string');
212+
});
213+
}
214+
215+
function checkForUnknownFields(actual, expected) {
216+
Object.keys(actual).forEach((field) => {
217+
assert(expected.includes(field), `'${field}' not expected in ${expected}`);
218+
});
40219
}
41220

42221
module.exports = { findReports, validate, validateContent };

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.