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 |