blob: 95f6d93bdcec588f027006afadc67a851b2c8e4f [file] [log] [blame]
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import unittest
import telemetry.timeline.bounds as timeline_bounds
from telemetry.timeline import model
import telemetry.timeline.slice as tracing_slice
from telemetry.web_perf.metrics. \
rendering_frame import GetFrameEventsInsideRange
from telemetry.web_perf.metrics.rendering_frame import MissingData
from telemetry.web_perf.metrics.rendering_frame import RenderingFrame
class RenderingFrameTestData(object):
def __init__(self):
self._begin_frame_id = 0
self._events = []
self._renderer_process = model.TimelineModel().GetOrCreateProcess(pid=1)
self._main_thread = self._renderer_process.GetOrCreateThread(tid=11)
self._compositor_thread = self._renderer_process.GetOrCreateThread(tid=12)
@property
def events(self):
return self._events
@property
def renderer_process(self):
return self._renderer_process
def AddSendEvent(self, ts=0, duration=1):
self._begin_frame_id += 1
event = self._CreateEvent(
RenderingFrame.send_begin_frame_event, ts, duration)
self._compositor_thread.PushSlice(event)
def AddBeginMainFrameEvent(self, ts=0, duration=1):
event = self._CreateEvent(
RenderingFrame.begin_main_frame_event, ts, duration)
self._main_thread.PushSlice(event)
def FinalizeImport(self):
self._renderer_process.FinalizeImport()
def _CreateEvent(self, event_name, ts, duration):
event = tracing_slice.Slice(None, 'cc,benchmark', event_name, ts,
duration=duration, args={'begin_frame_id': self._begin_frame_id})
self._events.append(event)
return event
def GenerateTimelineRange(start=0, end=100):
timeline_range = timeline_bounds.Bounds()
timeline_range.AddValue(start)
timeline_range.AddValue(end)
return timeline_range
class RenderingFrameUnitTest(unittest.TestCase):
def testRenderingFrame(self):
d = RenderingFrameTestData()
d.AddSendEvent(ts=10)
d.AddBeginMainFrameEvent(ts=20)
d.FinalizeImport()
frame = RenderingFrame(d.events)
self.assertEquals(10, frame.queueing_duration)
def testRenderingFrameMissingSendBeginFrameEvents(self):
d = RenderingFrameTestData()
d.AddBeginMainFrameEvent(ts=10)
d.FinalizeImport()
self.assertRaises(MissingData, RenderingFrame, d.events)
def testRenderingFrameDuplicateSendBeginFrameEvents(self):
d = RenderingFrameTestData()
d.AddSendEvent(ts=10)
d.AddBeginMainFrameEvent(ts=20)
d.AddSendEvent(ts=30)
d.FinalizeImport()
self.assertRaises(MissingData, RenderingFrame, d.events)
def testRenderingFrameMissingBeginMainFrameEvents(self):
d = RenderingFrameTestData()
d.AddSendEvent(ts=10)
d.FinalizeImport()
self.assertRaises(MissingData, RenderingFrame, d.events)
def testRenderingFrameDuplicateBeginMainFrameEvents(self):
d = RenderingFrameTestData()
d.AddSendEvent(ts=10)
d.AddBeginMainFrameEvent(ts=20)
d.AddBeginMainFrameEvent(ts=30)
d.AddBeginMainFrameEvent(ts=40)
d.FinalizeImport()
frame = RenderingFrame(d.events)
self.assertEquals(30, frame.queueing_duration)
def testFrameEventMissingBeginFrameId(self):
timeline = model.TimelineModel()
process = timeline.GetOrCreateProcess(pid=1)
main_thread = process.GetOrCreateThread(tid=11)
timeline_range = timeline_bounds.Bounds()
# Create an event without the begin_frame_id argument
event = tracing_slice.Slice(
None, 'cc,benchmark', RenderingFrame.begin_main_frame_event, 0)
main_thread.PushSlice(event)
process.FinalizeImport()
self.assertRaises(Exception, GetFrameEventsInsideRange, process,
timeline_range)
def testGetFrameEventsInsideRange(self):
"""Test a basic sequenece, with expected frame queueing delays A and B.
|----A----| |--B--|
Main: [1] [1] [2]
Compositor: [1] [2]
"""
d = RenderingFrameTestData()
d.AddSendEvent(ts=10)
d.AddBeginMainFrameEvent(ts=20)
d.AddBeginMainFrameEvent(ts=30)
d.AddSendEvent(ts=40)
d.AddBeginMainFrameEvent(ts=50)
d.FinalizeImport()
timeline_range = GenerateTimelineRange()
frame_events = GetFrameEventsInsideRange(d.renderer_process, timeline_range)
self.assertEquals(2, len(frame_events))
self.assertEquals(20, frame_events[0].queueing_duration)
self.assertEquals(10, frame_events[1].queueing_duration)
def testFrameEventsMissingDataNotIncluded(self):
"""Test a sequenece missing an initial SendBeginFrame.
Only one frame should be returned, with expected frame queueing delay A.
|--A--|
Main: [0] [0] [2]
Compositor: [2]
"""
d = RenderingFrameTestData()
d.AddBeginMainFrameEvent(ts=20)
d.AddBeginMainFrameEvent(ts=30)
d.AddSendEvent(ts=40)
d.AddBeginMainFrameEvent(ts=50)
d.FinalizeImport()
timeline_range = GenerateTimelineRange()
frame_events = GetFrameEventsInsideRange(d.renderer_process, timeline_range)
self.assertEquals(1, len(frame_events))
self.assertEquals(10, frame_events[0].queueing_duration)