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