| OLD | NEW |
| (Empty) |
| 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 os | |
| 6 import unittest | |
| 7 | |
| 8 from telemetry import story | |
| 9 from telemetry.internal.results import page_test_results | |
| 10 from telemetry.page import page as page_module | |
| 11 from telemetry.timeline import async_slice | |
| 12 from telemetry.timeline import model as model_module | |
| 13 from telemetry.value import improvement_direction | |
| 14 from telemetry.value import scalar | |
| 15 from telemetry.web_perf.metrics import timeline_based_metric | |
| 16 from telemetry.web_perf import timeline_based_measurement as tbm_module | |
| 17 | |
| 18 | |
| 19 class FakeSmoothMetric(timeline_based_metric.TimelineBasedMetric): | |
| 20 | |
| 21 def AddResults(self, model, renderer_thread, interaction_records, results): | |
| 22 results.AddValue(scalar.ScalarValue( | |
| 23 results.current_page, 'FakeSmoothMetric', 'ms', 1, | |
| 24 improvement_direction=improvement_direction.DOWN)) | |
| 25 results.AddValue(scalar.ScalarValue( | |
| 26 results.current_page, 'SmoothMetricRecords', 'count', | |
| 27 len(interaction_records), | |
| 28 improvement_direction=improvement_direction.DOWN)) | |
| 29 | |
| 30 | |
| 31 class FakeLoadingMetric(timeline_based_metric.TimelineBasedMetric): | |
| 32 | |
| 33 def AddResults(self, model, renderer_thread, interaction_records, results): | |
| 34 results.AddValue(scalar.ScalarValue( | |
| 35 results.current_page, 'FakeLoadingMetric', 'ms', 2, | |
| 36 improvement_direction=improvement_direction.DOWN)) | |
| 37 results.AddValue(scalar.ScalarValue( | |
| 38 results.current_page, 'LoadingMetricRecords', 'count', | |
| 39 len(interaction_records), | |
| 40 improvement_direction=improvement_direction.DOWN)) | |
| 41 | |
| 42 | |
| 43 class FakeStartupMetric(timeline_based_metric.TimelineBasedMetric): | |
| 44 | |
| 45 def AddResults(self, model, renderer_thread, interaction_records, results): | |
| 46 pass | |
| 47 | |
| 48 def AddWholeTraceResults(self, model, results): | |
| 49 results.AddValue(scalar.ScalarValue( | |
| 50 results.current_page, 'FakeStartupMetric', 'ms', 3, | |
| 51 improvement_direction=improvement_direction.DOWN)) | |
| 52 | |
| 53 | |
| 54 class TimelineBasedMetricTestData(object): | |
| 55 | |
| 56 def __init__(self, options): | |
| 57 self._model = model_module.TimelineModel() | |
| 58 renderer_process = self._model.GetOrCreateProcess(1) | |
| 59 self._renderer_thread = renderer_process.GetOrCreateThread(2) | |
| 60 self._renderer_thread.name = 'CrRendererMain' | |
| 61 self._foo_thread = renderer_process.GetOrCreateThread(3) | |
| 62 self._foo_thread.name = 'CrFoo' | |
| 63 | |
| 64 self._results_wrapper = tbm_module._TBMResultWrapper() | |
| 65 self._results = page_test_results.PageTestResults() | |
| 66 self._story_set = None | |
| 67 self._threads_to_records_map = None | |
| 68 self._tbm_options = options | |
| 69 | |
| 70 @property | |
| 71 def model(self): | |
| 72 return self._model | |
| 73 | |
| 74 @property | |
| 75 def renderer_thread(self): | |
| 76 return self._renderer_thread | |
| 77 | |
| 78 @property | |
| 79 def foo_thread(self): | |
| 80 return self._foo_thread | |
| 81 | |
| 82 @property | |
| 83 def threads_to_records_map(self): | |
| 84 return self._threads_to_records_map | |
| 85 | |
| 86 @property | |
| 87 def results(self): | |
| 88 return self._results | |
| 89 | |
| 90 def AddInteraction(self, thread, marker='', ts=0, duration=5): | |
| 91 assert thread in (self._renderer_thread, self._foo_thread) | |
| 92 thread.async_slices.append(async_slice.AsyncSlice( | |
| 93 'category', marker, timestamp=ts, duration=duration, | |
| 94 start_thread=self._renderer_thread, end_thread=self._renderer_thread, | |
| 95 thread_start=ts, thread_duration=duration)) | |
| 96 | |
| 97 def FinalizeImport(self): | |
| 98 self._model.FinalizeImport() | |
| 99 self._threads_to_records_map = ( | |
| 100 tbm_module._GetRendererThreadsToInteractionRecordsMap(self._model)) | |
| 101 self._story_set = story.StorySet(base_dir=os.path.dirname(__file__)) | |
| 102 self._story_set.AddStory(page_module.Page( | |
| 103 'http://www.bar.com/', self._story_set, self._story_set.base_dir)) | |
| 104 self._results.WillRunPage(self._story_set.stories[0]) | |
| 105 | |
| 106 def AddResults(self): | |
| 107 all_metrics = self._tbm_options.GetTimelineBasedMetrics() | |
| 108 | |
| 109 for thread, records in self._threads_to_records_map.iteritems(): | |
| 110 # pylint: disable=protected-access | |
| 111 metric = tbm_module._TimelineBasedMetrics( | |
| 112 self._model, thread, records, self._results_wrapper, all_metrics) | |
| 113 metric.AddResults(self._results) | |
| 114 | |
| 115 for metric in all_metrics: | |
| 116 metric.AddWholeTraceResults(self._model, self._results) | |
| 117 | |
| 118 self._results.DidRunPage(self._story_set.stories[0]) | |
| 119 | |
| 120 | |
| 121 class TimelineBasedMetricsTests(unittest.TestCase): | |
| 122 | |
| 123 def setUp(self): | |
| 124 self.actual_get_all_tbm_metrics = tbm_module._GetAllTimelineBasedMetrics | |
| 125 self._options = tbm_module.Options() | |
| 126 self._options.SetTimelineBasedMetrics( | |
| 127 (FakeSmoothMetric(), FakeLoadingMetric(), FakeStartupMetric())) | |
| 128 | |
| 129 def tearDown(self): | |
| 130 tbm_module._GetAllTimelineBasedMetrics = self.actual_get_all_tbm_metrics | |
| 131 | |
| 132 def testGetRendererThreadsToInteractionRecordsMap(self): | |
| 133 d = TimelineBasedMetricTestData(self._options) | |
| 134 # Insert 2 interaction records to renderer_thread and 1 to foo_thread | |
| 135 d.AddInteraction(d.renderer_thread, ts=0, duration=20, | |
| 136 marker='Interaction.LogicalName1') | |
| 137 d.AddInteraction(d.renderer_thread, ts=25, duration=5, | |
| 138 marker='Interaction.LogicalName2') | |
| 139 d.AddInteraction(d.foo_thread, ts=50, duration=15, | |
| 140 marker='Interaction.LogicalName3') | |
| 141 d.FinalizeImport() | |
| 142 | |
| 143 self.assertEquals(2, len(d.threads_to_records_map)) | |
| 144 | |
| 145 # Assert the 2 interaction records of renderer_thread are in the map. | |
| 146 self.assertIn(d.renderer_thread, d.threads_to_records_map) | |
| 147 interactions = d.threads_to_records_map[d.renderer_thread] | |
| 148 self.assertEquals(2, len(interactions)) | |
| 149 self.assertEquals(0, interactions[0].start) | |
| 150 self.assertEquals(20, interactions[0].end) | |
| 151 | |
| 152 self.assertEquals(25, interactions[1].start) | |
| 153 self.assertEquals(30, interactions[1].end) | |
| 154 | |
| 155 # Assert the 1 interaction records of foo_thread is in the map. | |
| 156 self.assertIn(d.foo_thread, d.threads_to_records_map) | |
| 157 interactions = d.threads_to_records_map[d.foo_thread] | |
| 158 self.assertEquals(1, len(interactions)) | |
| 159 self.assertEquals(50, interactions[0].start) | |
| 160 self.assertEquals(65, interactions[0].end) | |
| 161 | |
| 162 def testAddResults(self): | |
| 163 d = TimelineBasedMetricTestData(self._options) | |
| 164 d.AddInteraction(d.renderer_thread, ts=0, duration=20, | |
| 165 marker='Interaction.LogicalName1') | |
| 166 d.AddInteraction(d.foo_thread, ts=25, duration=5, | |
| 167 marker='Interaction.LogicalName2') | |
| 168 d.FinalizeImport() | |
| 169 d.AddResults() | |
| 170 self.assertEquals(1, len(d.results.FindAllPageSpecificValuesFromIRNamed( | |
| 171 'LogicalName1', 'FakeSmoothMetric'))) | |
| 172 self.assertEquals(1, len(d.results.FindAllPageSpecificValuesFromIRNamed( | |
| 173 'LogicalName2', 'FakeLoadingMetric'))) | |
| 174 self.assertEquals(1, len(d.results.FindAllPageSpecificValuesNamed( | |
| 175 'FakeStartupMetric'))) | |
| 176 | |
| 177 def testDuplicateInteractionsInDifferentThreads(self): | |
| 178 d = TimelineBasedMetricTestData(self._options) | |
| 179 d.AddInteraction(d.renderer_thread, ts=10, duration=5, | |
| 180 marker='Interaction.LogicalName/repeatable') | |
| 181 d.AddInteraction(d.foo_thread, ts=20, duration=5, | |
| 182 marker='Interaction.LogicalName') | |
| 183 self.assertRaises(tbm_module.InvalidInteractions, d.FinalizeImport) | |
| 184 | |
| 185 def testDuplicateRepeatableInteractionsInDifferentThreads(self): | |
| 186 d = TimelineBasedMetricTestData(self._options) | |
| 187 d.AddInteraction(d.renderer_thread, ts=10, duration=5, | |
| 188 marker='Interaction.LogicalName/repeatable') | |
| 189 d.AddInteraction(d.foo_thread, ts=20, duration=5, | |
| 190 marker='Interaction.LogicalName/repeatable') | |
| 191 self.assertRaises(tbm_module.InvalidInteractions, d.FinalizeImport) | |
| 192 | |
| 193 def testDuplicateUnrepeatableInteractionsInSameThread(self): | |
| 194 d = TimelineBasedMetricTestData(self._options) | |
| 195 d.AddInteraction(d.renderer_thread, ts=10, duration=5, | |
| 196 marker='Interaction.LogicalName') | |
| 197 d.AddInteraction(d.renderer_thread, ts=20, duration=5, | |
| 198 marker='Interaction.LogicalName') | |
| 199 d.FinalizeImport() | |
| 200 self.assertRaises(tbm_module.InvalidInteractions, d.AddResults) | |
| 201 | |
| 202 def testDuplicateRepeatableInteractions(self): | |
| 203 d = TimelineBasedMetricTestData(self._options) | |
| 204 d.AddInteraction(d.renderer_thread, ts=10, duration=5, | |
| 205 marker='Interaction.LogicalName/repeatable') | |
| 206 d.AddInteraction(d.renderer_thread, ts=20, duration=5, | |
| 207 marker='Interaction.LogicalName/repeatable') | |
| 208 d.FinalizeImport() | |
| 209 d.AddResults() | |
| 210 self.assertEquals(1, len(d.results.pages_that_succeeded)) | |
| OLD | NEW |