1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)# Copyright 2014 The Chromium Authors. All rights reserved.
2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)# found in the LICENSE file.
46e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)import sys
66e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)import unittest
7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)from telemetry.core.platform.profiler import vtune_profiler
9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)from telemetry.unittest import options_for_unittests
10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)from telemetry.unittest import simple_mock
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)from telemetry.unittest import tab_test_case
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class MockPopen(object):
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def __init__(self, returncode, stdout=None, stderr=None):
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self.returncode = returncode
17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self.stdout = stdout
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self.stderr = stderr
19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def communicate(self):
21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return (self.stdout, self.stderr)
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def wait(self):
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return self.returncode
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class MockSubprocess(object):
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def __init__(self):
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self.PIPE = simple_mock.MockObject()
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self.STDOUT = simple_mock.MockObject()
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self._num_collect_calls = 0
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self._num_stop_calls = 0
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  @property
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def num_collect_calls(self):
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return self._num_collect_calls
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  @property
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def num_stop_calls(self):
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return self._num_stop_calls
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def Popen(self, cmd, **_):
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self._AnalyzeCommand(cmd)
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return MockPopen(0)
45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def call(self, cmd):
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self._AnalyzeCommand(cmd)
48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def _AnalyzeCommand(self, cmd):
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if MockSubprocess._IsCollectCommand(cmd):
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      self._num_collect_calls += 1
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    elif MockSubprocess._IsStopCommand(cmd):
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      self._num_stop_calls += 1
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  @staticmethod
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def _IsCollectCommand(cmd):
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return '-collect' in cmd
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  @staticmethod
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def _IsStopCommand(cmd):
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    try:
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      cmd_idx = cmd.index('-command') + 1
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return cmd_idx < len(cmd) and cmd[cmd_idx] == 'stop'
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    except ValueError:
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return False
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class TestVTuneProfiler(unittest.TestCase):
696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def testVTuneProfilerIsSupported(self):
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    options = options_for_unittests.GetCopy()
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    mock_subprocess = simple_mock.MockObject()
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    mock_subprocess.ExpectCall(
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        'Popen').WithArgs(simple_mock.DONT_CARE).WillReturn(MockPopen(0))
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    mock_subprocess.SetAttribute('PIPE', simple_mock.MockObject())
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    mock_subprocess.SetAttribute('STDOUT', simple_mock.MockObject())
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    real_subprocess = vtune_profiler.subprocess
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    vtune_profiler.subprocess = mock_subprocess
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if options.browser_type.startswith('android'):
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      # On Android we're querying if 'su' is available.
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      mock_subprocess.ExpectCall('Popen').WithArgs(
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          simple_mock.DONT_CARE).WillReturn(MockPopen(0, 'su', None))
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    try:
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      self.assertTrue(
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          vtune_profiler.VTuneProfiler.is_supported(options.browser_type) or
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          sys.platform != 'linux2' or
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          options.browser_type.startswith('cros'))
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    finally:
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      vtune_profiler.subprocess = real_subprocess
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class TestVTuneProfilerTabTestCase(tab_test_case.TabTestCase):
976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def testVTuneProfiler(self):
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    mock_subprocess = MockSubprocess()
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    real_subprocess = vtune_profiler.subprocess
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    vtune_profiler.subprocess = mock_subprocess
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    try:
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      # pylint: disable=W0212
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      profiler = vtune_profiler.VTuneProfiler(self._browser._browser_backend,
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                              self._browser._platform_backend,
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                              'tmp',
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                              {})
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      profiler.CollectProfile()
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      self.assertEqual(mock_subprocess.num_collect_calls,
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       mock_subprocess.num_stop_calls)
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    finally:
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      vtune_profiler.subprocess = real_subprocess
114