blob: 1c21e5720e355b70178a57f790ea83bf1a972f97 [file]
#!/usr/bin/env vpython3
#
# Copyright 2019 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Unit tests for run_simpleperf.py"""
import os
import unittest
import mock # pylint: disable=import-error
from run_simpleperf import SimplePerfRunner
from run_simpleperf import StackAddressInterpreter
_EXAMPLE_WEBVIEW_PACKAGE_NAME = "com.google.android.webview"
_EXAMPLE_STACK_SCRIPT_INPUT = [
(
"11-15 00:00:00.000 11111 11111 E chromium: #00 0x0000001111111111 "
"/data/app/com.google.android.webview--8E2vMMZTpLVeEKY7ZgoHQ=="
"/lib/arm64/libwebviewchromium.so+0x00000000083a4db8"
),
(
"11-15 00:00:00.000 11111 11111 E chromium: #00 0x0000001111111111 "
"/data/app/com.google.android.webview--8E2vMMZTpLVeEKY7ZgoHQ=="
"/lib/arm64/libwebviewchromium.so+0x00000000083db114"
),
(
"11-15 00:00:00.000 11111 11111 E chromium: #00 0x0000001111111111 "
"/data/app/com.google.android.webview--8E2vMMZTpLVeEKY7ZgoHQ=="
"/lib/arm64/libwebviewchromium.so+0x000000000abcdef0"
),
]
_EXAMPLE_STACK_SCRIPT_OUTPUT = [
"Stack Trace:",
" RELADDR FUNCTION",
(
" 00000000083a4db8 mojo::core::ports::(anonymous namespace)::UpdateTLS("
"mojo::core::ports::PortLocker*, mojo::core::ports::PortLocker*) "
"../../mojo/core/ports/port_locker.cc:26:3"
),
"",
"-----------------------------------------------------",
"",
"Stack Trace:",
" RELADDR FUNCTION",
(
" 00000000083db114 viz::GLRenderer::SetUseProgram(viz::ProgramKey "
"const&, gfx::ColorSpace const&, gfx::ColorSpace const&) "
"../../components/viz/service/display/gl_renderer.cc:3267:14"
),
"",
"-----------------------------------------------------",
]
_ADDRESSES = ['83a4db8', '83db114', 'abcdef0'] # 3rd one is ignored
_WEBVIEW_LIB_NAME = 'libwebviewchromium.so'
_WEBVIEW_LIB_PATH = (
'/data/app/com.google.android.webview'
'--8E2vMMZTpLVeEKY7ZgoHQ==/lib/arm64/libwebviewchromium.so'
)
_EXAMPLE_INTERPRETER_OUTPUT = [
(
'83a4db8',
(
'mojo::core::ports::(anonymous namespace)::UpdateTLS('
'mojo::core::ports::PortLocker*, mojo::core::ports::PortLocker*)'
),
),
(
'83db114',
(
'viz::GLRenderer::SetUseProgram(viz::ProgramKey const&, '
'gfx::ColorSpace const&, gfx::ColorSpace const&)'
),
),
]
_EXAMPLE_INTERPRETER_OUTPUT_WITH_FILE_NAME_LINE = [
(
'83a4db8',
(
'mojo::core::ports::(anonymous namespace)::UpdateTLS('
'mojo::core::ports::PortLocker*, mojo::core::ports::PortLocker*)'
' | ../../mojo/core/ports/port_locker.cc:26:3'
),
),
(
'83db114',
(
'viz::GLRenderer::SetUseProgram(viz::ProgramKey const&, '
'gfx::ColorSpace const&, gfx::ColorSpace const&)'
' | ../../components/viz/service/display/gl_renderer.cc:3267:14'
),
),
]
_MOCK_ORIGINAL_REPORT = [
'"442": {"l": 28, "f": "libwebviewchromium.so[+3db7d84]"},',
'"443": {"l": 28, "f": "libwebviewchromium.so[+3db7a5c]"},',
'"444": {"l": 28, "f": "libwebviewchromium.so[+aaaaaaa]"},',
]
_MOCK_ADDRESSES = ['3db7d84', '3db7a5c', 'aaaaaaa']
_MOCK_ADDRESS_FUNCTION_NAME_PAIRS = [
('3db7d84', 'MyClass::FirstMethod(const char*)'),
('3db7a5c', 'MyClass::SecondMethod(int)'),
]
_MOCK_FINAL_REPORT = [
(
'"442": {"l": 28, "f": "libwebviewchromium.so[MyClass::'
'FirstMethod(const char*)]"},'
),
(
'"443": {"l": 28, "f": "libwebviewchromium.so[MyClass::'
'SecondMethod(int)]"},'
),
('"444": {"l": 28, "f": "libwebviewchromium.so[+aaaaaaa]"},'),
]
class _RunSimpleperfTest(unittest.TestCase):
"""Unit tests for the run_simpleperf module."""
def _AssertFileLines(self, mock_open, expected_lines):
handle = mock_open()
# Get 'str1', 'str2', ... from the call to f.write(str_i + '\n') which is
# saved as [(str1 + '\n'), (str2 + '\n'), ...].
actual_lines = [args[0][:-1] for (args, _) in handle.write.call_args_list]
self.assertEqual(expected_lines, actual_lines)
def setUp(self):
self.tmp_dir = '/tmp' # the actual directory won't be used in this test.
self.args = mock.Mock(
report_path=os.path.join(self.tmp_dir, 'report.html'),
show_file_line=False,
)
self.device = mock.Mock()
self.stack_address_interpreter = StackAddressInterpreter(
self.args, self.tmp_dir
)
self.simple_perf_runner = SimplePerfRunner(
self.device, self.args, self.tmp_dir, self.stack_address_interpreter
)
@mock.patch('run_simpleperf.open', new_callable=mock.mock_open)
def testStackAddressInterpreter(self, mock_open):
StackAddressInterpreter.RunStackScript = mock.Mock(
return_value=_EXAMPLE_STACK_SCRIPT_OUTPUT
)
self.assertEqual(
_EXAMPLE_INTERPRETER_OUTPUT,
self.stack_address_interpreter.Interpret(_ADDRESSES, _WEBVIEW_LIB_PATH),
)
self._AssertFileLines(mock_open, _EXAMPLE_STACK_SCRIPT_INPUT)
@mock.patch('run_simpleperf.open', new_callable=mock.mock_open)
def testStackAddressInterpreterWithFileNameLine(self, mock_open):
self.args.show_file_line = True
StackAddressInterpreter.RunStackScript = mock.Mock(
return_value=_EXAMPLE_STACK_SCRIPT_OUTPUT
)
self.assertEqual(
_EXAMPLE_INTERPRETER_OUTPUT_WITH_FILE_NAME_LINE,
self.stack_address_interpreter.Interpret(_ADDRESSES, _WEBVIEW_LIB_PATH),
)
self._AssertFileLines(mock_open, _EXAMPLE_STACK_SCRIPT_INPUT)
def testSimplePerfRunner_CollectAddresses(self):
addresses = self.simple_perf_runner.CollectAddresses(
_MOCK_ORIGINAL_REPORT, 'libwebviewchromium.so'
)
self.assertEqual(set(_MOCK_ADDRESSES), addresses)
def testSimplePerfRunner_ReplaceAddresses(self):
postprocessed_report = (
self.simple_perf_runner.ReplaceAddressesWithFunctionInfos(
_MOCK_ORIGINAL_REPORT,
_MOCK_ADDRESS_FUNCTION_NAME_PAIRS,
'libwebviewchromium.so',
)
)
self.assertEqual(_MOCK_FINAL_REPORT, postprocessed_report)
@mock.patch('run_simpleperf.open', new_callable=mock.mock_open)
def testSimplePerfRunner_Run(self, mock_open):
self.stack_address_interpreter.Interpret = mock.Mock(
return_value=_MOCK_ADDRESS_FUNCTION_NAME_PAIRS
)
SimplePerfRunner.RunSimplePerf = mock.Mock()
SimplePerfRunner.RunPackageCompile = mock.Mock()
SimplePerfRunner.GetOriginalReportHtml = mock.Mock(
return_value=_MOCK_ORIGINAL_REPORT
)
self.simple_perf_runner.GetCurrentWebViewProvider = mock.Mock(
return_value=_EXAMPLE_WEBVIEW_PACKAGE_NAME
)
self.simple_perf_runner.GetWebViewLibraryNameAndPath = mock.Mock(
return_value=(_WEBVIEW_LIB_NAME, _WEBVIEW_LIB_PATH)
)
self.simple_perf_runner.Run()
self._AssertFileLines(mock_open, _MOCK_FINAL_REPORT)
if __name__ == '__main__':
unittest.main()