/* Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";

// Test that we correctly set `moreChildrenAvailable` when doing a partial
// traversal of a dominator tree to create the initial incrementally loaded
// `DominatorTreeNode` tree.

// `tree` maps parent to children:
//
// 100
//   |- 200
//   |    |- 500
//   |    |- 600
//   |    `- 700
//   |- 300
//   |    |- 800
//   |    |- 900
//   `- 400
//        |- 1000
//        |- 1100
//        `- 1200
const tree = new Map([
  [100, [200, 300, 400]],
  [200, [500, 600, 700]],
  [300, [800, 900]],
  [400, [1000, 1100, 1200]],
]);

const mockDominatorTree = {
  root: 100,
  getRetainedSize: _ => 10,
  getImmediatelyDominated: id => (tree.get(id) || []).slice(),
};

const mockSnapshot = {
  describeNode: _ => ({
    objects: { count: 0, bytes: 0 },
    strings: { count: 0, bytes: 0 },
    scripts: { count: 0, bytes: 0 },
    other: { SomeType: { count: 1, bytes: 10 } },
    domNode: { count: 0, bytes: 0 },
  }),
};

const breakdown = {
  by: "coarseType",
  objects: { by: "count", count: true, bytes: true },
  strings: { by: "count", count: true, bytes: true },
  scripts: { by: "count", count: true, bytes: true },
  other: {
    by: "internalType",
    then: { by: "count", count: true, bytes: true },
  },
  domNode: { by: "count", count: true, bytes: true },
};

const expected = {
  nodeId: 100,
  label: ["other", "SomeType"],
  shallowSize: 10,
  retainedSize: 10,
  shortestPaths: undefined,
  children: [
    {
      nodeId: 200,
      label: ["other", "SomeType"],
      shallowSize: 10,
      retainedSize: 10,
      parentId: 100,
      shortestPaths: undefined,
      children: [
        {
          nodeId: 500,
          label: ["other", "SomeType"],
          shallowSize: 10,
          retainedSize: 10,
          parentId: 200,
          moreChildrenAvailable: false,
          shortestPaths: undefined,
          children: undefined,
        },
        {
          nodeId: 600,
          label: ["other", "SomeType"],
          shallowSize: 10,
          retainedSize: 10,
          parentId: 200,
          moreChildrenAvailable: false,
          shortestPaths: undefined,
          children: undefined,
        },
      ],
      moreChildrenAvailable: true,
    },
    {
      nodeId: 300,
      label: ["other", "SomeType"],
      shallowSize: 10,
      retainedSize: 10,
      parentId: 100,
      shortestPaths: undefined,
      children: [
        {
          nodeId: 800,
          label: ["other", "SomeType"],
          shallowSize: 10,
          retainedSize: 10,
          parentId: 300,
          moreChildrenAvailable: false,
          shortestPaths: undefined,
          children: undefined,
        },
        {
          nodeId: 900,
          label: ["other", "SomeType"],
          shallowSize: 10,
          retainedSize: 10,
          parentId: 300,
          moreChildrenAvailable: false,
          shortestPaths: undefined,
          children: undefined,
        },
      ],
      moreChildrenAvailable: false,
    },
  ],
  moreChildrenAvailable: true,
  parentId: undefined,
};

function run_test() {
  // Traverse the whole depth of the test tree, but one short of the number of
  // siblings. This will exercise the moreChildrenAvailable handling for
  // siblings.
  const actual = DominatorTreeNode.partialTraversal(
    mockDominatorTree,
    mockSnapshot,
    breakdown,
    // maxDepth
    4,
    // siblings
    2
  );

  dumpn("Expected = " + JSON.stringify(expected, null, 2));
  dumpn("Actual = " + JSON.stringify(actual, null, 2));

  assertStructurallyEquivalent(expected, actual);
}
