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 os 6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)import pickle 7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)import re 8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)import shutil 9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)import tempfile 106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)import unittest 11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 12116680a4aac90f2aa7413d9095a592090648e557Ben Murdochfrom telemetry import benchmark 13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)from telemetry.core import util 14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)from telemetry.core.platform.profiler import android_profiling_helper 15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)from telemetry.unittest import simple_mock 16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)from telemetry.unittest import tab_test_case 17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)def _GetLibrariesMappedIntoProcesses(device, pids): 20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) libs = set() 21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for pid in pids: 22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) maps_file = '/proc/%d/maps' % pid 23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch maps = device.ReadFile(maps_file, as_root=True) 24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for map_line in maps: 25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) lib = re.match(r'.*\s(/.*[.]so)$', map_line) 26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if lib: 27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) libs.add(lib.group(1)) 28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return libs 29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class TestAndroidProfilingHelper(unittest.TestCase): 32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) def testGetRequiredLibrariesForPerfProfile(self): 34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) perf_output = os.path.join( 35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) util.GetUnittestDataDir(), 'sample_perf_report_output.txt') 36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) with open(perf_output) as f: 37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) perf_output = f.read() 38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) mock_popen = simple_mock.MockObject() 40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) mock_popen.ExpectCall('communicate').WillReturn([None, perf_output]) 41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) mock_subprocess = simple_mock.MockObject() 43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) mock_subprocess.ExpectCall( 44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 'Popen').WithArgs(simple_mock.DONT_CARE).WillReturn(mock_popen) 45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) mock_subprocess.SetAttribute('PIPE', simple_mock.MockObject()) 46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) real_subprocess = android_profiling_helper.subprocess 48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) android_profiling_helper.subprocess = mock_subprocess 49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) try: 50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) libs = android_profiling_helper.GetRequiredLibrariesForPerfProfile('foo') 51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) self.assertEqual(libs, set([ 52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) '/data/app-lib/com.google.android.apps.chrome-2/libchrome.2016.0.so', 53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) '/system/lib/libart.so', 54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) '/system/lib/libc.so', 55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) '/system/lib/libm.so'])) 56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) finally: 57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) android_profiling_helper.subprocess = real_subprocess 58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch @benchmark.Enabled('android') 60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) def testGetRequiredLibrariesForVTuneProfile(self): 61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) vtune_db_output = os.path.join( 62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) util.GetUnittestDataDir(), 'sample_vtune_db_output') 63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) with open(vtune_db_output, 'rb') as f: 64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) vtune_db_output = pickle.load(f) 65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) mock_cursor = simple_mock.MockObject() 67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) mock_cursor.ExpectCall( 68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 'execute').WithArgs(simple_mock.DONT_CARE).WillReturn(vtune_db_output) 69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) mock_conn = simple_mock.MockObject() 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) mock_conn.ExpectCall('cursor').WillReturn(mock_cursor) 72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) mock_conn.ExpectCall('close') 73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) mock_sqlite3 = simple_mock.MockObject() 75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) mock_sqlite3.ExpectCall( 76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 'connect').WithArgs(simple_mock.DONT_CARE).WillReturn(mock_conn) 77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) real_sqlite3 = android_profiling_helper.sqlite3 79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) android_profiling_helper.sqlite3 = mock_sqlite3 80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) try: 81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) libs = android_profiling_helper.GetRequiredLibrariesForVTuneProfile('foo') 82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) self.assertEqual(libs, set([ 83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) '/data/app-lib/com.google.android.apps.chrome-1/libchrome.2019.0.so', 84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) '/system/lib/libdvm.so', 85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) '/system/lib/libc.so', 86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) '/system/lib/libm.so'])) 87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) finally: 88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) android_profiling_helper.sqlite3 = real_sqlite3 89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class TestAndroidProfilingHelperTabTestCase(tab_test_case.TabTestCase): 926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) def setUp(self): 946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) super(TestAndroidProfilingHelperTabTestCase, self).setUp() 956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) # pylint: disable=W0212 966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) browser_backend = self._browser._browser_backend 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self._device = browser_backend._adb.device() 986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch @benchmark.Enabled('android') 100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) def testCreateSymFs(self): 101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # pylint: disable=W0212 102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) browser_pid = self._browser._browser_backend.pid 103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) pids = ([browser_pid] + 104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) self._browser._platform_backend.GetChildPids(browser_pid)) 105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) libs = _GetLibrariesMappedIntoProcesses(self._device, pids) 106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) assert libs 107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) symfs_dir = tempfile.mkdtemp() 109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) try: 110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) kallsyms = android_profiling_helper.CreateSymFs(self._device, symfs_dir, 111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) libs) 112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # Check that we have kernel symbols. 114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) assert os.path.exists(kallsyms) 115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci is_unstripped = re.compile('^/data/app/.*\.so$') 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci has_unstripped = False 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # Check that all requested libraries are present. 120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for lib in libs: 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci has_unstripped = has_unstripped or is_unstripped.match(lib) 122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) assert os.path.exists(os.path.join(symfs_dir, lib[1:])), \ 123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) '%s not found in symfs' % lib 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci # Make sure we found at least one unstripped library. 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci assert has_unstripped 127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) finally: 128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) shutil.rmtree(symfs_dir) 129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 130116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch @benchmark.Enabled('android') 131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) def testGetToolchainBinaryPath(self): 132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) with tempfile.NamedTemporaryFile() as libc: 133116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch self._device.PullFile('/system/lib/libc.so', libc.name) 134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) path = android_profiling_helper.GetToolchainBinaryPath(libc.name, 135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 'objdump') 136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) assert os.path.exists(path) 137