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.
4import unittest
5
6from telemetry.timeline import inspector_importer
7from telemetry.timeline import inspector_timeline_data
8from telemetry.timeline import model
9
10_BACKGROUND_MESSAGE = {
11  'data': {},
12  'type': 'BeginFrame',
13  'thread': '2',
14  'startTime': 1352783525921.824}
15
16_SAMPLE_MESSAGE = {
17  'children': [
18    {'data': {},
19     'startTime': 1352783525921.823,
20     'type': 'BeginFrame',
21     'usedHeapSize': 1870736},
22    {'children': [],
23     'data': {'height': 723,
24              'width': 1272,
25              'x': 0,
26              'y': 0},
27     'endTime': 1352783525921.8992,
28     'frameId': '10.2',
29     'startTime': 1352783525921.8281,
30     'type': 'Layout',
31     'usedHeapSize': 1870736},
32    {'children': [
33        {'children': [],
34         'data': {'imageType': 'PNG'},
35         'endTime': 1352783525927.7939,
36         'startTime': 1352783525922.4241,
37         'type': 'DecodeImage',
38         'usedHeapSize': 1870736}
39        ],
40     'data': {'height': 432,
41              'width': 1272,
42              'x': 0,
43              'y': 8},
44     'endTime': 1352783525927.9822,
45     'frameId': '10.2',
46     'startTime': 1352783525921.9292,
47     'type': 'Paint',
48     'usedHeapSize': 1870736}
49    ],
50  'data': {},
51  'endTime': 1352783525928.041,
52  'startTime': 1352783525921.8049,
53  'type': 'Program'}
54
55class InspectorEventParsingTest(unittest.TestCase):
56  def testParsingWithSampleData(self):
57    root_event = (inspector_importer.InspectorTimelineImporter
58        .RawEventToTimelineEvent(_SAMPLE_MESSAGE))
59    self.assertTrue(root_event)
60    decode_image_event = [
61      child for child in root_event.IterEventsInThisContainerRecrusively()
62      if child.name == 'DecodeImage'][0]
63    self.assertEquals(decode_image_event.args['data']['imageType'], 'PNG')
64    self.assertTrue(decode_image_event.duration > 0)
65
66  def testParsingWithSimpleData(self):
67    raw_event = {'type': 'Foo',
68                 'startTime': 1,
69                 'endTime': 3,
70                 'children': []}
71    event = (inspector_importer.InspectorTimelineImporter
72        .RawEventToTimelineEvent(raw_event))
73    self.assertEquals('Foo', event.name)
74    self.assertEquals(1, event.start)
75    self.assertEquals(3, event.end)
76    self.assertEquals(2, event.duration)
77    self.assertEquals([], event.sub_slices)
78
79  def testParsingWithArgs(self):
80    raw_event = {'type': 'Foo',
81                 'startTime': 1,
82                 'endTime': 3,
83                 'foo': 7,
84                 'bar': {'x': 1}}
85    event = (inspector_importer.InspectorTimelineImporter
86        .RawEventToTimelineEvent(raw_event))
87    self.assertEquals('Foo', event.name)
88    self.assertEquals(1, event.start)
89    self.assertEquals(3, event.end)
90    self.assertEquals(2, event.duration)
91    self.assertEquals([], event.sub_slices)
92    self.assertEquals(7, event.args['foo'])
93    self.assertEquals(1, event.args['bar']['x'])
94
95  def testEventsWithNoStartTimeAreDropped(self):
96    raw_event = {'type': 'Foo',
97                 'endTime': 1,
98                 'children': []}
99    event = (inspector_importer.InspectorTimelineImporter.
100        RawEventToTimelineEvent(raw_event))
101    self.assertEquals(None, event)
102
103  def testEventsWithNoEndTimeAreOk(self):
104    raw_event = {'type': 'Foo',
105                 'startTime': 1,
106                 'children': []}
107    event = (inspector_importer.InspectorTimelineImporter.
108        RawEventToTimelineEvent(raw_event))
109    self.assertEquals(1, event.start)
110    self.assertEquals(1, event.end)
111
112  def testOutOfOrderData(self):
113    raw_event = {
114      'startTime': 5295.004, 'endTime': 5305.004,
115      'data': {}, 'type': 'Program',
116      'children': [
117        {'startTime': 5295.004, 'data': {'id': 0}, 'type': 'BeginFrame', },
118        {'startTime': 4492.973, 'endTime': 4493.086, 'data': {'rootNode': -3},
119         'type': 'PaintSetup'},
120        {'startTime': 5298.004, 'endTime': 5301.004, 'type': 'Paint',
121         'frameId': '53228.1',
122         'data': {'rootNode': -3, 'clip': [0, 0, 1018, 0, 1018, 764, 0, 764],
123                  'layerId': 10}, 'children': []},
124        {'startTime': 5301.004, 'endTime': 5305.004, 'data': {},
125         'type': 'CompositeLayers', 'children': []},
126        {'startTime': 5305.004, 'data': {}, 'type': 'MarkFirstPaint'}
127    ]}
128    timeline_data = inspector_timeline_data.InspectorTimelineData([raw_event])
129    model.TimelineModel(timeline_data=timeline_data, shift_world_to_zero=False)
130
131class InspectorImporterTest(unittest.TestCase):
132  def testImport(self):
133    messages = [_BACKGROUND_MESSAGE, _SAMPLE_MESSAGE]
134    timeline_data = inspector_timeline_data.InspectorTimelineData(messages)
135    m = model.TimelineModel(timeline_data=timeline_data,
136                            shift_world_to_zero=False)
137    self.assertEquals(1, len(m.processes))
138    process = m.processes.values()[0]
139    threads = process.threads
140    self.assertEquals(2, len(threads))
141    renderer_thread = threads[0]
142    self.assertEquals(1, len(renderer_thread.toplevel_slices))
143    self.assertEquals('Program',
144                      renderer_thread.toplevel_slices[0].name)
145    second_thread = threads['2']
146    self.assertEquals(1, len(second_thread.toplevel_slices))
147    self.assertEquals('BeginFrame',
148                      second_thread.toplevel_slices[0].name)
149