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