| #!/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() |