1#!/usr/bin/env vpython 2# Copyright 2017 The Chromium Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6"""Tests for process_profiles.py.""" 7 8import collections 9import unittest 10 11import process_profiles 12 13from test_utils import (ProfileFile, 14 SimpleTestSymbol, 15 TestSymbolOffsetProcessor, 16 TestProfileManager) 17 18class ProcessProfilesTestCase(unittest.TestCase): 19 START_SYMBOL = 'linker_script_start_of_text' 20 21 def setUp(self): 22 self.symbol_0 = SimpleTestSymbol(self.START_SYMBOL, 0, 0) 23 self.symbol_1 = SimpleTestSymbol('1', 6, 16) 24 self.symbol_2 = SimpleTestSymbol('2', 32, 8) 25 self.symbol_3 = SimpleTestSymbol('3', 40, 12) 26 self.offset_to_symbol_info = ( 27 [None] * 3 + [self.symbol_1] * 8 + [None] * 5 + [self.symbol_2] * 4 + 28 [self.symbol_3] * 6) 29 self.symbol_infos = [self.symbol_0, self.symbol_1, 30 self.symbol_2, self.symbol_3] 31 self._file_counter = 0 32 33 def MakeAnnotatedOffset(self, offset, counts): 34 ao = process_profiles.ProfileManager.AnnotatedOffset(offset) 35 ao._count = counts 36 return ao 37 38 def testGetOffsetToSymbolInfo(self): 39 processor = TestSymbolOffsetProcessor(self.symbol_infos) 40 self.assertListEqual(self.offset_to_symbol_info, 41 processor.GetDumpOffsetToSymbolInfo()) 42 43 def testOverlappingSymbols(self): 44 symbol_1 = SimpleTestSymbol(self.START_SYMBOL, 6, 8) 45 symbol_2 = SimpleTestSymbol('2', 10, 10) 46 processor = TestSymbolOffsetProcessor([symbol_1, symbol_2]) 47 self.assertListEqual([symbol_1] * 4 + [symbol_2] * 3, 48 processor.GetDumpOffsetToSymbolInfo()) 49 50 def testSymbolsBeforeStart(self): 51 self.symbol_infos = [SimpleTestSymbol(s.name, s.offset + 8, s.size) 52 for s in self.symbol_infos] 53 self.symbol_infos.append(SimpleTestSymbol('early', 0, 4)) 54 processor = TestSymbolOffsetProcessor(self.symbol_infos) 55 self.assertRaises(AssertionError, processor.GetDumpOffsetToSymbolInfo) 56 57 def testGetReachedOffsetsFromDump(self): 58 processor = TestSymbolOffsetProcessor(self.symbol_infos) 59 # 2 hits for symbol_1, 0 for symbol_2, 1 for symbol_3 60 dump = [8, 12, 48] 61 reached = processor.GetReachedOffsetsFromDump(dump) 62 self.assertListEqual([self.symbol_1.offset, self.symbol_3.offset], reached) 63 # Ordering matters, no repetitions 64 dump = [48, 12, 8, 12, 8, 16] 65 reached = processor.GetReachedOffsetsFromDump(dump) 66 self.assertListEqual([self.symbol_3.offset, self.symbol_1.offset], reached) 67 68 def testSymbolNameToPrimary(self): 69 symbol_infos = [SimpleTestSymbol('1', 8, 16), 70 SimpleTestSymbol('AnAlias', 8, 16), 71 SimpleTestSymbol('Another', 40, 16)] 72 processor = TestSymbolOffsetProcessor(symbol_infos) 73 self.assertDictEqual({8: symbol_infos[0], 74 40: symbol_infos[2]}, processor.OffsetToPrimaryMap()) 75 76 def testGetOrderedSymbols(self): 77 processor = TestSymbolOffsetProcessor(self.symbol_infos) 78 self.assertListEqual(['1', '3', self.START_SYMBOL], 79 processor.GetOrderedSymbols([7, 41, 5, 0])) 80 81 def testOffsetToSymbolsMap(self): 82 symbol_infos = [SimpleTestSymbol('1', 8, 16), 83 SimpleTestSymbol('AnAlias', 8, 16), 84 SimpleTestSymbol('Another', 40, 16)] 85 processor = TestSymbolOffsetProcessor(symbol_infos) 86 self.assertDictEqual({8: [symbol_infos[0], symbol_infos[1]], 87 40: [symbol_infos[2]]}, 88 processor.OffsetToSymbolsMap()) 89 90 def testPrimarySizeMismatch(self): 91 symbol_infos = [SimpleTestSymbol('1', 8, 16), 92 SimpleTestSymbol('AnAlias', 8, 32)] 93 processor = TestSymbolOffsetProcessor(symbol_infos) 94 self.assertRaises(AssertionError, processor.OffsetToPrimaryMap) 95 symbol_infos = [SimpleTestSymbol('1', 8, 0), 96 SimpleTestSymbol('2', 8, 32), 97 SimpleTestSymbol('3', 8, 32), 98 SimpleTestSymbol('4', 8, 0),] 99 processor = TestSymbolOffsetProcessor(symbol_infos) 100 self.assertDictEqual({8: symbol_infos[1]}, processor.OffsetToPrimaryMap()) 101 102 def testMatchSymbols(self): 103 symbols = [SimpleTestSymbol('W', 30, 10), 104 SimpleTestSymbol('Y', 60, 5), 105 SimpleTestSymbol('X', 100, 10)] 106 processor = TestSymbolOffsetProcessor(symbols) 107 self.assertListEqual(symbols[1:3], 108 processor.MatchSymbolNames(['Y', 'X'])) 109 110 def testSymbolsSize(self): 111 symbols = [SimpleTestSymbol('W', 10, 1), 112 SimpleTestSymbol('X', 20, 2), 113 SimpleTestSymbol('Y', 30, 4), 114 SimpleTestSymbol('Z', 40, 8)] 115 processor = TestSymbolOffsetProcessor(symbols) 116 self.assertEqual(13, processor.SymbolsSize(['W', 'Y', 'Z'])) 117 118 def testMedian(self): 119 self.assertEquals(None, process_profiles._Median([])) 120 self.assertEquals(5, process_profiles._Median([5])) 121 self.assertEquals(5, process_profiles._Median([1, 5, 20])) 122 self.assertEquals(5, process_profiles._Median([4, 6])) 123 self.assertEquals(5, process_profiles._Median([1, 4, 6, 100])) 124 self.assertEquals(5, process_profiles._Median([1, 4, 5, 6, 100])) 125 126 def testRunGroups(self): 127 files = [ProfileFile(40, 0), ProfileFile(100, 0), 128 ProfileFile(200, 1), ProfileFile(35, 1), 129 ProfileFile(42, 0), ProfileFile(95, 0)] 130 mgr = process_profiles.ProfileManager(files) 131 mgr._ComputeRunGroups() 132 self.assertEquals(3, len(mgr._run_groups)) 133 self.assertEquals(3, len(mgr._run_groups[0].Filenames())) 134 self.assertEquals(2, len(mgr._run_groups[1].Filenames())) 135 self.assertEquals(1, len(mgr._run_groups[2].Filenames())) 136 self.assertTrue(files[0] in mgr._run_groups[0].Filenames()) 137 self.assertTrue(files[3] in mgr._run_groups[0].Filenames()) 138 self.assertTrue(files[4] in mgr._run_groups[0].Filenames()) 139 self.assertTrue(files[1] in mgr._run_groups[1].Filenames()) 140 self.assertTrue(files[5] in mgr._run_groups[1].Filenames()) 141 self.assertTrue(files[2] in mgr._run_groups[2].Filenames()) 142 143 def testRunGroupSanity(self): 144 files = [] 145 # Generate 20 sets of files in groups separated by 60s. 146 for ts_base in xrange(0, 20): 147 ts = ts_base * 60 148 files.extend([ProfileFile(ts, 0, 'browser'), 149 ProfileFile(ts + 1, 0, 'renderer'), 150 ProfileFile(ts + 2, 1, 'browser'), 151 ProfileFile(ts + 3, 0, 'gpu'), 152 ProfileFile(ts + 2, 1, 'renderer'), 153 ProfileFile(ts + 5, 1, 'gpu')]) 154 # The following call should not assert. 155 process_profiles.ProfileManager(files)._ComputeRunGroups() 156 157 files.extend([ProfileFile(20 * 60, 0, 'browser'), 158 ProfileFile(20 * 60 + 2, 1, 'renderer'), 159 ProfileFile(21 * 60, 0, 'browser')] + 160 [ProfileFile(22 * 60, 0, 'renderer') 161 for _ in xrange(0, 10)]) 162 163 self.assertRaises(AssertionError, 164 process_profiles.ProfileManager(files)._ComputeRunGroups) 165 166 def testReadOffsets(self): 167 mgr = TestProfileManager({ 168 ProfileFile(30, 0): [1, 3, 5, 7], 169 ProfileFile(40, 1): [8, 10], 170 ProfileFile(50, 0): [13, 15]}) 171 self.assertListEqual([1, 3, 5, 7, 8, 10, 13, 15], 172 mgr.GetMergedOffsets()) 173 self.assertListEqual([8, 10], mgr.GetMergedOffsets(1)) 174 self.assertListEqual([], mgr.GetMergedOffsets(2)) 175 176 def testRunGroupOffsets(self): 177 mgr = TestProfileManager({ 178 ProfileFile(30, 0): [1, 2, 3, 4], 179 ProfileFile(150, 0): [9, 11, 13], 180 ProfileFile(40, 1): [5, 6, 7]}) 181 offsets_list = mgr.GetRunGroupOffsets() 182 self.assertEquals(2, len(offsets_list)) 183 self.assertListEqual([1, 2, 3, 4, 5, 6, 7], offsets_list[0]) 184 self.assertListEqual([9, 11, 13], offsets_list[1]) 185 offsets_list = mgr.GetRunGroupOffsets(0) 186 self.assertEquals(2, len(offsets_list)) 187 self.assertListEqual([1, 2, 3, 4], offsets_list[0]) 188 self.assertListEqual([9, 11, 13], offsets_list[1]) 189 offsets_list = mgr.GetRunGroupOffsets(1) 190 self.assertEquals(2, len(offsets_list)) 191 self.assertListEqual([5, 6, 7], offsets_list[0]) 192 self.assertListEqual([], offsets_list[1]) 193 194 def testSorted(self): 195 # The fact that the ProfileManager sorts by filename is implicit in the 196 # other tests. It is tested explicitly here. 197 mgr = TestProfileManager({ 198 ProfileFile(40, 0): [1, 2, 3, 4], 199 ProfileFile(150, 0): [9, 11, 13], 200 ProfileFile(30, 1): [5, 6, 7]}) 201 offsets_list = mgr.GetRunGroupOffsets() 202 self.assertEquals(2, len(offsets_list)) 203 self.assertListEqual([5, 6, 7, 1, 2, 3, 4], offsets_list[0]) 204 205 def testPhases(self): 206 mgr = TestProfileManager({ 207 ProfileFile(40, 0): [], 208 ProfileFile(150, 0): [], 209 ProfileFile(30, 1): [], 210 ProfileFile(30, 2): [], 211 ProfileFile(30, 0): []}) 212 self.assertEquals(set([0,1,2]), mgr.GetPhases()) 213 214 def testGetAnnotatedOffsets(self): 215 mgr = TestProfileManager({ 216 ProfileFile(40, 0, ''): [1, 2, 3], 217 ProfileFile(50, 1, ''): [3, 4, 5], 218 ProfileFile(51, 0, 'renderer'): [2, 3, 6], 219 ProfileFile(51, 1, 'gpu-process'): [6, 7], 220 ProfileFile(70, 0, ''): [2, 8, 9], 221 ProfileFile(70, 1, ''): [9]}) 222 offsets = mgr.GetAnnotatedOffsets() 223 self.assertListEqual([ 224 self.MakeAnnotatedOffset(1, {(0, 'browser'): 1}), 225 self.MakeAnnotatedOffset(2, {(0, 'browser'): 2, 226 (0, 'renderer'): 1}), 227 self.MakeAnnotatedOffset(3, {(0, 'browser'): 1, 228 (1, 'browser'): 1, 229 (0, 'renderer'): 1}), 230 self.MakeAnnotatedOffset(4, {(1, 'browser'): 1}), 231 self.MakeAnnotatedOffset(5, {(1, 'browser'): 1}), 232 self.MakeAnnotatedOffset(6, {(0, 'renderer'): 1, 233 (1, 'gpu-process'): 1}), 234 self.MakeAnnotatedOffset(7, {(1, 'gpu-process'): 1}), 235 self.MakeAnnotatedOffset(8, {(0, 'browser'): 1}), 236 self.MakeAnnotatedOffset(9, {(0, 'browser'): 1, 237 (1, 'browser'): 1})], 238 offsets) 239 self.assertListEqual(['browser', 'renderer'], 240 sorted(offsets[1].Processes())) 241 self.assertListEqual(['browser'], list(offsets[0].Processes())) 242 self.assertListEqual([0], list(offsets[1].Phases())) 243 self.assertListEqual([0, 1], sorted(offsets[2].Phases())) 244 self.assertListEqual([0, 1], sorted(mgr.GetPhases())) 245 246 247if __name__ == '__main__': 248 unittest.main() 249