# Copyright 2016 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import linux_perf_report as ipr
import StringIO
import unittest


PERF_SCRIPT_OUTPUT = """
# This line is a comment
# This should be ignored too
#
#    cdefab01  aRandomSymbol::Name(to, be, ignored)

   00000000 firstSymbol
   00000123 secondSymbol

   01234567 foo
   abcdef76 BytecodeHandler:bar
   76543210 baz

# Indentation shouldn't matter (neither should this line)

    01234567 foo
      abcdef76 BytecodeHandler:bar
        76543210 baz

      01234567 beep
   abcdef76 BytecodeHandler:bar
    76543210 baz

   01234567 hello
   abcdef76 v8::internal::Compiler
   00000000 Stub:CEntryStub
   76543210 world
   11111111 BytecodeHandler:nope

   00000000 Lost
   11111111 Builtin:InterpreterEntryTrampoline
   22222222 bar

   11111111 Builtin:InterpreterEntryTrampoline
   22222222 bar
"""


class LinuxPerfReportTest(unittest.TestCase):
  def test_collapsed_callchains_generator(self):
    perf_stream = StringIO.StringIO(PERF_SCRIPT_OUTPUT)
    callchains = list(ipr.collapsed_callchains_generator(perf_stream))
    self.assertListEqual(callchains, [
      ["foo", "BytecodeHandler:bar"],
      ["foo", "BytecodeHandler:bar"],
      ["beep", "BytecodeHandler:bar"],
      ["[entry trampoline]"],
    ])

  def test_collapsed_callchains_generator_show_other(self):
    perf_stream = StringIO.StringIO(PERF_SCRIPT_OUTPUT)
    callchains = list(ipr.collapsed_callchains_generator(perf_stream,
                                                         show_all=True))
    self.assertListEqual(callchains, [
      ['firstSymbol', 'secondSymbol', '[other]'],
      ["foo", "BytecodeHandler:bar"],
      ["foo", "BytecodeHandler:bar"],
      ["beep", "BytecodeHandler:bar"],
      ["hello", "v8::internal::Compiler", "[compiler]"],
      ["Lost", "[misattributed]"],
      ["[entry trampoline]"],
    ])

  def test_calculate_samples_count_per_callchain(self):
    counters = ipr.calculate_samples_count_per_callchain([
      ["foo", "BytecodeHandler:bar"],
      ["foo", "BytecodeHandler:bar"],
      ["beep", "BytecodeHandler:bar"],
      ["hello", "v8::internal::Compiler", "[compiler]"],
    ])
    self.assertItemsEqual(counters, [
      ('BytecodeHandler:bar;foo', 2),
      ('BytecodeHandler:bar;beep', 1),
      ('[compiler];v8::internal::Compiler;hello', 1),
    ])

  def test_calculate_samples_count_per_callchain(self):
    counters = ipr.calculate_samples_count_per_callchain([
      ["foo", "BytecodeHandler:bar"],
      ["foo", "BytecodeHandler:bar"],
      ["beep", "BytecodeHandler:bar"],
    ])
    self.assertItemsEqual(counters, [
      ('BytecodeHandler:bar;foo', 2),
      ('BytecodeHandler:bar;beep', 1),
    ])

  def test_calculate_samples_count_per_handler_show_compile(self):
    counters = ipr.calculate_samples_count_per_handler([
      ["foo", "BytecodeHandler:bar"],
      ["foo", "BytecodeHandler:bar"],
      ["beep", "BytecodeHandler:bar"],
      ["hello", "v8::internal::Compiler", "[compiler]"],
    ])
    self.assertItemsEqual(counters, [
      ("bar", 3),
      ("[compiler]", 1)
    ])

  def test_calculate_samples_count_per_handler_(self):
    counters = ipr.calculate_samples_count_per_handler([
      ["foo", "BytecodeHandler:bar"],
      ["foo", "BytecodeHandler:bar"],
      ["beep", "BytecodeHandler:bar"],
    ])
    self.assertItemsEqual(counters, [("bar", 3)])

  def test_multiple_handlers(self):
    perf_stream = StringIO.StringIO("""
        0000 foo(bar)
        1234 BytecodeHandler:first
        5678 a::random::call<to>(something, else)
        9abc BytecodeHandler:second
        def0 otherIrrelevant(stuff)
        1111 entrypoint
    """)
    callchains = list(ipr.collapsed_callchains_generator(perf_stream, False))
    self.assertListEqual(callchains, [
      ["foo", "BytecodeHandler:first"],
    ])

  def test_compiler_symbols_regex(self):
    compiler_symbols = [
      "v8::internal::Parser",
      "v8::internal::(anonymous namespace)::Compile",
      "v8::internal::Compiler::foo",
    ]
    for compiler_symbol in compiler_symbols:
      self.assertTrue(ipr.COMPILER_SYMBOLS_RE.match(compiler_symbol))

  def test_strip_function_parameters(self):
    def should_match(signature, name):
      self.assertEqual(ipr.strip_function_parameters(signature), name)

    should_match("foo(bar)", "foo"),
    should_match("Foo(foomatic::(anonymous)::bar(baz))", "Foo"),
    should_match("v8::(anonymous ns)::bar<thing(with, parentheses)>(baz, poe)",
       "v8::(anonymous ns)::bar<thing(with, parentheses)>")
