# Copyright 2014 The Chromium 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 sys

from telemetry.core.platform.profiler import vtune_profiler
from telemetry.unittest import options_for_unittests
from telemetry.unittest import simple_mock
from telemetry.unittest import tab_test_case

class MockPopen(object):
  def __init__(self, returncode, stdout=None, stderr=None):
    self.returncode = returncode
    self.stdout = stdout
    self.stderr = stderr

  def communicate(self):
    return (self.stdout, self.stderr)

  def wait(self):
    return self.returncode


class MockSubprocess(object):
  def __init__(self):
    self.PIPE = simple_mock.MockObject()
    self.STDOUT = simple_mock.MockObject()
    self._num_collect_calls = 0
    self._num_stop_calls = 0

  @property
  def num_collect_calls(self):
    return self._num_collect_calls

  @property
  def num_stop_calls(self):
    return self._num_stop_calls

  def Popen(self, cmd, **_):
    self._AnalyzeCommand(cmd)
    return MockPopen(0)

  def call(self, cmd):
    self._AnalyzeCommand(cmd)

  def _AnalyzeCommand(self, cmd):
    if MockSubprocess._IsCollectCommand(cmd):
      self._num_collect_calls += 1
    elif MockSubprocess._IsStopCommand(cmd):
      self._num_stop_calls += 1

  @staticmethod
  def _IsCollectCommand(cmd):
    return '-collect' in cmd

  @staticmethod
  def _IsStopCommand(cmd):
    try:
      cmd_idx = cmd.index('-command') + 1
      return cmd_idx < len(cmd) and cmd[cmd_idx] == 'stop'
    except ValueError:
      return False


class TestVTuneProfiler(tab_test_case.TabTestCase):
  def testVTuneProfilerIsSupported(self):
    options = options_for_unittests.GetCopy()

    mock_subprocess = simple_mock.MockObject()
    mock_subprocess.ExpectCall(
        'Popen').WithArgs(simple_mock.DONT_CARE).WillReturn(MockPopen(0))
    mock_subprocess.SetAttribute('PIPE', simple_mock.MockObject())
    mock_subprocess.SetAttribute('STDOUT', simple_mock.MockObject())

    real_subprocess = vtune_profiler.subprocess
    vtune_profiler.subprocess = mock_subprocess

    if options.browser_type.startswith('android'):
      # On Android we're querying if 'su' is available.
      mock_subprocess.ExpectCall('Popen').WithArgs(
          simple_mock.DONT_CARE).WillReturn(MockPopen(0, 'su', None))

    try:
      self.assertTrue(
          vtune_profiler.VTuneProfiler.is_supported(options.browser_type) or
          sys.platform != 'linux2' or
          options.browser_type.startswith('cros'))
    finally:
      vtune_profiler.subprocess = real_subprocess

  def testVTuneProfiler(self):
    mock_subprocess = MockSubprocess()
    real_subprocess = vtune_profiler.subprocess
    vtune_profiler.subprocess = mock_subprocess

    try:
      # pylint: disable=W0212
      profiler = vtune_profiler.VTuneProfiler(self._browser._browser_backend,
                                              self._browser._platform_backend,
                                              'tmp',
                                              {})
      profiler.CollectProfile()
      self.assertEqual(mock_subprocess.num_collect_calls,
                       mock_subprocess.num_stop_calls)
    finally:
      vtune_profiler.subprocess = real_subprocess
