| <!DOCTYPE html> |
| <!-- |
| Copyright 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/model/event_set.html"> |
| <link rel="import" |
| href="/tracing/ui/analysis/container_memory_dump_sub_view.html"> |
| <link rel="import" |
| href="/tracing/ui/analysis/memory_dump_sub_view_test_utils.html"> |
| <link rel="import" href="/tracing/ui/base/deep_utils.html"> |
| <link rel="import" href="/tracing/ui/brushing_state_controller.html"> |
| |
| <script> |
| 'use strict'; |
| |
| tr.b.unittest.testSuite(function() { |
| var EventSet = tr.model.EventSet; |
| var extractVmRegions = tr.ui.analysis.extractVmRegions; |
| var extractMemoryAllocatorDumps = tr.ui.analysis.extractMemoryAllocatorDumps; |
| var extractHeapDumps = tr.ui.analysis.extractHeapDumps; |
| |
| function createViewWithSelection(selection, opt_parentElement) { |
| var viewEl = document.createElement( |
| 'tr-ui-a-container-memory-dump-sub-view'); |
| if (opt_parentElement) |
| opt_parentElement.appendChild(viewEl); |
| if (selection === undefined) { |
| viewEl.selection = undefined; |
| } else { |
| // Rotate the list of selected dumps to check that the sub-view sorts |
| // them properly. |
| var length = selection.length; |
| viewEl.selection = new tr.model.EventSet( |
| selection.slice(length / 2, length).concat( |
| selection.slice(0, length / 2))); |
| } |
| return viewEl; |
| } |
| |
| function createAndCheckContainerMemoryDumpView( |
| test, containerMemoryDumps, detailsCheckCallback, opt_parentElement) { |
| var viewEl = |
| createViewWithSelection(containerMemoryDumps, opt_parentElement); |
| if (!opt_parentElement) |
| test.addHTMLOutput(viewEl); |
| |
| // The view should contain a stacked pane view with memory dump header and |
| // overview panes. |
| var stackedPaneViewEl = tr.b.findDeepElementMatching( |
| viewEl, 'tr-ui-a-stacked-pane-view'); |
| var headerPaneEl = tr.b.findDeepElementMatching( |
| stackedPaneViewEl, 'tr-ui-a-memory-dump-header-pane'); |
| var overviewPaneEl = tr.b.findDeepElementMatching( |
| stackedPaneViewEl, 'tr-ui-a-memory-dump-overview-pane'); |
| |
| // Check that the header pane and overview pane are correctly set up. |
| var processMemoryDumps = containerMemoryDumps.map(function(containerDump) { |
| return containerDump.processMemoryDumps; |
| }); |
| assert.deepEqual( |
| tr.b.asArray(headerPaneEl.containerMemoryDumps), containerMemoryDumps); |
| assert.deepEqual(overviewPaneEl.processMemoryDumps, processMemoryDumps); |
| assert.strictEqual( |
| overviewPaneEl.aggregationMode, headerPaneEl.aggregationMode); |
| |
| // Get the overview pane table to drive the details pane checks. |
| var overviewTableEl = tr.b.findDeepElementMatching( |
| overviewPaneEl, 'tr-ui-b-table'); |
| |
| function checkVmRegionsPane(pid) { |
| var detailsPaneEl = tr.b.findDeepElementMatching( |
| stackedPaneViewEl, 'tr-ui-a-memory-dump-vm-regions-details-pane'); |
| if (pid === undefined) { |
| assert.isUndefined(detailsPaneEl); |
| } else { |
| assert.deepEqual(tr.b.asArray(detailsPaneEl.vmRegions), |
| extractVmRegions(processMemoryDumps, pid)); |
| assert.strictEqual( |
| detailsPaneEl.aggregationMode, headerPaneEl.aggregationMode); |
| } |
| } |
| |
| function checkAllocatorPane(pid, allocatorName, withHeapDetailsPane) { |
| var allocatorDetailsPaneEl = tr.b.findDeepElementMatching( |
| stackedPaneViewEl, 'tr-ui-a-memory-dump-allocator-details-pane'); |
| if (pid === undefined) { |
| assert.isUndefined(allocatorDetailsPaneEl); |
| assert.isUndefined(allocatorName); // Test sanity check. |
| assert.isUndefined(withHeapDetailsPane); // Test sanity check. |
| return; |
| } |
| |
| assert.deepEqual( |
| tr.b.asArray(allocatorDetailsPaneEl.memoryAllocatorDumps), |
| extractMemoryAllocatorDumps(processMemoryDumps, pid, allocatorName)); |
| assert.strictEqual( |
| allocatorDetailsPaneEl.aggregationMode, headerPaneEl.aggregationMode); |
| |
| var heapDetailsPaneEl = tr.b.findDeepElementMatching( |
| stackedPaneViewEl, 'tr-ui-a-memory-dump-heap-details-pane'); |
| if (!withHeapDetailsPane) { |
| assert.isUndefined(heapDetailsPaneEl); |
| return; |
| } |
| |
| assert.deepEqual(tr.b.asArray(heapDetailsPaneEl.heapDumps), |
| extractHeapDumps(processMemoryDumps, pid, allocatorName)); |
| assert.strictEqual( |
| heapDetailsPaneEl.aggregationMode, headerPaneEl.aggregationMode); |
| } |
| |
| detailsCheckCallback( |
| overviewTableEl, checkVmRegionsPane, checkAllocatorPane); |
| } |
| |
| test('instantiate_empty', function() { |
| // All these views should be completely empty. |
| var unsetViewEl = document.createElement( |
| 'tr-ui-a-container-memory-dump-sub-view'); |
| this.addHTMLOutput(unsetViewEl); |
| assert.equal(unsetViewEl.getBoundingClientRect().width, 0); |
| assert.equal(unsetViewEl.getBoundingClientRect().height, 0); |
| |
| var undefinedViewEl = createViewWithSelection(undefined); |
| this.addHTMLOutput(undefinedViewEl); |
| assert.equal(undefinedViewEl.getBoundingClientRect().width, 0); |
| assert.equal(undefinedViewEl.getBoundingClientRect().height, 0); |
| |
| var emptyViewEl = createViewWithSelection([]); |
| this.addHTMLOutput(emptyViewEl); |
| assert.equal(emptyViewEl.getBoundingClientRect().width, 0); |
| assert.equal(emptyViewEl.getBoundingClientRect().height, 0); |
| }); |
| |
| test('instantiate_singleGlobalMemoryDump', function() { |
| createAndCheckContainerMemoryDumpView(this, |
| [tr.ui.analysis.createSingleTestGlobalMemoryDump()], |
| function(overviewTableEl, checkVmRegionsPane, checkAllocatorPane) { |
| // Nothing should be selected initially. |
| assert.isUndefined(overviewTableEl.selectedTableRow); |
| assert.isUndefined(overviewTableEl.selectedColumnIndex); |
| checkVmRegionsPane(undefined); |
| checkAllocatorPane(undefined); |
| |
| // Total resident of Process 1. |
| overviewTableEl.selectedTableRow = overviewTableEl.tableRows[0]; |
| overviewTableEl.selectedColumnIndex = 1; |
| checkVmRegionsPane(1 /* PID */); |
| checkAllocatorPane(undefined); |
| |
| // PSS of process 4. |
| overviewTableEl.selectedColumnIndex = 3; |
| overviewTableEl.selectedTableRow = overviewTableEl.tableRows[2]; |
| checkVmRegionsPane(undefined); |
| checkAllocatorPane(undefined); |
| |
| // Malloc of process 2. |
| overviewTableEl.selectedTableRow = overviewTableEl.tableRows[1]; |
| overviewTableEl.selectedColumnIndex = 8; |
| checkVmRegionsPane(undefined); |
| checkAllocatorPane(2 /* PID */, 'malloc', |
| false /* no heap details pane */); |
| }); |
| }); |
| |
| test('instantiate_multipleGlobalMemoryDumps', function() { |
| createAndCheckContainerMemoryDumpView(this, |
| tr.ui.analysis.createMultipleTestGlobalMemoryDumps(), |
| function(overviewTableEl, checkVmRegionsPane, checkAllocatorPane) { |
| // Nothing should be selected initially. |
| assert.isUndefined(overviewTableEl.selectedTableRow); |
| assert.isUndefined(overviewTableEl.selectedColumnIndex); |
| checkVmRegionsPane(undefined); |
| checkAllocatorPane(undefined); |
| |
| // Blink of Process 1. |
| overviewTableEl.selectedTableRow = overviewTableEl.tableRows[0]; |
| overviewTableEl.selectedColumnIndex = 7; |
| checkVmRegionsPane(undefined); |
| checkAllocatorPane(undefined); |
| |
| // Peak total resident of Process 4. |
| overviewTableEl.selectedTableRow = overviewTableEl.tableRows[3]; |
| overviewTableEl.selectedColumnIndex = 2; |
| checkVmRegionsPane(undefined); |
| checkAllocatorPane(undefined); |
| |
| // V8 of Process 3. |
| overviewTableEl.selectedTableRow = overviewTableEl.tableRows[2]; |
| overviewTableEl.selectedColumnIndex = 10; |
| checkVmRegionsPane(undefined); |
| checkAllocatorPane(3 /* PID */, 'v8', true /* heap details pane */); |
| }); |
| }); |
| |
| test('instantiate_singleProcessMemoryDump', function() { |
| createAndCheckContainerMemoryDumpView(this, |
| [tr.ui.analysis.createSingleTestProcessMemoryDump()], |
| function(overviewTableEl, checkVmRegionsPane, checkAllocatorPane) { |
| // Nothing should be selected initially. |
| assert.isUndefined(overviewTableEl.selectedTableRow); |
| assert.isUndefined(overviewTableEl.selectedColumnIndex); |
| checkVmRegionsPane(undefined); |
| checkAllocatorPane(undefined); |
| |
| // Tracing of Process 2. |
| overviewTableEl.selectedTableRow = overviewTableEl.tableRows[0]; |
| overviewTableEl.selectedColumnIndex = 11; |
| checkVmRegionsPane(undefined); |
| checkAllocatorPane(2 /* PID */, 'tracing', |
| false /* no heap details pane */); |
| |
| // Blink of Process 2. |
| overviewTableEl.selectedColumnIndex = 7; |
| checkVmRegionsPane(undefined); |
| checkAllocatorPane(2 /* PID */, 'blink', |
| false /* no heap details pane */); |
| |
| // Total resident of Process 2. |
| overviewTableEl.selectedColumnIndex = 1; |
| checkVmRegionsPane(2 /* PID */); |
| checkAllocatorPane(undefined); |
| }); |
| }); |
| |
| test('instantiate_multipleProcessMemoryDumps', function() { |
| createAndCheckContainerMemoryDumpView(this, |
| tr.ui.analysis.createMultipleTestProcessMemoryDumps(), |
| function(overviewTableEl, checkVmRegionsPane, checkAllocatorPane) { |
| // Nothing should be selected initially. |
| assert.isUndefined(overviewTableEl.selectedTableRow); |
| assert.isUndefined(overviewTableEl.selectedColumnIndex); |
| checkVmRegionsPane(undefined); |
| checkAllocatorPane(undefined); |
| |
| // Tracing of Process 2. |
| overviewTableEl.selectedTableRow = overviewTableEl.tableRows[0]; |
| overviewTableEl.selectedColumnIndex = 11; |
| checkVmRegionsPane(undefined); |
| checkAllocatorPane(2 /* PID */, 'tracing', |
| false /* no heap details pane */); |
| |
| // V8 of Process 2. |
| overviewTableEl.selectedColumnIndex = 10; |
| checkVmRegionsPane(undefined); |
| checkAllocatorPane(2 /* PID */, 'v8', |
| false /* no heap details pane */); |
| |
| // PSS of Process 2. |
| overviewTableEl.selectedColumnIndex = 3; |
| checkVmRegionsPane(2 /* PID */); |
| checkAllocatorPane(undefined); |
| }); |
| }); |
| |
| test('memory', function() { |
| var containerEl = document.createElement('div'); |
| containerEl.brushingStateController = |
| new tr.c.BrushingStateController(undefined); |
| |
| // Create the first container memory view. |
| createAndCheckContainerMemoryDumpView(this, |
| [tr.ui.analysis.createSingleTestProcessMemoryDump()], |
| function(overviewTableEl, checkVmRegionsPane, checkAllocatorPane) { |
| // Nothing should be selected initially. |
| assert.isUndefined(overviewTableEl.selectedTableRow); |
| assert.isUndefined(overviewTableEl.selectedColumnIndex); |
| checkVmRegionsPane(undefined); |
| checkAllocatorPane(undefined); |
| |
| // Select V8 of Process 2. |
| overviewTableEl.selectedTableRow = overviewTableEl.tableRows[0]; |
| overviewTableEl.selectedColumnIndex = 10; |
| checkVmRegionsPane(undefined); |
| checkAllocatorPane(2 /* PID */, 'v8', |
| false /* no heap details pane */); |
| }, containerEl); |
| |
| // Destroy the first container memory view. |
| containerEl.textContent = ''; |
| |
| // Create the second container memory view. |
| createAndCheckContainerMemoryDumpView(this, |
| tr.ui.analysis.createMultipleTestGlobalMemoryDumps(), |
| function(overviewTableEl, checkVmRegionsPane, checkAllocatorPane) { |
| // V8 of Process 2 should still be selected (even though the selection |
| // changed). |
| assert.strictEqual( |
| overviewTableEl.selectedTableRow, overviewTableEl.tableRows[1]); |
| assert.equal(overviewTableEl.selectedColumnIndex, 10); |
| checkVmRegionsPane(undefined); |
| checkAllocatorPane(2 /* PID */, 'v8', |
| false /* no heap details pane */); |
| }, containerEl); |
| }); |
| |
| test('instantiate_differentProcessMemoryDumps', function() { |
| var globalMemoryDumps = |
| tr.ui.analysis.createMultipleTestGlobalMemoryDumps(); |
| // 2 dumps in Process 1, 3 dumps in Process 2, and 1 dump in Process 4 |
| // (intentionally shuffled to check sorting). |
| var differentProcessDumps = [ |
| globalMemoryDumps[1].processMemoryDumps[2], |
| globalMemoryDumps[0].processMemoryDumps[1], |
| globalMemoryDumps[0].processMemoryDumps[2], |
| globalMemoryDumps[1].processMemoryDumps[4], |
| globalMemoryDumps[1].processMemoryDumps[1], |
| globalMemoryDumps[2].processMemoryDumps[2] |
| ]; |
| |
| var viewEl = createViewWithSelection(differentProcessDumps); |
| this.addHTMLOutput(viewEl); |
| |
| var tableEl = tr.b.findDeepElementMatching(viewEl, 'tr-ui-b-table'); |
| assert.lengthOf(tableEl.tableRows, 3); |
| assert.lengthOf(tableEl.tableColumns, 1); |
| var rows = tableEl.tableRows; |
| var column = tableEl.tableColumns[0]; |
| |
| assert.equal(column.value(rows[0]).textContent, |
| '2 memory dumps in Process 1'); |
| assert.equal(column.value(rows[1]).textContent, |
| '3 memory dumps in Process 2'); |
| assert.equal(column.value(rows[2]).textContent, |
| '1 memory dump in Process 4'); |
| |
| // Check that the analysis link is associated with the right dumps. |
| assert.sameMembers(tr.b.asArray(column.value(rows[1]).selection), [ |
| globalMemoryDumps[0].processMemoryDumps[2], |
| globalMemoryDumps[1].processMemoryDumps[2], |
| globalMemoryDumps[2].processMemoryDumps[2] |
| ]); |
| |
| assert.lengthOf(rows[1].subRows, 3); |
| var subRow = rows[1].subRows[0]; |
| |
| // Check the timestamp. |
| assert.equal(column.value(subRow).children[0].value, 42); |
| |
| // Check that the analysis link is associated with the right dump. |
| assert.sameMembers(tr.b.asArray(column.value(subRow).selection), |
| [globalMemoryDumps[0].processMemoryDumps[2]]); |
| }); |
| }); |
| </script> |