1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
13 from telemetry
.core
import util
14 from telemetry
import decorators
15 from telemetry
.internal
.platform
.profiler
import android_profiling_helper
16 from telemetry
.testing
import simple_mock
17 from telemetry
.testing
import tab_test_case
20 def _GetLibrariesMappedIntoProcesses(device
, pids
):
23 maps_file
= '/proc/%d/maps' % pid
24 maps
= device
.ReadFile(maps_file
, as_root
=True).splitlines()
26 lib
= re
.match(r
'.*\s(/.*[.]so)$', map_line
)
28 libs
.add(lib
.group(1))
32 class TestFileMetadataMatches(unittest
.TestCase
):
34 self
.tempdir
= tempfile
.mkdtemp()
35 self
.filename_a
= os
.path
.join(self
.tempdir
, 'filea')
36 self
.filename_b
= os
.path
.join(self
.tempdir
, 'fileb')
38 with
open(self
.filename_a
, 'w') as f
:
42 shutil
.rmtree(self
.tempdir
)
44 def testDoesntMatchNonExistant(self
):
46 android_profiling_helper
._FileMetadataMatches
(
47 self
.filename_a
, self
.filename_b
))
49 def testDoesntMatchJustExistence(self
):
50 with
open(self
.filename_b
, 'w') as f
:
54 android_profiling_helper
._FileMetadataMatches
(
55 self
.filename_a
, self
.filename_b
))
57 def testDoesntMatchCopy(self
):
58 # This test can run so fast that the file system doesn't have enough
59 # accuracy to differentiate between the copy and initial file times.
60 # Hence we need to guarantee a delay here.
62 shutil
.copy(self
.filename_a
, self
.filename_b
)
64 android_profiling_helper
._FileMetadataMatches
(
65 self
.filename_a
, self
.filename_b
))
67 def testMatchesAfterCopy2(self
):
68 shutil
.copy2(self
.filename_a
, self
.filename_b
)
70 android_profiling_helper
._FileMetadataMatches
(
71 self
.filename_a
, self
.filename_b
))
73 def testDoesntMatchAfterCopy2ThenModify(self
):
74 shutil
.copy2(self
.filename_a
, self
.filename_b
)
76 filea
= open(self
.filename_a
, 'w')
77 filea
.write('moar testing!')
81 android_profiling_helper
._FileMetadataMatches
(
82 self
.filename_a
, self
.filename_b
))
84 def testDoesntMatchAfterCopy2ThenModifyStats(self
):
85 shutil
.copy2(self
.filename_a
, self
.filename_b
)
86 os
.utime(self
.filename_a
, (20, 20))
88 android_profiling_helper
._FileMetadataMatches
(
89 self
.filename_a
, self
.filename_b
))
91 def testMatchesAfterCopyStatWithDifferentContent(self
):
92 fileb
= open(self
.filename_b
, 'w')
93 fileb
.write('blahing')
96 shutil
.copystat(self
.filename_a
, self
.filename_b
)
99 android_profiling_helper
._FileMetadataMatches
(
100 self
.filename_a
, self
.filename_b
))
103 class TestAndroidProfilingHelper(unittest
.TestCase
):
105 @decorators.Enabled('linux')
106 def testGetRequiredLibrariesForPerfProfile(self
):
107 perf_output
= os
.path
.join(
108 util
.GetUnittestDataDir(), 'sample_perf_report_output.txt')
109 with
open(perf_output
) as f
:
110 perf_output
= f
.read()
112 mock_popen
= simple_mock
.MockObject()
113 mock_popen
.ExpectCall('communicate').WillReturn([None, perf_output
])
115 mock_subprocess
= simple_mock
.MockObject()
116 mock_subprocess
.ExpectCall(
117 'Popen').WithArgs(simple_mock
.DONT_CARE
).WillReturn(mock_popen
)
118 mock_subprocess
.SetAttribute('PIPE', simple_mock
.MockObject())
120 real_subprocess
= android_profiling_helper
.subprocess
121 android_profiling_helper
.subprocess
= mock_subprocess
123 libs
= android_profiling_helper
.GetRequiredLibrariesForPerfProfile('foo')
124 self
.assertEqual(libs
, set([
125 '/data/app-lib/com.google.android.apps.chrome-2/libchrome.2016.0.so',
126 '/system/lib/libart.so',
127 '/system/lib/libc.so',
128 '/system/lib/libm.so']))
130 android_profiling_helper
.subprocess
= real_subprocess
132 @decorators.Enabled('android')
133 def testGetRequiredLibrariesForVTuneProfile(self
):
134 vtune_db_output
= os
.path
.join(
135 util
.GetUnittestDataDir(), 'sample_vtune_db_output')
136 with
open(vtune_db_output
, 'rb') as f
:
137 vtune_db_output
= pickle
.load(f
)
139 mock_cursor
= simple_mock
.MockObject()
140 mock_cursor
.ExpectCall(
141 'execute').WithArgs(simple_mock
.DONT_CARE
).WillReturn(vtune_db_output
)
143 mock_conn
= simple_mock
.MockObject()
144 mock_conn
.ExpectCall('cursor').WillReturn(mock_cursor
)
145 mock_conn
.ExpectCall('close')
147 mock_sqlite3
= simple_mock
.MockObject()
148 mock_sqlite3
.ExpectCall(
149 'connect').WithArgs(simple_mock
.DONT_CARE
).WillReturn(mock_conn
)
151 real_sqlite3
= android_profiling_helper
.sqlite3
152 android_profiling_helper
.sqlite3
= mock_sqlite3
154 libs
= android_profiling_helper
.GetRequiredLibrariesForVTuneProfile('foo')
155 self
.assertEqual(libs
, set([
156 '/data/app-lib/com.google.android.apps.chrome-1/libchrome.2019.0.so',
157 '/system/lib/libdvm.so',
158 '/system/lib/libc.so',
159 '/system/lib/libm.so']))
161 android_profiling_helper
.sqlite3
= real_sqlite3
164 class TestAndroidProfilingHelperTabTestCase(tab_test_case
.TabTestCase
):
167 super(TestAndroidProfilingHelperTabTestCase
, self
).setUp()
168 # pylint: disable=protected-access
169 browser_backend
= self
._browser
._browser
_backend
170 self
._device
= browser_backend
.device()
172 # https://github.com/catapult-project/catapult/issues/3099 (Android)
173 @decorators.Disabled('all')
174 def testCreateSymFs(self
):
175 # pylint: disable=protected-access
176 browser_pid
= self
._browser
._browser
_backend
.pid
177 pids
= ([browser_pid
] +
178 self
._browser
._platform
_backend
.GetChildPids(browser_pid
))
179 libs
= _GetLibrariesMappedIntoProcesses(self
._device
, pids
)
182 symfs_dir
= tempfile
.mkdtemp()
184 kallsyms
= android_profiling_helper
.CreateSymFs(self
._device
, symfs_dir
,
187 # Check that we have kernel symbols.
188 assert os
.path
.exists(kallsyms
)
190 is_unstripped
= re
.compile(r
'^/data/app(-lib)?/.*\.so$')
191 has_unstripped
= False
193 # Check that all requested libraries are present.
195 has_unstripped
= has_unstripped
or is_unstripped
.match(lib
)
196 assert os
.path
.exists(os
.path
.join(symfs_dir
, lib
[1:])), \
197 '%s not found in symfs' % lib
199 # Make sure we found at least one unstripped library.
200 assert has_unstripped
202 shutil
.rmtree(symfs_dir
)
204 # Test fails: crbug.com/437081
205 # @decorators.Enabled('android')
206 @decorators.Disabled('all')
207 def testGetToolchainBinaryPath(self
):
208 with tempfile
.NamedTemporaryFile() as libc
:
209 self
._device
.PullFile('/system/lib/libc.so', libc
.name
)
210 path
= android_profiling_helper
.GetToolchainBinaryPath(libc
.name
,
212 assert path
and os
.path
.exists(path
)