diff options
Diffstat (limited to 'dom/heapsnapshot/tests/unit/test_HeapAnalyses_takeCensus_04.js')
-rw-r--r-- | dom/heapsnapshot/tests/unit/test_HeapAnalyses_takeCensus_04.js | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/dom/heapsnapshot/tests/unit/test_HeapAnalyses_takeCensus_04.js b/dom/heapsnapshot/tests/unit/test_HeapAnalyses_takeCensus_04.js new file mode 100644 index 000000000..769a2d99d --- /dev/null +++ b/dom/heapsnapshot/tests/unit/test_HeapAnalyses_takeCensus_04.js @@ -0,0 +1,118 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Test that the HeapAnalyses{Client,Worker} can send SavedFrame stacks from +// by-allocation-stack reports from the worker. + +function run_test() { + run_next_test(); +} + +add_task(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 + `); // 6 + + // Create one allocationMarker with tracking turned off, + // so it will have no associated stack. + g.f(); + + dbg.memory.allocationSamplingProbability = 1; + + for (let [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 }); + yield 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 } = yield 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(map.__proto__.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. + let 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(); +}); |