summaryrefslogtreecommitdiffstats
path: root/devtools/shared/heapsnapshot/tests/xpcshell/test_getReportLeaves_01.js
blob: 04aae90e991690ae8130b704031fd70fa59fc18a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/* Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";

// Test basic functionality of `CensusUtils.getReportLeaves`.

function run_test() {
  const BREAKDOWN = {
    by: "coarseType",
    objects: {
      by: "objectClass",
      then: { by: "count", count: true, bytes: true },
      other: { by: "count", count: true, bytes: true },
    },
    strings: { by: "count", count: true, bytes: true },
    scripts: {
      by: "filename",
      then: {
        by: "internalType",
        then: { by: "count", count: true, bytes: true },
      },
      noFilename: {
        by: "internalType",
        then: { by: "count", count: true, bytes: true },
      },
    },
    other: {
      by: "internalType",
      then: { by: "count", count: true, bytes: true },
    },
    domNode: {
      by: "descriptiveType",
      then: { by: "count", count: true, bytes: true },
    },
  };

  const REPORT = {
    objects: {
      Array: { count: 6, bytes: 60 },
      Function: { count: 1, bytes: 10 },
      Object: { count: 1, bytes: 10 },
      RegExp: { count: 1, bytes: 10 },
      other: { count: 0, bytes: 0 },
    },
    strings: { count: 1, bytes: 10 },
    scripts: {
      "foo.js": {
        JSScript: { count: 1, bytes: 10 },
        "js::jit::IonScript": { count: 1, bytes: 10 },
      },
      noFilename: {
        JSScript: { count: 1, bytes: 10 },
        "js::jit::IonScript": { count: 1, bytes: 10 },
      },
    },
    other: {
      "js::Shape": { count: 7, bytes: 70 },
      "js::BaseShape": { count: 1, bytes: 10 },
    },
    domNode: {},
  };

  const root = censusReportToCensusTreeNode(BREAKDOWN, REPORT);
  dumpn("CensusTreeNode tree = " + JSON.stringify(root, null, 4));

  (function assertEveryNodeCanFindItsLeaf(node) {
    if (node.reportLeafIndex) {
      const [leaf] = CensusUtils.getReportLeaves(
        new Set([node.reportLeafIndex]),
        BREAKDOWN,
        REPORT
      );
      ok(
        leaf,
        "Should be able to find leaf " +
          "for a node with a reportLeafIndex = " +
          node.reportLeafIndex
      );
    }

    if (node.children) {
      for (const child of node.children) {
        assertEveryNodeCanFindItsLeaf(child);
      }
    }
  })(root);

  // Test finding multiple leaves at a time.

  function find(name, node) {
    if (node.name === name) {
      return node;
    }

    if (node.children) {
      for (const child of node.children) {
        const found = find(name, child);
        if (found) {
          return found;
        }
      }
    }

    return undefined;
  }

  const arrayNode = find("Array", root);
  ok(arrayNode);
  equal(typeof arrayNode.reportLeafIndex, "number");

  const shapeNode = find("js::Shape", root);
  ok(shapeNode);
  equal(typeof shapeNode.reportLeafIndex, "number");

  const indices = new Set([
    arrayNode.reportLeafIndex,
    shapeNode.reportLeafIndex,
  ]);
  const leaves = CensusUtils.getReportLeaves(indices, BREAKDOWN, REPORT);
  equal(leaves.length, 2);

  // `getReportLeaves` does not guarantee order of the results, so handle both
  // cases.
  ok(leaves.some(l => l === REPORT.objects.Array));
  ok(leaves.some(l => l === REPORT.other["js::Shape"]));

  // Test that bad indices do not yield results.

  const none = CensusUtils.getReportLeaves(
    new Set([999999999999]),
    BREAKDOWN,
    REPORT
  );
  equal(none.length, 0);
}