Index: tracing/tracing/extras/chrome/estimated_input_latency_test.html |
diff --git a/tracing/tracing/extras/chrome/estimated_input_latency_test.html b/tracing/tracing/extras/chrome/estimated_input_latency_test.html |
index eaece9222cdce0df4f819414aaad96c98d755ca6..7a4b167f009886e4e898e5f409f8850923cfbf05 100644 |
--- a/tracing/tracing/extras/chrome/estimated_input_latency_test.html |
+++ b/tracing/tracing/extras/chrome/estimated_input_latency_test.html |
@@ -8,6 +8,7 @@ found in the LICENSE file. |
<link rel="import" href="/tracing/base/assert_utils.html"> |
<link rel="import" href="/tracing/core/test_utils.html"> |
<link rel="import" href="/tracing/extras/chrome/estimated_input_latency.html"> |
+<link rel="import" href="/tracing/metrics/system_health/loading_metric.html"> |
<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html"> |
<script> |
@@ -15,6 +16,7 @@ found in the LICENSE file. |
tr.b.unittest.testSuite(function() { |
+ var getInteractiveTimestamps = tr.e.chrome.getInteractiveTimestamps; |
var getPostInteractiveTaskWindows = tr.e.chrome.getPostInteractiveTaskWindows; |
var getNavStartTimestamps = tr.e.chrome.getNavStartTimestamps; |
var assertRangeEquals = tr.b.assertRangeEquals; |
@@ -37,45 +39,135 @@ tr.b.unittest.testSuite(function() { |
}); |
} |
+ function newSchedulerTask(startTime, duration) { |
+ return tr.c.TestUtils.newSliceEx({ |
+ cat: 'toplevel', |
+ title: 'TaskQueueManager::ProcessTaskFromWorkQueue', |
+ start: startTime, |
+ duration: duration |
+ }); |
+ } |
+ |
+ /** |
+ * Adds a FrameLoader snapshot to rendererProcess that is used by test FMP |
+ * candidate slices. |
+ */ |
+ function addTestFrame(rendererProcess) { |
+ rendererProcess.objects.addSnapshot( |
+ 'ptr', 'loading', 'FrameLoader', 300, { |
+ isLoadingMainFrame: true, |
+ frame: {id_ref: '0xdeadbeef'}, |
+ documentLoaderURL: 'http://example.com' |
+ }); |
+ } |
+ |
+ function addNavigationStart(mainThread, startNavTime) { |
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
+ cat: 'blink.user_timing', |
+ title: 'navigationStart', |
+ start: startNavTime, |
+ duration: 0.0, |
+ args: {frame: '0xdeadbeef'} |
+ })); |
+ } |
+ |
+ function addFMPCandidate(mainThread, fmpTime) { |
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
+ cat: 'loading', |
+ title: 'firstMeaningfulPaintCandidate', |
+ start: fmpTime, |
+ duration: 0.0, |
+ args: {frame: '0xdeadbeef'} |
+ })); |
+ } |
+ |
+ function addSchedulerTask(mainThread, startTime, duration) { |
+ mainThread.sliceGroup.pushSlice(newSchedulerTask(startTime, duration)); |
+ } |
+ |
+ function addDummyTask(mainThread, startTime) { |
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
+ cat: 'dummy', |
+ title: 'dummyTitle', |
+ start: startTime, |
+ duration: 0.0 |
+ })); |
+ } |
+ |
test('getNavStartTimestamps', () => { |
var model = createTestModel(rendererProcess => { |
var mainThread = rendererProcess.getOrCreateThread(MAIN_THREAD_ID); |
- mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
- cat: 'blink.user_timing', |
- title: 'navigationStart', |
- start: 0, |
- duration: 0.0, |
- args: {frame: '0xdeadbeef'} |
- })); |
- |
- mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
- cat: 'blink.user_timing', |
- title: 'navigationStart', |
- start: 10, |
- duration: 0.0, |
- args: {frame: '0xdeadbeef'} |
- })); |
- |
- mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
- cat: 'blink.user_timing', |
- title: 'navigationStart', |
- start: 30, |
- duration: 0.0, |
- args: {frame: '0xdeadbeef'} |
- })); |
+ addNavigationStart(mainThread, 0); |
+ addNavigationStart(mainThread, 10); |
+ addNavigationStart(mainThread, 30); |
}); |
var chromeHelper = model.getOrCreateHelper( |
tr.model.helpers.ChromeModelHelper); |
var rendererHelper = chromeHelper.rendererHelpers[RENDERER_PROCESS_ID]; |
var navStartTimestamps = getNavStartTimestamps(rendererHelper); |
- assert.equal(navStartTimestamps.length, 3); |
// It is ok to assert equality for floating point numbers here because |
// the timestamps should remain unmodified. |
assert.deepEqual(navStartTimestamps, [0, 10, 30]); |
}); |
+ /** |
+ * Checks getInteractiveTimestamps works as intended. If the definition of |
+ * TTI metric changes, this test may begin to fail and we may need to adjust |
+ * our EIL implementation. |
+ */ |
+ test('getInteractiveTimestamps', () => { |
+ var model = createTestModel(rendererProcess => { |
+ addTestFrame(rendererProcess); |
+ |
+ var mainThread = rendererProcess.getOrCreateThread(MAIN_THREAD_ID); |
+ addNavigationStart(mainThread, 0); |
+ addFMPCandidate(mainThread, 5000); |
+ |
+ addNavigationStart(mainThread, 100000); |
+ addFMPCandidate(mainThread, 110000); |
+ |
+ // To detect when a page has become interactive, we need to find a large |
+ // enough window of no long tasks. Adding a dummy task sufficiently far |
+ // away extends the bounds of the model so that it can contain this |
+ // window. In a non-test scenario, we always record traces for long enough |
+ // that this is not an issue. |
+ addDummyTask(mainThread, 900000); |
+ }); |
+ |
+ var interactiveTimestampsMap = getInteractiveTimestamps(model); |
+ var interactiveTimestamps = |
+ interactiveTimestampsMap.get(RENDERER_PROCESS_ID); |
+ assert.deepEqual( |
+ interactiveTimestamps.sort((a, b) => a - b), [5000, 110000]); |
+ }); |
+ |
+ test('getInteractiveTimestampsMultiRenderer', () => { |
+ var model = tr.c.TestUtils.newModel(model => { |
+ var rendererProcesses = []; |
+ for (var pid = 1; pid <= 5; pid++) { |
+ var rendererProcess = model.getOrCreateProcess(pid); |
+ var mainThread = rendererProcess.getOrCreateThread(pid + 10); |
+ mainThread.name = 'CrRendererMain'; |
+ |
+ addTestFrame(rendererProcess); |
+ addNavigationStart(mainThread, pid * 1000); |
+ addFMPCandidate(mainThread, pid * 1000 + 2000); |
+ addNavigationStart(mainThread, pid * 2000); |
+ addFMPCandidate(mainThread, pid * 2000 + 2000); |
+ addDummyTask(mainThread, 100000); |
+ } |
+ }); |
+ |
+ var interactiveTimestampsMap = getInteractiveTimestamps(model); |
+ for (var [pid, interactiveTimestamps] of interactiveTimestampsMap) { |
+ assert.deepEqual( |
+ interactiveTimestamps.sort((a, b) => a - b), |
+ [pid * 1000 + 2000, pid * 2000 + 2000]); |
+ } |
+ }); |
+ |
test('singlePostInteractiveWindow', () => { |
var interactiveTimestamps = [50]; |
var navStartTimestamps = [0]; |