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.
5 from measurements
import oilpan_gc_times
7 from telemetry
.internal
.results
import page_test_results
8 from telemetry
.page
import page
as page_module
9 from telemetry
.testing
import options_for_unittests
10 from telemetry
.testing
import page_test_test_case
11 from telemetry
.timeline
import model
12 from telemetry
.timeline
import slice as slice_data
14 import mock
# pylint: disable=import-error
17 class TestOilpanGCTimesPage(page_module
.Page
):
18 def __init__(self
, page_set
):
19 super(TestOilpanGCTimesPage
, self
).__init
__(
20 'file://blank.html', page_set
, page_set
.base_dir
)
22 def RunPageInteractions(self
, action_runner
):
23 with action_runner
.CreateGestureInteraction('ScrollAction'):
24 action_runner
.ScrollPage()
27 class OilpanGCTimesTestData(object):
28 def __init__(self
, thread_name
):
29 self
._model
= model
.TimelineModel()
30 self
._renderer
_process
= self
._model
.GetOrCreateProcess(1)
31 self
._renderer
_thread
= self
._renderer
_process
.GetOrCreateThread(2)
32 self
._renderer
_thread
.name
= thread_name
33 self
._results
= page_test_results
.PageTestResults()
39 def AddSlice(self
, name
, timestamp
, duration
, args
):
40 new_slice
= slice_data
.Slice(
49 self
._renderer
_thread
.all_slices
.append(new_slice
)
52 def AddAsyncSlice(self
, name
, timestamp
, duration
, args
):
53 new_slice
= slice_data
.Slice(
62 self
._renderer
_thread
.async_slices
.append(new_slice
)
65 def ClearResults(self
):
66 self
._results
= page_test_results
.PageTestResults()
68 class OilpanGCTimesTest(page_test_test_case
.PageTestTestCase
):
69 """Smoke test for Oilpan GC pause time measurements.
71 Runs OilpanGCTimes measurement on some simple pages and verifies
72 that all metrics were added to the results. The test is purely functional,
73 i.e. it only checks if the metrics are present and non-zero.
75 _KEY_MARK
= 'Heap::collectGarbage'
76 _KEY_LAZY_SWEEP
= 'ThreadHeap::lazySweepPages'
77 _KEY_COMPLETE_SWEEP
= 'ThreadState::completeSweep'
78 _KEY_COALESCE
= 'ThreadHeap::coalesce'
79 _KEY_MEASURE
= 'BlinkGCTimeMeasurement'
80 # Do not add 'forced' in reasons to measure.
81 _GC_REASONS
= ['precise', 'conservative', 'idle']
84 self
._options
= options_for_unittests
.GetCopy()
86 # Disable for accessing private API of _OilpanGCTimesBase.
87 # pylint: disable=protected-access
88 def testForParsingOldFormat(self
):
89 def getMetric(results
, name
):
90 metrics
= results
.FindAllPageSpecificValuesNamed(name
)
91 self
.assertEquals(1, len(metrics
))
92 return metrics
[0].GetBuildbotValue()
94 data
= self
._GenerateDataForParsingOldFormat
()
96 measurement
= oilpan_gc_times
._OilpanGCTimesBase
()
98 tab
= mock
.MagicMock()
100 'measurements.oilpan_gc_times.TimelineModel') as MockTimelineModel
:
101 MockTimelineModel
.return_value
= data
._model
102 measurement
.ValidateAndMeasurePage(None, tab
, data
.results
)
104 results
= data
.results
105 self
.assertEquals(7, len(getMetric(results
, 'oilpan_coalesce')))
106 self
.assertEquals(3, len(getMetric(results
, 'oilpan_precise_mark')))
107 self
.assertEquals(3, len(getMetric(results
, 'oilpan_precise_lazy_sweep')))
108 self
.assertEquals(3, len(getMetric(results
,
109 'oilpan_precise_complete_sweep')))
110 self
.assertEquals(1, len(getMetric(results
, 'oilpan_conservative_mark')))
111 self
.assertEquals(1, len(getMetric(results
,
112 'oilpan_conservative_lazy_sweep')))
113 self
.assertEquals(1, len(getMetric(results
,
114 'oilpan_conservative_complete_sweep')))
115 self
.assertEquals(2, len(getMetric(results
, 'oilpan_forced_mark')))
116 self
.assertEquals(2, len(getMetric(results
, 'oilpan_forced_lazy_sweep')))
117 self
.assertEquals(2, len(getMetric(results
,
118 'oilpan_forced_complete_sweep')))
120 # Disable for accessing private API of _OilpanGCTimesBase.
121 # pylint: disable=protected-access
122 def testForParsing(self
):
123 def getMetric(results
, name
):
124 metrics
= results
.FindAllPageSpecificValuesNamed(name
)
125 self
.assertEquals(1, len(metrics
))
126 return metrics
[0].GetBuildbotValue()
128 data
= self
._GenerateDataForParsing
()
130 measurement
= oilpan_gc_times
._OilpanGCTimesBase
()
131 measurement
._timeline
_model
= data
._model
132 tab
= mock
.MagicMock()
134 'measurements.oilpan_gc_times.TimelineModel') as MockTimelineModel
:
135 MockTimelineModel
.return_value
= data
._model
136 measurement
.ValidateAndMeasurePage(None, tab
, data
.results
)
138 results
= data
.results
139 self
.assertEquals(8, len(getMetric(results
, 'oilpan_coalesce')))
140 self
.assertEquals(4, len(getMetric(results
, 'oilpan_precise_mark')))
141 self
.assertEquals(4, len(getMetric(results
, 'oilpan_precise_lazy_sweep')))
142 self
.assertEquals(4, len(getMetric(results
,
143 'oilpan_precise_complete_sweep')))
144 self
.assertEquals(4, len(getMetric(results
, 'oilpan_conservative_mark')))
145 self
.assertEquals(4, len(getMetric(results
,
146 'oilpan_conservative_lazy_sweep')))
147 self
.assertEquals(4, len(getMetric(results
,
148 'oilpan_conservative_complete_sweep')))
149 self
.assertEquals(1, len(getMetric(results
, 'oilpan_forced_mark')))
150 self
.assertEquals(1, len(getMetric(results
, 'oilpan_forced_lazy_sweep')))
151 self
.assertEquals(1, len(getMetric(results
,
152 'oilpan_forced_complete_sweep')))
153 self
.assertEquals(2, len(getMetric(results
, 'oilpan_idle_mark')))
154 self
.assertEquals(2, len(getMetric(results
, 'oilpan_idle_lazy_sweep')))
155 self
.assertEquals(2, len(getMetric(results
,
156 'oilpan_idle_complete_sweep')))
158 def testForSmoothness(self
):
159 ps
= self
.CreateStorySetFromFileInUnittestDataDir(
160 'create_many_objects.html')
161 measurement
= oilpan_gc_times
.OilpanGCTimesForSmoothness()
162 results
= self
.RunMeasurement(measurement
, ps
, options
=self
._options
)
163 self
.assertEquals(0, len(results
.failures
))
166 for gc_reason
in self
._GC
_REASONS
:
167 label
= 'oilpan_%s_mark' % gc_reason
168 gc_events
.extend(results
.FindAllPageSpecificValuesNamed(label
))
169 self
.assertLess(0, len(gc_events
))
171 def testForBlinkPerf(self
):
172 ps
= self
.CreateStorySetFromFileInUnittestDataDir(
173 'create_many_objects.html')
174 measurement
= oilpan_gc_times
.OilpanGCTimesForBlinkPerf()
175 results
= self
.RunMeasurement(measurement
, ps
, options
=self
._options
)
176 self
.assertEquals(0, len(results
.failures
))
179 for gc_reason
in self
._GC
_REASONS
:
180 label
= 'oilpan_%s_mark' % gc_reason
181 gc_events
.extend(results
.FindAllPageSpecificValuesNamed(label
))
182 self
.assertLess(0, len(gc_events
))
184 def _GenerateDataForEmptyPageSet(self
):
185 page_set
= self
.CreateEmptyPageSet()
186 page
= TestOilpanGCTimesPage(page_set
)
187 page_set
.AddStory(page
)
189 data
= OilpanGCTimesTestData('CrRendererMain')
190 # Pretend we are about to run the tests to silence lower level asserts.
191 data
.results
.WillRunPage(page
)
195 def _GenerateDataForParsingOldFormat(self
):
196 data
= self
._GenerateDataForEmptyPageSet
()
197 data
.AddSlice(self
._KEY
_MARK
, 1, 1, {'precise': True, 'forced': False})
198 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 2, 2, {})
199 data
.AddSlice(self
._KEY
_COALESCE
, 4, 3, {})
200 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 7, 4, {})
201 data
.AddSlice(self
._KEY
_COALESCE
, 11, 5, {})
202 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 16, 6, {})
203 data
.AddSlice(self
._KEY
_MARK
, 22, 7, {'precise': True, 'forced': False})
204 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 29, 8, {})
205 data
.AddSlice(self
._KEY
_COALESCE
, 37, 9, {})
206 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 46, 10, {})
207 data
.AddSlice(self
._KEY
_MARK
, 56, 11, {'precise': False, 'forced': False})
208 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 67, 12, {})
209 data
.AddSlice(self
._KEY
_COALESCE
, 79, 13, {})
210 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 92, 14, {})
211 data
.AddSlice(self
._KEY
_MARK
, 106, 15, {'precise': True, 'forced': False})
212 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 121, 16, {})
213 data
.AddSlice(self
._KEY
_COALESCE
, 137, 17, {})
214 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 154, 18, {})
215 data
.AddSlice(self
._KEY
_MARK
, 172, 19, {'precise': False, 'forced': True})
216 data
.AddSlice(self
._KEY
_COALESCE
, 191, 20, {})
217 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 211, 21, {})
218 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 232, 22, {})
219 data
.AddSlice(self
._KEY
_MARK
, 254, 23, {'precise': True, 'forced': True})
220 data
.AddSlice(self
._KEY
_COALESCE
, 277, 24, {})
221 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 301, 25, {})
222 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 326, 26, {})
225 def _GenerateDataForParsing(self
):
226 data
= self
._GenerateDataForEmptyPageSet
()
227 data
.AddSlice(self
._KEY
_MARK
, 1, 1,
228 {'lazySweeping': True, 'gcReason': 'ConservativeGC'})
229 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 2, 2, {})
230 data
.AddSlice(self
._KEY
_COALESCE
, 4, 3, {})
231 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 7, 4, {})
232 data
.AddSlice(self
._KEY
_COALESCE
, 11, 5, {})
233 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 16, 6, {})
234 data
.AddSlice(self
._KEY
_MARK
, 22, 7,
235 {'lazySweeping': True, 'gcReason': 'PreciseGC'})
236 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 29, 8, {})
237 data
.AddSlice(self
._KEY
_COALESCE
, 37, 9, {})
238 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 46, 10, {})
239 data
.AddSlice(self
._KEY
_MARK
, 56, 11,
240 {'lazySweeping': False, 'gcReason': 'ConservativeGC'})
241 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 67, 12, {})
242 data
.AddSlice(self
._KEY
_COALESCE
, 79, 13, {})
243 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 92, 14, {})
244 data
.AddSlice(self
._KEY
_MARK
, 106, 15,
245 {'lazySweeping': False, 'gcReason': 'PreciseGC'})
246 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 121, 16, {})
247 data
.AddSlice(self
._KEY
_COALESCE
, 137, 17, {})
248 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 154, 18, {})
249 data
.AddSlice(self
._KEY
_MARK
, 172, 19,
250 {'lazySweeping': False, 'gcReason': 'ForcedGCForTesting'})
251 data
.AddSlice(self
._KEY
_COALESCE
, 191, 20, {})
252 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 211, 21, {})
253 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 232, 22, {})
254 data
.AddSlice(self
._KEY
_MARK
, 254, 23,
255 {'lazySweeping': False, 'gcReason': 'IdleGC'})
256 data
.AddSlice(self
._KEY
_COALESCE
, 277, 24, {})
257 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 301, 25, {})
258 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 326, 26, {})
260 # Following events are covered with 'BlinkGCTimeMeasurement' event.
261 first_measure
= data
.AddSlice(self
._KEY
_COALESCE
, 352, 27, {})
262 data
.AddSlice(self
._KEY
_MARK
, 380, 28,
263 {'lazySweeping': True, 'gcReason': 'ConservativeGC'})
264 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 408, 29, {})
265 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 437, 30, {})
266 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 467, 31, {})
267 data
.AddSlice(self
._KEY
_MARK
, 498, 32,
268 {'lazySweeping': True, 'gcReason': 'PreciseGC'})
269 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 530, 33, {})
270 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 563, 34, {})
271 data
.AddSlice(self
._KEY
_MARK
, 597, 35,
272 {'lazySweeping': False, 'gcReason': 'ConservativeGC'})
273 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 632, 36, {})
274 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 667, 37, {})
275 data
.AddSlice(self
._KEY
_MARK
, 704, 38,
276 {'lazySweeping': False, 'gcReason': 'PreciseGC'})
277 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 742, 39, {})
278 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 781, 40, {})
279 data
.AddSlice(self
._KEY
_MARK
, 821, 41,
280 {'lazySweeping': False, 'gcReason': 'ForcedGCForTesting'})
281 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 862, 42, {})
282 data
.AddSlice(self
._KEY
_MARK
, 904, 43,
283 {'lazySweeping': False, 'gcReason': 'IdleGC'})
284 last_measure
= data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 947, 44, {})
287 async_dur
= last_measure
.end
- first_measure
.start
288 data
.AddAsyncSlice(self
._KEY
_MEASURE
, first_measure
.start
, async_dur
, {})