1# Copyright 2016 the V8 project 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 linux_perf_report as ipr 6import StringIO 7import unittest 8 9 10PERF_SCRIPT_OUTPUT = """ 11# This line is a comment 12# This should be ignored too 13# 14# cdefab01 aRandomSymbol::Name(to, be, ignored) 15 16 00000000 firstSymbol 17 00000123 secondSymbol 18 19 01234567 foo 20 abcdef76 BytecodeHandler:bar 21 76543210 baz 22 23# Indentation shouldn't matter (neither should this line) 24 25 01234567 foo 26 abcdef76 BytecodeHandler:bar 27 76543210 baz 28 29 01234567 beep 30 abcdef76 BytecodeHandler:bar 31 76543210 baz 32 33 01234567 hello 34 abcdef76 v8::internal::Compiler 35 00000000 Stub:CEntryStub 36 76543210 world 37 11111111 BytecodeHandler:nope 38 39 00000000 Lost 40 11111111 Builtin:InterpreterEntryTrampoline 41 22222222 bar 42 43 00000000 hello 44 11111111 LazyCompile:~Foo 45 46 11111111 Builtin:InterpreterEntryTrampoline 47 22222222 bar 48""" 49 50 51class LinuxPerfReportTest(unittest.TestCase): 52 def test_collapsed_callchains_generator(self): 53 perf_stream = StringIO.StringIO(PERF_SCRIPT_OUTPUT) 54 callchains = list(ipr.collapsed_callchains_generator(perf_stream)) 55 self.assertListEqual(callchains, [ 56 ['firstSymbol', 'secondSymbol', '[other]'], 57 ["foo", "BytecodeHandler:bar", "[interpreter]"], 58 ["foo", "BytecodeHandler:bar", "[interpreter]"], 59 ["beep", "BytecodeHandler:bar", "[interpreter]"], 60 ["hello", "v8::internal::Compiler", "Stub:CEntryStub", "[compiler]"], 61 ["Lost", "[misattributed]"], 62 ["hello", "LazyCompile:~Foo", "[jit]"], 63 ["[entry trampoline]"], 64 ]) 65 66 def test_collapsed_callchains_generator_hide_other(self): 67 perf_stream = StringIO.StringIO(PERF_SCRIPT_OUTPUT) 68 callchains = list(ipr.collapsed_callchains_generator(perf_stream, 69 hide_other=True, 70 hide_compiler=True, 71 hide_jit=True)) 72 self.assertListEqual(callchains, [ 73 ["foo", "BytecodeHandler:bar", "[interpreter]"], 74 ["foo", "BytecodeHandler:bar", "[interpreter]"], 75 ["beep", "BytecodeHandler:bar", "[interpreter]"], 76 ["Lost", "[misattributed]"], 77 ["[entry trampoline]"], 78 ]) 79 80 def test_calculate_samples_count_per_callchain(self): 81 counters = ipr.calculate_samples_count_per_callchain([ 82 ["foo", "BytecodeHandler:bar"], 83 ["foo", "BytecodeHandler:bar"], 84 ["beep", "BytecodeHandler:bar"], 85 ["hello", "v8::internal::Compiler", "[compiler]"], 86 ]) 87 self.assertItemsEqual(counters, [ 88 ('BytecodeHandler:bar;foo', 2), 89 ('BytecodeHandler:bar;beep', 1), 90 ('[compiler];v8::internal::Compiler;hello', 1), 91 ]) 92 93 def test_calculate_samples_count_per_callchain(self): 94 counters = ipr.calculate_samples_count_per_callchain([ 95 ["foo", "BytecodeHandler:bar"], 96 ["foo", "BytecodeHandler:bar"], 97 ["beep", "BytecodeHandler:bar"], 98 ]) 99 self.assertItemsEqual(counters, [ 100 ('BytecodeHandler:bar;foo', 2), 101 ('BytecodeHandler:bar;beep', 1), 102 ]) 103 104 def test_calculate_samples_count_per_handler_show_compile(self): 105 counters = ipr.calculate_samples_count_per_handler([ 106 ["foo", "BytecodeHandler:bar"], 107 ["foo", "BytecodeHandler:bar"], 108 ["beep", "BytecodeHandler:bar"], 109 ["hello", "v8::internal::Compiler", "[compiler]"], 110 ]) 111 self.assertItemsEqual(counters, [ 112 ("bar", 3), 113 ("[compiler]", 1) 114 ]) 115 116 def test_calculate_samples_count_per_handler_(self): 117 counters = ipr.calculate_samples_count_per_handler([ 118 ["foo", "BytecodeHandler:bar"], 119 ["foo", "BytecodeHandler:bar"], 120 ["beep", "BytecodeHandler:bar"], 121 ]) 122 self.assertItemsEqual(counters, [("bar", 3)]) 123 124 def test_multiple_handlers(self): 125 perf_stream = StringIO.StringIO(""" 126 0000 foo(bar) 127 1234 BytecodeHandler:first 128 5678 a::random::call<to>(something, else) 129 9abc BytecodeHandler:second 130 def0 otherIrrelevant(stuff) 131 1111 entrypoint 132 """) 133 callchains = list(ipr.collapsed_callchains_generator(perf_stream, False)) 134 self.assertListEqual(callchains, [ 135 ["foo", "BytecodeHandler:first", "[interpreter]"], 136 ]) 137 138 def test_compiler_symbols_regex(self): 139 compiler_symbols = [ 140 "v8::internal::Parser", 141 "v8::internal::(anonymous namespace)::Compile", 142 "v8::internal::Compiler::foo", 143 ] 144 for compiler_symbol in compiler_symbols: 145 self.assertTrue(ipr.COMPILER_SYMBOLS_RE.match(compiler_symbol)) 146 147 def test_jit_code_symbols_regex(self): 148 jit_code_symbols = [ 149 "LazyCompile:~Foo blah.js", 150 "Eval:*", 151 "Script:*Bar tmp.js", 152 ] 153 for jit_code_symbol in jit_code_symbols: 154 self.assertTrue(ipr.JIT_CODE_SYMBOLS_RE.match(jit_code_symbol)) 155 156 def test_strip_function_parameters(self): 157 def should_match(signature, name): 158 self.assertEqual(ipr.strip_function_parameters(signature), name) 159 160 should_match("foo(bar)", "foo"), 161 should_match("Foo(foomatic::(anonymous)::bar(baz))", "Foo"), 162 should_match("v8::(anonymous ns)::bar<thing(with, parentheses)>(baz, poe)", 163 "v8::(anonymous ns)::bar<thing(with, parentheses)>") 164 165if __name__ == '__main__': 166 unittest.main() 167