summaryrefslogtreecommitdiff
path: root/test/common
diff options
context:
space:
mode:
Diffstat (limited to 'test/common')
-rw-r--r--test/common/README.md37
-rw-r--r--test/common/heap.js80
2 files changed, 117 insertions, 0 deletions
diff --git a/test/common/README.md b/test/common/README.md
index 111ce45b00..c0051ad9f7 100644
--- a/test/common/README.md
+++ b/test/common/README.md
@@ -10,6 +10,7 @@ This directory contains modules used to test the Node.js implementation.
* [DNS module](#dns-module)
* [Duplex pair helper](#duplex-pair-helper)
* [Fixtures module](#fixtures-module)
+* [Heap dump checker module](#heap-dump-checker-module)
* [HTTP2 module](#http2-module)
* [Internet module](#internet-module)
* [tmpdir module](#tmpdir-module)
@@ -538,6 +539,42 @@ Returns the result of
Returns the result of
`fs.readFileSync(path.join(fixtures.fixturesDir, 'keys', arg), 'enc')`.
+## Heap dump checker module
+
+This provides utilities for checking the validity of heap dumps.
+This requires the usage of `--expose-internals`.
+
+### heap.recordState()
+
+Create a heap dump and an embedder graph copy for inspection.
+The returned object has a `validateSnapshotNodes` function similar to the
+one listed below. (`heap.validateSnapshotNodes(...)` is a shortcut for
+`heap.recordState().validateSnapshotNodes(...)`.)
+
+### heap.validateSnapshotNodes(name, expected, options)
+
+* `name` [<string>] Look for this string as the name of heap dump nodes.
+* `expected` [<Array>] A list of objects, possibly with an `children`
+ property that points to expected other adjacent nodes.
+* `options` [<Array>]
+ * `loose` [<boolean>] Do not expect an exact listing of occurrences
+ of nodes with name `name` in `expected`.
+
+Create a heap dump and an embedder graph copy and validate occurrences.
+
+<!-- eslint-disable no-undef, no-unused-vars, node-core/required-modules, strict -->
+```js
+validateSnapshotNodes('TLSWRAP', [
+ {
+ children: [
+ { name: 'enc_out' },
+ { name: 'enc_in' },
+ { name: 'TLSWrap' }
+ ]
+ }
+]);
+```
+
## HTTP/2 Module
The http2.js module provides a handful of utilities for creating mock HTTP/2
diff --git a/test/common/heap.js b/test/common/heap.js
new file mode 100644
index 0000000000..a02de9a606
--- /dev/null
+++ b/test/common/heap.js
@@ -0,0 +1,80 @@
+/* eslint-disable node-core/required-modules */
+'use strict';
+const assert = require('assert');
+const util = require('util');
+
+let internalTestHeap;
+try {
+ internalTestHeap = require('internal/test/heap');
+} catch (e) {
+ console.log('using `test/common/heap.js` requires `--expose-internals`');
+ throw e;
+}
+const { createJSHeapDump, buildEmbedderGraph } = internalTestHeap;
+
+class State {
+ constructor() {
+ this.snapshot = createJSHeapDump();
+ this.embedderGraph = buildEmbedderGraph();
+ }
+
+ validateSnapshotNodes(name, expected, { loose = false } = {}) {
+ const snapshot = this.snapshot.filter(
+ (node) => node.name === 'Node / ' + name && node.type !== 'string');
+ if (loose)
+ assert(snapshot.length >= expected.length);
+ else
+ assert.strictEqual(snapshot.length, expected.length);
+ for (const expectedNode of expected) {
+ if (expectedNode.children) {
+ for (const expectedChild of expectedNode.children) {
+ const check = typeof expectedChild === 'function' ?
+ expectedChild :
+ (node) => [expectedChild.name, 'Node / ' + expectedChild.name]
+ .includes(node.name);
+
+ assert(snapshot.some((node) => {
+ return node.outgoingEdges.map((edge) => edge.toNode).some(check);
+ }), `expected to find child ${util.inspect(expectedChild)} ` +
+ `in ${util.inspect(snapshot)}`);
+ }
+ }
+ }
+
+ const graph = this.embedderGraph.filter((node) => node.name === name);
+ if (loose)
+ assert(graph.length >= expected.length);
+ else
+ assert.strictEqual(graph.length, expected.length);
+ for (const expectedNode of expected) {
+ if (expectedNode.edges) {
+ for (const expectedChild of expectedNode.children) {
+ const check = typeof expectedChild === 'function' ?
+ expectedChild : (node) => {
+ return node.name === expectedChild.name ||
+ (node.value &&
+ node.value.constructor &&
+ node.value.constructor.name === expectedChild.name);
+ };
+
+ assert(graph.some((node) => node.edges.some(check)),
+ `expected to find child ${util.inspect(expectedChild)} ` +
+ `in ${util.inspect(snapshot)}`);
+ }
+ }
+ }
+ }
+}
+
+function recordState() {
+ return new State();
+}
+
+function validateSnapshotNodes(...args) {
+ return recordState().validateSnapshotNodes(...args);
+}
+
+module.exports = {
+ recordState,
+ validateSnapshotNodes
+};