import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo

This commit is contained in:
Roy Tam 2018-01-19 03:59:58 +08:00
commit dcd9973243
150858 changed files with 23884658 additions and 0 deletions

View file

@ -0,0 +1,20 @@
[DEFAULT]
support-files =
head.js
[test_CensusTreeItem_01.html]
[test_DominatorTree_01.html]
[test_DominatorTree_02.html]
[test_DominatorTree_03.html]
[test_DominatorTreeItem_01.html]
[test_Heap_01.html]
[test_Heap_02.html]
[test_Heap_03.html]
[test_Heap_04.html]
[test_Heap_05.html]
[test_List_01.html]
[test_ShortestPaths_01.html]
[test_ShortestPaths_02.html]
[test_SnapshotListItem_01.html]
[test_Toolbar_01.html]
[test_TreeMap_01.html]

View file

@ -0,0 +1,335 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
var { BrowserLoader } = Cu.import("resource://devtools/client/shared/browser-loader.js", {});
var { require } = BrowserLoader({
baseURI: "resource://devtools/client/memory/",
window
});
var { Assert } = require("resource://testing-common/Assert.jsm");
var Services = require("Services");
var { Task } = require("devtools/shared/task");
var EXPECTED_DTU_ASSERT_FAILURE_COUNT = 0;
SimpleTest.registerCleanupFunction(function () {
if (DevToolsUtils.assertionFailureCount !== EXPECTED_DTU_ASSERT_FAILURE_COUNT) {
ok(false, "Should have had the expected number of DevToolsUtils.assert() failures. Expected " +
EXPECTED_DTU_ASSERT_FAILURE_COUNT + ", got " + DevToolsUtils.assertionFailureCount);
}
});
var DevToolsUtils = require("devtools/shared/DevToolsUtils");
var { immutableUpdate } = DevToolsUtils;
var flags = require("devtools/shared/flags");
flags.testing = true;
var constants = require("devtools/client/memory/constants");
var {
censusDisplays,
diffingState,
labelDisplays,
dominatorTreeState,
snapshotState,
viewState,
censusState
} = constants;
const {
L10N,
} = require("devtools/client/memory/utils");
var models = require("devtools/client/memory/models");
var Immutable = require("devtools/client/shared/vendor/immutable");
var React = require("devtools/client/shared/vendor/react");
var ReactDOM = require("devtools/client/shared/vendor/react-dom");
var Heap = React.createFactory(require("devtools/client/memory/components/heap"));
var CensusTreeItem = React.createFactory(require("devtools/client/memory/components/census-tree-item"));
var DominatorTreeComponent = React.createFactory(require("devtools/client/memory/components/dominator-tree"));
var DominatorTreeItem = React.createFactory(require("devtools/client/memory/components/dominator-tree-item"));
var ShortestPaths = React.createFactory(require("devtools/client/memory/components/shortest-paths"));
var TreeMap = React.createFactory(require("devtools/client/memory/components/tree-map"));
var SnapshotListItem = React.createFactory(require("devtools/client/memory/components/snapshot-list-item"));
var List = React.createFactory(require("devtools/client/memory/components/list"));
var Toolbar = React.createFactory(require("devtools/client/memory/components/toolbar"));
// All tests are asynchronous.
SimpleTest.waitForExplicitFinish();
var noop = () => {};
var TEST_CENSUS_TREE_ITEM_PROPS = Object.freeze({
item: Object.freeze({
bytes: 10,
count: 1,
totalBytes: 10,
totalCount: 1,
name: "foo",
children: [
Object.freeze({
bytes: 10,
count: 1,
totalBytes: 10,
totalCount: 1,
name: "bar",
})
]
}),
depth: 0,
arrow: ">",
focused: true,
getPercentBytes: () => 50,
getPercentCount: () => 50,
showSign: false,
onViewSourceInDebugger: noop,
inverted: false,
});
// Counter for mock DominatorTreeNode ids.
var TEST_NODE_ID_COUNTER = 0;
/**
* Create a mock DominatorTreeNode for testing, with sane defaults. Override any
* property by providing it on `opts`. Optionally pass child nodes as well.
*
* @param {Object} opts
* @param {Array<DominatorTreeNode>?} children
*
* @returns {DominatorTreeNode}
*/
function makeTestDominatorTreeNode(opts, children) {
const nodeId = TEST_NODE_ID_COUNTER++;
const node = Object.assign({
nodeId,
label: ["other", "SomeType"],
shallowSize: 1,
retainedSize: (children || []).reduce((size, c) => size + c.retainedSize, 1),
parentId: undefined,
children,
moreChildrenAvailable: true,
}, opts);
if (children && children.length) {
children.map(c => c.parentId = node.nodeId);
}
return node;
}
var TEST_DOMINATOR_TREE = Object.freeze({
dominatorTreeId: 666,
root: (function makeTree(depth = 0) {
let children;
if (depth <= 3) {
children = [
makeTree(depth + 1),
makeTree(depth + 1),
makeTree(depth + 1),
];
}
return makeTestDominatorTreeNode({}, children);
}()),
expanded: new Set(),
focused: null,
error: null,
display: labelDisplays.coarseType,
activeFetchRequestCount: null,
state: dominatorTreeState.LOADED,
});
var TEST_DOMINATOR_TREE_PROPS = Object.freeze({
dominatorTree: TEST_DOMINATOR_TREE,
onLoadMoreSiblings: noop,
onViewSourceInDebugger: noop,
onExpand: noop,
onCollapse: noop,
});
var TEST_SHORTEST_PATHS_PROPS = Object.freeze({
graph: Object.freeze({
nodes: [
{ id: 1, label: ["other", "SomeType"] },
{ id: 2, label: ["other", "SomeType"] },
{ id: 3, label: ["other", "SomeType"] },
],
edges: [
{ from: 1, to: 2, name: "1->2" },
{ from: 1, to: 3, name: "1->3" },
{ from: 2, to: 3, name: "2->3" },
],
}),
});
var TEST_SNAPSHOT = Object.freeze({
id: 1337,
selected: true,
path: "/fake/path/to/snapshot",
census: Object.freeze({
report: Object.freeze({
objects: Object.freeze({ count: 4, bytes: 400 }),
scripts: Object.freeze({ count: 3, bytes: 300 }),
strings: Object.freeze({ count: 2, bytes: 200 }),
other: Object.freeze({ count: 1, bytes: 100 }),
}),
display: Object.freeze({
displayName: "Test Display",
tooltip: "Test display tooltup",
inverted: false,
breakdown: Object.freeze({
by: "coarseType",
objects: Object.freeze({ by: "count", count: true, bytes: true }),
scripts: Object.freeze({ by: "count", count: true, bytes: true }),
strings: Object.freeze({ by: "count", count: true, bytes: true }),
other: Object.freeze({ by: "count", count: true, bytes: true }),
}),
}),
state: censusState.SAVED,
inverted: false,
filter: null,
expanded: new Set(),
focused: null,
parentMap: Object.freeze(Object.create(null))
}),
dominatorTree: TEST_DOMINATOR_TREE,
error: null,
imported: false,
creationTime: 0,
state: snapshotState.READ,
});
var TEST_HEAP_PROPS = Object.freeze({
onSnapshotClick: noop,
onLoadMoreSiblings: noop,
onCensusExpand: noop,
onCensusCollapse: noop,
onDominatorTreeExpand: noop,
onDominatorTreeCollapse: noop,
onCensusFocus: noop,
onDominatorTreeFocus: noop,
onViewSourceInDebugger: noop,
diffing: null,
view: { state: viewState.CENSUS, },
snapshot: TEST_SNAPSHOT,
sizes: Object.freeze({ shortestPathsSize: .5 }),
onShortestPathsResize: noop,
});
var TEST_TOOLBAR_PROPS = Object.freeze({
censusDisplays: [
censusDisplays.coarseType,
censusDisplays.allocationStack,
censusDisplays.invertedAllocationStack,
],
censusDisplay: censusDisplays.coarseType,
onTakeSnapshotClick: noop,
onImportClick: noop,
onCensusDisplayChange: noop,
onToggleRecordAllocationStacks: noop,
allocations: models.allocations,
onToggleInverted: noop,
inverted: false,
filterString: null,
setFilterString: noop,
diffing: null,
onToggleDiffing: noop,
view: { state: viewState.CENSUS, },
onViewChange: noop,
labelDisplays: [
labelDisplays.coarseType,
labelDisplays.allocationStack,
],
labelDisplay: labelDisplays.coarseType,
onLabelDisplayChange: noop,
snapshots: [],
});
function makeTestCensusNode() {
return {
name: "Function",
bytes: 100,
totalBytes: 100,
count: 100,
totalCount: 100,
children: []
};
}
var TEST_TREE_MAP_PROPS = Object.freeze({
treeMap: Object.freeze({
report: {
name: null,
bytes: 0,
totalBytes: 400,
count: 0,
totalCount: 400,
children: [
{
name: "objects",
bytes: 0,
totalBytes: 200,
count: 0,
totalCount: 200,
children: [ makeTestCensusNode(), makeTestCensusNode() ]
},
{
name: "other",
bytes: 0,
totalBytes: 200,
count: 0,
totalCount: 200,
children: [ makeTestCensusNode(), makeTestCensusNode() ],
}
]
}
})
});
var TEST_SNAPSHOT_LIST_ITEM_PROPS = Object.freeze({
onClick: noop,
onSave: noop,
onDelete: noop,
item: TEST_SNAPSHOT,
index: 1234,
});
function onNextAnimationFrame(fn) {
return () =>
requestAnimationFrame(() =>
requestAnimationFrame(fn));
}
/**
* Render the provided ReactElement in the provided HTML container.
* Returns a Promise that will resolve the rendered element as a React
* component.
*/
function renderComponent(element, container) {
return new Promise(resolve => {
let component = ReactDOM.render(element, container,
onNextAnimationFrame(() => {
dumpn("Rendered = " + container.innerHTML);
resolve(component);
}));
});
}
function setState(component, newState) {
return new Promise(resolve => {
component.setState(newState, onNextAnimationFrame(resolve));
});
}
function setProps(component, newProps) {
return new Promise(resolve => {
component.setProps(newProps, onNextAnimationFrame(resolve));
});
}
function dumpn(msg) {
dump(`MEMORY-TEST: ${msg}\n`);
}

