test_dominator_trees_06.js (4179B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 // Test that we can incrementally fetch a subtree of a dominator tree. 7 8 const { 9 dominatorTreeState, 10 viewState, 11 } = require("resource://devtools/client/memory/constants.js"); 12 const { 13 takeSnapshotAndCensus, 14 fetchImmediatelyDominated, 15 } = require("resource://devtools/client/memory/actions/snapshot.js"); 16 const DominatorTreeLazyChildren = require("resource://devtools/client/memory/dominator-tree-lazy-children.js"); 17 18 const { 19 changeView, 20 } = require("resource://devtools/client/memory/actions/view.js"); 21 22 add_task(async function () { 23 const front = new StubbedMemoryFront(); 24 const heapWorker = new HeapAnalysesClient(); 25 await front.attach(); 26 const store = Store(); 27 const { getState, dispatch } = store; 28 29 dispatch(changeView(viewState.DOMINATOR_TREE)); 30 dispatch(takeSnapshotAndCensus(front, heapWorker)); 31 32 // Wait for the dominator tree to finish being fetched. 33 await waitUntilState( 34 store, 35 state => 36 state.snapshots[0] && 37 state.snapshots[0].dominatorTree && 38 state.snapshots[0].dominatorTree.state === dominatorTreeState.LOADED 39 ); 40 ok( 41 getState().snapshots[0].dominatorTree.root, 42 "The dominator tree was fetched" 43 ); 44 45 // Find a node that has children, but none of them are loaded. 46 47 function findNode(node) { 48 if (node.moreChildrenAvailable && !node.children) { 49 return node; 50 } 51 52 if (node.children) { 53 for (const child of node.children) { 54 const found = findNode(child); 55 if (found) { 56 return found; 57 } 58 } 59 } 60 61 return null; 62 } 63 64 const oldRoot = getState().snapshots[0].dominatorTree.root; 65 const oldNode = findNode(oldRoot); 66 ok( 67 oldNode, 68 "Should have found a node with children that are not loaded since we " + 69 "only send partial dominator trees across initially and load the rest " + 70 "on demand" 71 ); 72 Assert.notStrictEqual( 73 oldNode, 74 oldRoot, 75 "But the node should not be the root" 76 ); 77 78 const lazyChildren = new DominatorTreeLazyChildren(oldNode.nodeId, 0); 79 dispatch( 80 fetchImmediatelyDominated( 81 heapWorker, 82 getState().snapshots[0].id, 83 lazyChildren 84 ) 85 ); 86 87 equal( 88 getState().snapshots[0].dominatorTree.state, 89 dominatorTreeState.INCREMENTAL_FETCHING, 90 "Fetching immediately dominated children should put us in the " + 91 "INCREMENTAL_FETCHING state" 92 ); 93 94 await waitUntilState( 95 store, 96 state => 97 state.snapshots[0].dominatorTree.state === dominatorTreeState.LOADED 98 ); 99 ok( 100 true, 101 "The dominator tree should go back to LOADED after the incremental " + 102 "fetching is done." 103 ); 104 105 const newRoot = getState().snapshots[0].dominatorTree.root; 106 Assert.notStrictEqual( 107 oldRoot, 108 newRoot, 109 "When we insert new nodes, we get a new tree" 110 ); 111 equal( 112 oldRoot.children.length, 113 newRoot.children.length, 114 "The new tree's root should have the same number of children as the " + 115 "old root's" 116 ); 117 118 let differentChildrenCount = 0; 119 for (let i = 0; i < oldRoot.children.length; i++) { 120 if (oldRoot.children[i] !== newRoot.children[i]) { 121 differentChildrenCount++; 122 } 123 } 124 equal( 125 differentChildrenCount, 126 1, 127 "All subtrees except the subtree we inserted incrementally fetched " + 128 "children into should be the same because we use persistent updates" 129 ); 130 131 // Find the new node which has the children inserted. 132 133 function findNewNode(node) { 134 if (node.nodeId === oldNode.nodeId) { 135 return node; 136 } 137 138 if (node.children) { 139 for (const child of node.children) { 140 const found = findNewNode(child); 141 if (found) { 142 return found; 143 } 144 } 145 } 146 147 return null; 148 } 149 150 const newNode = findNewNode(newRoot); 151 ok(newNode, "Should find the node in the new tree again"); 152 Assert.notStrictEqual( 153 newNode, 154 oldNode, 155 "We did not mutate the old node in place, instead created a new node" 156 ); 157 ok(newNode.children, "And the new node should have the children attached"); 158 159 heapWorker.destroy(); 160 await front.detach(); 161 });