blob: f4bfbfb68f3d2e5756a6a5fd462bef14d27360af [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/core/test_utils.html">
<link rel="import" href="/tracing/model/heap_dump.html">
<link rel="import" href="/tracing/model/memory_allocator_dump.html">
<link rel="import" href="/tracing/model/memory_dump_test_utils.html">
<link rel="import" href="/tracing/ui/analysis/memory_dump_overview_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/ui/brushing_state_controller.html">
<script>
'use strict';
tr.b.unittest.testSuite(function() {
var ScalarNumeric = tr.v.ScalarNumeric;
var sizeInBytes_smallerIsBetter =
tr.b.Unit.byName.sizeInBytes_smallerIsBetter;
var MemoryAllocatorDump = tr.model.MemoryAllocatorDump;
var HeapDump = tr.model.HeapDump;
var AggregationMode = tr.ui.analysis.MemoryColumn.AggregationMode;
var checkSizeNumericFields = tr.ui.analysis.checkSizeNumericFields;
var checkColor = tr.ui.analysis.checkColor;
var checkColumns = tr.ui.analysis.checkColumns;
var checkColumnInfosAndColor = tr.ui.analysis.checkColumnInfosAndColor;
var convertToProcessMemoryDumps = tr.ui.analysis.convertToProcessMemoryDumps;
var extractProcessMemoryDumps = tr.ui.analysis.extractProcessMemoryDumps;
var extractVmRegions = tr.ui.analysis.extractVmRegions;
var extractMemoryAllocatorDumps = tr.ui.analysis.extractMemoryAllocatorDumps;
var isElementDisplayed = tr.ui.analysis.isElementDisplayed;
var addProcessMemoryDump = tr.model.MemoryDumpTestUtils.addProcessMemoryDump;
var addGlobalMemoryDump = tr.model.MemoryDumpTestUtils.addGlobalMemoryDump;
var ProcessNameColumn = tr.ui.analysis.ProcessNameColumn;
var UsedMemoryColumn = tr.ui.analysis.UsedMemoryColumn;
var PeakMemoryColumn = tr.ui.analysis.PeakMemoryColumn;
var ByteStatColumn = tr.ui.analysis.ByteStatColumn;
var AllocatorColumn = tr.ui.analysis.AllocatorColumn;
var TracingColumn = tr.ui.analysis.TracingColumn;
function spanMatcher(expectedTitle) {
return function(actualTitle) {
assert.instanceOf(actualTitle, HTMLElement);
assert.strictEqual(actualTitle.tagName, 'SPAN');
assert.strictEqual(Polymer.dom(actualTitle).textContent, expectedTitle);
};
}
function colorLegendMatcher(expectedTitle) {
return function(actualTitle) {
assert.instanceOf(actualTitle, HTMLElement);
assert.strictEqual(actualTitle.tagName, 'TR-UI-B-COLOR-LEGEND');
assert.strictEqual(actualTitle.label, expectedTitle);
};
}
var EXPECTED_COLUMNS = [
{ title: 'Process', type: ProcessNameColumn, noAggregation: true },
{ title: spanMatcher('Total resident'), type: UsedMemoryColumn },
{ title: spanMatcher('Peak total resident'), type: PeakMemoryColumn },
{ title: spanMatcher('PSS'), type: ByteStatColumn },
{ title: spanMatcher('Private dirty'), type: ByteStatColumn },
{ title: spanMatcher('Swapped'), type: ByteStatColumn },
{ title: spanMatcher('Private'), type: UsedMemoryColumn },
{ title: colorLegendMatcher('blink'), type: AllocatorColumn },
{ title: colorLegendMatcher('gpu'), type: AllocatorColumn },
{ title: colorLegendMatcher('malloc'), type: AllocatorColumn },
{ title: colorLegendMatcher('oilpan'), type: AllocatorColumn },
{ title: colorLegendMatcher('v8'), type: AllocatorColumn },
{ title: spanMatcher('tracing'), type: TracingColumn }
];
function checkRow(columns, row, expectedTitle, expectedSizes,
expectedContexts) {
// Check title.
var formattedTitle = columns[0].formatTitle(row);
if (typeof expectedTitle === 'function')
expectedTitle(formattedTitle);
else
assert.strictEqual(formattedTitle, expectedTitle);
// Check all sizes. The first assert below is a test sanity check.
assert.lengthOf(expectedSizes, columns.length - 1 /* all except title */);
for (var i = 0; i < expectedSizes.length; i++)
checkSizeNumericFields(row, columns[i + 1], expectedSizes[i]);
// There should be no row nesting on the overview pane.
assert.isUndefined(row.subRows);
if (expectedContexts)
assert.deepEqual(tr.b.asArray(row.contexts), expectedContexts);
else
assert.isUndefined(row.contexts);
}
function checkRows(columns, actualRows, expectedRows) {
if (expectedRows === undefined) {
assert.isUndefined(actualRows);
return;
}
assert.lengthOf(actualRows, expectedRows.length);
for (var i = 0; i < expectedRows.length; i++) {
var actualRow = actualRows[i];
var expectedRow = expectedRows[i];
checkRow(columns, actualRow, expectedRow.title, expectedRow.sizes,
expectedRow.contexts);
}
}
function checkSpanWithColor(span, expectedText, expectedColorReservedName) {
assert.strictEqual(span.tagName, 'SPAN');
assert.strictEqual(Polymer.dom(span).textContent, expectedText);
checkColor(span.style.color, expectedColorReservedName);
}
function checkColorLegend(legend, expectedLabel) {
assert.strictEqual(legend.tagName, 'TR-UI-B-COLOR-LEGEND');
assert.strictEqual(legend.label, expectedLabel);
}
function createAndCheckMemoryDumpOverviewPane(
test, processMemoryDumps, expectedRows, expectedFooterRows,
aggregationMode) {
var viewEl =
tr.ui.analysis.createTestPane('tr-ui-a-memory-dump-overview-pane');
viewEl.processMemoryDumps = processMemoryDumps;
viewEl.aggregationMode = aggregationMode;
viewEl.rebuild();
test.addHTMLOutput(viewEl);
// Check that the table is shown.
assert.isTrue(isElementDisplayed(viewEl.$.table));
assert.isFalse(isElementDisplayed(viewEl.$.info_text));
assert.isUndefined(viewEl.createChildPane());
var table = viewEl.$.table;
var columns = table.tableColumns;
checkColumns(columns, EXPECTED_COLUMNS, aggregationMode);
var rows = table.tableRows;
checkRows(columns, table.tableRows, expectedRows);
checkRows(columns, table.footerRows, expectedFooterRows);
}
var FIELD = 1 << 0;
var DUMP = 1 << 1;
function checkOverviewColumnInfosAndColor(column, fieldAndDumpMask,
dumpCreatedCallback, expectedInfos, expectedColorReservedName) {
var fields = fieldAndDumpMask.map(function(mask, index) {
return mask & FIELD ?
new ScalarNumeric(sizeInBytes_smallerIsBetter, 1024 + 32 * index) :
undefined;
});
var contexts;
if (dumpCreatedCallback === undefined) {
contexts = undefined;
} else {
tr.c.TestUtils.newModel(function(model) {
var process = model.getOrCreateProcess(1);
fieldAndDumpMask.forEach(function(mask, i) {
var timestamp = 10 + i;
var gmd = addGlobalMemoryDump(model, {ts: timestamp});
if (mask & DUMP) {
var pmd = addProcessMemoryDump(gmd, process, {ts: timestamp});
dumpCreatedCallback(pmd, mask);
}
});
contexts = model.globalMemoryDumps.map(function(gmd) {
return gmd.processMemoryDumps[1];
});
});
}
checkColumnInfosAndColor(
column, fields, contexts, expectedInfos, expectedColorReservedName);
}
test('instantiate_empty', function() {
tr.ui.analysis.createAndCheckEmptyPanes(this,
'tr-ui-a-memory-dump-overview-pane', 'processMemoryDumps',
function(viewEl) {
// Check that the info text is shown.
assert.isTrue(isElementDisplayed(viewEl.$.info_text));
assert.isFalse(isElementDisplayed(viewEl.$.table));
});
});
test('instantiate_singleGlobalMemoryDump', function() {
var processMemoryDumps = convertToProcessMemoryDumps(
[tr.ui.analysis.createSingleTestGlobalMemoryDump()]);
createAndCheckMemoryDumpOverviewPane(this,
processMemoryDumps,
[ // Table rows.
{
title: colorLegendMatcher('Process 1'),
sizes: [[29884416], undefined, [9437184], [5767168], undefined,
undefined, undefined, undefined, [7340032], undefined,
undefined, [2097152]],
contexts: extractProcessMemoryDumps(processMemoryDumps, 1)
},
{
title: colorLegendMatcher('Process 2'),
sizes: [[17825792], [39845888], [18350080], [0], [32], [8912896],
[7340032], [0], [1048576], [1], [5242880], [1572864]],
contexts: extractProcessMemoryDumps(processMemoryDumps, 2)
},
{
title: colorLegendMatcher('Process 4'),
sizes: [undefined, [17825792], undefined, undefined, undefined,
undefined, undefined, undefined, undefined, undefined,
undefined, undefined],
contexts: extractProcessMemoryDumps(processMemoryDumps, 4)
}
],
[ // Footer rows.
{
title: 'Total',
sizes: [[47710208], [57671680], [27787264], [5767168], [32],
[8912896], [7340032], [0], [8388608], [1], [5242880],
[3670016]],
contexts: undefined
}
],
undefined /* no aggregation */);
});
test('instantiate_multipleGlobalMemoryDumps', function() {
var processMemoryDumps = convertToProcessMemoryDumps(
tr.ui.analysis.createMultipleTestGlobalMemoryDumps());
createAndCheckMemoryDumpOverviewPane(this,
processMemoryDumps,
[ // Table rows.
{
title: colorLegendMatcher('Process 1'),
sizes: [[31457280, 29884416, undefined], undefined,
[10485760, 9437184, undefined], [8388608, 5767168, undefined],
undefined, undefined, undefined, undefined,
[undefined, 7340032, undefined], undefined, undefined,
[undefined, 2097152, undefined]],
contexts: extractProcessMemoryDumps(processMemoryDumps, 1)
},
{
title: colorLegendMatcher('Process 2'),
sizes: [[19398656, 17825792, 15728640],
[40370176, 39845888, 40894464], [18350080, 18350080, 18350080],
[0, 0, -2621440], [32, 32, 64], [10485760, 8912896, 7340032],
[undefined, 7340032, 6291456], [undefined, 0, 1048576],
[2097152, 1048576, 786432], [undefined, 1, undefined],
[5242880, 5242880, 5767168], [1048576, 1572864, 2097152]],
contexts: extractProcessMemoryDumps(processMemoryDumps, 2)
},
{
title: colorLegendMatcher('Process 3'),
sizes: [undefined, undefined, undefined, undefined, undefined,
undefined, undefined, undefined, undefined,
[2147483648, undefined, 1073741824],
[1073741824, undefined, 2147483648], undefined],
contexts: extractProcessMemoryDumps(processMemoryDumps, 3)
},
{
title: colorLegendMatcher('Process 4'),
sizes: [undefined, [undefined, 17825792, 17825792], undefined,
undefined, undefined, undefined, undefined, undefined,
undefined, undefined, undefined, undefined],
contexts: extractProcessMemoryDumps(processMemoryDumps, 4)
}
],
[ // Footer rows.
{
title: 'Total',
sizes: [[50855936, 47710208, 15728640],
[40370176, 57671680, 58720256], [28835840, 27787264, 18350080],
[8388608, 5767168, -2621440], [32, 32, 64],
[10485760, 8912896, 7340032], [undefined, 7340032, 6291456],
[undefined, 0, 1048576], [2097152, 8388608, 786432],
[2147483648, 1, 1073741824], [1078984704, 5242880, 2153250816],
[1048576, 3670016, 2097152]],
contexts: undefined
}
],
AggregationMode.DIFF);
});
test('instantiate_singleProcessMemoryDump', function() {
var processMemoryDumps = convertToProcessMemoryDumps(
[tr.ui.analysis.createSingleTestProcessMemoryDump()]);
createAndCheckMemoryDumpOverviewPane(this,
processMemoryDumps,
[ // Table rows.
{
title: colorLegendMatcher('Process 2'),
sizes: [[17825792], [39845888], [18350080], [0], [32], [8912896],
[7340032], [0], [1048576], [1], [5242880], [1572864]],
contexts: extractProcessMemoryDumps(processMemoryDumps, 2)
}
],
[] /* footer rows */,
undefined /* no aggregation */);
});
test('instantiate_multipleProcessMemoryDumps', function() {
var processMemoryDumps = convertToProcessMemoryDumps(
tr.ui.analysis.createMultipleTestProcessMemoryDumps());
createAndCheckMemoryDumpOverviewPane(this,
processMemoryDumps,
[ // Table rows.
{
title: colorLegendMatcher('Process 2'),
sizes: [[19398656, 17825792, 15728640],
[40370176, 39845888, 40894464], [18350080, 18350080, 18350080],
[0, 0, -2621440], [32, 32, 64], [10485760, 8912896, 7340032],
[undefined, 7340032, 6291456], [undefined, 0, 1048576],
[2097152, 1048576, 786432], [undefined, 1, undefined],
[5242880, 5242880, 5767168], [1048576, 1572864, 2097152]],
contexts: extractProcessMemoryDumps(processMemoryDumps, 2)
}
],
[] /* footer rows */,
AggregationMode.MAX);
});
test('selection', function() {
var processMemoryDumps = convertToProcessMemoryDumps(
tr.ui.analysis.createMultipleTestGlobalMemoryDumps());
var viewEl =
tr.ui.analysis.createTestPane('tr-ui-a-memory-dump-overview-pane');
viewEl.processMemoryDumps = processMemoryDumps;
viewEl.aggregationMode = AggregationMode.DIFF;
viewEl.rebuild();
this.addHTMLOutput(viewEl);
var table = viewEl.$.table;
// Simulate clicking on the 'malloc' cell of the second process.
table.selectedTableRow = table.tableRows[1];
table.selectedColumnIndex = 9;
assert.lengthOf(viewEl.requestedChildPanes, 2);
var lastChildPane = viewEl.requestedChildPanes[1];
assert.equal(
lastChildPane.tagName, 'TR-UI-A-MEMORY-DUMP-ALLOCATOR-DETAILS-PANE');
assert.strictEqual(lastChildPane.aggregationMode, AggregationMode.DIFF);
assert.deepEqual(lastChildPane.memoryAllocatorDumps,
extractMemoryAllocatorDumps(processMemoryDumps, 2, 'malloc'));
// Simulate clicking on the 'Oilpan' cell of the second process.
table.selectedColumnIndex = 10;
assert.lengthOf(viewEl.requestedChildPanes, 3);
var lastChildPane = viewEl.requestedChildPanes[2];
assert.isUndefined(viewEl.lastChildPane);
});
test('memory', function() {
var processMemoryDumps = convertToProcessMemoryDumps(
tr.ui.analysis.createMultipleTestGlobalMemoryDumps());
var containerEl = document.createElement('div');
containerEl.brushingStateController =
new tr.c.BrushingStateController(undefined);
function simulateView(pids, aggregationMode,
expectedSelectedCellFieldValues, expectedSelectedRowTitle,
expectedSelectedColumnIndex, callback) {
var viewEl =
tr.ui.analysis.createTestPane('tr-ui-a-memory-dump-overview-pane');
var table = viewEl.$.table;
Polymer.dom(containerEl).textContent = '';
Polymer.dom(containerEl).appendChild(viewEl);
var displayedProcessMemoryDumps = processMemoryDumps.map(
function(memoryDumps) {
return tr.b.filterItems(memoryDumps, function(pid, pmd) {
return pids.indexOf(pmd.process.pid) !== -1;
});
});
viewEl.processMemoryDumps = displayedProcessMemoryDumps;
viewEl.aggregationMode = aggregationMode;
viewEl.rebuild();
if (expectedSelectedCellFieldValues === undefined) {
assert.isUndefined(viewEl.childPaneBuilder);
} else {
checkSizeNumericFields(table.selectedTableRow,
table.tableColumns[table.selectedColumnIndex],
expectedSelectedCellFieldValues);
}
assert.strictEqual(
table.selectedColumnIndex, expectedSelectedColumnIndex);
if (expectedSelectedRowTitle === undefined)
assert.isUndefined(table.selectedTableRow);
else
assert.equal(table.selectedTableRow.title, expectedSelectedRowTitle);
callback(viewEl, viewEl.$.table);
}
simulateView(
[1, 2, 3, 4], // All processes.
AggregationMode.DIFF,
undefined, undefined, undefined, // No cell should be selected.
function(view, table) {
assert.isUndefined(view.createChildPane());
// Select the 'PSS' column of the second process.
table.selectedTableRow = table.tableRows[1];
table.selectedColumnIndex = 3;
});
simulateView(
[2, 3],
AggregationMode.MAX,
[18350080, 18350080, 18350080], 'Process 2', 3, /* PSS */
function(view, table) {
var childPane = view.createChildPane();
assert.equal(
childPane.tagName, 'TR-UI-A-MEMORY-DUMP-VM-REGIONS-DETAILS-PANE');
assert.deepEqual(tr.b.asArray(childPane.vmRegions),
extractVmRegions(processMemoryDumps, 2));
assert.strictEqual(childPane.aggregationMode, AggregationMode.MAX);
});
simulateView(
[3],
undefined, /* No aggregation */
undefined, undefined, undefined, // No cell selected.
function(view, table) {
assert.isUndefined(view.createChildPane());
});
simulateView(
[1, 2, 3, 4],
AggregationMode.DIFF,
[18350080, 18350080, 18350080], 'Process 2', 3, /* PSS */
function(view, table) {
var childPane = view.createChildPane();
assert.equal(
childPane.tagName, 'TR-UI-A-MEMORY-DUMP-VM-REGIONS-DETAILS-PANE');
assert.deepEqual(tr.b.asArray(childPane.vmRegions),
extractVmRegions(processMemoryDumps, 2));
assert.strictEqual(childPane.aggregationMode, AggregationMode.DIFF);
// Select the 'v8' column of the first process (empty cell).
table.selectedTableRow = table.tableRows[0];
table.selectedColumnIndex = 10;
});
simulateView(
[1],
undefined, /* No aggregation */
undefined, undefined, undefined, // No cell should selected.
function(view, table) {
assert.isUndefined(view.createChildPane());
// Select 'Total resident' column of the first process.
table.selectedTableRow = table.tableRows[0];
table.selectedColumnIndex = 1;
});
simulateView(
[1, 2, 3, 4],
AggregationMode.MAX,
[31457280, 29884416, undefined], 'Process 1', 1, /* Total resident */
function(view, table) {
var childPane = view.createChildPane();
assert.equal(
childPane.tagName, 'TR-UI-A-MEMORY-DUMP-VM-REGIONS-DETAILS-PANE');
assert.deepEqual(tr.b.asArray(childPane.vmRegions),
extractVmRegions(processMemoryDumps, 1));
assert.strictEqual(childPane.aggregationMode, AggregationMode.MAX);
});
});
test('processNameColumn_formatTitle', function() {
var c = new ProcessNameColumn();
// With context (total row).
assert.strictEqual(c.formatTitle({
title: 'Total',
usedMemoryCells: {}
}), 'Total');
// Without context (process row).
var title = c.formatTitle({
title: 'Process 1',
usedMemoryCells: {},
contexts: [tr.ui.analysis.createSingleTestProcessMemoryDump()]
});
checkColorLegend(title, 'Process 1');
});
test('usedMemoryColumn', function() {
var c = new UsedMemoryColumn('Private', 'bytes', tr.b.identity,
AggregationMode.DIFF);
checkSpanWithColor(c.title, 'Private',
'used_memory_column' /* blue (column title) */);
checkColor(c.color(undefined /* contexts */),
'used_memory_column' /* blue (column cells) */);
});
test('peakMemoryColumn', function() {
var c = new PeakMemoryColumn('Peak', 'bytes', tr.b.identity,
AggregationMode.MAX);
checkSpanWithColor(c.title, 'Peak',
'used_memory_column' /* blue (column title) */);
checkColor(c.color(undefined) /* contexts */,
'used_memory_column' /* blue (column cells) */);
var RESETTABLE_PEAK = 1 << 2;
var NON_RESETTABLE_PEAK = 1 << 3;
function checkPeakColumnInfosAndColor(fieldAndDumpMask, expectedInfos) {
checkOverviewColumnInfosAndColor(c,
fieldAndDumpMask,
function(pmd, mask) {
if (mask & RESETTABLE_PEAK) {
assert.strictEqual(
mask & NON_RESETTABLE_PEAK, 0); // Test sanity check.
pmd.arePeakResidentBytesResettable = true;
} else if (mask & NON_RESETTABLE_PEAK) {
pmd.arePeakResidentBytesResettable = false;
}
},
expectedInfos,
'used_memory_column');
}
// No context.
checkOverviewColumnInfosAndColor(c,
[FIELD],
undefined /* no context */,
[] /* no infos */,
'used_memory_column' /* blue color */);
checkOverviewColumnInfosAndColor(c,
[FIELD, FIELD, 0, FIELD],
undefined /* no context */,
[] /* no infos */,
'used_memory_column' /* blue color */);
// All resettable.
var EXPECTED_RESETTABLE_INFO = {
icon: '\u21AA',
message: 'Peak RSS since previous memory dump.'
};
checkPeakColumnInfosAndColor([
FIELD | DUMP | RESETTABLE_PEAK
], [EXPECTED_RESETTABLE_INFO]);
checkPeakColumnInfosAndColor([
FIELD | DUMP | RESETTABLE_PEAK,
DUMP /* ignored because there's no field */,
0,
FIELD | DUMP | RESETTABLE_PEAK
], [EXPECTED_RESETTABLE_INFO]);
// All non-resettable.
var EXPECTED_NON_RESETTABLE_INFO = {
icon: '\u21A6',
message: 'Peak RSS since process startup. Finer grained peaks require ' +
'a Linux kernel version \u2265 4.0.'
};
checkPeakColumnInfosAndColor([
FIELD | DUMP | NON_RESETTABLE_PEAK
], [EXPECTED_NON_RESETTABLE_INFO]);
checkPeakColumnInfosAndColor([
0,
DUMP | RESETTABLE_PEAK /* ignored because there's no field */,
FIELD | DUMP | NON_RESETTABLE_PEAK,
FIELD | DUMP | NON_RESETTABLE_PEAK
], [EXPECTED_NON_RESETTABLE_INFO]);
// Combination (warning).
var EXPECTED_COMBINATION_INFO = {
icon: '\u26A0',
message: 'Both resettable and non-resettable peak RSS values were ' +
'provided by the process',
color: 'red'
};
checkPeakColumnInfosAndColor([
FIELD | DUMP | NON_RESETTABLE_PEAK,
0,
FIELD | DUMP | RESETTABLE_PEAK,
0
], [EXPECTED_COMBINATION_INFO]);
});
test('byteStatColumn', function() {
var c = new ByteStatColumn('Stat', 'bytes', tr.b.identity,
AggregationMode.DIFF);
checkSpanWithColor(c.title, 'Stat',
'used_memory_column' /* blue (column title) */);
var HAS_OWN_VM_REGIONS = 1 << 2;
function checkByteStatColumnInfosAndColor(
fieldAndDumpMask, expectedInfos, expectedIsOlderColor) {
checkOverviewColumnInfosAndColor(c,
fieldAndDumpMask,
function(pmd, mask) {
if (mask & HAS_OWN_VM_REGIONS)
pmd.vmRegions = [];
},
expectedInfos,
expectedIsOlderColor ?
'older_used_memory_column' /* light blue */ :
'used_memory_column' /* blue color */);
}
var EXPECTED_ALL_OLDER_VALUES = {
icon: '\u26AF',
message: 'Older value (only heavy (purple) memory dumps contain ' +
'memory maps).'
};
var EXPECTED_SOME_OLDER_VALUES = {
icon: '\u26AF',
message: 'Older value at some selected timestamps (only heavy ' +
'(purple) memory dumps contain memory maps).'
};
// No context.
checkOverviewColumnInfosAndColor(c,
[FIELD],
undefined /* no context */,
[] /* no infos */,
'used_memory_column' /* blue color */);
checkOverviewColumnInfosAndColor(c,
[FIELD, FIELD, 0, FIELD],
undefined /* no context */,
[] /* no infos */,
'used_memory_column' /* blue color */);
// All process memory dumps have own VM regions.
checkByteStatColumnInfosAndColor([
FIELD | DUMP | HAS_OWN_VM_REGIONS
], [] /* no infos */, false /* blue color */);
checkByteStatColumnInfosAndColor([
FIELD | DUMP | HAS_OWN_VM_REGIONS,
FIELD | DUMP | HAS_OWN_VM_REGIONS,
0,
FIELD | DUMP | HAS_OWN_VM_REGIONS
], [] /* no infos */, false /* blue color */);
// No process memory dumps have own VM regions.
checkByteStatColumnInfosAndColor([
FIELD | DUMP
], [EXPECTED_ALL_OLDER_VALUES], true /* light blue */);
checkByteStatColumnInfosAndColor([
FIELD | DUMP,
FIELD | DUMP
], [EXPECTED_ALL_OLDER_VALUES], true /* light blue */);
// Some process memory dumps don't have own VM regions.
checkByteStatColumnInfosAndColor([
FIELD | DUMP,
0,
FIELD | DUMP
], [EXPECTED_SOME_OLDER_VALUES], true /* light blue */);
checkByteStatColumnInfosAndColor([
FIELD | DUMP | HAS_OWN_VM_REGIONS,
FIELD | DUMP,
FIELD | DUMP | HAS_OWN_VM_REGIONS
], [EXPECTED_SOME_OLDER_VALUES], false /* blue */);
});
test('allocatorColumn', function() {
var c = new AllocatorColumn('Allocator', 'bytes', tr.b.identity,
AggregationMode.MAX);
checkColorLegend(c.title, 'Allocator');
checkColor(c.color(undefined /* contexts */),
undefined /* no color (column cells) */);
var HAS_HEAP_DUMPS = 1 << 2;
var HAS_ALLOCATOR_HEAP_DUMP = 1 << 3;
var MISSING_SIZE = 1 << 4;
function checkAllocatorColumnInfosAndColor(fieldAndDumpMask,
expectedInfos) {
checkOverviewColumnInfosAndColor(c,
fieldAndDumpMask,
function(pmd, mask) {
if (mask & HAS_HEAP_DUMPS)
pmd.heapDumps = {};
if (mask & HAS_ALLOCATOR_HEAP_DUMP)
pmd.heapDumps['Allocator'] = new HeapDump(pmd, 'Allocator');
var mad = new MemoryAllocatorDump(pmd, 'Allocator');
if (!(mask & MISSING_SIZE)) {
mad.addNumeric('size',
new ScalarNumeric(sizeInBytes_smallerIsBetter, 7));
}
pmd.memoryAllocatorDumps = [mad];
},
expectedInfos,
undefined /* no color */);
}
// No context.
checkOverviewColumnInfosAndColor(c,
[FIELD],
undefined /* no context */,
[] /* no infos */,
undefined /* no color */);
checkOverviewColumnInfosAndColor(c,
[FIELD, FIELD, 0, FIELD],
undefined /* no context */,
[] /* no infos */,
undefined /* no color */);
// No infos.
checkAllocatorColumnInfosAndColor([
FIELD | DUMP
], [] /* no infos */);
checkAllocatorColumnInfosAndColor([
FIELD | DUMP,
FIELD | DUMP | HAS_HEAP_DUMPS,
0,
FIELD | DUMP
], [] /* infos */);
var EXPECTED_ALL_HAVE_ALLOCATOR_HEAP_DUMP = {
icon: '\u2630',
message: 'Heap dump provided.'
};
var EXPECTED_SOME_HAVE_ALLOCATOR_HEAP_DUMP = {
icon: '\u2630',
message: 'Heap dump provided at some selected timestamps.'
};
// All process memory dumps have heap dumps.
checkAllocatorColumnInfosAndColor([
FIELD | DUMP | HAS_HEAP_DUMPS | HAS_ALLOCATOR_HEAP_DUMP
], [EXPECTED_ALL_HAVE_ALLOCATOR_HEAP_DUMP]);
checkAllocatorColumnInfosAndColor([
FIELD | DUMP | HAS_HEAP_DUMPS | HAS_ALLOCATOR_HEAP_DUMP,
FIELD | DUMP | HAS_HEAP_DUMPS | HAS_ALLOCATOR_HEAP_DUMP,
FIELD | DUMP | HAS_HEAP_DUMPS | HAS_ALLOCATOR_HEAP_DUMP
], [EXPECTED_ALL_HAVE_ALLOCATOR_HEAP_DUMP]);
// Some process memory dumps have heap dumps.
checkAllocatorColumnInfosAndColor([
0,
FIELD | DUMP | HAS_HEAP_DUMPS | HAS_ALLOCATOR_HEAP_DUMP
], [EXPECTED_SOME_HAVE_ALLOCATOR_HEAP_DUMP]);
checkAllocatorColumnInfosAndColor([
FIELD | DUMP | HAS_HEAP_DUMPS | HAS_ALLOCATOR_HEAP_DUMP,
FIELD | DUMP | HAS_HEAP_DUMPS,
FIELD | DUMP | HAS_HEAP_DUMPS | HAS_ALLOCATOR_HEAP_DUMP
], [EXPECTED_SOME_HAVE_ALLOCATOR_HEAP_DUMP]);
var EXPECTED_ALL_MISSING_SIZE = {
icon: '\u26A0',
message: 'Size was not provided.',
color: 'red'
};
var EXPECTED_SOME_MISSING_SIZE = {
icon: '\u26A0',
message: 'Size was not provided at some selected timestamps.',
color: 'red'
};
// All process memory dumps are missing allocator size.
checkAllocatorColumnInfosAndColor([
FIELD | DUMP | MISSING_SIZE
], [EXPECTED_ALL_MISSING_SIZE]);
checkAllocatorColumnInfosAndColor([
FIELD | DUMP | MISSING_SIZE,
FIELD | DUMP | MISSING_SIZE,
FIELD | DUMP | MISSING_SIZE
], [EXPECTED_ALL_MISSING_SIZE]);
// Some process memory dumps use Android memtrack PSS fallback.
checkAllocatorColumnInfosAndColor([
0,
FIELD | DUMP | MISSING_SIZE
], [EXPECTED_SOME_MISSING_SIZE]);
checkAllocatorColumnInfosAndColor([
FIELD | DUMP | MISSING_SIZE,
FIELD | DUMP,
FIELD | DUMP | MISSING_SIZE
], [EXPECTED_SOME_MISSING_SIZE]);
// Combination of heap dump and memtrack fallback infos.
checkAllocatorColumnInfosAndColor([
FIELD | DUMP | MISSING_SIZE | HAS_HEAP_DUMPS |
HAS_ALLOCATOR_HEAP_DUMP
], [
EXPECTED_ALL_HAVE_ALLOCATOR_HEAP_DUMP,
EXPECTED_ALL_MISSING_SIZE
]);
checkAllocatorColumnInfosAndColor([
FIELD | DUMP | HAS_HEAP_DUMPS | HAS_ALLOCATOR_HEAP_DUMP,
FIELD | DUMP,
FIELD | DUMP | MISSING_SIZE
], [
EXPECTED_SOME_HAVE_ALLOCATOR_HEAP_DUMP,
EXPECTED_SOME_MISSING_SIZE
]);
});
test('tracingColumn', function() {
var c = new TracingColumn('Tracing', 'bytes', tr.b.identity,
AggregationMode.DIFF);
checkSpanWithColor(c.title, 'Tracing',
'tracing_memory_column' /* expected column title gray color */);
checkColor(c.color(undefined /* contexts */),
'tracing_memory_column' /* expected column cells gray color */);
});
});
</script>