1# Copyright 2013 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4import sys 5 6from measurements import smoothness 7from metrics import power 8from telemetry.core import exceptions 9from telemetry.core import wpr_modes 10from telemetry.page import page 11from telemetry.page import page_test 12from telemetry.unittest import options_for_unittests 13from telemetry.unittest import page_test_test_case 14from telemetry.unittest import test 15 16class FakeTracingController(object): 17 def __init__(self): 18 self.category_filter = None 19 def Start(self, _options, category_filter, _timeout): 20 self.category_filter = category_filter 21 22 23class FakePlatform(object): 24 def __init__(self): 25 self.tracing_controller = FakeTracingController() 26 def IsRawDisplayFrameRateSupported(self): 27 return False 28 def CanMonitorPower(self): 29 return False 30 31 32class FakeBrowser(object): 33 def __init__(self): 34 self.platform = FakePlatform() 35 36 37class AnimatedPage(page.Page): 38 def __init__(self, page_set): 39 super(AnimatedPage, self).__init__( 40 url='file://animated_page.html', 41 page_set=page_set, base_dir=page_set.base_dir) 42 43 def RunSmoothness(self, action_runner): 44 action_runner.Wait(.2) 45 46 47class FakeTab(object): 48 def __init__(self): 49 self.browser = FakeBrowser() 50 51 def ExecuteJavaScript(self, js): 52 pass 53 54class SmoothnessUnitTest(page_test_test_case.PageTestTestCase): 55 """Smoke test for smoothness measurement 56 57 Runs smoothness measurement on a simple page and verifies 58 that all metrics were added to the results. The test is purely functional, 59 i.e. it only checks if the metrics are present and non-zero. 60 """ 61 def testSyntheticDelayConfiguration(self): 62 test_page = page.Page('http://dummy', None) 63 test_page.synthetic_delays = { 64 'cc.BeginMainFrame': { 'target_duration': 0.012 }, 65 'cc.DrawAndSwap': { 'target_duration': 0.012, 'mode': 'alternating' }, 66 'gpu.PresentingFrame': { 'target_duration': 0.012 } 67 } 68 69 tab = FakeTab() 70 measurement = smoothness.Smoothness() 71 measurement.WillStartBrowser(tab.browser.platform) 72 measurement.WillNavigateToPage(test_page, tab) 73 measurement.WillRunActions(test_page, tab) 74 75 expected_category_filter = set([ 76 'DELAY(cc.BeginMainFrame;0.012000;static)', 77 'DELAY(cc.DrawAndSwap;0.012000;alternating)', 78 'DELAY(gpu.PresentingFrame;0.012000;static)', 79 'benchmark' 80 ]) 81 tracing_controller = tab.browser.platform.tracing_controller 82 actual_category_filter = ( 83 tracing_controller.category_filter.included_categories) 84 85 # FIXME: Put blink.console into the expected above and remove these two 86 # remove entries when the blink.console change has rolled into chromium. 87 actual_category_filter.remove('webkit.console') 88 actual_category_filter.remove('blink.console') 89 90 if expected_category_filter != actual_category_filter: 91 sys.stderr.write("Expected category filter: %s\n" % 92 repr(expected_category_filter)) 93 sys.stderr.write("Actual category filter filter: %s\n" % 94 repr(actual_category_filter)) 95 self.assertEquals(expected_category_filter, actual_category_filter) 96 97 def setUp(self): 98 self._options = options_for_unittests.GetCopy() 99 self._options.browser_options.wpr_mode = wpr_modes.WPR_OFF 100 101 def testSmoothness(self): 102 ps = self.CreatePageSetFromFileInUnittestDataDir('scrollable_page.html') 103 measurement = smoothness.Smoothness() 104 results = self.RunMeasurement(measurement, ps, options=self._options) 105 self.assertEquals(0, len(results.failures)) 106 107 frame_times = results.FindAllPageSpecificValuesNamed('frame_times') 108 self.assertEquals(len(frame_times), 1) 109 self.assertGreater(frame_times[0].GetRepresentativeNumber(), 0) 110 111 mean_frame_time = results.FindAllPageSpecificValuesNamed('mean_frame_time') 112 self.assertEquals(len(mean_frame_time), 1) 113 self.assertGreater(mean_frame_time[0].GetRepresentativeNumber(), 0) 114 115 jank = results.FindAllPageSpecificValuesNamed('jank') 116 self.assertEquals(len(jank), 1) 117 self.assertGreater(jank[0].GetRepresentativeNumber(), 0) 118 119 mostly_smooth = results.FindAllPageSpecificValuesNamed('mostly_smooth') 120 self.assertEquals(len(mostly_smooth), 1) 121 self.assertGreaterEqual(mostly_smooth[0].GetRepresentativeNumber(), 0) 122 123 mean_input_event_latency = results.FindAllPageSpecificValuesNamed( 124 'mean_input_event_latency') 125 if mean_input_event_latency: 126 self.assertEquals(len(mean_input_event_latency), 1) 127 self.assertGreater( 128 mean_input_event_latency[0].GetRepresentativeNumber(), 0) 129 130 @test.Disabled('mac', 'chromeos') # http://crbug.com/403903 131 def testSmoothnessForPageWithNoGesture(self): 132 ps = self.CreateEmptyPageSet() 133 ps.AddPage(AnimatedPage(ps)) 134 135 measurement = smoothness.Smoothness() 136 results = self.RunMeasurement(measurement, ps, options=self._options) 137 self.assertEquals(0, len(results.failures)) 138 139 mostly_smooth = results.FindAllPageSpecificValuesNamed('mostly_smooth') 140 self.assertEquals(len(mostly_smooth), 1) 141 self.assertGreaterEqual(mostly_smooth[0].GetRepresentativeNumber(), 0) 142 143 def testCleanUpTrace(self): 144 self.TestTracingCleanedUp(smoothness.Smoothness, self._options) 145 146 def testCleanUpPowerMetric(self): 147 class FailPage(page.Page): 148 def __init__(self, page_set): 149 super(FailPage, self).__init__( 150 url='file://blank.html', 151 page_set=page_set, base_dir=page_set.base_dir) 152 def RunSmoothness(self, _): 153 raise exceptions.IntentionalException 154 155 class FakePowerMetric(power.PowerMetric): 156 start_called = False 157 stop_called = True 158 def Start(self, _1, _2): 159 self.start_called = True 160 def Stop(self, _1, _2): 161 self.stop_called = True 162 163 ps = self.CreateEmptyPageSet() 164 ps.AddPage(FailPage(ps)) 165 166 class BuggyMeasurement(smoothness.Smoothness): 167 fake_power = None 168 # Inject fake power metric. 169 def WillStartBrowser(self, platform): 170 self.fake_power = self._power_metric = FakePowerMetric(platform) 171 172 measurement = BuggyMeasurement() 173 try: 174 self.RunMeasurement(measurement, ps) 175 except page_test.TestNotSupportedOnPlatformFailure: 176 pass 177 178 self.assertTrue(measurement.fake_power.start_called) 179 self.assertTrue(measurement.fake_power.stop_called) 180