| # Copyright 2014 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. |
| |
| import os |
| import unittest |
| |
| from telemetry import test |
| from telemetry.core import wpr_modes |
| from telemetry.timeline import model as model_module |
| from telemetry.timeline import async_slice |
| from telemetry.page import page_measurement_unittest_base |
| from telemetry.page import page_set |
| from telemetry.page import page as page_module |
| # pylint: disable=W0401,W0614 |
| from telemetry.page.actions.all_page_actions import * |
| from telemetry.results import page_measurement_results |
| from telemetry.unittest import options_for_unittests |
| from telemetry.web_perf import timeline_based_measurement as tbm_module |
| from telemetry.web_perf.metrics import timeline_based_metric |
| |
| |
| class TimelineBasedMetricsTests(unittest.TestCase): |
| |
| def setUp(self): |
| model = model_module.TimelineModel() |
| renderer_thread = model.GetOrCreateProcess(1).GetOrCreateThread(2) |
| renderer_thread.name = 'CrRendererMain' |
| |
| # [ X ] |
| # [ Y ] |
| renderer_thread.BeginSlice('cat1', 'x.y', 10, 0) |
| renderer_thread.EndSlice(20, 20) |
| |
| renderer_thread.async_slices.append(async_slice.AsyncSlice( |
| 'cat', 'Interaction.LogicalName1/is_smooth', |
| timestamp=0, duration=20, |
| start_thread=renderer_thread, end_thread=renderer_thread, |
| thread_start=5, thread_duration=15)) |
| renderer_thread.async_slices.append(async_slice.AsyncSlice( |
| 'cat', 'Interaction.LogicalName2/is_responsive', |
| timestamp=25, duration=5, |
| start_thread=renderer_thread, end_thread=renderer_thread, |
| thread_start=25, thread_duration=5)) |
| model.FinalizeImport() |
| |
| self.model = model |
| self.renderer_thread = renderer_thread |
| |
| def testFindTimelineInteractionRecords(self): |
| metric = tbm_module._TimelineBasedMetrics( # pylint: disable=W0212 |
| self.model, self.renderer_thread, lambda _: []) |
| interactions = metric.FindTimelineInteractionRecords() |
| self.assertEquals(2, len(interactions)) |
| self.assertTrue(interactions[0].is_smooth) |
| self.assertEquals(0, interactions[0].start) |
| self.assertEquals(20, interactions[0].end) |
| |
| self.assertTrue(interactions[1].is_responsive) |
| self.assertEquals(25, interactions[1].start) |
| self.assertEquals(30, interactions[1].end) |
| |
| def testAddResults(self): |
| results = page_measurement_results.PageMeasurementResults() |
| |
| class FakeSmoothMetric(timeline_based_metric.TimelineBasedMetric): |
| |
| def AddResults(self, model, renderer_thread, |
| interaction_records, results): |
| results.Add('FakeSmoothMetric', 'ms', 1) |
| |
| class FakeLoadingMetric(timeline_based_metric.TimelineBasedMetric): |
| |
| def AddResults(self, model, renderer_thread, |
| interaction_records, results): |
| for r in interaction_records: |
| assert r.logical_name == 'LogicalName2' |
| results.Add('FakeLoadingMetric', 'ms', 2) |
| |
| def CreateMetricsForTimelineInteractionRecord(interaction): |
| res = [] |
| if interaction.is_smooth: |
| res.append(FakeSmoothMetric()) |
| if interaction.is_responsive: |
| res.append(FakeLoadingMetric()) |
| return res |
| |
| metric = tbm_module._TimelineBasedMetrics( # pylint: disable=W0212 |
| self.model, self.renderer_thread, |
| CreateMetricsForTimelineInteractionRecord) |
| ps = page_set.PageSet(file_path=os.path.dirname(__file__)) |
| ps.AddPageWithDefaultRunNavigate('http://www.bar.com/') |
| |
| results.WillMeasurePage(ps.pages[0]) |
| metric.AddResults(results) |
| results.DidMeasurePage() |
| |
| v = results.FindAllPageSpecificValuesNamed('LogicalName1-FakeSmoothMetric') |
| self.assertEquals(len(v), 1) |
| v = results.FindAllPageSpecificValuesNamed('LogicalName2-FakeLoadingMetric') |
| self.assertEquals(len(v), 1) |
| |
| |
| class TestTimelinebasedMeasurementPage(page_module.Page): |
| |
| def __init__(self, ps, base_dir): |
| super(TestTimelinebasedMeasurementPage, self).__init__( |
| 'file://interaction_enabled_page.html', ps, base_dir) |
| |
| def RunSmoothness(self, action_runner): |
| action_runner.Wait(2) |
| action_runner.TapElement('#drawer') |
| action_runner.Wait(1) |
| |
| |
| class TimelineBasedMeasurementTest( |
| page_measurement_unittest_base.PageMeasurementUnitTestBase): |
| |
| def setUp(self): |
| self._options = options_for_unittests.GetCopy() |
| self._options.browser_options.wpr_mode = wpr_modes.WPR_OFF |
| |
| # Disabled due to flakiness: crbug.com/368386 |
| @test.Disabled |
| def testSmoothnessTimelineBasedMeasurementForSmoke(self): |
| ps = self.CreatePageSetFromFileInUnittestDataDir( |
| 'interaction_enabled_page.html') |
| setattr(ps.pages[0], 'RunSmoothness', { |
| 'action': 'wait', 'javascript': 'window.animationDone'}) |
| measurement = tbm_module.TimelineBasedMeasurement() |
| results = self.RunMeasurement(measurement, ps, |
| options=self._options) |
| self.assertEquals(0, len(results.failures)) |
| v = results.FindAllPageSpecificValuesNamed('CenterAnimation-jank') |
| self.assertEquals(len(v), 1) |
| v = results.FindAllPageSpecificValuesNamed('DrawerAnimation-jank') |
| self.assertEquals(len(v), 1) |
| |
| # Disabled since mainthread_jank metric is not supported on windows platform. |
| @test.Disabled('win') |
| def testMainthreadJankTimelineBasedMeasurement(self): |
| ps = self.CreateEmptyPageSet() |
| ps.AddPage(TestTimelinebasedMeasurementPage(ps, ps.base_dir)) |
| |
| measurement = tbm_module.TimelineBasedMeasurement() |
| results = self.RunMeasurement(measurement, ps, |
| options=self._options) |
| self.assertEquals(0, len(results.failures)) |
| |
| # In interaction_enabled_page.html, we create a jank loop based on |
| # window.performance.now() (basically loop for x milliseconds). |
| # Since window.performance.now() uses wall-time |
| # instead of thread time, we set time to looping to 100ms in |
| # interaction_enabled_page.html and only assert the biggest jank > 50ms here |
| # to account for the fact that the browser may deschedule during the jank |
| # loop. |
| v = results.FindAllPageSpecificValuesNamed( |
| 'JankThreadJSRun-responsive-biggest_jank_thread_time') |
| self.assertGreaterEqual(v[0].value, 50) |
| |
| v = results.FindAllPageSpecificValuesNamed( |
| 'JankThreadJSRun-responsive-total_big_jank_thread_time') |
| self.assertGreaterEqual(v[0].value, 50) |