diff options
Diffstat (limited to 'devtools/client/memory/test/xpcshell/test_dominator_trees_06.js')
-rw-r--r-- | devtools/client/memory/test/xpcshell/test_dominator_trees_06.js | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/devtools/client/memory/test/xpcshell/test_dominator_trees_06.js b/devtools/client/memory/test/xpcshell/test_dominator_trees_06.js new file mode 100644 index 0000000000..7caffb972e --- /dev/null +++ b/devtools/client/memory/test/xpcshell/test_dominator_trees_06.js @@ -0,0 +1,161 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Test that we can incrementally fetch a subtree of a dominator tree. + +const { + dominatorTreeState, + viewState, +} = require("resource://devtools/client/memory/constants.js"); +const { + takeSnapshotAndCensus, + fetchImmediatelyDominated, +} = require("resource://devtools/client/memory/actions/snapshot.js"); +const DominatorTreeLazyChildren = require("resource://devtools/client/memory/dominator-tree-lazy-children.js"); + +const { + changeView, +} = require("resource://devtools/client/memory/actions/view.js"); + +add_task(async function () { + const front = new StubbedMemoryFront(); + const heapWorker = new HeapAnalysesClient(); + await front.attach(); + const store = Store(); + const { getState, dispatch } = store; + + dispatch(changeView(viewState.DOMINATOR_TREE)); + dispatch(takeSnapshotAndCensus(front, heapWorker)); + + // Wait for the dominator tree to finish being fetched. + await waitUntilState( + store, + state => + state.snapshots[0] && + state.snapshots[0].dominatorTree && + state.snapshots[0].dominatorTree.state === dominatorTreeState.LOADED + ); + ok( + getState().snapshots[0].dominatorTree.root, + "The dominator tree was fetched" + ); + + // Find a node that has children, but none of them are loaded. + + function findNode(node) { + if (node.moreChildrenAvailable && !node.children) { + return node; + } + + if (node.children) { + for (const child of node.children) { + const found = findNode(child); + if (found) { + return found; + } + } + } + + return null; + } + + const oldRoot = getState().snapshots[0].dominatorTree.root; + const oldNode = findNode(oldRoot); + ok( + oldNode, + "Should have found a node with children that are not loaded since we " + + "only send partial dominator trees across initially and load the rest " + + "on demand" + ); + Assert.notStrictEqual( + oldNode, + oldRoot, + "But the node should not be the root" + ); + + const lazyChildren = new DominatorTreeLazyChildren(oldNode.nodeId, 0); + dispatch( + fetchImmediatelyDominated( + heapWorker, + getState().snapshots[0].id, + lazyChildren + ) + ); + + equal( + getState().snapshots[0].dominatorTree.state, + dominatorTreeState.INCREMENTAL_FETCHING, + "Fetching immediately dominated children should put us in the " + + "INCREMENTAL_FETCHING state" + ); + + await waitUntilState( + store, + state => + state.snapshots[0].dominatorTree.state === dominatorTreeState.LOADED + ); + ok( + true, + "The dominator tree should go back to LOADED after the incremental " + + "fetching is done." + ); + + const newRoot = getState().snapshots[0].dominatorTree.root; + Assert.notStrictEqual( + oldRoot, + newRoot, + "When we insert new nodes, we get a new tree" + ); + equal( + oldRoot.children.length, + newRoot.children.length, + "The new tree's root should have the same number of children as the " + + "old root's" + ); + + let differentChildrenCount = 0; + for (let i = 0; i < oldRoot.children.length; i++) { + if (oldRoot.children[i] !== newRoot.children[i]) { + differentChildrenCount++; + } + } + equal( + differentChildrenCount, + 1, + "All subtrees except the subtree we inserted incrementally fetched " + + "children into should be the same because we use persistent updates" + ); + + // Find the new node which has the children inserted. + + function findNewNode(node) { + if (node.nodeId === oldNode.nodeId) { + return node; + } + + if (node.children) { + for (const child of node.children) { + const found = findNewNode(child); + if (found) { + return found; + } + } + } + + return null; + } + + const newNode = findNewNode(newRoot); + ok(newNode, "Should find the node in the new tree again"); + Assert.notStrictEqual( + newNode, + oldNode, + "We did not mutate the old node in place, instead created a new node" + ); + ok(newNode.children, "And the new node should have the children attached"); + + heapWorker.destroy(); + await front.detach(); +}); |