1 # Copyright 2014 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. 4 5 import unittest 6 7 from telemetry.results import page_test_results 8 from telemetry.page import page as page_module 9 from telemetry.web_perf.metrics import smoothness 10 11 12 class _MockRenderingStats(object): 13 14 stats = ['frame_timestamps', 'frame_times', 'paint_times', 15 'painted_pixel_counts', 'record_times', 16 'recorded_pixel_counts', 'rasterize_times', 17 'rasterized_pixel_counts', 'approximated_pixel_percentages', 18 'input_event_latency', 'frame_queueing_durations', 19 'scroll_update_latency', 'gesture_scroll_update_latency'] 20 21 def __init__(self, **kwargs): 22 self.errors = {} 23 for stat in self.stats: 24 value = kwargs[stat] if stat in kwargs else None 25 setattr(self, stat, value) 26 27 28 #pylint: disable=W0212 29 class SmoothnessMetricUnitTest(unittest.TestCase): 30 31 def setUp(self): 32 self.metric = smoothness.SmoothnessMetric() 33 self.page = page_module.Page('file://blank.html') 34 self.good_timestamps = [[10, 20], [30, 40, 50]] 35 self.not_enough_frames_timestamps = [[10], [20, 30, 40]] 36 37 def testPopulateResultsFromStats(self): 38 stats = _MockRenderingStats() 39 for stat in _MockRenderingStats.stats: 40 # Just set fake data for all of the relevant arrays of stats typically 41 # found in a RenderingStats object. 42 setattr(stats, stat, [[10, 20], [30, 40, 50]]) 43 results = page_test_results.PageTestResults() 44 results.WillRunPage(self.page) 45 self.metric._PopulateResultsFromStats(results, stats) 46 current_page_run = results.current_page_run 47 self.assertTrue(current_page_run.ok) 48 self.assertEquals(11, len(current_page_run.values)) 49 50 def testHasEnoughFrames(self): 51 # This list will pass since every sub-array has at least 2 frames. 52 has_enough_frames = self.metric._HasEnoughFrames(self.good_timestamps) 53 self.assertTrue(has_enough_frames) 54 55 def testHasEnoughFramesWithNotEnoughFrames(self): 56 # This list will fail since the first sub-array only has a single frame. 57 has_enough_frames = self.metric._HasEnoughFrames( 58 self.not_enough_frames_timestamps) 59 self.assertFalse(has_enough_frames) 60 61 def testComputeLatencyMetric(self): 62 stats = _MockRenderingStats(frame_timestamps=self.good_timestamps, 63 input_event_latency=[[10, 20], [30, 40, 50]]) 64 mean_value, discrepancy_value = self.metric._ComputeLatencyMetric( 65 self.page, stats, 'input_event_latency', stats.input_event_latency) 66 self.assertEquals(30, mean_value.value) 67 self.assertEquals(60, discrepancy_value.value) 68 69 def testComputeLatencyMetricWithMissingData(self): 70 stats = _MockRenderingStats(frame_timestamps=self.good_timestamps, 71 input_event_latency=[[], []]) 72 value = self.metric._ComputeLatencyMetric( 73 self.page, stats, 'input_event_latency', stats.input_event_latency) 74 self.assertEquals((), value) 75 76 def testComputeLatencyMetricWithNotEnoughFrames(self): 77 stats = _MockRenderingStats( 78 frame_timestamps=self.not_enough_frames_timestamps, 79 input_event_latency=[[], []]) 80 mean_value, discrepancy_value = self.metric._ComputeLatencyMetric( 81 self.page, stats, 'input_event_latency', stats.input_event_latency) 82 self.assertEquals(None, mean_value.value) 83 self.assertEquals(smoothness.NOT_ENOUGH_FRAMES_MESSAGE, 84 mean_value.none_value_reason) 85 self.assertEquals(None, discrepancy_value.value) 86 self.assertEquals(smoothness.NOT_ENOUGH_FRAMES_MESSAGE, 87 discrepancy_value.none_value_reason) 88 89 def testComputeGestureScrollUpdateLatency(self): 90 stats = _MockRenderingStats( 91 frame_timestamps=self.good_timestamps, 92 gesture_scroll_update_latency=[[10, 20], [30, 40, 50]]) 93 gesture_value = self.metric._ComputeFirstGestureScrollUpdateLatency( 94 self.page, stats)[0] 95 self.assertEquals(10, gesture_value.value) 96 97 def testComputeGestureScrollUpdateLatencyWithMissingData(self): 98 stats = _MockRenderingStats( 99 frame_timestamps=self.good_timestamps, 100 gesture_scroll_update_latency=[[], []]) 101 value = self.metric._ComputeFirstGestureScrollUpdateLatency( 102 self.page, stats) 103 self.assertEquals((), value) 104 105 def testComputeGestureScrollUpdateLatencyWithNotEnoughFrames(self): 106 stats = _MockRenderingStats( 107 frame_timestamps=self.not_enough_frames_timestamps, 108 gesture_scroll_update_latency=[[10, 20], [30, 40, 50]]) 109 gesture_value = self.metric._ComputeFirstGestureScrollUpdateLatency( 110 self.page, stats)[0] 111 self.assertEquals(None, gesture_value.value) 112 self.assertEquals(smoothness.NOT_ENOUGH_FRAMES_MESSAGE, 113 gesture_value.none_value_reason) 114 115 def testComputeQueueingDuration(self): 116 stats = _MockRenderingStats(frame_timestamps=self.good_timestamps, 117 frame_queueing_durations=[[10, 20], [30, 40]]) 118 list_of_scalar_values = self.metric._ComputeQueueingDuration(self.page, 119 stats) 120 self.assertEquals([10, 20, 30, 40], list_of_scalar_values.values) 121 122 def testComputeQueueingDurationWithMissingData(self): 123 stats = _MockRenderingStats(frame_timestamps=self.good_timestamps, 124 frame_queueing_durations=[[], []]) 125 list_of_scalar_values = self.metric._ComputeQueueingDuration( 126 self.page, stats) 127 self.assertEquals(None, list_of_scalar_values.values) 128 self.assertEquals('No frame queueing durations recorded.', 129 list_of_scalar_values.none_value_reason) 130 131 def testComputeQueueingDurationWithMissingDataAndErrorValue(self): 132 stats = _MockRenderingStats(frame_timestamps=self.good_timestamps, 133 frame_queueing_durations=[[], []]) 134 stats.errors['frame_queueing_durations'] = ( 135 'Current chrome version does not support the queueing delay metric.') 136 list_of_scalar_values = self.metric._ComputeQueueingDuration( 137 self.page, stats) 138 self.assertEquals(None, list_of_scalar_values.values) 139 self.assertEquals( 140 'Current chrome version does not support the queueing delay metric.', 141 list_of_scalar_values.none_value_reason) 142 143 def testComputeQueueingDurationWithNotEnoughFrames(self): 144 stats = _MockRenderingStats( 145 frame_timestamps=self.not_enough_frames_timestamps, 146 frame_queueing_durations=[[10, 20], [30, 40, 50]]) 147 list_of_scalar_values = self.metric._ComputeQueueingDuration(self.page, 148 stats) 149 self.assertEquals(None, list_of_scalar_values.values) 150 self.assertEquals(smoothness.NOT_ENOUGH_FRAMES_MESSAGE, 151 list_of_scalar_values.none_value_reason) 152 153 def testComputeFrameTimeMetric(self): 154 stats = _MockRenderingStats(frame_timestamps=self.good_timestamps, 155 frame_times=[[10, 20], [30, 40, 50]]) 156 frame_times_value, mean_frame_time_value, mostly_smooth_value = ( 157 self.metric._ComputeFrameTimeMetric(self.page, stats)) 158 self.assertEquals([10, 20, 30, 40, 50], frame_times_value.values) 159 self.assertEquals(30, mean_frame_time_value.value) 160 self.assertEquals(0, mostly_smooth_value.value) 161 162 def testComputeFrameTimeMetricWithNotEnoughFrames(self): 163 stats = _MockRenderingStats( 164 frame_timestamps=self.not_enough_frames_timestamps, 165 frame_times=[[10, 20], [30, 40, 50]]) 166 frame_times_value, mean_frame_time_value, mostly_smooth_value = ( 167 self.metric._ComputeFrameTimeMetric(self.page, stats)) 168 self.assertEquals(None, frame_times_value.values) 169 self.assertEquals(smoothness.NOT_ENOUGH_FRAMES_MESSAGE, 170 frame_times_value.none_value_reason) 171 self.assertEquals(None, mean_frame_time_value.value) 172 self.assertEquals(smoothness.NOT_ENOUGH_FRAMES_MESSAGE, 173 mean_frame_time_value.none_value_reason) 174 self.assertEquals(None, mostly_smooth_value.value) 175 self.assertEquals(smoothness.NOT_ENOUGH_FRAMES_MESSAGE, 176 mostly_smooth_value.none_value_reason) 177 178 def testComputeFrameTimeDiscrepancy(self): 179 stats = _MockRenderingStats(frame_timestamps=self.good_timestamps) 180 jank_value = self.metric._ComputeFrameTimeDiscrepancy(self.page, stats) 181 self.assertEquals(10, jank_value.value) 182 183 def testComputeFrameTimeDiscrepancyWithNotEnoughFrames(self): 184 stats = _MockRenderingStats( 185 frame_timestamps=self.not_enough_frames_timestamps) 186 jank_value = self.metric._ComputeFrameTimeDiscrepancy(self.page, stats) 187 self.assertEquals(None, jank_value.value) 188 self.assertEquals(smoothness.NOT_ENOUGH_FRAMES_MESSAGE, 189 jank_value.none_value_reason) 190 191 def testComputeMeanPixelsApproximated(self): 192 stats = _MockRenderingStats( 193 frame_timestamps=self.good_timestamps, 194 approximated_pixel_percentages=[[10, 20], [30, 40, 50]]) 195 mean_pixels_value = self.metric._ComputeMeanPixelsApproximated( 196 self.page, stats) 197 self.assertEquals(30, mean_pixels_value.value) 198 199 def testComputeMeanPixelsApproximatedWithNotEnoughFrames(self): 200 stats = _MockRenderingStats( 201 frame_timestamps=self.not_enough_frames_timestamps, 202 approximated_pixel_percentages=[[10, 20], [30, 40, 50]]) 203 mean_pixels_value = self.metric._ComputeMeanPixelsApproximated( 204 self.page, stats) 205 self.assertEquals(None, mean_pixels_value.value) 206 self.assertEquals(smoothness.NOT_ENOUGH_FRAMES_MESSAGE, 207 mean_pixels_value.none_value_reason) 208