blob: 6d2990f742ed7432b9fe1c718171f9726d2473a0 [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright (c) 2015 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<link rel='import' href='/tracing/base/iteration_helpers.html'>
<link rel='import'
href='/tracing/ui/analysis/memory_dump_heap_details_pane.html'>
<link rel='import'
href='/tracing/ui/analysis/memory_dump_sub_view_test_utils.html'>
<link rel='import' href='/tracing/ui/analysis/memory_dump_sub_view_util.html'>
<link rel='import' href='/tracing/core/test_utils.html'>
<link rel='import' href='/tracing/model/heap_dump.html'>
<script>
'use strict';
tr.b.unittest.testSuite(function() {
var HeapDump = tr.model.HeapDump;
var AggregationMode = tr.ui.analysis.MemoryColumn.AggregationMode;
var addGlobalMemoryDump = tr.ui.analysis.addGlobalMemoryDump;
var addProcessMemoryDump = tr.ui.analysis.addProcessMemoryDump;
var checkSizeAttributes = tr.ui.analysis.checkSizeAttributes;
var isElementDisplayed = tr.ui.analysis.isElementDisplayed;
function createHeapDumps() {
var model = new tr.Model();
var process = model.getOrCreateProcess(1);
function heapTrace(/* topStackFrame, ..., leafStackFrame */) {
var titles =
Array.prototype.concat.apply([undefined /* root */], arguments);
return tr.c.TestUtils.newStackTrace(model, titles);
}
// First timestamp.
var gmd1 = addGlobalMemoryDump(model, -10);
var pmd1 = addProcessMemoryDump(gmd1, process, -11);
var hd1 = new HeapDump(pmd1, 'partition_alloc');
hd1.addEntry(undefined /* sum over all traces */, 4194304 /* 4 MiB */);
hd1.addEntry(heapTrace('MessageLoop::RunTask', 'FunctionCall'),
102400 /* 100 KiB */);
hd1.addEntry(heapTrace('MessageLoop::RunTask', 'FunctionCall',
'V8.Execute'), 1048576 /* 1 MiB */);
hd1.addEntry(heapTrace('MessageLoop::RunTask', 'FunctionCall',
'FunctionCall'), 204800 /* 200 KiB */);
hd1.addEntry(heapTrace('MessageLoop::RunTask', 'V8.Execute', 'FunctionCall',
'V8.Execute'), 2097152 /* 2 MiB */);
hd1.addEntry(heapTrace('MessageLoop::RunTask', 'V8.Execute',
'FunctionCall'), 307200 /* 300 KiB */);
// Second timestamp.
var gmd2 = addGlobalMemoryDump(model, 10);
var pmd2 = addProcessMemoryDump(gmd2, process, 11);
var hd2 = new HeapDump(pmd2, 'partition_alloc');
hd2.addEntry(undefined /* sum over all traces */,
3145728 /* 3 MiB, lower than the actual sum (should be ignored) */);
hd2.addEntry(heapTrace(/* empty trace */),
131072 /* 128 KiB */);
hd2.addEntry(heapTrace('MessageLoop::RunTask', 'FunctionCall'),
393216 /* 384 KiB */);
hd2.addEntry(heapTrace('MessageLoop::RunTask', 'FunctionCall',
'V8.Execute'), 1572864 /* 1.5 MiB */);
hd2.addEntry(heapTrace('MessageLoop::RunTask', 'V8.Execute', 'FunctionCall',
'V8.Execute'), 2621440 /* 2.5 MiB */);
hd2.addEntry(heapTrace('MessageLoop::RunTask', 'FunctionCall',
'FunctionCall', 'FunctionCall'), 204800 /* 200 KiB */);
return [hd1, hd2];
}
function checkTableAndViewModeSelectorDislayed(viewEl, displayed) {
assert.strictEqual(isElementDisplayed(viewEl.$.info_text), !displayed);
assert.strictEqual(isElementDisplayed(viewEl.$.table), displayed);
assert.strictEqual(
isElementDisplayed(viewEl.$.view_mode_container), displayed);
}
function checkColumns(columns, expectedAggregationMode) {
var EXPECTED_COLUMN_NAMES = [
'Stack frame',
'Total size',
'Self size'
];
// First column doesn't change value over time (no aggregation).
var VARIABLE_CELLS_START_INDEX = 1;
// Check column names.
assert.lengthOf(columns, EXPECTED_COLUMN_NAMES.length);
for (var i = 0; i < EXPECTED_COLUMN_NAMES.length; i++)
assert.equal(columns[i].title, EXPECTED_COLUMN_NAMES[i]);
// Check aggregation modes.
for (var i = 0; i < EXPECTED_COLUMN_NAMES.length; i++) {
assert.strictEqual(columns[i].aggregationMode,
i < VARIABLE_CELLS_START_INDEX ? undefined : expectedAggregationMode);
}
}
function checkRow(columns, row, expectedTitle, expectedTotalSizes,
expectedSelfSizes, expectedDefinedValues) {
var formattedTitle = columns[0].formatTitle(row);
assert.equal(formattedTitle, expectedTitle);
checkSizeAttributes(row, columns[1], expectedTotalSizes);
checkSizeAttributes(row, columns[2], expectedSelfSizes);
if (expectedDefinedValues)
assert.deepEqual(tr.b.asArray(row.defined), expectedDefinedValues);
else
assert.isUndefined(row.defined);
}
function checkRows(columns, rows, expectedStructure) {
if (expectedStructure === undefined) {
assert.isUndefined(rows);
return;
}
if (typeof expectedStructure === 'number') {
assert.lengthOf(rows, expectedStructure);
return;
}
assert.lengthOf(rows, expectedStructure.length);
for (var i = 0; i < expectedStructure.length; i++) {
var row = rows[i];
var expectedRowStructure = expectedStructure[i];
checkRow(columns, row, expectedRowStructure.title,
expectedRowStructure.total, expectedRowStructure.self,
expectedRowStructure.defined);
checkRows(columns, row.subRows, expectedRowStructure.children);
}
}
function checkTable(viewEl, expectedAggregationMode, expectedStructure) {
checkTableAndViewModeSelectorDislayed(viewEl, true);
var table = viewEl.$.table;
var columns = table.tableColumns;
var rows = table.tableRows;
checkColumns(columns, expectedAggregationMode);
checkRows(columns, rows, expectedStructure);
}
function changeView(viewEl, bottomUpView) {
tr.b.findDeepElementMatching(viewEl, 'select').selectedValue = bottomUpView;
viewEl.rebuild();
}
test('instantiate_empty', function() {
tr.ui.analysis.createAndCheckEmptyPanes(this,
'tr-ui-a-memory-dump-heap-details-pane', 'heapDumps',
function(viewEl) {
// Check that the info text is shown.
checkTableAndViewModeSelectorDislayed(viewEl, false);
});
});
test('instantiate_noEntries', function() {
var heapDumps = createHeapDumps().slice(0, 1);
heapDumps[0].entries = [];
var viewEl = tr.ui.analysis.createTestPane(
'tr-ui-a-memory-dump-heap-details-pane');
viewEl.heapDumps = heapDumps;
viewEl.rebuild();
this.addHTMLOutput(viewEl);
// Top-down view.
checkTable(viewEl, undefined /* no aggregation */, [
{
title: 'partition_alloc',
total: [0],
self: [0],
defined: [true]
}
]);
changeView(viewEl, true /* bottom-up view */);
// Bottom-up view.
checkTable(viewEl, undefined /* no aggregation */, [
{
title: 'partition_alloc',
total: [0],
self: [0],
defined: [true]
}
]);
changeView(viewEl, false /* top-down view */);
});
test('instantiate_single', function() {
var heapDumps = createHeapDumps().slice(0, 1);
var viewEl = tr.ui.analysis.createTestPane(
'tr-ui-a-memory-dump-heap-details-pane');
viewEl.heapDumps = heapDumps;
viewEl.rebuild();
this.addHTMLOutput(viewEl);
// Top-down view (default).
checkTable(viewEl, undefined /* no aggregation */, [
{
title: 'partition_alloc',
total: [4194304],
self: [0],
defined: [true],
children: [
{
title: 'MessageLoop::RunTask',
total: [3760128],
self: [0],
defined: [true],
children: [
{
title: 'FunctionCall',
total: [1355776],
self: [102400],
defined: [true],
children: [
{
title: 'V8.Execute',
total: [1048576],
self: [1048576],
defined: [true]
},
{
title: 'FunctionCall',
total: [204800],
self: [204800],
defined: [true]
}
]
},
{
title: 'V8.Execute',
total: [2404352],
self: [0],
defined: [true],
children: [
{
title: 'FunctionCall',
total: [2404352],
self: [307200],
defined: [true],
children: [
{
title: 'V8.Execute',
total: [2097152],
self: [2097152],
defined: [true]
}
]
}
]
}
]
},
{
title: '<unspecified>',
total: [434176],
self: [434176],
defined: [true]
}
]
}
]);
changeView(viewEl, true /* bottom-up view */);
checkTable(viewEl, undefined /* no aggregation */, [
{
title: 'partition_alloc',
total: [4194304],
self: [0],
defined: [true],
children: [
{
title: 'MessageLoop::RunTask',
total: [3760128],
self: [0],
defined: [true]
},
{
title: 'FunctionCall',
total: [3760128],
self: [614400],
defined: [true],
children: [
{
title: 'MessageLoop::RunTask',
total: [1355776],
self: [102400],
defined: [true]
},
{
title: 'FunctionCall',
total: [204800],
self: [204800],
defined: [true],
children: [
{
title: 'MessageLoop::RunTask',
total: [204800],
self: [204800],
defined: [true]
}
]
},
{
title: 'V8.Execute',
total: [2404352],
self: [307200],
defined: [true],
children: [
{
title: 'MessageLoop::RunTask',
total: [2404352],
self: [307200],
defined: [true]
}
]
}
]
},
{
title: 'V8.Execute',
total: [3452928],
self: [3145728],
defined: [true],
children: [
{
title: 'FunctionCall',
total: [3145728],
self: [3145728],
defined: [true],
children: [
{
title: 'MessageLoop::RunTask',
total: [1048576],
self: [1048576],
defined: [true]
},
{
title: 'V8.Execute',
total: [2097152],
self: [2097152],
defined: [true],
children: [
{
title: 'MessageLoop::RunTask',
total: [2097152],
self: [2097152],
defined: [true]
}
]
}
]
},
{
title: 'MessageLoop::RunTask',
total: [2404352],
self: [0],
defined: [true]
}
]
},
{
title: '<unspecified>',
total: [434176],
self: [434176],
defined: [true]
}
]
}
]);
});
test('instantiate_multipleDiff', function() {
var heapDumps = createHeapDumps();
var viewEl = tr.ui.analysis.createTestPane(
'tr-ui-a-memory-dump-heap-details-pane');
viewEl.heapDumps = heapDumps;
viewEl.aggregationMode = AggregationMode.DIFF;
viewEl.rebuild();
this.addHTMLOutput(viewEl);
changeView(viewEl, true /* bottom-up view */);
checkTable(viewEl, AggregationMode.DIFF, [
{
title: 'partition_alloc',
total: [4194304, 4923392],
self: [0, 131072],
defined: [true, true],
children: [
{
title: 'MessageLoop::RunTask',
total: [3760128, 4792320],
self: [0, 0],
defined: [true, true]
},
{
title: 'FunctionCall',
total: [3760128, 4792320],
self: [614400, 598016],
defined: [true, true],
children: [
{
title: 'MessageLoop::RunTask',
total: [1355776, 2170880],
self: [102400, 393216],
defined: [true, true]
},
{
title: 'FunctionCall',
total: [204800, 204800],
self: [204800, 204800],
defined: [true, true],
children: [
{
title: 'MessageLoop::RunTask',
total: [204800, 204800],
self: [204800, 0],
defined: [true, true]
},
{
title: 'FunctionCall',
total: [undefined, 204800],
self: [undefined, 204800],
defined: [undefined, true],
children: [
{
title: 'MessageLoop::RunTask',
total: [undefined, 204800],
self: [undefined, 204800],
defined: [undefined, true]
}
]
}
]
},
{
title: 'V8.Execute',
total: [2404352, 2621440],
self: [307200, 0],
defined: [true, true],
children: [
{
title: 'MessageLoop::RunTask',
total: [2404352, 2621440],
self: [307200, 0],
defined: [true, true]
}
]
}
]
},
{
title: 'V8.Execute',
total: [3452928, 4194304],
self: [3145728, 4194304],
defined: [true, true],
children: [
{
title: 'FunctionCall',
total: [3145728, 4194304],
self: [3145728, 4194304],
defined: [true, true],
children: [
{
title: 'MessageLoop::RunTask',
total: [1048576, 1572864],
self: [1048576, 1572864],
defined: [true, true]
},
{
title: 'V8.Execute',
total: [2097152, 2621440],
self: [2097152, 2621440],
defined: [true, true],
children: [
{
title: 'MessageLoop::RunTask',
total: [2097152, 2621440],
self: [2097152, 2621440],
defined: [true, true]
}
]
}
]
},
{
title: 'MessageLoop::RunTask',
total: [2404352, 2621440],
self: [0, 0],
defined: [true, true]
}
]
},
{
title: '<unspecified>',
total: [434176, undefined],
self: [434176, undefined],
defined: [true, undefined]
}
]
}
]);
changeView(viewEl, false /* top-down view */);
checkTable(viewEl, AggregationMode.DIFF, [
{
title: 'partition_alloc',
total: [4194304, 4923392],
self: [0, 131072],
defined: [true, true],
children: [
{
title: 'MessageLoop::RunTask',
total: [3760128, 4792320],
self: [0, 0],
defined: [true, true],
children: [
{
title: 'FunctionCall',
total: [1355776, 2170880],
self: [102400, 393216],
defined: [true, true],
children: [
{
title: 'V8.Execute',
total: [1048576, 1572864],
self: [1048576, 1572864],
defined: [true, true]
},
{
title: 'FunctionCall',
total: [204800, 204800],
self: [204800, 0],
defined: [true, true],
children: [
{
title: 'FunctionCall',
total: [undefined, 204800],
self: [undefined, 204800],
defined: [undefined, true]
}
]
}
]
},
{
title: 'V8.Execute',
total: [2404352, 2621440],
self: [0, 0],
defined: [true, true],
children: [
{
title: 'FunctionCall',
total: [2404352, 2621440],
self: [307200, 0],
defined: [true, true],
children: [
{
title: 'V8.Execute',
total: [2097152, 2621440],
self: [2097152, 2621440],
defined: [true, true]
}
]
}
]
}
]
},
{
title: '<unspecified>',
total: [434176, undefined],
self: [434176, undefined],
defined: [true, undefined]
}
]
}
]);
});
test('instantiate_multipleMax', function() {
var heapDumps = createHeapDumps();
var viewEl = tr.ui.analysis.createTestPane(
'tr-ui-a-memory-dump-heap-details-pane');
viewEl.heapDumps = heapDumps;
viewEl.aggregationMode = AggregationMode.MAX;
viewEl.rebuild();
this.addHTMLOutput(viewEl);
changeView(viewEl, true /* bottom-up view */);
checkTable(viewEl, AggregationMode.MAX, [
{
title: 'partition_alloc',
total: [4194304, 4923392],
self: [0, 131072],
defined: [true, true],
children: 4 // No need to check the full structure again.
}
]);
});
test('instantiate_multipleWithUndefined', function() {
var heapDumps = createHeapDumps();
heapDumps.splice(1, 0, undefined);
var viewEl = tr.ui.analysis.createTestPane(
'tr-ui-a-memory-dump-heap-details-pane');
viewEl.heapDumps = heapDumps;
viewEl.aggregationMode = AggregationMode.DIFF;
viewEl.rebuild();
this.addHTMLOutput(viewEl);
// Top-down view (default).
checkTable(viewEl, AggregationMode.DIFF, [
{
title: 'partition_alloc',
total: [4194304, undefined, 4923392],
self: [0, undefined, 131072],
defined: [true, false, true],
children: 2 // No need to check the full structure again.
}
]);
});
});
</script>