blob: ae87c1834e7eb1f97c0d21dbe9092094a7637c41 [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright 2017 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/core/test_utils.html">
<link rel="import" href="/tracing/metrics/spa_navigation_helper.html">
<script>
'use strict';
tr.b.unittest.testSuite(function() {
const RENDERER_PROCESS_ID = 1234;
const RENDERER_PROCESS_MAIN_THREAD_ID = 1;
const BROWSER_PROCESS_ID = 1;
const BROWSER_PROCESS_MAIN_THREAD_ID = 12;
const PAINT_UPDATE_TITLE =
'PaintLayerCompositor::updateIfNeededRecursive';
const SPA_NAVIGATION_EVENT_TITLE =
'FrameLoader::updateForSameDocumentNavigation';
function createChromeProcessesOnModel(model) {
const rendererProcess = model.getOrCreateProcess(RENDERER_PROCESS_ID);
const mainThread = rendererProcess.getOrCreateThread(
RENDERER_PROCESS_MAIN_THREAD_ID);
mainThread.name = 'CrRendererMain';
const browserProcess = model.getOrCreateProcess(BROWSER_PROCESS_ID);
const browserMainThread = browserProcess.getOrCreateThread(
BROWSER_PROCESS_MAIN_THREAD_ID);
browserMainThread.name = 'CrBrowserMain';
}
function addThreadSlice(model, title, timestamp, args) {
const rendererProcess = model.getOrCreateProcess(RENDERER_PROCESS_ID);
const mainThread = rendererProcess.getOrCreateThread(
RENDERER_PROCESS_MAIN_THREAD_ID);
mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
cat: 'blink',
title,
start: timestamp,
duration: 0.1,
args
}));
}
function addLatencyInfoFlowEvent(model, timestamp, bindId) {
const latencyInfoFlowSlice = tr.c.TestUtils.newSliceEx({
cat: 'input,benchmark',
title: 'LatencyInfo.Flow',
start: timestamp,
duration: 0.1,
bindId,
args: {step: 'handleInputEventMain'}
});
const handleInputEventSlice = tr.c.TestUtils.newSliceEx({
cat: 'blink,rail',
title: 'WebViewImpl::handleInputEvent',
start: timestamp + 1, // Assume handleInputEvent always delays 1ms.
duration: 0.1,
args: {type: 'MouseUp'}
});
const rendererProcess = model.getOrCreateProcess(RENDERER_PROCESS_ID);
const mainThread = rendererProcess.getOrCreateThread(
RENDERER_PROCESS_MAIN_THREAD_ID);
handleInputEventSlice.parentSlice = latencyInfoFlowSlice;
mainThread.sliceGroup.pushSlice(latencyInfoFlowSlice);
mainThread.sliceGroup.pushSlice(handleInputEventSlice);
}
function addInputLatencySlice(model, start, traceId) {
const browserProcess = model.getOrCreateProcess(BROWSER_PROCESS_ID);
const browserMainThread = browserProcess.getOrCreateThread(
BROWSER_PROCESS_MAIN_THREAD_ID);
browserMainThread.sliceGroup.pushSlice(tr.c.TestUtils.newAsyncSliceEx({
cat: 'benchmark,latencyInfo,rail',
title: 'InputLatency::MouseUp',
start,
duration: 0.1,
args: {
data: {
trace_id: traceId
}
}
}));
}
function addGoToIndexSlice(model, timestamp) {
const browserProcess = model.getOrCreateProcess(BROWSER_PROCESS_ID);
const browserMainThread = browserProcess.getOrCreateThread(
BROWSER_PROCESS_MAIN_THREAD_ID);
browserMainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
cat: 'browser,navigation,benchmark',
title: 'NavigationControllerImpl::GoToIndex',
start: timestamp,
duration: 0.1
}));
}
function getSpaNavigations(model) {
const modelHelper = model.getOrCreateHelper(
tr.model.helpers.ChromeModelHelper);
const rendererHelpers = modelHelper.rendererHelpers;
const browserHelper = modelHelper.browserHelper;
let spaNavigations = [];
for (const rendererHelper of Object.values(rendererHelpers)) {
spaNavigations = spaNavigations.concat(
tr.metrics.findSpaNavigationsOnRenderer(
rendererHelper, browserHelper));
}
return spaNavigations;
}
test('findSpaNavigations_noSpaNavEvent', function() {
const model = tr.c.TestUtils.newModel(model => {
createChromeProcessesOnModel(model);
addLatencyInfoFlowEvent(model, 75, '0x600000057');
addInputLatencySlice(model, 55, 25769803863);
addThreadSlice(model, PAINT_UPDATE_TITLE, 101);
});
const spaNavigations = getSpaNavigations(model);
assert.lengthOf(spaNavigations, 0);
});
test('findSpaNavigations_noLatencyInfoFlowEvent', function() {
const model = tr.c.TestUtils.newModel(model => {
createChromeProcessesOnModel(model);
addThreadSlice(model, SPA_NAVIGATION_EVENT_TITLE, 100);
addInputLatencySlice(model, 55, 25769803863);
addThreadSlice(model, PAINT_UPDATE_TITLE, 101);
});
const spaNavigations = getSpaNavigations(model);
assert.lengthOf(spaNavigations, 0);
});
test('findSpaNavigations_noNavStartEvent', function() {
const model = tr.c.TestUtils.newModel(model => {
createChromeProcessesOnModel(model);
addThreadSlice(model, SPA_NAVIGATION_EVENT_TITLE, 100);
addLatencyInfoFlowEvent(model, 75, '0x600000057');
addThreadSlice(model, PAINT_UPDATE_TITLE, 101);
});
const spaNavigations = getSpaNavigations(model);
assert.lengthOf(spaNavigations, 0);
});
test('findSpaNavigations_noFirstPaintEvent', function() {
const model = tr.c.TestUtils.newModel(model => {
createChromeProcessesOnModel(model);
addThreadSlice(model, SPA_NAVIGATION_EVENT_TITLE, 100);
addLatencyInfoFlowEvent(model, 75, '0x600000057');
addInputLatencySlice(model, 55, 25769803863);
});
const spaNavigations = getSpaNavigations(model);
assert.lengthOf(spaNavigations, 0);
});
test('findSpaNavigations_inputLatencyAsNavStart', function() {
const URL = 'https://11111';
const model = tr.c.TestUtils.newModel(model => {
createChromeProcessesOnModel(model);
addThreadSlice(model, SPA_NAVIGATION_EVENT_TITLE, 100,
{url: URL});
addLatencyInfoFlowEvent(model, 75, '0x600000057');
addInputLatencySlice(model, 55, 25769803863);
addThreadSlice(model, PAINT_UPDATE_TITLE, 101);
});
const spaNavigations = getSpaNavigations(model);
assert.lengthOf(spaNavigations, 1);
assert.strictEqual(
spaNavigations[0].navStartCandidates.inputLatencyAsyncSlice.start, 55);
assert.strictEqual(
spaNavigations[0].navStartCandidates.goToIndexSlice, undefined);
assert.strictEqual(spaNavigations[0].firstPaintEvent.start, 101);
assert.strictEqual(spaNavigations[0].url, URL);
});
test('findSpaNavigations_goToIndexAsNavStart', function() {
const URL = 'https://11111';
const model = tr.c.TestUtils.newModel(model => {
createChromeProcessesOnModel(model);
addThreadSlice(model, SPA_NAVIGATION_EVENT_TITLE, 100,
{url: URL});
addGoToIndexSlice(model, 55);
addThreadSlice(model, PAINT_UPDATE_TITLE, 101);
});
const spaNavigations = getSpaNavigations(model);
assert.lengthOf(spaNavigations, 1);
assert.strictEqual(
spaNavigations[0].navStartCandidates.goToIndexSlice.start, 55);
assert.strictEqual(
spaNavigations[0].navStartCandidates.inputLatencyAsyncSlice, undefined);
assert.strictEqual(spaNavigations[0].firstPaintEvent.start, 101);
assert.strictEqual(spaNavigations[0].url, URL);
});
test('findSpaNavigations_multipleSpaNavs', function() {
const URL1 = 'https://11111';
const URL2 = 'https://22222';
const URL3 = 'https://33333';
const model = tr.c.TestUtils.newModel(model => {
createChromeProcessesOnModel(model);
addThreadSlice(model, SPA_NAVIGATION_EVENT_TITLE, 100,
{url: URL1});
addThreadSlice(model, SPA_NAVIGATION_EVENT_TITLE, 200,
{url: URL2});
addThreadSlice(model, SPA_NAVIGATION_EVENT_TITLE, 300,
{url: URL3});
addLatencyInfoFlowEvent(model, 75, '0x600000057');
addLatencyInfoFlowEvent(model, 175, '0x6000000c2');
addLatencyInfoFlowEvent(model, 275, '0x60000010d');
addInputLatencySlice(model, 55, 25769803863);
addGoToIndexSlice(model, 65);
addInputLatencySlice(model, 155, 25769803970);
addInputLatencySlice(model, 255, 25769804045);
addThreadSlice(model, PAINT_UPDATE_TITLE, 101);
addThreadSlice(model, PAINT_UPDATE_TITLE, 102);
addThreadSlice(model, PAINT_UPDATE_TITLE, 201);
addThreadSlice(model, PAINT_UPDATE_TITLE, 301);
});
const spaNavigations = getSpaNavigations(model);
assert.lengthOf(spaNavigations, 3);
spaNavigations.sort((spa1, spa2) =>
spa1.navStartCandidates.inputLatencyAsyncSlice.start -
spa2.navStartCandidates.inputLatencyAsyncSlice.start);
assert.strictEqual(
spaNavigations[0].navStartCandidates.inputLatencyAsyncSlice.start, 55);
assert.strictEqual(
spaNavigations[1].navStartCandidates.inputLatencyAsyncSlice.start, 155);
assert.strictEqual(
spaNavigations[2].navStartCandidates.inputLatencyAsyncSlice.start, 255);
assert.strictEqual(
spaNavigations[0].navStartCandidates.goToIndexSlice, undefined);
assert.strictEqual(
spaNavigations[1].navStartCandidates.goToIndexSlice, undefined);
assert.strictEqual(
spaNavigations[2].navStartCandidates.goToIndexSlice, undefined);
assert.strictEqual(spaNavigations[0].firstPaintEvent.start, 101);
assert.strictEqual(spaNavigations[1].firstPaintEvent.start, 201);
assert.strictEqual(spaNavigations[2].firstPaintEvent.start, 301);
assert.strictEqual(spaNavigations[0].url, URL1);
assert.strictEqual(spaNavigations[1].url, URL2);
assert.strictEqual(spaNavigations[2].url, URL3);
});
});
</script>