process_profiles_unittest.py 10 KB

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