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 task_execution_time
6 from telemetry
import decorators
7 from telemetry
.core
import wpr_modes
8 from telemetry
.page
import page
as page_module
9 from telemetry
.results
import page_test_results
10 from telemetry
.timeline
import model
as model_module
11 from telemetry
.timeline
import slice as slice_data
12 from telemetry
.unittest_util
import options_for_unittests
13 from telemetry
.unittest_util
import page_test_test_case
16 class TestTaskExecutionTimePage(page_module
.Page
):
18 def __init__(self
, page_set
, base_dir
):
19 super(TestTaskExecutionTimePage
, self
).__init
__(
20 'file://blank.html', page_set
, base_dir
)
22 def RunPageInteractions(self
, action_runner
):
23 interaction
= action_runner
.BeginGestureInteraction(
24 'ScrollAction', is_smooth
=True)
25 action_runner
.ScrollPage()
29 class TaskExecutionTimeUnitTest(page_test_test_case
.PageTestTestCase
):
32 self
._options
= options_for_unittests
.GetCopy()
33 self
._options
.browser_options
.wpr_mode
= wpr_modes
.WPR_OFF
35 @decorators.Enabled('android')
36 def testSomeResultsReturnedFromDummyPage(self
):
37 ps
= self
.CreateEmptyPageSet()
38 ps
.AddUserStory(TestTaskExecutionTimePage(ps
, ps
.base_dir
))
39 measurement
= task_execution_time
.TaskExecutionTime()
41 results
= self
.RunMeasurement(measurement
, ps
, options
=self
._options
)
43 self
.assertGreater(len(results
.all_page_specific_values
), 0)
45 @decorators.Enabled('android')
46 def testSlicesConformToRequiredNamingConventionsUsingDummyPage(self
):
47 """This test ensures the presence of required keywords.
49 Some arbitrary keywords are required to generate the names of the top 10
50 tasks. The code has a weak dependancy on 'src_func', 'class' and 'line'
51 existing; if they exist in a slice's args they are used to generate a
52 name, if they don't exists the code falls back to using the name of the
53 slice, which is less clear.
55 If the code has been refactored and these keywords no longer exist
56 the code that relies on them in task_execution_time.py should be
57 updated to use the appropriate technique for assertaining this data
58 (and this test changed in the same way).
60 ps
= self
.CreateEmptyPageSet()
61 ps
.AddUserStory(TestTaskExecutionTimePage(ps
, ps
.base_dir
))
62 measurement
= task_execution_time
.TaskExecutionTime()
64 self
.RunMeasurement(measurement
, ps
, options
=self
._options
)
66 required_keywords
= {'src_func': 0, 'class': 0, 'line': 0}
68 # Check all slices and count the uses of the required keywords.
69 for thread
in measurement
._renderer
_process
.threads
.values():
70 for slice_info
in thread
.IterAllSlices():
71 _CheckSliceForKeywords(slice_info
, required_keywords
)
73 # Confirm that all required keywords have at least one instance.
74 for use_counts
in required_keywords
.values():
75 self
.assertGreater(use_counts
, 0)
77 def testMockedResults(self
):
78 task_execution_time_metric
= task_execution_time
.TaskExecutionTime()
79 ps
= self
.CreateEmptyPageSet()
80 page
= TestTaskExecutionTimePage(ps
, ps
.base_dir
)
83 # Get the name of a thread used by task_execution_time metric and set up
84 # some dummy execution data pretending to be from that thread & process.
85 first_thread_name
= task_execution_time_metric
._RENDERER
_THREADS
[0]
86 data
= TaskExecutionTestData(first_thread_name
)
87 task_execution_time_metric
._renderer
_process
= data
._renderer
_process
89 # Pretend we're about to run the tests to silence lower level asserts.
90 data
.results
.WillRunPage(page
)
91 data
.AddSlice('fast', 0, 1)
92 data
.AddSlice('medium', 0, 500)
93 data
.AddSlice('slow', 0, 1000)
95 # Run the code we are testing.
96 task_execution_time_metric
.ValidateAndMeasurePage(None, None, data
.results
)
98 # Confirm we get back 3 results that are correctly sorted and named.
99 self
.assertEqual(len(data
.results
.all_page_specific_values
), 3)
101 data
.results
.all_page_specific_values
[0].name
,
102 'process 1:' + first_thread_name
+ ':slow')
104 data
.results
.all_page_specific_values
[1].name
,
105 'process 1:' + first_thread_name
+ ':medium')
107 data
.results
.all_page_specific_values
[2].name
,
108 'process 1:' + first_thread_name
+ ':fast')
109 self
.assertEqual(data
.results
.all_page_specific_values
[0].value
, 1000)
110 self
.assertEqual(data
.results
.all_page_specific_values
[1].value
, 500)
111 self
.assertEqual(data
.results
.all_page_specific_values
[2].value
, 1)
113 def testIdleTasksAreReported(self
):
114 task_execution_time_metric
= task_execution_time
.TaskExecutionTime()
115 ps
= self
.CreateEmptyPageSet()
116 page
= TestTaskExecutionTimePage(ps
, ps
.base_dir
)
117 ps
.AddUserStory(page
)
119 # Get the name of a thread used by task_execution_time metric and set up
120 # some dummy execution data pretending to be from that thread & process.
121 first_thread_name
= task_execution_time_metric
._RENDERER
_THREADS
[0]
122 data
= TaskExecutionTestData(first_thread_name
)
123 task_execution_time_metric
._renderer
_process
= data
._renderer
_process
125 # Pretend we're about to run the tests to silence lower level asserts.
126 data
.results
.WillRunPage(page
)
128 # Make a slice that looks like an idle task parent.
130 slice_duration
= 1000
131 parent_slice
= data
.AddSlice(
132 task_execution_time_metric
.IDLE_SECTION_TRIGGER
,
135 # Add a sub-slice, this should be reported back as occuring in idle time.
136 sub_slice
= slice_data
.Slice(
142 parent_slice
.sub_slices
.append(sub_slice
)
144 # Add a non-idle task.
145 data
.AddSlice('not_idle', slice_start_time
, slice_duration
)
147 # Run the code we are testing.
148 task_execution_time_metric
.ValidateAndMeasurePage(None, None, data
.results
)
150 # The 'slow_sub_slice' should be inside the Idle section and therefore
151 # removed from the results.
152 for result
in data
.results
.all_page_specific_values
:
153 if 'slow_sub_slice' in result
.name
:
154 self
.fail('Tasks within idle section should not be reported')
156 # The 'not_idle' slice should not have the IDLE_SECTION added to its name
158 for result
in data
.results
.all_page_specific_values
:
159 if 'not_idle' in result
.name
:
161 task_execution_time_metric
.IDLE_SECTION
165 self
.fail('Task was incorrectly marked as Idle')
168 def _CheckSliceForKeywords(slice_info
, required_keywords
):
169 for argument
in slice_info
.args
:
170 if argument
in required_keywords
:
171 required_keywords
[argument
] += 1
172 # recurse into our sub-slices.
173 for sub_slice
in slice_info
.sub_slices
:
174 _CheckSliceForKeywords(sub_slice
, required_keywords
)
177 class TaskExecutionTestData(object):
179 def __init__(self
, thread_name
):
180 self
._model
= model_module
.TimelineModel()
181 self
._renderer
_process
= self
._model
.GetOrCreateProcess(1)
182 self
._renderer
_thread
= self
._renderer
_process
.GetOrCreateThread(2)
183 self
._renderer
_thread
.name
= thread_name
184 self
._results
= page_test_results
.PageTestResults()
196 def AddSlice(self
, name
, timestamp
, duration
):
197 new_slice
= slice_data
.Slice(
206 self
._renderer
_thread
.all_slices
.append(new_slice
)