diff options
Diffstat (limited to 'devtools/shared/heapsnapshot/tests/xpcshell/test_HeapAnalyses_takeCensus_04.js')
-rw-r--r-- | devtools/shared/heapsnapshot/tests/xpcshell/test_HeapAnalyses_takeCensus_04.js | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/devtools/shared/heapsnapshot/tests/xpcshell/test_HeapAnalyses_takeCensus_04.js b/devtools/shared/heapsnapshot/tests/xpcshell/test_HeapAnalyses_takeCensus_04.js new file mode 100644 index 0000000000..26f78ad4f7 --- /dev/null +++ b/devtools/shared/heapsnapshot/tests/xpcshell/test_HeapAnalyses_takeCensus_04.js @@ -0,0 +1,133 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + +// Test that the HeapAnalyses{Client,Worker} can send SavedFrame stacks from +// by-allocation-stack reports from the worker. + +add_task(async function test() { + const client = new HeapAnalysesClient(); + + // Track some allocation stacks. + + const g = newGlobal(); + const dbg = new Debugger(g); + g.eval(` // 1 + this.log = []; // 2 + function f() { this.log.push(allocationMarker()); } // 3 + function g() { this.log.push(allocationMarker()); } // 4 + function h() { this.log.push(allocationMarker()); } // 5 + `); + + // Create one allocationMarker with tracking turned off, + // so it will have no associated stack. + g.f(); + + dbg.memory.allocationSamplingProbability = 1; + + for (const [func, n] of [ + [g.f, 20], + [g.g, 10], + [g.h, 5], + ]) { + for (let i = 0; i < n; i++) { + dbg.memory.trackingAllocationSites = true; + // All allocations of allocationMarker occur with this line as the oldest + // stack frame. + func(); + dbg.memory.trackingAllocationSites = false; + } + } + + // Take a heap snapshot. + + const snapshotFilePath = saveNewHeapSnapshot({ debugger: dbg }); + await client.readHeapSnapshot(snapshotFilePath); + ok(true, "Should have read the heap snapshot"); + + // Run a census broken down by class name -> allocation stack so we can grab + // only the AllocationMarker objects we have complete control over. + + const { report } = await client.takeCensus(snapshotFilePath, { + breakdown: { + by: "objectClass", + then: { + by: "allocationStack", + then: { + by: "count", + bytes: true, + count: true, + }, + noStack: { + by: "count", + bytes: true, + count: true, + }, + }, + }, + }); + + // Test the generated report. + + ok(report, "Should get a report"); + + const map = report.AllocationMarker; + ok(map, "Should get AllocationMarkers in the report."); + // From a module with a different global, and therefore a different Map + // constructor, so we can't use instanceof. + equal(Object.getPrototypeOf(map).constructor.name, "Map"); + + equal( + map.size, + 4, + "Should have 4 allocation stacks (including the lack of a stack)" + ); + + // Gather the stacks we are expecting to appear as keys, and + // check that there are no unexpected keys. + const stacks = {}; + + map.forEach((v, k) => { + if (k === "noStack") { + // No need to save this key. + } else if ( + k.functionDisplayName === "f" && + k.parent.functionDisplayName === "test" + ) { + stacks.f = k; + } else if ( + k.functionDisplayName === "g" && + k.parent.functionDisplayName === "test" + ) { + stacks.g = k; + } else if ( + k.functionDisplayName === "h" && + k.parent.functionDisplayName === "test" + ) { + stacks.h = k; + } else { + dumpn("Unexpected allocation stack:"); + k.toString() + .split(/\n/g) + .forEach(s => dumpn(s)); + ok(false); + } + }); + + ok(map.get("noStack")); + equal(map.get("noStack").count, 1); + + ok(stacks.f); + ok(map.get(stacks.f)); + equal(map.get(stacks.f).count, 20); + + ok(stacks.g); + ok(map.get(stacks.g)); + equal(map.get(stacks.g).count, 10); + + ok(stacks.h); + ok(map.get(stacks.h)); + equal(map.get(stacks.h).count, 5); + + client.destroy(); +}); |