1# Copyright 2013 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
5import unittest
6
7from metrics import test_page_test_results
8from metrics import timeline
9from telemetry.timeline import model as model_module
10from telemetry.web_perf import timeline_interaction_record as tir_module
11
12def _GetInteractionRecord(start, end):
13  return tir_module.TimelineInteractionRecord("test-record", start, end)
14
15
16class LoadTimesTimelineMetric(unittest.TestCase):
17  def GetResults(self, metric, model, renderer_thread, interaction_records):
18    results = test_page_test_results.TestPageTestResults(self)
19    metric.AddResults(model, renderer_thread, interaction_records, results)
20    return results
21
22  def testSanitizing(self):
23    model = model_module.TimelineModel()
24    renderer_main = model.GetOrCreateProcess(1).GetOrCreateThread(2)
25    renderer_main.name = 'CrRendererMain'
26
27    # [      X       ]
28    #      [  Y  ]
29    renderer_main.BeginSlice('cat1', 'x.y', 10, 0)
30    renderer_main.EndSlice(20, 20)
31    model.FinalizeImport()
32
33    metric = timeline.LoadTimesTimelineMetric()
34    results = self.GetResults(
35      metric, model=model, renderer_thread=renderer_main,
36      interaction_records=[_GetInteractionRecord(0, float('inf'))])
37    results.AssertHasPageSpecificScalarValue(
38      'CrRendererMain|x_y', 'ms', 10)
39    results.AssertHasPageSpecificScalarValue(
40      'CrRendererMain|x_y_max', 'ms', 10)
41    results.AssertHasPageSpecificScalarValue(
42      'CrRendererMain|x_y_avg', 'ms', 10)
43
44  def testTimelineBetweenRange(self):
45    model = model_module.TimelineModel()
46    renderer_main = model.GetOrCreateProcess(1).GetOrCreateThread(2)
47    renderer_main.name = 'CrRendererMain'
48
49    #   [          X         ]    [       Z      ]
50    #           [  Y  ]               [   T    ]
51    #   [ interaction record ]
52    renderer_main.BeginSlice('cat1', 'x.y', 10, 0)
53    renderer_main.EndSlice(20, 20)
54    renderer_main.BeginSlice('cat1', 'z.t', 30, 0)
55    renderer_main.EndSlice(35, 35)
56    model.FinalizeImport()
57
58    metric = timeline.LoadTimesTimelineMetric()
59    results = self.GetResults(
60      metric, model=model, renderer_thread=renderer_main,
61      interaction_records=[_GetInteractionRecord(10, 20)])
62    results.AssertHasPageSpecificScalarValue(
63      'CrRendererMain|x_y', 'ms', 10)
64    results.AssertHasPageSpecificScalarValue(
65      'CrRendererMain|x_y_max', 'ms', 10)
66    results.AssertHasPageSpecificScalarValue(
67      'CrRendererMain|x_y_avg', 'ms', 10)
68
69
70  def testCounterSanitizing(self):
71    model = model_module.TimelineModel()
72    renderer_main = model.GetOrCreateProcess(1).GetOrCreateThread(2)
73    renderer_main.name = 'CrRendererMain'
74
75    x_counter = renderer_main.parent.GetOrCreateCounter('cat', 'x.y')
76    x_counter.samples += [1, 2]
77    x_counter.series_names += ['a']
78    x_counter.timestamps += [0, 1]
79    model.FinalizeImport()
80
81    metric = timeline.LoadTimesTimelineMetric()
82    results = self.GetResults(
83      metric, model=model, renderer_thread=renderer_main,
84      interaction_records=[_GetInteractionRecord(0, float('inf'))])
85    results.AssertHasPageSpecificScalarValue(
86      'cat_x_y', 'count', 3)
87    results.AssertHasPageSpecificScalarValue(
88      'cat_x_y_avg', 'count', 1.5)
89
90
91class ThreadTimesTimelineMetricUnittest(unittest.TestCase):
92  def GetResults(self, metric, model, renderer_thread, interaction_record):
93    results = test_page_test_results.TestPageTestResults(self)
94    metric.AddResults(model, renderer_thread, interaction_record,
95                                results)
96    return results
97
98  def testResults(self):
99    model = model_module.TimelineModel()
100    renderer_main = model.GetOrCreateProcess(1).GetOrCreateThread(2)
101    renderer_main.name = 'CrRendererMain'
102
103    metric = timeline.ThreadTimesTimelineMetric()
104    metric.details_to_report = timeline.ReportMainThreadOnly
105    results = self.GetResults(metric, model, renderer_main.parent,
106                              [_GetInteractionRecord(1,2)])
107
108    # Test that all result thread categories exist
109    for name in timeline.TimelineThreadCategories.values():
110      results.GetPageSpecificValueNamed(timeline.ThreadCpuTimeResultName(name))
111
112  def testBasic(self):
113    model = model_module.TimelineModel()
114    renderer_main = model.GetOrCreateProcess(1).GetOrCreateThread(2)
115    renderer_main.name = 'CrRendererMain'
116
117    # Create two frame swaps (Results times should be divided by two)
118    cc_main = model.GetOrCreateProcess(1).GetOrCreateThread(3)
119    cc_main.name = 'Compositor'
120    cc_main.BeginSlice('cc_cat', timeline.FrameTraceName, 10, 10)
121    cc_main.EndSlice(11, 11)
122    cc_main.BeginSlice('cc_cat', timeline.FrameTraceName, 12, 12)
123    cc_main.EndSlice(13, 13)
124
125    # [      X       ]   [ Z ]
126    #      [  Y  ]
127    renderer_main.BeginSlice('cat1', 'X', 10, 0)
128    renderer_main.BeginSlice('cat2', 'Y', 15, 5)
129    renderer_main.EndSlice(16, 5.5)
130    renderer_main.EndSlice(30, 19.5)
131    renderer_main.BeginSlice('cat1', 'Z', 31, 20)
132    renderer_main.BeginSlice('cat1', 'Z', 33, 21)
133    model.FinalizeImport()
134
135    # Exclude 'Z' using an action-range.
136    metric = timeline.ThreadTimesTimelineMetric()
137    metric.details_to_report = timeline.ReportMainThreadOnly
138    results = self.GetResults(metric, model, renderer_main.parent,
139                              [_GetInteractionRecord(10, 30)])
140
141
142    # Test a couple specific results.
143    assert_results = {
144      timeline.ThreadCpuTimeResultName('renderer_main') : 9.75,
145      timeline.ThreadDetailResultName('renderer_main','cat1') : 9.5,
146      timeline.ThreadDetailResultName('renderer_main','cat2') : 0.5,
147      timeline.ThreadDetailResultName('renderer_main','idle') : 0
148    }
149    for name, value in assert_results.iteritems():
150      results.AssertHasPageSpecificScalarValue(name, 'ms', value)
151
152  def testOverheadIsRemoved(self):
153    model = model_module.TimelineModel()
154    renderer_main = model.GetOrCreateProcess(1).GetOrCreateThread(2)
155    renderer_main.name = 'CrRendererMain'
156
157    # Create one frame swap.
158    cc_main = model.GetOrCreateProcess(1).GetOrCreateThread(3)
159    cc_main.name = 'Compositor'
160    cc_main.BeginSlice('cc_cat', timeline.FrameTraceName, 10, 10)
161    cc_main.EndSlice(11, 11)
162
163    # [      X       ]
164    #    [Overhead]
165    overhead_category = timeline.OverheadTraceCategory
166    overhead_name = timeline.OverheadTraceName
167    renderer_main.BeginSlice('cat1', 'X', 10, 0)
168    renderer_main.BeginSlice(overhead_category, overhead_name, 15, 5)
169    renderer_main.EndSlice(16, 6)
170    renderer_main.EndSlice(30, 10)
171    model.FinalizeImport()
172
173    # Include everything in an action-range.
174    metric = timeline.ThreadTimesTimelineMetric()
175    metric.details_to_report = timeline.ReportMainThreadOnly
176    results = self.GetResults(metric, model, renderer_main.parent,
177                              [_GetInteractionRecord(10, 30)])
178
179    # Test a couple specific results.
180    assert_results = {
181      timeline.ThreadCpuTimeResultName('renderer_main') : 9.0,
182    }
183    for name, value in assert_results.iteritems():
184      results.AssertHasPageSpecificScalarValue(name, 'ms', value)
185