From 64b040c78f79b5083116d4c318ed5104dd6ef872 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Jos=C3=A9=20Arboleda?= Date: Thu, 25 Apr 2024 15:52:35 -0500 Subject: [PATCH] src: fix the base case in the heap profiler JSON generation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the base case, the last node needs to have an empty array with no childrens, this commit handles that by creating an empty array for it. Fixes: https://github.com/nodesource/nsolid/issues/124 Signed-off-by: Juan José Arboleda --- src/nsolid/nsolid_heap_snapshot.cc | 4 ++- .../test-nsolid-heap-sampling-stream.js | 35 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/nsolid/nsolid_heap_snapshot.cc b/src/nsolid/nsolid_heap_snapshot.cc index 7287ec92d6..32cb36190f 100644 --- a/src/nsolid/nsolid_heap_snapshot.cc +++ b/src/nsolid/nsolid_heap_snapshot.cc @@ -97,8 +97,10 @@ nlohmann::ordered_json build_sampling_heap_profile_node( result["id"] = node->node_id; // Add children if there are any - if (node->children.empty()) + if (node->children.empty()) { + result["children"] = nlohmann::ordered_json::array(); return result; + } // Recursively build children nlohmann::ordered_json children; diff --git a/test/parallel/test-nsolid-heap-sampling-stream.js b/test/parallel/test-nsolid-heap-sampling-stream.js index 0074403e7b..32f475d575 100644 --- a/test/parallel/test-nsolid-heap-sampling-stream.js +++ b/test/parallel/test-nsolid-heap-sampling-stream.js @@ -102,10 +102,45 @@ const { { let profile = ''; const stream = nsolid.heapSamplingStream(0, 1200); + // Do some allocations to make sure we have some data to sample + const arr = []; + for (let i = 0; i < 1000; i++) { + arr.push(new Array(1000)); + } stream.on('data', (data) => { profile += data; }); stream.on('end', common.mustCall(() => { assert(JSON.parse(profile)); + testProfileSchema(JSON.parse(profile)); })); } + +function testProfileSchema (profile) { + // Basic object schema test + assert(profile.head); + assert(profile.samples); + + testCallFrame(profile.head); + + // Recursive schema test per sample callframe + function testCallFrame (head) { + assert(Number.isInteger(head.callFrame.columnNumber)); + assert(Number.isInteger(head.callFrame.lineNumber)); + assert(Number.isInteger(head.selfSize)); + assert(Number.isInteger(head.callFrame.scriptId)); + assert(Number.isInteger(head.id)); + assert(head.callFrame.functionName === '' || + typeof head.callFrame.functionName === 'string'); + assert(head.callFrame.url === '' || typeof head.callFrame.url === 'string'); + assert(Array.isArray(head.children)); + testChildren(head.children); + } + + // Recursive children schema test + function testChildren (children) { + let isTestDone = children.length === 0; + if (!isTestDone) return testCallFrame(children[0]); + assert(isTestDone); + } +}