tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_HeapSnapshot_deepStack_01.js (2777B)


      1 /* Any copyright is dedicated to the Public Domain.
      2   http://creativecommons.org/publicdomain/zero/1.0/ */
      3 "use strict";
      4 
      5 // Test that we can save a core dump with very deep allocation stacks and read
      6 // it back into a HeapSnapshot.
      7 
      8 function stackDepth(stack) {
      9  return stack ? 1 + stackDepth(stack.parent) : 0;
     10 }
     11 
     12 function run_test() {
     13  Services.prefs.setBoolPref(
     14    "security.allow_parent_unrestricted_js_loads",
     15    true
     16  );
     17  Services.prefs.setBoolPref("security.allow_eval_with_system_principal", true);
     18  Services.prefs.setBoolPref("security.allow_eval_in_parent_process", true);
     19  registerCleanupFunction(() => {
     20    Services.prefs.clearUserPref("security.allow_parent_unrestricted_js_loads");
     21    Services.prefs.clearUserPref("security.allow_eval_with_system_principal");
     22    Services.prefs.clearUserPref("security.allow_eval_in_parent_process");
     23  });
     24 
     25  // Create a Debugger observing a debuggee's allocations.
     26  const debuggee = new Cu.Sandbox(null);
     27  const dbg = new Debugger(debuggee);
     28  dbg.memory.trackingAllocationSites = true;
     29 
     30  // Allocate some objects in the debuggee that will have their allocation
     31  // stacks recorded by the Debugger.
     32 
     33  debuggee.eval("this.objects = []");
     34  debuggee.eval(
     35    function recursiveAllocate(n) {
     36      if (n <= 0) {
     37        return;
     38      }
     39 
     40      // Make sure to recurse before pushing the object so that when TCO is
     41      // implemented sometime in the future, it doesn't invalidate this test.
     42      recursiveAllocate(n - 1);
     43      this.objects.push({});
     44    }.toString()
     45  );
     46  debuggee.eval("recursiveAllocate = recursiveAllocate.bind(this);");
     47  debuggee.eval("recursiveAllocate(200);");
     48 
     49  // Now save a snapshot that will include the allocation stacks and read it
     50  // back again.
     51 
     52  const filePath = ChromeUtils.saveHeapSnapshot({ runtime: true });
     53  ok(true, "Should be able to save a snapshot.");
     54 
     55  const snapshot = ChromeUtils.readHeapSnapshot(filePath);
     56  ok(snapshot, "Should be able to read a heap snapshot");
     57  ok(HeapSnapshot.isInstance(snapshot), "Should be an instanceof HeapSnapshot");
     58 
     59  const report = snapshot.takeCensus({
     60    breakdown: {
     61      by: "allocationStack",
     62      then: { by: "count", bytes: true, count: true },
     63      noStack: { by: "count", bytes: true, count: true },
     64    },
     65  });
     66 
     67  // Keep this synchronized with `HeapSnapshot::MAX_STACK_DEPTH`!
     68  const MAX_STACK_DEPTH = 60;
     69 
     70  let foundStacks = false;
     71  report.forEach((v, k) => {
     72    if (k === "noStack") {
     73      return;
     74    }
     75 
     76    foundStacks = true;
     77    const depth = stackDepth(k);
     78    dumpn("Stack depth is " + depth);
     79    Assert.lessOrEqual(
     80      depth,
     81      MAX_STACK_DEPTH,
     82      "Every stack should have depth less than or equal to the maximum stack depth"
     83    );
     84  });
     85  ok(foundStacks);
     86 
     87  do_test_finished();
     88 }