17
17
#include < hermes/CompileJS.h>
18
18
#include < hermes/Support/JSONEmitter.h>
19
19
#include < hermes/Support/SerialExecutor.h>
20
+ #include < hermes/VM/HeapSnapshot.h>
20
21
#include < hermes/cdp/CDPAgent.h>
21
22
#include < hermes/cdp/CDPDebugAPI.h>
22
23
#include < hermes/cdp/JSONValueInterfaces.h>
@@ -149,7 +150,8 @@ class CDPAgentTest : public ::testing::Test {
149
150
// / \p messageID specifies the id of the snapshot request.
150
151
// / \p ignoreTrackingNotifications indicates whether lastSeenObjectId and
151
152
// / heapStatsUpdate notifications are tolerated before the snapshot arrives.
152
- void expectHeapSnapshot (
153
+ // / \return the completed heap snapshot JSON object
154
+ JSONObject *expectHeapSnapshot (
153
155
int messageID,
154
156
bool ignoreTrackingNotifications = false );
155
157
@@ -381,7 +383,7 @@ void CDPAgentTest::expectErrorMessageContaining(
381
383
ASSERT_NE (errorMessage.find (substring), std::string::npos);
382
384
}
383
385
384
- void CDPAgentTest::expectHeapSnapshot (
386
+ JSONObject * CDPAgentTest::expectHeapSnapshot (
385
387
int messageID,
386
388
bool ignoreTrackingNotifications) {
387
389
// Expect chunk notifications until the snapshot object is complete. Fail if
@@ -398,12 +400,14 @@ void CDPAgentTest::expectHeapSnapshot(
398
400
continue ;
399
401
}
400
402
401
- ASSERT_EQ (method, " HeapProfiler.addHeapSnapshotChunk" );
403
+ EXPECT_EQ (method, " HeapProfiler.addHeapSnapshotChunk" );
402
404
snapshot << jsonScope_.getString (note, {" params" , " chunk" });
403
405
} while (!jsonScope_.tryParseObject (snapshot.str ()).has_value ());
404
406
405
407
// Expect the snapshot response after all chunks have been received.
406
408
ensureOkResponse (waitForMessage (), messageID);
409
+
410
+ return jsonScope_.parseObject (snapshot.str ());
407
411
}
408
412
409
413
jsi::Value CDPAgentTest::shouldStop (
@@ -3393,7 +3397,7 @@ TEST_F(CDPAgentTest, RuntimeValidatesExecutionContextId) {
3393
3397
expectErrorMessageContaining (kExecutionContextSubstring , msgId++);
3394
3398
}
3395
3399
3396
- TEST_F (CDPAgentTest, HeapProfilerSnapshot ) {
3400
+ TEST_F (CDPAgentTest, HeapProfilerSnapshotCaptureNumeric ) {
3397
3401
int msgId = 1 ;
3398
3402
3399
3403
#ifdef HERMES_MEMORY_INSTRUMENTATION
@@ -3410,8 +3414,65 @@ TEST_F(CDPAgentTest, HeapProfilerSnapshot) {
3410
3414
sendRequest (
3411
3415
" HeapProfiler.takeHeapSnapshot" , msgId, [](::hermes::JSONEmitter &json) {
3412
3416
json.emitKeyValue (" reportProgress" , false );
3417
+ json.emitKeyValue (" captureNumericValue" , true );
3413
3418
});
3414
- expectHeapSnapshot (msgId);
3419
+ JSONObject *root = expectHeapSnapshot (msgId);
3420
+ const JSONArray &nodes = *llvh::cast<JSONArray>(root->at (" nodes" ));
3421
+
3422
+ bool found = false ;
3423
+ auto nodesIt = nodes.begin ();
3424
+ const auto nodesEnd = nodes.end ();
3425
+ while (nodesIt != nodesEnd) {
3426
+ auto type = static_cast <::hermes::vm::HeapSnapshot::NodeType>(
3427
+ static_cast <unsigned >(llvh::cast<JSONNumber>(*nodesIt)->getValue ()));
3428
+ if (type == ::hermes::vm::HeapSnapshot::NodeType::Number) {
3429
+ found = true ;
3430
+ }
3431
+ nodesIt += ::hermes::vm::HeapSnapshot::V8_SNAPSHOT_NODE_FIELD_COUNT;
3432
+ }
3433
+ EXPECT_TRUE (found);
3434
+
3435
+ // Expect no more chunks are pending.
3436
+ expectNothing ();
3437
+ #else
3438
+ sendRequest (
3439
+ " HeapProfiler.takeHeapSnapshot" , msgId, [](::hermes::JSONEmitter &json) {
3440
+ json.emitKeyValue (" reportProgress" , false );
3441
+ json.emitKeyValue (" captureNumericValue" , true );
3442
+ });
3443
+ expectErrorMessageContaining (kMemoryInstrumentationSubstring , msgId);
3444
+ #endif // HERMES_MEMORY_INSTRUMENTATION
3445
+ }
3446
+
3447
+ TEST_F (CDPAgentTest, HeapProfilerSnapshotNoNumeric) {
3448
+ int msgId = 1 ;
3449
+
3450
+ #ifdef HERMES_MEMORY_INSTRUMENTATION
3451
+ auto setStopFlag = llvh::make_scope_exit ([this ] {
3452
+ // break out of loop
3453
+ stopFlag_.store (true );
3454
+ });
3455
+
3456
+ scheduleScript (R"(
3457
+ while(!shouldStop());
3458
+ )" );
3459
+
3460
+ // Request a heap snapshot and expect it to arrive.
3461
+ // Expect captureNumericValue to default to false when not provided.
3462
+ sendRequest (
3463
+ " HeapProfiler.takeHeapSnapshot" , msgId, [](::hermes::JSONEmitter &json) {
3464
+ json.emitKeyValue (" reportProgress" , false );
3465
+ });
3466
+ JSONObject *root = expectHeapSnapshot (msgId);
3467
+ const JSONArray &nodes = *llvh::cast<JSONArray>(root->at (" nodes" ));
3468
+ auto nodesIt = nodes.begin ();
3469
+ const auto nodesEnd = nodes.end ();
3470
+ while (nodesIt != nodesEnd) {
3471
+ auto type = static_cast <::hermes::vm::HeapSnapshot::NodeType>(
3472
+ static_cast <unsigned >(llvh::cast<JSONNumber>(*nodesIt)->getValue ()));
3473
+ EXPECT_NE (type, ::hermes::vm::HeapSnapshot::NodeType::Number);
3474
+ nodesIt += ::hermes::vm::HeapSnapshot::V8_SNAPSHOT_NODE_FIELD_COUNT;
3475
+ }
3415
3476
3416
3477
// Expect no more chunks are pending.
3417
3478
expectNothing ();
0 commit comments