View file

@ -0,0 +1,65 @@
<!DOCTYPE HTML>
<html>
<!--
Test that children pointers show up at the correct times.
-->
<head>
<meta charset="utf-8">
<title>Tree component test</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<!-- Give the container height so that the whole tree is rendered. -->
<div id="container" style="height: 900px;"></div>
<pre id="test">
<script src="head.js" type="application/javascript;version=1.8"></script>
<script type="application/javascript;version=1.8">
window.onload = Task.async(function* () {
try {
const container = document.getElementById("container");
yield renderComponent(CensusTreeItem(immutableUpdate(TEST_CENSUS_TREE_ITEM_PROPS, {
inverted: true,
depth: 0,
})), container);
ok(!container.querySelector(".children-pointer"),
"Don't show children pointer for roots when we are inverted");
yield renderComponent(CensusTreeItem(immutableUpdate(TEST_CENSUS_TREE_ITEM_PROPS, {
inverted: true,
depth: 1,
})), container);
ok(container.querySelector(".children-pointer"),
"Do show children pointer for non-roots when we are inverted");
yield renderComponent(CensusTreeItem(immutableUpdate(TEST_CENSUS_TREE_ITEM_PROPS, {
inverted: false,
item: immutableUpdate(TEST_CENSUS_TREE_ITEM_PROPS.item, { children: undefined }),
})), container);
ok(!container.querySelector(".children-pointer"),
"Don't show children pointer when non-inverted and no children");
yield renderComponent(CensusTreeItem(immutableUpdate(TEST_CENSUS_TREE_ITEM_PROPS, {
inverted: false,
depth: 0,
item: immutableUpdate(TEST_CENSUS_TREE_ITEM_PROPS.item, { children: [{}] }),
})), container);
ok(container.querySelector(".children-pointer"),
"Do show children pointer when non-inverted and have children");
} catch(e) {
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
} finally {
SimpleTest.finish();
}
});
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,45 @@
<!DOCTYPE HTML>
<html>
<!--
Test that we don't display `JS::ubi::RootList` for the root, and instead show "GC Roots".
-->
<head>
<meta charset="utf-8">
<title>Tree component test</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<!-- Give the container height so that the whole tree is rendered. -->
<div id="container" style="height: 900px;"></div>
<pre id="test">
<script src="head.js" type="application/javascript;version=1.8"></script>
<script type="application/javascript;version=1.8">
window.onload = Task.async(function* () {
try {
const container = document.getElementById("container");
yield renderComponent(DominatorTreeItem({
item: makeTestDominatorTreeNode({ label: ["other", "JS::ubi::RootList"] }),
depth: 0,
arrow: React.DOM.div(),
focused: true,
getPercentSize: _ => 50,
onViewSourceInDebugger: _ => { },
}), container);
ok(container.textContent.indexOf("JS::ubi::RootList") == -1,
"Should not display `JS::ubi::RootList`");
ok(container.textContent.indexOf("GC Roots") >= 0,
"Should display `GC Roots` instead");
} catch(e) {
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
} finally {
SimpleTest.finish();
}
});
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,50 @@
<!DOCTYPE HTML>
<html>
<!--
Test that we show a place holder for a subtree we are lazily fetching.
-->
<head>
<meta charset="utf-8">
<title>Tree component test</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<!-- Give the container height so that the whole tree is rendered. -->
<div id="container" style="height: 900px;"></div>
<pre id="test">
<script src="head.js" type="application/javascript;version=1.8"></script>
<script type="application/javascript;version=1.8">
window.onload = Task.async(function* () {
try {
const container = document.getElementById("container");
const root = makeTestDominatorTreeNode({ moreChildrenAvailable: true});
ok(!root.children);
const expanded = new Set();
expanded.add(root.nodeId);
yield renderComponent(DominatorTreeComponent(immutableUpdate(TEST_DOMINATOR_TREE_PROPS, {
dominatorTree: immutableUpdate(TEST_DOMINATOR_TREE_PROPS.dominatorTree, {
expanded,
root,
state: dominatorTreeState.INCREMENTAL_FETCHING,
activeFetchRequestCount: 1,
}),
})), container);
ok(container.querySelector(".subtree-fetching"),
"Expanded nodes with more children available, but no children " +
"loaded, should get a placeholder");
} catch(e) {
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
} finally {
SimpleTest.finish();
}
});
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,50 @@
<!DOCTYPE HTML>
<html>
<!--
Test that we show a link to load more children when some (but not all) are loaded.
-->
<head>
<meta charset="utf-8">
<title>Tree component test</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<!-- Give the container height so that the whole tree is rendered. -->
<div id="container" style="height: 900px;"></div>
<pre id="test">
<script src="head.js" type="application/javascript;version=1.8"></script>
<script type="application/javascript;version=1.8">
window.onload = Task.async(function* () {
try {
const container = document.getElementById("container");
const root = makeTestDominatorTreeNode({ moreChildrenAvailable: true }, [
makeTestDominatorTreeNode({}),
]);
ok(root.children);
ok(root.moreChildrenAvailable);
const expanded = new Set();
expanded.add(root.nodeId);
yield renderComponent(DominatorTreeComponent(immutableUpdate(TEST_DOMINATOR_TREE_PROPS, {
dominatorTree: immutableUpdate(TEST_DOMINATOR_TREE_PROPS.dominatorTree, {
expanded,
root,
}),
})), container);
ok(container.querySelector(".more-children"),
"Should get a link to load more children");
} catch(e) {
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
} finally {
SimpleTest.finish();
}
});
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,75 @@
<!DOCTYPE HTML>
<html>
<!--
Test that expanded DominatorTreeItems are correctly rendered and updated
-->
<head>
<meta charset="utf-8">
<title>Tree component test</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<!-- Give the container height so that the whole tree is rendered. -->
<div id="container" style="height: 900px;"></div>
<pre id="test">
<script src="head.js" type="application/javascript;version=1.8"></script>
<script type="application/javascript;version=1.8">
window.onload = Task.async(function* () {
try {
const container = document.getElementById("container");
// simple tree with one root and one child
const root = makeTestDominatorTreeNode(
{ moreChildrenAvailable: false },
[
makeTestDominatorTreeNode({ moreChildrenAvailable: false }),
]);
ok(root.children);
// root node is expanded
const expanded = new Set();
expanded.add(root.nodeId);
let component = yield renderComponent(
DominatorTreeComponent(immutableUpdate(
TEST_DOMINATOR_TREE_PROPS,
{
dominatorTree: immutableUpdate(
TEST_DOMINATOR_TREE_PROPS.dominatorTree,
{ expanded, root }
),
})), container);
ok(true, "Dominator tree rendered");
is(container.querySelectorAll(".tree-node").length, 2,
"Should display two rows");
is(container.querySelectorAll(".arrow.open").length, 1,
"Should display one expanded arrow");
yield setProps(component, immutableUpdate(
TEST_DOMINATOR_TREE_PROPS,
{
dominatorTree: immutableUpdate(
TEST_DOMINATOR_TREE_PROPS.dominatorTree,
{ expanded: new Set(), root }
)
}));
ok(true, "Dominator tree props updated to collapse all nodes");
is(container.querySelectorAll(".tree-node").length, 1,
"Should display only one row");
is(container.querySelectorAll(".arrow.open").length, 0,
"Should display no expanded arrow");
} catch(e) {
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
} finally {
SimpleTest.finish();
}
});
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,50 @@
<!DOCTYPE HTML>
<html>
<!--
Test that rendering a dominator tree error is handled correctly.
-->
<head>
<meta charset="utf-8">
<title>Tree component test</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<div id="container"></div>
<pre id="test">
<script src="head.js" type="application/javascript;version=1.8"></script>
<script type="application/javascript;version=1.8">
window.onload = Task.async(function* () {
try {
ok(React, "Should get React");
ok(Heap, "Should get Heap");
const errorMessage = "Something went wrong!";
const container = document.getElementById("container");
const props = immutableUpdate(TEST_HEAP_PROPS, {
view: { state: viewState.DOMINATOR_TREE, },
snapshot: immutableUpdate(TEST_HEAP_PROPS.snapshot, {
dominatorTree: {
error: new Error(errorMessage),
state: dominatorTreeState.ERROR,
}
})
});
yield renderComponent(Heap(props), container);
ok(container.querySelector(".error"), "Should render an error view");
ok(container.textContent.indexOf(errorMessage) !== -1,
"Should see our error message");
} catch(e) {
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
} finally {
SimpleTest.finish();
}
});
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,78 @@
<!DOCTYPE HTML>
<html>
<!--
Test that the currently selected view is rendered.
-->
<head>
<meta charset="utf-8">
<title>Tree component test</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<div id="container"></div>
<pre id="test">
<script src="head.js" type="application/javascript;version=1.8"></script>
<script type="application/javascript;version=1.8">
window.onload = Task.async(function* () {
try {
ok(React, "Should get React");
ok(Heap, "Should get Heap");
const errorMessage = "Something went wrong!";
const container = document.getElementById("container");
// Dominator tree view.
yield renderComponent(Heap(immutableUpdate(TEST_HEAP_PROPS, {
view: { state: viewState.DOMINATOR_TREE, },
})), container);
ok(container.querySelector(`[data-state=${dominatorTreeState.LOADED}]`),
"Should render the dominator tree.");
// Census view.
yield renderComponent(Heap(immutableUpdate(TEST_HEAP_PROPS, {
view: { state: viewState.CENSUS, },
})), container);
ok(container.querySelector(`[data-state=${censusState.SAVED}]`),
"Should render the census.");
// Diffing view.
yield renderComponent(Heap(immutableUpdate(TEST_HEAP_PROPS, {
view: { state: viewState.DIFFING, },
snapshot: null,
diffing: {
firstSnapshotId: null,
secondSnapshotId: null,
census: null,
error: null,
state: diffingState.SELECTING,
},
})), container);
ok(container.querySelector(`[data-state=${diffingState.SELECTING}]`),
"Should render the diffing.");
// Initial view.
yield renderComponent(Heap(immutableUpdate(TEST_HEAP_PROPS, {
snapshot: null,
diffing: null,
})), container);
ok(container.querySelector("[data-state=initial]"),
"With no snapshot, nor a diffing, should render initial prompt.");
} catch(e) {
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
} finally {
SimpleTest.finish();
}
});
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,74 @@
<!DOCTYPE HTML>
<html>
<!--
Test that we show a throbber while computing and fetching dominator trees,
but not in other dominator tree states.
-->
<head>
<meta charset="utf-8">
<title>Tree component test</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<div id="container"></div>
<pre id="test">
<script src="head.js" type="application/javascript;version=1.8"></script>
<script type="application/javascript;version=1.8">
window.onload = Task.async(function* () {
try {
const container = document.getElementById("container");
for (let state of [dominatorTreeState.COMPUTING, dominatorTreeState.FETCHING]) {
yield renderComponent(Heap(immutableUpdate(TEST_HEAP_PROPS, {
view: { state: viewState.DOMINATOR_TREE, },
snapshot: immutableUpdate(TEST_HEAP_PROPS.snapshot, {
dominatorTree: immutableUpdate(TEST_HEAP_PROPS.snapshot.dominatorTree, {
state,
root: null,
dominatorTreeId: state === dominatorTreeState.FETCHING ? 1 : null,
}),
}),
})), container);
ok(container.querySelector(".devtools-throbber"),
`Should show a throbber for state = ${state}`);
}
for (let state of [dominatorTreeState.LOADED, dominatorTreeState.INCREMENTAL_FETCHING]) {
yield renderComponent(Heap(immutableUpdate(TEST_HEAP_PROPS, {
view: { state: viewState.DOMINATOR_TREE, },
snapshot: immutableUpdate(TEST_HEAP_PROPS.snapshot, {
dominatorTree: immutableUpdate(TEST_HEAP_PROPS.snapshot.dominatorTree, {
state,
activeFetchRequestCount: state === dominatorTreeState.INCREMENTAL_FETCHING ? 1 : undefined,
}),
}),
})), container);
ok(!container.querySelector(".devtools-throbber"),
`Should not show a throbber for state = ${state}`);
}
yield renderComponent(Heap(immutableUpdate(TEST_HEAP_PROPS, {
view: { state: viewState.DOMINATOR_TREE, },
snapshot: immutableUpdate(TEST_HEAP_PROPS.snapshot, {
dominatorTree: {
state: dominatorTreeState.ERROR,
error: new Error("example error for testing"),
},
}),
})), container);
ok(!container.querySelector(".devtools-throbber"),
`Should not show a throbber for ERROR state`);
} catch(e) {
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
} finally {
SimpleTest.finish();
}
});
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,121 @@
<!DOCTYPE HTML>
<html>
<!--
Test that we show the "hey you're not recording allocation stacks" message at the appropriate times.
-->
<head>
<meta charset="utf-8">
<title>Tree component test</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<div id="container"></div>
<pre id="test">
<script src="head.js" type="application/javascript;version=1.8"></script>
<script type="application/javascript;version=1.8">
window.onload = Task.async(function* () {
try {
const container = document.getElementById("container");
yield renderComponent(Heap(immutableUpdate(TEST_HEAP_PROPS, {
snapshot: immutableUpdate(TEST_HEAP_PROPS.snapshot, {
census: immutableUpdate(TEST_HEAP_PROPS.snapshot.census, {
report: {
bytes: 1,
totalBytes: 1,
count: 1,
totalCount: 1,
id: 1,
parent: undefined,
children: [
{
name: "noStack",
bytes: 1,
totalBytes: 1,
count: 1,
totalCount: 1,
children: undefined,
id: 3,
parent: 1,
}
]
},
display: censusDisplays.allocationStack,
}),
}),
})), container);
ok(container.querySelector(".no-allocation-stacks"),
"When there are no allocation stacks, we should show the message");
yield renderComponent(Heap(immutableUpdate(TEST_HEAP_PROPS, {
snapshot: immutableUpdate(TEST_HEAP_PROPS.snapshot, {
census: immutableUpdate(TEST_HEAP_PROPS.snapshot.census, {
report: {
bytes: 1,
totalBytes: 1,
count: 1,
totalCount: 1,
id: 1,
parent: undefined,
children: [
{
name: Cu.getJSTestingFunctions().saveStack(),
bytes: 1,
totalBytes: 1,
count: 1,
totalCount: 1,
children: undefined,
id: 2,
parent: 1,
},
{
name: "noStack",
bytes: 1,
totalBytes: 1,
count: 1,
totalCount: 1,
children: undefined,
id: 3,
parent: 1,
}
]
},
display: censusDisplays.allocationStack,
}),
}),
})), container);
ok(!container.querySelector(".no-allocation-stacks"),
"When there are allocation stacks, we should not show the message");
yield renderComponent(Heap(immutableUpdate(TEST_HEAP_PROPS, {
snapshot: immutableUpdate(TEST_HEAP_PROPS.snapshot, {
census: immutableUpdate(TEST_HEAP_PROPS.snapshot.census, {
report: {
bytes: 1,
totalBytes: 1,
count: 1,
totalCount: 1,
id: 1,
parent: undefined,
children: undefined
},
display: censusDisplays.allocationStack,
}),
}),
})), container);
ok(!container.querySelector(".no-allocation-stacks"),
"When there isn't census data, we should not show the message");
} catch(e) {
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
} finally {
SimpleTest.finish();
}
});
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,132 @@
<!DOCTYPE HTML>
<html>
<!--
Test that we show a message when the census results are empty.
-->
<head>
<meta charset="utf-8">
<title>Tree component test</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<div id="container"></div>
<pre id="test">
<script src="head.js" type="application/javascript;version=1.8"></script>
<script type="application/javascript;version=1.8">
window.onload = Task.async(function* () {
try {
const container = document.getElementById("container");
yield renderComponent(Heap(immutableUpdate(TEST_HEAP_PROPS, {
snapshot: immutableUpdate(TEST_HEAP_PROPS.snapshot, {
census: immutableUpdate(TEST_HEAP_PROPS.snapshot.census, {
report: {
bytes: 1,
totalBytes: 1,
count: 1,
totalCount: 1,
id: 1,
parent: undefined,
children: [
{
name: Cu.getJSTestingFunctions().saveStack(),
bytes: 1,
totalBytes: 1,
count: 1,
totalCount: 1,
children: undefined,
id: 2,
parent: 1,
},
{
name: "noStack",
bytes: 1,
totalBytes: 1,
count: 1,
totalCount: 1,
children: undefined,
id: 3,
parent: 1,
}
]
},
display: censusDisplays.allocationStack,
}),
}),
})), container);
ok(!container.querySelector(".empty"),
"When the report is not empty, we should not show the empty message");
// Empty Census Report
const emptyCensus = {
report: {
bytes: 0,
totalBytes: 0,
count: 0,
totalCount: 0,
id: 1,
parent: undefined,
children: undefined,
},
parentMap: Object.create(null),
display: censusDisplays.allocationStack,
filter: null,
expanded: new Immutable.Set(),
focused: null,
state: censusState.SAVED,
};
yield renderComponent(Heap(immutableUpdate(TEST_HEAP_PROPS, {
snapshot: immutableUpdate(TEST_HEAP_PROPS.snapshot, {
census: immutableUpdate(TEST_HEAP_PROPS.snapshot.census, emptyCensus),
}),
})), container);
ok(container.querySelector(".empty"),
"When the report is empty in census view, we show the empty message");
ok(container.textContent.indexOf(L10N.getStr("heapview.empty")) >= 0);
// Empty Diffing Report
yield renderComponent(Heap(immutableUpdate(TEST_HEAP_PROPS, {
view: { state: viewState.DIFFING, },
diffing: {
firstSnapshotId: 1,
secondSnapshotId: 2,
census: emptyCensus,
state: diffingState.TOOK_DIFF,
},
snapshot: null,
})), container);
ok(container.querySelector(".empty"),
"When the report is empty in diffing view, the empty message is shown");
ok(container.textContent.indexOf(L10N.getStr("heapview.no-difference")) >= 0);
// Empty Filtered Census
yield renderComponent(Heap(immutableUpdate(TEST_HEAP_PROPS, {
snapshot: immutableUpdate(TEST_HEAP_PROPS.snapshot, {
census: immutableUpdate(TEST_HEAP_PROPS.snapshot.census, immutableUpdate(emptyCensus, {
filter: "zzzz"
})),
}),
})), container);
ok(container.querySelector(".empty"),
"When the report is empty in census view w/ filter, we show the empty message");
ok(container.textContent.indexOf(L10N.getStr("heapview.none-match")) >= 0);
} catch(e) {
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
} finally {
SimpleTest.finish();
}
});
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,74 @@
<!DOCTYPE HTML>
<html>
<!--
Test to verify the delete button calls the onDelete handler for an item
-->
<head>
<meta charset="utf-8">
<title>Tree component test</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<div id="container"></div>
<pre id="test">
<script src="head.js" type="application/javascript;version=1.8"></script>
<script type="application/javascript;version=1.8">
window.onload = Task.async(function* () {
try {
const container = document.getElementById("container");
let deletedSnapshots = [];
let snapshots = [ TEST_SNAPSHOT, TEST_SNAPSHOT, TEST_SNAPSHOT ]
.map((snapshot, index) => immutableUpdate(snapshot, {
index: snapshot.index + index
}));
yield renderComponent(
List({
itemComponent: SnapshotListItem,
onClick: noop,
onDelete: (item) => deletedSnapshots.push(item),
items: snapshots
}),
container
);
let deleteButtons = container.querySelectorAll('.delete');
is(container.querySelectorAll('.snapshot-list-item').length, 3,
"There are 3 list items\n");
is(deletedSnapshots.length, 0,
"Not snapshots have been deleted\n");
deleteButtons[1].click();
is(deletedSnapshots.length, 1, "One snapshot was deleted\n");
is(deletedSnapshots[0], snapshots[1],
"Deleted snapshot was added to the deleted list\n");
deleteButtons[0].click();
is(deletedSnapshots.length, 2, "Two snapshots were deleted\n");
is(deletedSnapshots[1], snapshots[0],
"Deleted snapshot was added to the deleted list\n");
deleteButtons[2].click();
is(deletedSnapshots.length, 3, "Three snapshots were deleted\n");
is(deletedSnapshots[2], snapshots[2],
"Deleted snapshot was added to the deleted list\n");
} catch(e) {
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
} finally {
SimpleTest.finish();
}
});
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,112 @@
<!DOCTYPE HTML>
<html>
<!--
Test that the ShortestPaths component properly renders a graph of the merged shortest paths.
-->
<head>
<meta charset="utf-8">
<title>Tree component test</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
<script type="application/javascript"
src="chrome://devtools/content/shared/vendor/d3.js">
</script>
<script type="application/javascript"
src="chrome://devtools/content/shared/vendor/dagre-d3.js">
</script>
</head>
<body>
<!-- Give the container height so that the whole tree is rendered. -->
<div id="container" style="height: 900px;"></div>
<pre id="test">
<script src="head.js" type="application/javascript;version=1.8"></script>
<script type="application/javascript;version=1.8">
window.onload = Task.async(function* () {
try {
const container = document.getElementById("container");
yield renderComponent(ShortestPaths(TEST_SHORTEST_PATHS_PROPS), container);
let found1 = false;
let found2 = false;
let found3 = false;
let found1to2 = false;
let found1to3 = false;
let found2to3 = false;
const tspans = [...container.querySelectorAll("tspan")];
for (let el of tspans) {
const text = el.textContent.trim();
dumpn("tspan's text = " + text);
switch (text) {
// Nodes
case "other SomeType @ 0x1": {
ok(!found1, "Should only find node 1 once");
found1 = true;
break;
}
case "other SomeType @ 0x2": {
ok(!found2, "Should only find node 2 once");
found2 = true;
break;
}
case "other SomeType @ 0x3": {
ok(!found3, "Should only find node 3 once");
found3 = true;
break;
}
// Edges
case "1->2": {
ok(!found1to2, "Should only find edge 1->2 once");
found1to2 = true;
break;
}
case "1->3": {
ok(!found1to3, "Should only find edge 1->3 once");
found1to3 = true;
break;
}
case "2->3": {
ok(!found2to3, "Should only find edge 2->3 once");
found2to3 = true;
break;
}
// Unexpected
default: {
ok(false, `Unexpected tspan: ${text}`);
break;
}
}
}
ok(found1, "Should have rendered node 1");
ok(found2, "Should have rendered node 2");
ok(found3, "Should have rendered node 3");
ok(found1to2, "Should have rendered edge 1->2");
ok(found1to3, "Should have rendered edge 1->3");
ok(found2to3, "Should have rendered edge 2->3");
} catch(e) {
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
} finally {
SimpleTest.finish();
}
});
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,45 @@
<!DOCTYPE HTML>
<html>
<!--
Test that the ShortestPaths component renders a suggestion to select a node when there is no graph.
-->
<head>
<meta charset="utf-8">
<title>Tree component test</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
<script type="application/javascript"
src="chrome://devtools/content/shared/vendor/d3.js">
</script>
<script type="application/javascript"
src="chrome://devtools/content/shared/vendor/dagre-d3.js">
</script>
</head>
<body>
<!-- Give the container height so that the whole tree is rendered. -->
<div id="container" style="height: 900px;"></div>
<pre id="test">
<script src="head.js" type="application/javascript;version=1.8"></script>
<script type="application/javascript;version=1.8">
window.onload = Task.async(function* () {
try {
const container = document.getElementById("container");
yield renderComponent(ShortestPaths(immutableUpdate(TEST_SHORTEST_PATHS_PROPS,
{ graph: null })),
container);
ok(container.textContent.indexOf(L10N.getStr("shortest-paths.select-node")) !== -1,
"The node selection prompt is displayed");
} catch(e) {
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
} finally {
SimpleTest.finish();
}
});
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,53 @@
<!DOCTYPE HTML>
<html>
<!--
Test to verify that the delete button only shows up for a snapshot when it has a
path.
-->
<head>
<meta charset="utf-8">
<title>Tree component test</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<div id="container"></div>
<pre id="test">
<script src="head.js" type="application/javascript;version=1.8"></script>
<script type="application/javascript;version=1.8">
window.onload = Task.async(function* () {
try {
const container = document.getElementById("container");
yield renderComponent(
SnapshotListItem(TEST_SNAPSHOT_LIST_ITEM_PROPS),
container
);
ok(container.querySelector('.delete'),
"Should have delete button when there is a path");
const pathlessProps = immutableUpdate(
TEST_SNAPSHOT_LIST_ITEM_PROPS,
{item: immutableUpdate(TEST_SNAPSHOT, {path: null})}
);
yield renderComponent(
SnapshotListItem(pathlessProps),
container
);
ok(!container.querySelector('.delete'),
"No delete button should be found if there is no path\n");
} catch(e) {
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
} finally {
SimpleTest.finish();
}
});
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,47 @@
<!DOCTYPE HTML>
<html>
<!--
Test that the Toolbar component shows the view switcher only at the appropriate times.
-->
<head>
<meta charset="utf-8">
<title>Tree component test</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<div id="container"></div>
<pre id="test">
<script src="head.js" type="application/javascript;version=1.8"></script>
<script type="application/javascript;version=1.8">
window.onload = Task.async(function* () {
try {
const container = document.getElementById("container");
// Census and dominator tree views.
for (let view of [viewState.CENSUS, viewState.DOMINATOR_TREE]) {
yield renderComponent(Toolbar(immutableUpdate(TEST_TOOLBAR_PROPS, {
view: { state: view },
})), container);
ok(container.querySelector("#select-view"),
`The view selector is shown in view = ${view}`);
}
yield renderComponent(Toolbar(immutableUpdate(TEST_TOOLBAR_PROPS, {
view: { state: viewState.DIFFING, },
})), container);
ok(!container.querySelector("#select-view"),
"The view selector is NOT shown in the DIFFING view");
} catch(e) {
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
} finally {
SimpleTest.finish();
}
});
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,44 @@
<!DOCTYPE HTML>
<html>
<!--
Test that the Tree Map correctly renders onto 2 managed canvases.
-->
<head>
<meta charset="utf-8">
<title>Tree component test</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
<script type="application/javascript"
src="chrome://devtools/content/shared/vendor/d3.js">
</script>
</head>
<body>
<!-- Give the container height so that the whole tree is rendered. -->
<div id="container" style="height: 900px;"></div>
<pre id="test">
<script src="head.js" type="application/javascript;version=1.8"></script>
<script type="application/javascript;version=1.8">
window.onload = Task.async(function*() {
try {
const container = document.getElementById("container");
yield renderComponent(TreeMap(TEST_TREE_MAP_PROPS), container);
let treeMapContainer = container.querySelector(".tree-map-container");
ok(treeMapContainer, "Component creates a container");
let canvases = treeMapContainer.querySelectorAll("canvas");
is(canvases.length, 2, "Creates 2 canvases");
} catch(e) {
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
} finally {
SimpleTest.finish();
}
});
</script>
</pre>
</body>
</html>