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
.results
import page_test_results
9 from telemetry
.timeline
import model
10 from telemetry
.timeline
import slice as slice_data
11 from telemetry
.unittest_util
import options_for_unittests
12 from telemetry
.unittest_util
import page_test_test_case
13 from telemetry
.page
import page
as page_module
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'
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
.CreatePageSetFromFileInUnittestDataDir('create_many_objects.html')
160 measurement
= oilpan_gc_times
.OilpanGCTimesForSmoothness()
161 results
= self
.RunMeasurement(measurement
, ps
, options
=self
._options
)
162 self
.assertEquals(0, len(results
.failures
))
164 precise
= results
.FindAllPageSpecificValuesNamed('oilpan_precise_mark')
165 conservative
= results
.FindAllPageSpecificValuesNamed(
166 'oilpan_conservative_mark')
167 self
.assertLess(0, len(precise
) + len(conservative
))
169 def testForBlinkPerf(self
):
170 ps
= self
.CreatePageSetFromFileInUnittestDataDir('create_many_objects.html')
171 measurement
= oilpan_gc_times
.OilpanGCTimesForBlinkPerf()
172 results
= self
.RunMeasurement(measurement
, ps
, options
=self
._options
)
173 self
.assertEquals(0, len(results
.failures
))
175 precise
= results
.FindAllPageSpecificValuesNamed('oilpan_precise_mark')
176 conservative
= results
.FindAllPageSpecificValuesNamed(
177 'oilpan_conservative_mark')
178 self
.assertLess(0, len(precise
) + len(conservative
))
180 def _GenerateDataForEmptyPageSet(self
):
181 page_set
= self
.CreateEmptyPageSet()
182 page
= TestOilpanGCTimesPage(page_set
)
183 page_set
.AddUserStory(page
)
185 data
= OilpanGCTimesTestData('CrRendererMain')
186 # Pretend we are about to run the tests to silence lower level asserts.
187 data
.results
.WillRunPage(page
)
191 def _GenerateDataForParsingOldFormat(self
):
192 data
= self
._GenerateDataForEmptyPageSet
()
193 data
.AddSlice(self
._KEY
_MARK
, 1, 1, {'precise': True, 'forced': False})
194 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 2, 2, {})
195 data
.AddSlice(self
._KEY
_COALESCE
, 4, 3, {})
196 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 7, 4, {})
197 data
.AddSlice(self
._KEY
_COALESCE
, 11, 5, {})
198 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 16, 6, {})
199 data
.AddSlice(self
._KEY
_MARK
, 22, 7, {'precise': True, 'forced': False})
200 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 29, 8, {})
201 data
.AddSlice(self
._KEY
_COALESCE
, 37, 9, {})
202 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 46, 10, {})
203 data
.AddSlice(self
._KEY
_MARK
, 56, 11, {'precise': False, 'forced': False})
204 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 67, 12, {})
205 data
.AddSlice(self
._KEY
_COALESCE
, 79, 13, {})
206 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 92, 14, {})
207 data
.AddSlice(self
._KEY
_MARK
, 106, 15, {'precise': True, 'forced': False})
208 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 121, 16, {})
209 data
.AddSlice(self
._KEY
_COALESCE
, 137, 17, {})
210 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 154, 18, {})
211 data
.AddSlice(self
._KEY
_MARK
, 172, 19, {'precise': False, 'forced': True})
212 data
.AddSlice(self
._KEY
_COALESCE
, 191, 20, {})
213 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 211, 21, {})
214 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 232, 22, {})
215 data
.AddSlice(self
._KEY
_MARK
, 254, 23, {'precise': True, 'forced': True})
216 data
.AddSlice(self
._KEY
_COALESCE
, 277, 24, {})
217 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 301, 25, {})
218 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 326, 26, {})
221 def _GenerateDataForParsing(self
):
222 data
= self
._GenerateDataForEmptyPageSet
()
223 data
.AddSlice(self
._KEY
_MARK
, 1, 1,
224 {'lazySweeping': True, 'gcReason': 'ConservativeGC'})
225 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 2, 2, {})
226 data
.AddSlice(self
._KEY
_COALESCE
, 4, 3, {})
227 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 7, 4, {})
228 data
.AddSlice(self
._KEY
_COALESCE
, 11, 5, {})
229 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 16, 6, {})
230 data
.AddSlice(self
._KEY
_MARK
, 22, 7,
231 {'lazySweeping': True, 'gcReason': 'PreciseGC'})
232 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 29, 8, {})
233 data
.AddSlice(self
._KEY
_COALESCE
, 37, 9, {})
234 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 46, 10, {})
235 data
.AddSlice(self
._KEY
_MARK
, 56, 11,
236 {'lazySweeping': False, 'gcReason': 'ConservativeGC'})
237 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 67, 12, {})
238 data
.AddSlice(self
._KEY
_COALESCE
, 79, 13, {})
239 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 92, 14, {})
240 data
.AddSlice(self
._KEY
_MARK
, 106, 15,
241 {'lazySweeping': False, 'gcReason': 'PreciseGC'})
242 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 121, 16, {})
243 data
.AddSlice(self
._KEY
_COALESCE
, 137, 17, {})
244 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 154, 18, {})
245 data
.AddSlice(self
._KEY
_MARK
, 172, 19,
246 {'lazySweeping': False, 'gcReason': 'ForcedGCForTesting'})
247 data
.AddSlice(self
._KEY
_COALESCE
, 191, 20, {})
248 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 211, 21, {})
249 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 232, 22, {})
250 data
.AddSlice(self
._KEY
_MARK
, 254, 23,
251 {'lazySweeping': False, 'gcReason': 'IdleGC'})
252 data
.AddSlice(self
._KEY
_COALESCE
, 277, 24, {})
253 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 301, 25, {})
254 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 326, 26, {})
256 # Following events are covered with 'BlinkGCTimeMeasurement' event.
257 first_measure
= data
.AddSlice(self
._KEY
_COALESCE
, 352, 27, {})
258 data
.AddSlice(self
._KEY
_MARK
, 380, 28,
259 {'lazySweeping': True, 'gcReason': 'ConservativeGC'})
260 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 408, 29, {})
261 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 437, 30, {})
262 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 467, 31, {})
263 data
.AddSlice(self
._KEY
_MARK
, 498, 32,
264 {'lazySweeping': True, 'gcReason': 'PreciseGC'})
265 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 530, 33, {})
266 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 563, 34, {})
267 data
.AddSlice(self
._KEY
_MARK
, 597, 35,
268 {'lazySweeping': False, 'gcReason': 'ConservativeGC'})
269 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 632, 36, {})
270 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 667, 37, {})
271 data
.AddSlice(self
._KEY
_MARK
, 704, 38,
272 {'lazySweeping': False, 'gcReason': 'PreciseGC'})
273 data
.AddSlice(self
._KEY
_LAZY
_SWEEP
, 742, 39, {})
274 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 781, 40, {})
275 data
.AddSlice(self
._KEY
_MARK
, 821, 41,
276 {'lazySweeping': False, 'gcReason': 'ForcedGCForTesting'})
277 data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 862, 42, {})
278 data
.AddSlice(self
._KEY
_MARK
, 904, 43,
279 {'lazySweeping': False, 'gcReason': 'IdleGC'})
280 last_measure
= data
.AddSlice(self
._KEY
_COMPLETE
_SWEEP
, 947, 44, {})
283 async_dur
= last_measure
.end
- first_measure
.start
284 data
.AddAsyncSlice(self
._KEY
_MEASURE
, first_measure
.start
, async_dur
, {})