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. 4 5import unittest 6 7from telemetry.timeline import model as model_module 8from telemetry.timeline import slice as slice_module 9from telemetry.timeline import async_slice 10from telemetry.web_perf import timeline_interaction_record as tir_module 11 12 13class ParseTests(unittest.TestCase): 14 15 def testParse(self): 16 self.assertTrue(tir_module.IsTimelineInteractionRecord( 17 'Interaction.Foo')) 18 self.assertTrue(tir_module.IsTimelineInteractionRecord( 19 'Interaction.Foo/Bar')) 20 self.assertFalse(tir_module.IsTimelineInteractionRecord( 21 'SomethingRandom')) 22 23 24class TimelineInteractionRecordTests(unittest.TestCase): 25 26 def CreateSimpleRecordWithName(self, event_name): 27 s = async_slice.AsyncSlice( 28 'cat', event_name, 29 timestamp=0, duration=200, thread_start=20, thread_duration=100) 30 return tir_module.TimelineInteractionRecord.FromAsyncEvent(s) 31 32 def CreateTestSliceFromTimeRanges( 33 self, parent_thread, time_start, time_end, thread_start, thread_end): 34 duration = time_end - time_start 35 thread_duration = thread_end - thread_start 36 return slice_module.Slice(parent_thread, 'Test', 'foo', time_start, 37 duration, thread_start, thread_duration) 38 39 def testCreate(self): 40 r = self.CreateSimpleRecordWithName('Interaction.LogicalName') 41 self.assertEquals('LogicalName', r.label) 42 self.assertEquals(False, r.is_smooth) 43 self.assertEquals(False, r.is_responsive) 44 45 r = self.CreateSimpleRecordWithName('Interaction.LogicalName/is_smooth') 46 self.assertEquals('LogicalName', r.label) 47 self.assertEquals(True, r.is_smooth) 48 self.assertEquals(False, r.is_responsive) 49 50 r = self.CreateSimpleRecordWithName( 51 'Interaction.LogicalNameWith/Slash/is_smooth') 52 self.assertEquals('LogicalNameWith/Slash', r.label) 53 self.assertEquals(True, r.is_smooth) 54 self.assertEquals(False, r.is_responsive) 55 56 r = self.CreateSimpleRecordWithName( 57 'Interaction.LogicalNameWith/Slash/is_smooth,is_responsive') 58 self.assertEquals('LogicalNameWith/Slash', r.label) 59 self.assertEquals(True, r.is_smooth) 60 self.assertEquals(True, r.is_responsive) 61 62 def testGetJavaScriptMarker(self): 63 smooth_marker = tir_module.GetJavaScriptMarker( 64 'MyLabel', [tir_module.IS_SMOOTH]) 65 self.assertEquals('Interaction.MyLabel/is_smooth', smooth_marker) 66 slr_marker = tir_module.GetJavaScriptMarker( 67 'MyLabel', [tir_module.IS_SMOOTH, tir_module.IS_RESPONSIVE]) 68 self.assertEquals('Interaction.MyLabel/is_smooth,is_responsive', slr_marker) 69 70 def testGetOverlappedThreadTimeForSliceInSameThread(self): 71 # Create a renderer thread. 72 model = model_module.TimelineModel() 73 renderer_main = model.GetOrCreateProcess(1).GetOrCreateThread(2) 74 model.FinalizeImport() 75 76 # Make a record that starts at 30ms and ends at 60ms in thread time. 77 s = async_slice.AsyncSlice( 78 'cat', 'Interaction.Test/is_smooth', 79 timestamp=0, duration=200, start_thread=renderer_main, 80 end_thread=renderer_main, thread_start=30, thread_duration=30) 81 record = tir_module.TimelineInteractionRecord.FromAsyncEvent(s) 82 83 # Non overlapped range on the left of event. 84 s1 = self.CreateTestSliceFromTimeRanges(renderer_main, 0, 100, 10, 20) 85 self.assertEquals(0, record.GetOverlappedThreadTimeForSlice(s1)) 86 87 # Non overlapped range on the right of event. 88 s2 = self.CreateTestSliceFromTimeRanges(renderer_main, 0, 100, 70, 90) 89 self.assertEquals(0, record.GetOverlappedThreadTimeForSlice(s2)) 90 91 # Overlapped range on the left of event. 92 s3 = self.CreateTestSliceFromTimeRanges(renderer_main, 0, 100, 20, 50) 93 self.assertEquals(20, record.GetOverlappedThreadTimeForSlice(s3)) 94 95 # Overlapped range in the middle of event. 96 s4 = self.CreateTestSliceFromTimeRanges(renderer_main, 0, 100, 40, 50) 97 self.assertEquals(10, record.GetOverlappedThreadTimeForSlice(s4)) 98 99 # Overlapped range on the left of event. 100 s5 = self.CreateTestSliceFromTimeRanges(renderer_main, 0, 100, 50, 90) 101 self.assertEquals(10, record.GetOverlappedThreadTimeForSlice(s5)) 102 103 def testRepr(self): 104 # Create a renderer thread. 105 model = model_module.TimelineModel() 106 renderer_main = model.GetOrCreateProcess(1).GetOrCreateThread(2) 107 model.FinalizeImport() 108 109 s = async_slice.AsyncSlice( 110 'cat', 'Interaction.Test/is_smooth', 111 timestamp=0, duration=200, start_thread=renderer_main, 112 end_thread=renderer_main, thread_start=30, thread_duration=30) 113 record = tir_module.TimelineInteractionRecord.FromAsyncEvent(s) 114 expected_repr = ( 115 'TimelineInteractionRecord(label=\'Test\', ' 116 'start=0.000000, end=200.000000, flags=is_smooth, ' 117 'async_event=TimelineEvent(name=\'Interaction.Test/is_smooth\',' 118 ' start=0.000000, duration=200, thread_start=30, thread_duration=30))') 119 self.assertEquals(expected_repr, repr(record)) 120 121 122 def testGetOverlappedThreadTimeForSliceInDifferentThread(self): 123 # Create a renderer thread and another thread. 124 model = model_module.TimelineModel() 125 renderer_main = model.GetOrCreateProcess(1).GetOrCreateThread(2) 126 another_thread = model.GetOrCreateProcess(1).GetOrCreateThread(3) 127 model.FinalizeImport() 128 129 # Make a record that starts at 50ms and ends at 150ms in wall time, and is 130 # scheduled 75% of the time (hence thread_duration = 100ms*75% = 75ms). 131 s = async_slice.AsyncSlice( 132 'cat', 'Interaction.Test/is_smooth', 133 timestamp=50, duration=100, start_thread=renderer_main, 134 end_thread=renderer_main, thread_start=55, thread_duration=75) 135 record = tir_module.TimelineInteractionRecord.FromAsyncEvent(s) 136 137 # Non overlapped range on the left of event. 138 s1 = self.CreateTestSliceFromTimeRanges(another_thread, 25, 40, 28, 30) 139 self.assertEquals(0, record.GetOverlappedThreadTimeForSlice(s1)) 140 141 # Non overlapped range on the right of event. 142 s2 = self.CreateTestSliceFromTimeRanges(another_thread, 200, 300, 270, 290) 143 self.assertEquals(0, record.GetOverlappedThreadTimeForSlice(s2)) 144 145 # Overlapped range on the left of event, and slice is scheduled 50% of the 146 # time. 147 # The overlapped wall-time duration is 50ms. 148 # The overlapped thread-time duration is 50ms * 75% * 50% = 18.75 149 s3 = self.CreateTestSliceFromTimeRanges(another_thread, 0, 100, 20, 70) 150 self.assertEquals(18.75, record.GetOverlappedThreadTimeForSlice(s3)) 151 152 # Overlapped range in the middle of event, and slice is scheduled 20% of the 153 # time. 154 # The overlapped wall-time duration is 40ms. 155 # The overlapped thread-time duration is 40ms * 75% * 20% = 6 156 s4 = self.CreateTestSliceFromTimeRanges(another_thread, 100, 140, 120, 128) 157 self.assertEquals(6, record.GetOverlappedThreadTimeForSlice(s4)) 158 159 # Overlapped range on the left of event, and slice is scheduled 100% of the 160 # time. 161 # The overlapped wall-time duration is 32ms. 162 # The overlapped thread-time duration is 32ms * 75% * 100% = 24 163 s5 = self.CreateTestSliceFromTimeRanges(another_thread, 118, 170, 118, 170) 164 self.assertEquals(24, record.GetOverlappedThreadTimeForSlice(s5)) 165