133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# Copyright 2014 The Chromium Authors. All rights reserved.
233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# Use of this source code is governed by a BSD-style license that can be
333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# found in the LICENSE file.
433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport random
633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport unittest
733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckfrom telemetry.timeline import async_slice
933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckfrom telemetry.timeline import bounds
1033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckfrom telemetry.timeline import model
1133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckfrom telemetry.util import perf_tests_helper
1233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckfrom telemetry.util import statistics
1333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckfrom telemetry.web_perf.metrics import rendering_stats
1433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
1533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
1633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckclass MockTimer(object):
1733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  """A mock timer class which can generate random durations.
1833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
1933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  An instance of this class is used as a global timer to generate random
2033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  durations for stats and consistent timestamps for all mock trace events.
2133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  The unit of time is milliseconds.
2233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  """
2333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
2433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  def __init__(self):
2533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    self.milliseconds = 0
2633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
2733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  def Advance(self, low=0.1, high=1):
2833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    delta = random.uniform(low, high)
2933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    self.milliseconds += delta
3033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    return delta
3133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
3233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  def AdvanceAndGet(self, low=0.1, high=1):
3333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    self.Advance(low, high)
3433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    return self.milliseconds
3533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
3633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
37a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craikclass MockVblankTimer(object):
38a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  """A mock vblank timer class which can generate random durations.
39a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik
40a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  An instance of this class is used as a vblank timer to generate random
41a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  durations for drm stats and consistent timeval for mock trace drm events.
42a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  The unit of time is microseconds.
43a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  """
44a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik
45a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  def __init__(self):
46a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    self.microseconds = 200000000
47a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik
48a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  def TvAdvance(self, low=100, high=1000):
49a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    delta = random.randint(low, high)
50a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    self.microseconds += delta
51a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    return delta
52a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik
53a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  def TvAdvanceAndGet(self, low=100, high=1000):
54a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    self.TvAdvance(low, high)
55a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    return self.microseconds
56a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik
57a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik
5833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckclass ReferenceRenderingStats(object):
5933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  """ Stores expected data for comparison with actual RenderingStats """
6033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
6133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  def __init__(self):
6233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    self.frame_timestamps = []
6333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    self.frame_times = []
6433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    self.approximated_pixel_percentages = []
6533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    self.checkerboarded_pixel_percentages = []
6633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
6733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  def AppendNewRange(self):
6833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    self.frame_timestamps.append([])
6933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    self.frame_times.append([])
7033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    self.approximated_pixel_percentages.append([])
7133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    self.checkerboarded_pixel_percentages.append([])
7233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
7333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
7433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckclass ReferenceInputLatencyStats(object):
7533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  """ Stores expected data for comparison with actual input latency stats """
7633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
7733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  def __init__(self):
7833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    self.input_event_latency = []
7933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    self.input_event = []
8033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
8133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
8233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckdef AddSurfaceFlingerStats(mock_timer, thread, first_frame,
8333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                           ref_stats=None):
8433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  """ Adds a random surface flinger stats event.
8533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
8633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  thread: The timeline model thread to which the event will be added.
8733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  first_frame: Is this the first frame within the bounds of an action?
8833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  ref_stats: A ReferenceRenderingStats object to record expected values.
8933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  """
90a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  # Create random data and timestamp for impl thread rendering stats.
9133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  data = {'frame_count': 1,
9233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck          'refresh_period': 16.6666}
9333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  timestamp = mock_timer.AdvanceAndGet()
9433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
9533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  # Add a slice with the event data to the given thread.
9633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  thread.PushCompleteSlice(
9733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      'SurfaceFlinger', 'vsync_before',
9833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      timestamp, duration=0.0, thread_timestamp=None, thread_duration=None,
9933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      args={'data': data})
10033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
10133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  if not ref_stats:
10233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    return
10333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
10433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  # Add timestamp only if a frame was output
10533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  if data['frame_count'] == 1:
10633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    if not first_frame:
10733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      # Add frame_time if this is not the first frame in within the bounds of an
10833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      # action.
10933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      prev_timestamp = ref_stats.frame_timestamps[-1][-1]
11033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      ref_stats.frame_times[-1].append(timestamp - prev_timestamp)
11133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    ref_stats.frame_timestamps[-1].append(timestamp)
11233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
11333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
114a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craikdef AddDrmEventFlipStats(mock_timer, vblank_timer, thread,
115a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik                         first_frame, ref_stats=None):
116a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  """ Adds a random drm flip complete event.
117a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik
118a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  thread: The timeline model thread to which the event will be added.
119a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  first_frame: Is this the first frame within the bounds of an action?
120a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  ref_stats: A ReferenceRenderingStats object to record expected values.
121a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  """
122a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  # Create random data and timestamp for drm thread flip complete stats.
123a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  vblank_timeval = vblank_timer.TvAdvanceAndGet()
124a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  vblank_tv_sec = vblank_timeval / 1000000
125a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  vblank_tv_usec = vblank_timeval % 1000000
126a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  data = {'frame_count': 1,
127a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik          'vblank.tv_usec': vblank_tv_usec,
128a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik          'vblank.tv_sec': vblank_tv_sec}
129a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  timestamp = mock_timer.AdvanceAndGet()
130a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik
131a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  # Add a slice with the event data to the given thread.
132a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  thread.PushCompleteSlice(
133a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik      'benchmark,drm', 'DrmEventFlipComplete',
134a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik      timestamp, duration=0.0, thread_timestamp=None, thread_duration=None,
135a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik      args={'data': data})
136a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik
137a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  if not ref_stats:
138a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    return
139a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik
140a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  # Add vblank timeval only if a frame was output.
141a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  cur_timestamp = vblank_tv_sec * 1000.0 + vblank_tv_usec / 1000.0
142a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  if not first_frame:
143a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    # Add frame_time if this is not the first frame in within the bounds of an
144a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    # action.
145a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    prev_timestamp = ref_stats.frame_timestamps[-1][-1]
146a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    ref_stats.frame_times[-1].append(cur_timestamp - prev_timestamp)
147a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  ref_stats.frame_timestamps[-1].append(cur_timestamp)
148a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik
149a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik
15033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckdef AddDisplayRenderingStats(mock_timer, thread, first_frame,
15133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                             ref_stats=None):
15233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  """ Adds a random display rendering stats event.
15333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
15433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  thread: The timeline model thread to which the event will be added.
15533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  first_frame: Is this the first frame within the bounds of an action?
15633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  ref_stats: A ReferenceRenderingStats object to record expected values.
15733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  """
158a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  # Create random data and timestamp for main thread rendering stats.
15933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  data = {'frame_count': 1}
16033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  timestamp = mock_timer.AdvanceAndGet()
16133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
16233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  # Add a slice with the event data to the given thread.
16333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  thread.PushCompleteSlice(
16433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      'benchmark', 'BenchmarkInstrumentation::DisplayRenderingStats',
16533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      timestamp, duration=0.0, thread_timestamp=None, thread_duration=None,
16633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      args={'data': data})
16733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
16833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  if not ref_stats:
16933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    return
17033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
17133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  # Add timestamp only if a frame was output
17233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  if not first_frame:
17333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    # Add frame_time if this is not the first frame in within the bounds of an
17433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    # action.
17533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    prev_timestamp = ref_stats.frame_timestamps[-1][-1]
17633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    ref_stats.frame_times[-1].append(timestamp - prev_timestamp)
17733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  ref_stats.frame_timestamps[-1].append(timestamp)
17833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
17933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
18033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckdef AddImplThreadRenderingStats(mock_timer, thread, first_frame,
18133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                                ref_stats=None):
18233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  """ Adds a random impl thread rendering stats event.
18333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
18433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  thread: The timeline model thread to which the event will be added.
18533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  first_frame: Is this the first frame within the bounds of an action?
18633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  ref_stats: A ReferenceRenderingStats object to record expected values.
18733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  """
188a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  # Create random data and timestamp for impl thread rendering stats.
18933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  data = {'frame_count': 1,
19033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck          'visible_content_area': random.uniform(0, 100),
19133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck          'approximated_visible_content_area': random.uniform(0, 5),
19233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck          'checkerboarded_visible_content_area': random.uniform(0, 5)}
19333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  timestamp = mock_timer.AdvanceAndGet()
19433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
19533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  # Add a slice with the event data to the given thread.
19633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  thread.PushCompleteSlice(
19733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      'benchmark', 'BenchmarkInstrumentation::ImplThreadRenderingStats',
19833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      timestamp, duration=0.0, thread_timestamp=None, thread_duration=None,
19933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      args={'data': data})
20033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
20133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  if not ref_stats:
20233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    return
20333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
20433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  # Add timestamp only if a frame was output
20533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  if data['frame_count'] == 1:
20633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    if not first_frame:
20733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      # Add frame_time if this is not the first frame in within the bounds of an
20833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      # action.
20933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      prev_timestamp = ref_stats.frame_timestamps[-1][-1]
21033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      ref_stats.frame_times[-1].append(timestamp - prev_timestamp)
21133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    ref_stats.frame_timestamps[-1].append(timestamp)
21233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
21333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  ref_stats.approximated_pixel_percentages[-1].append(
21433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      round(statistics.DivideIfPossibleOrZero(
21533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck          data['approximated_visible_content_area'],
21633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck          data['visible_content_area']) * 100.0, 3))
21733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
21833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  ref_stats.checkerboarded_pixel_percentages[-1].append(
21933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      round(statistics.DivideIfPossibleOrZero(
22033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck          data['checkerboarded_visible_content_area'],
22133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck          data['visible_content_area']) * 100.0, 3))
22233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
22333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckdef AddInputLatencyStats(mock_timer, start_thread, end_thread,
22433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                         ref_latency_stats=None):
22533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  """ Adds a random input latency stats event.
22633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
22733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  start_thread: The start thread on which the async slice is added.
22833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  end_thread: The end thread on which the async slice is ended.
22933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  ref_latency_stats: A ReferenceInputLatencyStats object for expected values.
23033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  """
23133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
23233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  original_comp_time = mock_timer.AdvanceAndGet(2, 4) * 1000.0
23333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  ui_comp_time = mock_timer.AdvanceAndGet(2, 4) * 1000.0
23433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  begin_comp_time = mock_timer.AdvanceAndGet(2, 4) * 1000.0
23533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  forward_comp_time = mock_timer.AdvanceAndGet(2, 4) * 1000.0
23633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  end_comp_time = mock_timer.AdvanceAndGet(10, 20) * 1000.0
23733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
23833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  data = {rendering_stats.ORIGINAL_COMP_NAME: {'time': original_comp_time},
23933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck          rendering_stats.UI_COMP_NAME: {'time': ui_comp_time},
24033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck          rendering_stats.BEGIN_COMP_NAME: {'time': begin_comp_time},
24133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck          rendering_stats.END_COMP_NAME: {'time': end_comp_time}}
24233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
24333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  timestamp = mock_timer.AdvanceAndGet(2, 4)
24433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
24533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  tracing_async_slice = async_slice.AsyncSlice(
24633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      'benchmark', 'InputLatency', timestamp)
24733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
24833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  async_sub_slice = async_slice.AsyncSlice(
24933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      'benchmark', rendering_stats.GESTURE_SCROLL_UPDATE_EVENT_NAME, timestamp)
25033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  async_sub_slice.args = {'data': data}
25133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  async_sub_slice.parent_slice = tracing_async_slice
25233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  async_sub_slice.start_thread = start_thread
25333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  async_sub_slice.end_thread = end_thread
25433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
25533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  tracing_async_slice.sub_slices.append(async_sub_slice)
25633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  tracing_async_slice.start_thread = start_thread
25733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  tracing_async_slice.end_thread = end_thread
25833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  start_thread.AddAsyncSlice(tracing_async_slice)
25933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
26033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  # Add scroll update latency info.
26133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  scroll_update_data = {
26233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      rendering_stats.BEGIN_SCROLL_UPDATE_COMP_NAME: {'time': begin_comp_time},
26333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      rendering_stats.FORWARD_SCROLL_UPDATE_COMP_NAME:
26433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck          {'time': forward_comp_time},
26533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      rendering_stats.END_COMP_NAME: {'time': end_comp_time}
26633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  }
26733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
26833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  scroll_async_slice = async_slice.AsyncSlice(
26933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      'benchmark', 'InputLatency', timestamp)
27033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
27133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  scroll_async_sub_slice = async_slice.AsyncSlice(
27233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      'benchmark', rendering_stats.MAIN_THREAD_SCROLL_UPDATE_EVENT_NAME,
27333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      timestamp)
27433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  scroll_async_sub_slice.args = {'data': scroll_update_data}
27533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  scroll_async_sub_slice.parent_slice = scroll_async_slice
27633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  scroll_async_sub_slice.start_thread = start_thread
27733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  scroll_async_sub_slice.end_thread = end_thread
27833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
27933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  scroll_async_slice.sub_slices.append(scroll_async_sub_slice)
28033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  scroll_async_slice.start_thread = start_thread
28133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  scroll_async_slice.end_thread = end_thread
28233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  start_thread.AddAsyncSlice(scroll_async_slice)
28333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
28433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  # Also add some dummy frame statistics so we can feed the resulting timeline
28533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  # to RenderingStats.
28633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  AddImplThreadRenderingStats(mock_timer, end_thread, False)
28733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
28833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  if not ref_latency_stats:
28933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    return
29033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
29133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  ref_latency_stats.input_event.append(async_sub_slice)
29233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  ref_latency_stats.input_event.append(scroll_async_sub_slice)
29333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  ref_latency_stats.input_event_latency.append((
29433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      rendering_stats.GESTURE_SCROLL_UPDATE_EVENT_NAME,
29533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      (data[rendering_stats.END_COMP_NAME]['time'] -
29633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck       data[rendering_stats.ORIGINAL_COMP_NAME]['time']) / 1000.0))
29733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  scroll_update_time = (
29833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      scroll_update_data[rendering_stats.END_COMP_NAME]['time'] -
29933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      scroll_update_data[rendering_stats.BEGIN_SCROLL_UPDATE_COMP_NAME]['time'])
30033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  ref_latency_stats.input_event_latency.append((
30133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      rendering_stats.MAIN_THREAD_SCROLL_UPDATE_EVENT_NAME,
30233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      scroll_update_time / 1000.0))
30333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
30433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
30533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckclass RenderingStatsUnitTest(unittest.TestCase):
30633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
30733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  def testHasRenderingStats(self):
30833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    timeline = model.TimelineModel()
30933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    timer = MockTimer()
31033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
31133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    # A process without rendering stats
31233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    process_without_stats = timeline.GetOrCreateProcess(pid=1)
31333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    thread_without_stats = process_without_stats.GetOrCreateThread(tid=11)
31433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    process_without_stats.FinalizeImport()
31533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    self.assertFalse(rendering_stats.HasRenderingStats(thread_without_stats))
31633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
31733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    # A process with rendering stats, but no frames in them
31833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    process_without_frames = timeline.GetOrCreateProcess(pid=2)
31933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    thread_without_frames = process_without_frames.GetOrCreateThread(tid=21)
32033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    process_without_frames.FinalizeImport()
32133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    self.assertFalse(rendering_stats.HasRenderingStats(thread_without_frames))
32233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
32333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    # A process with rendering stats and frames in them
32433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    process_with_frames = timeline.GetOrCreateProcess(pid=3)
32533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    thread_with_frames = process_with_frames.GetOrCreateThread(tid=31)
32633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    AddImplThreadRenderingStats(timer, thread_with_frames, True, None)
32733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    process_with_frames.FinalizeImport()
32833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    self.assertTrue(rendering_stats.HasRenderingStats(thread_with_frames))
32933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
330a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  def testHasDrmStats(self):
331a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    timeline = model.TimelineModel()
332a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    timer = MockTimer()
333a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    vblank_timer = MockVblankTimer()
334a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik
335a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    # A process without drm stats
336a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    process_without_stats = timeline.GetOrCreateProcess(pid=5)
337a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    thread_without_stats = process_without_stats.GetOrCreateThread(tid=51)
338a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    process_without_stats.FinalizeImport()
339a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    self.assertFalse(rendering_stats.HasDrmStats(thread_without_stats))
340a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik
341a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    # A process with drm stats and frames in them
342a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    process_with_frames = timeline.GetOrCreateProcess(pid=6)
343a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    thread_with_frames = process_with_frames.GetOrCreateThread(tid=61)
344a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    AddDrmEventFlipStats(timer, vblank_timer, thread_with_frames, True, None)
345a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    process_with_frames.FinalizeImport()
346a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    self.assertTrue(rendering_stats.HasDrmStats(thread_with_frames))
347a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik
34833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  def testBothSurfaceFlingerAndDisplayStats(self):
34933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    timeline = model.TimelineModel()
35033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    timer = MockTimer()
35133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
35233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    ref_stats = ReferenceRenderingStats()
35333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    ref_stats.AppendNewRange()
35433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    surface_flinger = timeline.GetOrCreateProcess(pid=4)
35533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    surface_flinger.name = 'SurfaceFlinger'
35633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    surface_flinger_thread = surface_flinger.GetOrCreateThread(tid=41)
35733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer = timeline.GetOrCreateProcess(pid=2)
35833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    browser = timeline.GetOrCreateProcess(pid=3)
35933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    browser_main = browser.GetOrCreateThread(tid=31)
36033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    browser_main.BeginSlice('webkit.console', 'ActionA',
36133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                            timer.AdvanceAndGet(2, 4), '')
36233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
36333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    # Create SurfaceFlinger stats and display rendering stats.
36433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    for i in xrange(0, 10):
36533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      first = (i == 0)
36633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      AddSurfaceFlingerStats(timer, surface_flinger_thread, first, ref_stats)
36733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      timer.Advance(2, 4)
36833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
36933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    for i in xrange(0, 10):
37033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      first = (i == 0)
37133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      AddDisplayRenderingStats(timer, browser_main, first, None)
37233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      timer.Advance(5, 10)
37333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
37433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    browser_main.EndSlice(timer.AdvanceAndGet())
37533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    timer.Advance(2, 4)
37633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
37733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    browser.FinalizeImport()
37833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer.FinalizeImport()
37933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    timeline_markers = timeline.FindTimelineMarkers(['ActionA'])
38033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    timeline_ranges = [bounds.Bounds.CreateFromEvent(marker)
38133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                       for marker in timeline_markers]
38233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    stats = rendering_stats.RenderingStats(
383a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik        renderer, browser, surface_flinger, None, timeline_ranges)
38433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
38533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    # Compare rendering stats to reference - Only SurfaceFlinger stats should
38633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    # count
38733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    self.assertEquals(stats.frame_timestamps, ref_stats.frame_timestamps)
38833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    self.assertEquals(stats.frame_times, ref_stats.frame_times)
38933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
390a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik  def testBothDrmAndDisplayStats(self):
391a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    timeline = model.TimelineModel()
392a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    timer = MockTimer()
393a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    vblank_timer = MockVblankTimer()
394a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik
395a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    ref_stats = ReferenceRenderingStats()
396a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    ref_stats.AppendNewRange()
397a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    gpu = timeline.GetOrCreateProcess(pid=6)
398a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    gpu.name = 'GPU Process'
399a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    gpu_drm_thread = gpu.GetOrCreateThread(tid=61)
400a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    renderer = timeline.GetOrCreateProcess(pid=2)
401a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    browser = timeline.GetOrCreateProcess(pid=3)
402a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    browser_main = browser.GetOrCreateThread(tid=31)
403a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    browser_main.BeginSlice('webkit.console', 'ActionA',
404a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik                            timer.AdvanceAndGet(2, 4), '')
405a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    vblank_timer.TvAdvance(2000, 4000)
406a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik
407a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    # Create drm flip stats and display rendering stats.
408a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    for i in xrange(0, 10):
409a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik      first = (i == 0)
410a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik      AddDrmEventFlipStats(timer, vblank_timer, gpu_drm_thread,
411a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik                           first, ref_stats)
412a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik      timer.Advance(2, 4)
413a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik      vblank_timer.TvAdvance(2000, 4000)
414a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik
415a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    for i in xrange(0, 10):
416a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik      first = (i == 0)
417a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik      AddDisplayRenderingStats(timer, browser_main, first, None)
418a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik      timer.Advance(5, 10)
419a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik      vblank_timer.TvAdvance(5000, 10000)
420a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik
421a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    browser_main.EndSlice(timer.AdvanceAndGet())
422a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    timer.Advance(2, 4)
423a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    vblank_timer.TvAdvance(2000, 4000)
424a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik
425a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    browser.FinalizeImport()
426a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    renderer.FinalizeImport()
427a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    timeline_markers = timeline.FindTimelineMarkers(['ActionA'])
428a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    timeline_ranges = [bounds.Bounds.CreateFromEvent(marker)
429a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik                       for marker in timeline_markers]
430a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    stats = rendering_stats.RenderingStats(
431a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik        renderer, browser, None, gpu, timeline_ranges)
432a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik
433a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    # Compare rendering stats to reference - Only drm flip stats should
434a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    # count
435a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    self.assertEquals(stats.frame_timestamps, ref_stats.frame_timestamps)
436a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik    self.assertEquals(stats.frame_times, ref_stats.frame_times)
437a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik
43833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  def testBothDisplayAndImplStats(self):
43933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    timeline = model.TimelineModel()
44033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    timer = MockTimer()
44133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
44233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    ref_stats = ReferenceRenderingStats()
44333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    ref_stats.AppendNewRange()
44433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer = timeline.GetOrCreateProcess(pid=2)
44533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    browser = timeline.GetOrCreateProcess(pid=3)
44633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    browser_main = browser.GetOrCreateThread(tid=31)
44733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    browser_main.BeginSlice('webkit.console', 'ActionA',
44833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                            timer.AdvanceAndGet(2, 4), '')
44933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
45033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    # Create main, impl, and display rendering stats.
45133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    for i in xrange(0, 10):
45233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      first = (i == 0)
45333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      AddImplThreadRenderingStats(timer, browser_main, first, None)
45433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      timer.Advance(2, 4)
45533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
45633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    for i in xrange(0, 10):
45733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      first = (i == 0)
45833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      AddDisplayRenderingStats(timer, browser_main, first, ref_stats)
45933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      timer.Advance(5, 10)
46033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
46133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    browser_main.EndSlice(timer.AdvanceAndGet())
46233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    timer.Advance(2, 4)
46333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
46433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    browser.FinalizeImport()
46533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer.FinalizeImport()
46633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    timeline_markers = timeline.FindTimelineMarkers(['ActionA'])
46733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    timeline_ranges = [bounds.Bounds.CreateFromEvent(marker)
46833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                       for marker in timeline_markers]
46933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    stats = rendering_stats.RenderingStats(
470a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik        renderer, browser, None, None, timeline_ranges)
47133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
47233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    # Compare rendering stats to reference - Only display stats should count
47333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    self.assertEquals(stats.frame_timestamps, ref_stats.frame_timestamps)
47433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    self.assertEquals(stats.frame_times, ref_stats.frame_times)
47533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
47633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  def testRangeWithoutFrames(self):
47733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    timer = MockTimer()
47833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    timeline = model.TimelineModel()
47933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
48033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    # Create a renderer process, with a main thread and impl thread.
48133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer = timeline.GetOrCreateProcess(pid=2)
48233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer_main = renderer.GetOrCreateThread(tid=21)
48333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer_compositor = renderer.GetOrCreateThread(tid=22)
48433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
48533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    # Create 10 main and impl rendering stats events for Action A.
48633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer_main.BeginSlice('webkit.console', 'ActionA',
48733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                             timer.AdvanceAndGet(2, 4), '')
48833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    for i in xrange(0, 10):
48933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      first = (i == 0)
49033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      AddImplThreadRenderingStats(timer, renderer_compositor, first, None)
49133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer_main.EndSlice(timer.AdvanceAndGet(2, 4))
49233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    timer.Advance(2, 4)
49333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
49433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    # Create 5 main and impl rendering stats events not within any action.
49533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    for i in xrange(0, 5):
49633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      first = (i == 0)
49733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      AddImplThreadRenderingStats(timer, renderer_compositor, first, None)
49833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
49933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    # Create Action B without any frames. This should trigger
50033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    # NotEnoughFramesError when the RenderingStats object is created.
50133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer_main.BeginSlice('webkit.console', 'ActionB',
50233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                             timer.AdvanceAndGet(2, 4), '')
50333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer_main.EndSlice(timer.AdvanceAndGet(2, 4))
50433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
50533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer.FinalizeImport()
50633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
50733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    timeline_markers = timeline.FindTimelineMarkers(['ActionA', 'ActionB'])
50833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    timeline_ranges = [bounds.Bounds.CreateFromEvent(marker)
50933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                       for marker in timeline_markers]
51033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
51133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    stats = rendering_stats.RenderingStats(
512a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik        renderer, None, None, None, timeline_ranges)
51333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    self.assertEquals(0, len(stats.frame_timestamps[1]))
51433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
51533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  def testFromTimeline(self):
51633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    timeline = model.TimelineModel()
51733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
51833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    # Create a browser process and a renderer process, and a main thread and
51933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    # impl thread for each.
52033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    browser = timeline.GetOrCreateProcess(pid=1)
52133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    browser_compositor = browser.GetOrCreateThread(tid=12)
52233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer = timeline.GetOrCreateProcess(pid=2)
52333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer_main = renderer.GetOrCreateThread(tid=21)
52433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer_compositor = renderer.GetOrCreateThread(tid=22)
52533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
52633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    timer = MockTimer()
52733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer_ref_stats = ReferenceRenderingStats()
52833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    browser_ref_stats = ReferenceRenderingStats()
52933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
53033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    # Create 10 main and impl rendering stats events for Action A.
53133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer_main.BeginSlice('webkit.console', 'ActionA',
53233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                             timer.AdvanceAndGet(2, 4), '')
53333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer_ref_stats.AppendNewRange()
53433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    browser_ref_stats.AppendNewRange()
53533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    for i in xrange(0, 10):
53633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      first = (i == 0)
53733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      AddImplThreadRenderingStats(
53833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck          timer, renderer_compositor, first, renderer_ref_stats)
53933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      AddImplThreadRenderingStats(
54033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck          timer, browser_compositor, first, browser_ref_stats)
54133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer_main.EndSlice(timer.AdvanceAndGet(2, 4))
54233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
54333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    # Create 5 main and impl rendering stats events not within any action.
54433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    for i in xrange(0, 5):
54533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      first = (i == 0)
54633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      AddImplThreadRenderingStats(timer, renderer_compositor, first, None)
54733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      AddImplThreadRenderingStats(timer, browser_compositor, first, None)
54833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
54933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    # Create 10 main and impl rendering stats events for Action B.
55033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer_main.BeginSlice('webkit.console', 'ActionB',
55133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                             timer.AdvanceAndGet(2, 4), '')
55233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer_ref_stats.AppendNewRange()
55333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    browser_ref_stats.AppendNewRange()
55433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    for i in xrange(0, 10):
55533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      first = (i == 0)
55633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      AddImplThreadRenderingStats(
55733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck          timer, renderer_compositor, first, renderer_ref_stats)
55833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      AddImplThreadRenderingStats(
55933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck          timer, browser_compositor, first, browser_ref_stats)
56033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer_main.EndSlice(timer.AdvanceAndGet(2, 4))
56133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
56233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    # Create 10 main and impl rendering stats events for Action A.
56333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer_main.BeginSlice('webkit.console', 'ActionA',
56433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                             timer.AdvanceAndGet(2, 4), '')
56533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer_ref_stats.AppendNewRange()
56633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    browser_ref_stats.AppendNewRange()
56733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    for i in xrange(0, 10):
56833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      first = (i == 0)
56933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      AddImplThreadRenderingStats(
57033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck          timer, renderer_compositor, first, renderer_ref_stats)
57133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      AddImplThreadRenderingStats(
57233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck          timer, browser_compositor, first, browser_ref_stats)
57333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer_main.EndSlice(timer.AdvanceAndGet(2, 4))
57433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    timer.Advance(2, 4)
57533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
57633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    browser.FinalizeImport()
57733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer.FinalizeImport()
57833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
57933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    timeline_markers = timeline.FindTimelineMarkers(
58033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        ['ActionA', 'ActionB', 'ActionA'])
58133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    timeline_ranges = [bounds.Bounds.CreateFromEvent(marker)
58233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                       for marker in timeline_markers]
58333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    stats = rendering_stats.RenderingStats(
584a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik        renderer, browser, None, None, timeline_ranges)
58533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
58633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    # Compare rendering stats to reference.
58733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    self.assertEquals(stats.frame_timestamps,
58833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                      browser_ref_stats.frame_timestamps)
58933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    self.assertEquals(stats.frame_times, browser_ref_stats.frame_times)
59033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    self.assertEquals(stats.approximated_pixel_percentages,
59133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                      renderer_ref_stats.approximated_pixel_percentages)
59233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    self.assertEquals(stats.checkerboarded_pixel_percentages,
59333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                      renderer_ref_stats.checkerboarded_pixel_percentages)
59433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
59533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck  def testInputLatencyFromTimeline(self):
59633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    timeline = model.TimelineModel()
59733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
59833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    # Create a browser process and a renderer process.
59933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    browser = timeline.GetOrCreateProcess(pid=1)
60033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    browser_main = browser.GetOrCreateThread(tid=11)
60133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer = timeline.GetOrCreateProcess(pid=2)
60233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer_main = renderer.GetOrCreateThread(tid=21)
60333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
60433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    timer = MockTimer()
60533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    ref_latency = ReferenceInputLatencyStats()
60633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
60733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    # Create 10 input latency stats events for Action A.
60833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer_main.BeginSlice('webkit.console', 'ActionA',
60933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                             timer.AdvanceAndGet(2, 4), '')
61033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    for _ in xrange(0, 10):
61133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      AddInputLatencyStats(timer, browser_main, renderer_main, ref_latency)
61233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer_main.EndSlice(timer.AdvanceAndGet(2, 4))
61333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
61433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    # Create 5 input latency stats events not within any action.
61533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    timer.Advance(2, 4)
61633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    for _ in xrange(0, 5):
61733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      AddInputLatencyStats(timer, browser_main, renderer_main, None)
61833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
61933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    # Create 10 input latency stats events for Action B.
62033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer_main.BeginSlice('webkit.console', 'ActionB',
62133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                             timer.AdvanceAndGet(2, 4), '')
62233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    for _ in xrange(0, 10):
62333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      AddInputLatencyStats(timer, browser_main, renderer_main, ref_latency)
62433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer_main.EndSlice(timer.AdvanceAndGet(2, 4))
62533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
62633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    # Create 10 input latency stats events for Action A.
62733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer_main.BeginSlice('webkit.console', 'ActionA',
62833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                             timer.AdvanceAndGet(2, 4), '')
62933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    for _ in xrange(0, 10):
63033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      AddInputLatencyStats(timer, browser_main, renderer_main, ref_latency)
63133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer_main.EndSlice(timer.AdvanceAndGet(2, 4))
63233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
63333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    browser.FinalizeImport()
63433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    renderer.FinalizeImport()
63533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
63633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    latency_events = []
63733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
63833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    timeline_markers = timeline.FindTimelineMarkers(
63933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        ['ActionA', 'ActionB', 'ActionA'])
64033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    timeline_ranges = [bounds.Bounds.CreateFromEvent(marker)
64133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                       for marker in timeline_markers]
64233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    for timeline_range in timeline_ranges:
64333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      if timeline_range.is_empty:
64433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        continue
64533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck      latency_events.extend(rendering_stats.GetLatencyEvents(
64633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck          browser, timeline_range))
64733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
64833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    self.assertEquals(latency_events, ref_latency.input_event)
64933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    event_latency_result = rendering_stats.ComputeEventLatencies(latency_events)
65033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    self.assertEquals(event_latency_result,
65133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                      ref_latency.input_event_latency)
65233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
65333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    stats = rendering_stats.RenderingStats(
654a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craik        renderer, browser, None, None, timeline_ranges)
65533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    self.assertEquals(
65633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        perf_tests_helper.FlattenList(stats.input_event_latency),
65733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        [latency for name, latency in ref_latency.input_event_latency
65833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck         if name != rendering_stats.MAIN_THREAD_SCROLL_UPDATE_EVENT_NAME])
65933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    self.assertEquals(
66033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        perf_tests_helper.FlattenList(stats.main_thread_scroll_latency),
66133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        [latency for name, latency in ref_latency.input_event_latency
66233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck         if name == rendering_stats.MAIN_THREAD_SCROLL_UPDATE_EVENT_NAME])
66333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    self.assertEquals(
66433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        perf_tests_helper.FlattenList(stats.gesture_scroll_update_latency),
66533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        [latency for name, latency in ref_latency.input_event_latency
66633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck         if name == rendering_stats.GESTURE_SCROLL_UPDATE_EVENT_NAME])
667