diff options
author | jbudorick <jbudorick@chromium.org> | 2015-02-17 11:33:13 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-02-17 19:34:28 +0000 |
commit | bcec82d59869b43f0507d244e84798c6ce1cfcf9 (patch) | |
tree | e1d769680e85c405aa5039e88187a0309597c272 /build/android | |
parent | bc462ea514cba4bec764f5ae6a6593d6c8e57868 (diff) | |
download | chromium_src-bcec82d59869b43f0507d244e84798c6ce1cfcf9.zip chromium_src-bcec82d59869b43f0507d244e84798c6ce1cfcf9.tar.gz chromium_src-bcec82d59869b43f0507d244e84798c6ce1cfcf9.tar.bz2 |
[Android] Migrate DeviceUtils.GetMemoryUsageForPid to adb_wrapper.
BUG=267773
Review URL: https://codereview.chromium.org/924003003
Cr-Commit-Position: refs/heads/master@{#316624}
Diffstat (limited to 'build/android')
-rw-r--r-- | build/android/pylib/device/device_utils.py | 50 | ||||
-rwxr-xr-x | build/android/pylib/device/device_utils_test.py | 189 |
2 files changed, 113 insertions, 126 deletions
diff --git a/build/android/pylib/device/device_utils.py b/build/android/pylib/device/device_utils.py index eba5e02..af224a7 100644 --- a/build/android/pylib/device/device_utils.py +++ b/build/android/pylib/device/device_utils.py @@ -8,6 +8,8 @@ Eventually, this will be based on adb_wrapper. """ # pylint: disable=unused-argument +import collections +import itertools import logging import multiprocessing import os @@ -1306,14 +1308,54 @@ class DeviceUtils(object): retries: number of retries Returns: - A 2-tuple containing: - - A dict containing the overall memory usage statistics for the PID. - - A dict containing memory usage statistics broken down by mapping. + A dict containing memory usage statistics for the PID. May include: + Size, Rss, Pss, Shared_Clean, Shared_Dirty, Private_Clean, + Private_Dirty, VmHWM Raises: CommandTimeoutError on timeout. """ - return self.old_interface.GetMemoryUsageForPid(pid) + result = collections.defaultdict(int) + + try: + result.update(self._GetMemoryUsageForPidFromSmaps(pid)) + except device_errors.CommandFailedError: + logging.exception('Error getting memory usage from smaps') + + try: + result.update(self._GetMemoryUsageForPidFromStatus(pid)) + except device_errors.CommandFailedError: + logging.exception('Error getting memory usage from status') + + return result + + def _GetMemoryUsageForPidFromSmaps(self, pid): + SMAPS_COLUMNS = ( + 'Size', 'Rss', 'Pss', 'Shared_Clean', 'Shared_Dirty', 'Private_Clean', + 'Private_Dirty') + + showmap_out = self.RunShellCommand( + ['showmap', str(pid)], as_root=True, check_return=True) + if not showmap_out: + raise device_errors.CommandFailedError('No output from showmap') + + split_totals = showmap_out[-1].split() + if (not split_totals + or len(split_totals) != 9 + or split_totals[-1] != 'TOTAL'): + raise device_errors.CommandFailedError( + 'Invalid output from showmap: %s' % '\n'.join(showmap_out)) + + return dict(itertools.izip(SMAPS_COLUMNS, (int(n) for n in split_totals))) + + def _GetMemoryUsageForPidFromStatus(self, pid): + for line in self.ReadFile( + '/proc/%s/status' % str(pid), as_root=True).splitlines(): + if line.startswith('VmHWM:'): + return {'VmHWM': int(line.split()[1])} + else: + raise device_errors.CommandFailedError( + 'Could not find memory peak value for pid %s', str(pid)) @decorators.WithTimeoutAndRetriesFromInstance() def GetLogcatMonitor(self, timeout=None, retries=None, *args, **kwargs): diff --git a/build/android/pylib/device/device_utils_test.py b/build/android/pylib/device/device_utils_test.py index 8a25f25..9900e46 100755 --- a/build/android/pylib/device/device_utils_test.py +++ b/build/android/pylib/device/device_utils_test.py @@ -39,7 +39,7 @@ sys.path.append(os.path.join( import mock # pylint: disable=F0401 -class DeviceUtilsTest(unittest.TestCase): +class DeviceUtilsInitTest(unittest.TestCase): def testInitWithStr(self): serial_as_str = str('0123456789abcdef') @@ -121,79 +121,6 @@ class _PatchedFunction(object): self.mocked = mocked -class DeviceUtilsOldImplTest(unittest.TestCase): - - class AndroidCommandsCalls(object): - - def __init__(self, test_case, cmd_ret, comp): - self._cmds = cmd_ret - self._comp = comp - self._run_command = _PatchedFunction() - self._test_case = test_case - self._total_received = 0 - - def __enter__(self): - self._run_command.patched = mock.patch( - 'run_command.RunCommand', - side_effect=lambda c, **kw: self._ret(c)) - self._run_command.mocked = self._run_command.patched.__enter__() - - def _ret(self, actual_cmd): - if sys.exc_info()[0] is None: - on_failure_fmt = ('\n' - ' received command: %s\n' - ' expected command: %s') - self._test_case.assertGreater( - len(self._cmds), self._total_received, - msg=on_failure_fmt % (actual_cmd, None)) - expected_cmd, ret = self._cmds[self._total_received] - self._total_received += 1 - self._test_case.assertTrue( - self._comp(expected_cmd, actual_cmd), - msg=on_failure_fmt % (actual_cmd, expected_cmd)) - return ret - return '' - - def __exit__(self, exc_type, exc_val, exc_tb): - self._run_command.patched.__exit__(exc_type, exc_val, exc_tb) - if exc_type is None: - on_failure = "adb commands don't match.\nExpected:%s\nActual:%s" % ( - ''.join('\n %s' % c for c, _ in self._cmds), - ''.join('\n %s' % a[0] - for _, a, kw in self._run_command.mocked.mock_calls)) - self._test_case.assertEqual( - len(self._cmds), len(self._run_command.mocked.mock_calls), - msg=on_failure) - for (expected_cmd, _r), (_n, actual_args, actual_kwargs) in zip( - self._cmds, self._run_command.mocked.mock_calls): - self._test_case.assertEqual(1, len(actual_args), msg=on_failure) - self._test_case.assertTrue(self._comp(expected_cmd, actual_args[0]), - msg=on_failure) - self._test_case.assertTrue('timeout_time' in actual_kwargs, - msg=on_failure) - self._test_case.assertTrue('retry_count' in actual_kwargs, - msg=on_failure) - - def assertNoAdbCalls(self): - return type(self).AndroidCommandsCalls(self, [], str.__eq__) - - def assertCalls(self, cmd, ret, comp=str.__eq__): - return type(self).AndroidCommandsCalls(self, [(cmd, ret)], comp) - - def assertCallsSequence(self, cmd_ret, comp=str.__eq__): - return type(self).AndroidCommandsCalls(self, cmd_ret, comp) - - def setUp(self): - self._get_adb_path_patch = mock.patch('pylib.constants.GetAdbPath', - mock.Mock(return_value='adb')) - self._get_adb_path_patch.start() - self.device = device_utils.DeviceUtils( - '0123456789abcdef', default_timeout=1, default_retries=0) - - def tearDown(self): - self._get_adb_path_patch.stop() - - def _AdbWrapperMock(test_serial): adb = mock.Mock(spec=adb_wrapper.AdbWrapper) adb.__str__ = mock.Mock(return_value=test_serial) @@ -201,7 +128,7 @@ def _AdbWrapperMock(test_serial): return adb -class DeviceUtilsNewImplTest(mock_calls.TestCase): +class DeviceUtilsTest(mock_calls.TestCase): def setUp(self): self.adb = _AdbWrapperMock('0123456789abcdef') @@ -230,7 +157,7 @@ class DeviceUtilsNewImplTest(mock_calls.TestCase): msg, str(self.device))) -class DeviceUtilsIsOnlineTest(DeviceUtilsNewImplTest): +class DeviceUtilsIsOnlineTest(DeviceUtilsTest): def testIsOnline_true(self): with self.assertCall(self.call.adb.GetState(), 'device'): @@ -245,7 +172,7 @@ class DeviceUtilsIsOnlineTest(DeviceUtilsNewImplTest): self.assertFalse(self.device.IsOnline()) -class DeviceUtilsHasRootTest(DeviceUtilsNewImplTest): +class DeviceUtilsHasRootTest(DeviceUtilsTest): def testHasRoot_true(self): with self.assertCall(self.call.adb.Shell('ls /root'), 'foo\n'): @@ -256,7 +183,7 @@ class DeviceUtilsHasRootTest(DeviceUtilsNewImplTest): self.assertFalse(self.device.HasRoot()) -class DeviceUtilsEnableRootTest(DeviceUtilsNewImplTest): +class DeviceUtilsEnableRootTest(DeviceUtilsTest): def testEnableRoot_succeeds(self): with self.assertCalls( @@ -279,7 +206,7 @@ class DeviceUtilsEnableRootTest(DeviceUtilsNewImplTest): self.device.EnableRoot() -class DeviceUtilsIsUserBuildTest(DeviceUtilsNewImplTest): +class DeviceUtilsIsUserBuildTest(DeviceUtilsTest): def testIsUserBuild_yes(self): with self.assertCall( @@ -292,7 +219,7 @@ class DeviceUtilsIsUserBuildTest(DeviceUtilsNewImplTest): self.assertFalse(self.device.IsUserBuild()) -class DeviceUtilsGetExternalStoragePathTest(DeviceUtilsNewImplTest): +class DeviceUtilsGetExternalStoragePathTest(DeviceUtilsTest): def testGetExternalStoragePath_succeeds(self): with self.assertCall( @@ -306,7 +233,7 @@ class DeviceUtilsGetExternalStoragePathTest(DeviceUtilsNewImplTest): self.device.GetExternalStoragePath() -class DeviceUtilsGetApplicationPathTest(DeviceUtilsNewImplTest): +class DeviceUtilsGetApplicationPathTest(DeviceUtilsTest): def testGetApplicationPath_exists(self): with self.assertCalls( @@ -333,7 +260,7 @@ class DeviceUtilsGetApplicationPathTest(DeviceUtilsNewImplTest): @mock.patch('time.sleep', mock.Mock()) -class DeviceUtilsWaitUntilFullyBootedTest(DeviceUtilsNewImplTest): +class DeviceUtilsWaitUntilFullyBootedTest(DeviceUtilsTest): def testWaitUntilFullyBooted_succeedsNoWifi(self): with self.assertCalls( @@ -443,7 +370,7 @@ class DeviceUtilsWaitUntilFullyBootedTest(DeviceUtilsNewImplTest): @mock.patch('time.sleep', mock.Mock()) -class DeviceUtilsRebootTest(DeviceUtilsNewImplTest): +class DeviceUtilsRebootTest(DeviceUtilsTest): def testReboot_nonBlocking(self): with self.assertCalls( @@ -469,7 +396,7 @@ class DeviceUtilsRebootTest(DeviceUtilsNewImplTest): self.device.Reboot(block=True, wifi=True) -class DeviceUtilsInstallTest(DeviceUtilsNewImplTest): +class DeviceUtilsInstallTest(DeviceUtilsTest): def testInstall_noPriorInstall(self): with self.assertCalls( @@ -526,7 +453,7 @@ class DeviceUtilsInstallTest(DeviceUtilsNewImplTest): self.device.Install('/fake/test/app.apk', retries=0) -class DeviceUtilsRunShellCommandTest(DeviceUtilsNewImplTest): +class DeviceUtilsRunShellCommandTest(DeviceUtilsTest): def setUp(self): super(DeviceUtilsRunShellCommandTest, self).setUp() @@ -675,7 +602,7 @@ class DeviceUtilsGetDevicePieWrapper(DeviceUtilsNewImplTest): @mock.patch('time.sleep', mock.Mock()) -class DeviceUtilsKillAllTest(DeviceUtilsNewImplTest): +class DeviceUtilsKillAllTest(DeviceUtilsTest): def testKillAll_noMatchingProcesses(self): with self.assertCall(self.call.adb.Shell('ps'), @@ -726,7 +653,7 @@ class DeviceUtilsKillAllTest(DeviceUtilsNewImplTest): self.device.KillAll('some.process', signum=signal.SIGTERM)) -class DeviceUtilsStartActivityTest(DeviceUtilsNewImplTest): +class DeviceUtilsStartActivityTest(DeviceUtilsTest): def testStartActivity_actionOnly(self): test_intent = intent.Intent(action='android.intent.action.VIEW') @@ -890,7 +817,7 @@ class DeviceUtilsStartActivityTest(DeviceUtilsNewImplTest): self.device.StartActivity(test_intent) -class DeviceUtilsStartInstrumentationTest(DeviceUtilsNewImplTest): +class DeviceUtilsStartInstrumentationTest(DeviceUtilsTest): def testStartInstrumentation_nothing(self): with self.assertCalls( @@ -932,7 +859,7 @@ class DeviceUtilsStartInstrumentationTest(DeviceUtilsNewImplTest): finish=False, raw=False, extras={'foo': 'Foo', 'bar': 'Bar'}) -class DeviceUtilsBroadcastIntentTest(DeviceUtilsNewImplTest): +class DeviceUtilsBroadcastIntentTest(DeviceUtilsTest): def testBroadcastIntent_noExtras(self): test_intent = intent.Intent(action='test.package.with.an.INTENT') @@ -960,7 +887,7 @@ class DeviceUtilsBroadcastIntentTest(DeviceUtilsNewImplTest): self.device.BroadcastIntent(test_intent) -class DeviceUtilsGoHomeTest(DeviceUtilsNewImplTest): +class DeviceUtilsGoHomeTest(DeviceUtilsTest): def testGoHome(self): with self.assertCall( @@ -970,7 +897,7 @@ class DeviceUtilsGoHomeTest(DeviceUtilsNewImplTest): self.device.GoHome() -class DeviceUtilsForceStopTest(DeviceUtilsNewImplTest): +class DeviceUtilsForceStopTest(DeviceUtilsTest): def testForceStop(self): with self.assertCall( @@ -979,7 +906,7 @@ class DeviceUtilsForceStopTest(DeviceUtilsNewImplTest): self.device.ForceStop('this.is.a.test.package') -class DeviceUtilsClearApplicationStateTest(DeviceUtilsNewImplTest): +class DeviceUtilsClearApplicationStateTest(DeviceUtilsTest): def testClearApplicationState_packageDoesntExist(self): with self.assertCalls( @@ -1012,14 +939,14 @@ class DeviceUtilsClearApplicationStateTest(DeviceUtilsNewImplTest): self.device.ClearApplicationState('this.package.exists') -class DeviceUtilsSendKeyEventTest(DeviceUtilsNewImplTest): +class DeviceUtilsSendKeyEventTest(DeviceUtilsTest): def testSendKeyEvent(self): with self.assertCall(self.call.adb.Shell('input keyevent 66'), ''): self.device.SendKeyEvent(66) -class DeviceUtilsPushChangedFilesIndividuallyTest(DeviceUtilsNewImplTest): +class DeviceUtilsPushChangedFilesIndividuallyTest(DeviceUtilsTest): def testPushChangedFilesIndividually_empty(self): test_files = [] @@ -1041,7 +968,7 @@ class DeviceUtilsPushChangedFilesIndividuallyTest(DeviceUtilsNewImplTest): self.device._PushChangedFilesIndividually(test_files) -class DeviceUtilsPushChangedFilesZippedTest(DeviceUtilsNewImplTest): +class DeviceUtilsPushChangedFilesZippedTest(DeviceUtilsTest): def testPushChangedFilesZipped_empty(self): test_files = [] @@ -1080,7 +1007,7 @@ class DeviceUtilsPushChangedFilesZippedTest(DeviceUtilsNewImplTest): ('/test/host/path/file2', '/test/device/path/file2')]) -class DeviceUtilsFileExistsTest(DeviceUtilsNewImplTest): +class DeviceUtilsFileExistsTest(DeviceUtilsTest): def testFileExists_usingTest_fileExists(self): with self.assertCall( @@ -1096,7 +1023,7 @@ class DeviceUtilsFileExistsTest(DeviceUtilsNewImplTest): self.assertFalse(self.device.FileExists('/does/not/exist')) -class DeviceUtilsPullFileTest(DeviceUtilsNewImplTest): +class DeviceUtilsPullFileTest(DeviceUtilsTest): def testPullFile_existsOnDevice(self): with mock.patch('os.path.exists', return_value=True): @@ -1117,7 +1044,7 @@ class DeviceUtilsPullFileTest(DeviceUtilsNewImplTest): '/test/file/host/path') -class DeviceUtilsReadFileTest(DeviceUtilsNewImplTest): +class DeviceUtilsReadFileTest(DeviceUtilsTest): def testReadFile_exists(self): with self.assertCall( @@ -1145,7 +1072,7 @@ class DeviceUtilsReadFileTest(DeviceUtilsNewImplTest): as_root=True)) -class DeviceUtilsWriteFileTest(DeviceUtilsNewImplTest): +class DeviceUtilsWriteFileTest(DeviceUtilsTest): def testWriteFileWithPush_success(self): tmp_host = MockTempFile('/tmp/file/on.host') @@ -1208,7 +1135,7 @@ class DeviceUtilsWriteFileTest(DeviceUtilsNewImplTest): self.device.WriteFile('/test/file', 'contents', as_root=True) -class DeviceUtilsLsTest(DeviceUtilsNewImplTest): +class DeviceUtilsLsTest(DeviceUtilsTest): def testLs_directory(self): result = [('.', adb_wrapper.DeviceStat(16889, 4096, 1417436123)), @@ -1226,7 +1153,7 @@ class DeviceUtilsLsTest(DeviceUtilsNewImplTest): self.device.Ls('/data/local/tmp/testfile.txt')) -class DeviceUtilsStatTest(DeviceUtilsNewImplTest): +class DeviceUtilsStatTest(DeviceUtilsTest): def testStat_file(self): result = [('.', adb_wrapper.DeviceStat(16889, 4096, 1417436123)), @@ -1256,7 +1183,7 @@ class DeviceUtilsStatTest(DeviceUtilsNewImplTest): self.device.Stat('/data/local/tmp/does.not.exist.txt') -class DeviceUtilsSetJavaAssertsTest(DeviceUtilsNewImplTest): +class DeviceUtilsSetJavaAssertsTest(DeviceUtilsTest): def testSetJavaAsserts_enable(self): with self.assertCalls( @@ -1296,7 +1223,7 @@ class DeviceUtilsSetJavaAssertsTest(DeviceUtilsNewImplTest): self.assertFalse(self.device.SetJavaAsserts(True)) -class DeviceUtilsGetPropTest(DeviceUtilsNewImplTest): +class DeviceUtilsGetPropTest(DeviceUtilsTest): def testGetProp_exists(self): with self.assertCall( @@ -1330,7 +1257,7 @@ class DeviceUtilsGetPropTest(DeviceUtilsNewImplTest): cache=True, retries=3)) -class DeviceUtilsSetPropTest(DeviceUtilsNewImplTest): +class DeviceUtilsSetPropTest(DeviceUtilsTest): def testSetProp(self): with self.assertCall( @@ -1351,7 +1278,7 @@ class DeviceUtilsSetPropTest(DeviceUtilsNewImplTest): self.device.SetProp('test.property', 'new_value', check=True) -class DeviceUtilsGetPidsTest(DeviceUtilsNewImplTest): +class DeviceUtilsGetPidsTest(DeviceUtilsTest): def testGetPids_noMatches(self): with self.assertCall(self.call.adb.Shell('ps'), @@ -1387,7 +1314,7 @@ class DeviceUtilsGetPidsTest(DeviceUtilsNewImplTest): self.device.GetPids('exact.match')) -class DeviceUtilsTakeScreenshotTest(DeviceUtilsNewImplTest): +class DeviceUtilsTakeScreenshotTest(DeviceUtilsTest): def testTakeScreenshot_fileNameProvided(self): with self.assertCalls( @@ -1401,22 +1328,18 @@ class DeviceUtilsTakeScreenshotTest(DeviceUtilsNewImplTest): self.device.TakeScreenshot('/test/host/screenshot.png') -class DeviceUtilsGetMemoryUsageForPidTest(DeviceUtilsOldImplTest): +class DeviceUtilsGetMemoryUsageForPidTest(DeviceUtilsTest): def setUp(self): super(DeviceUtilsGetMemoryUsageForPidTest, self).setUp() - self.device.old_interface._privileged_command_runner = ( - self.device.old_interface.RunShellCommand) - self.device.old_interface._protected_file_access_method_initialized = True def testGetMemoryUsageForPid_validPid(self): - with self.assertCallsSequence([ - ("adb -s 0123456789abcdef shell 'showmap 1234'", - '100 101 102 103 104 105 106 107 TOTAL\r\n'), - ("adb -s 0123456789abcdef shell " - "'cat \"/proc/1234/status\" 2> /dev/null'", - 'VmHWM: 1024 kB') - ]): + with self.assertCalls( + (self.call.device.RunShellCommand( + ['showmap', '1234'], as_root=True, check_return=True), + ['100 101 102 103 104 105 106 107 TOTAL']), + (self.call.device.ReadFile('/proc/1234/status', as_root=True), + 'VmHWM: 1024 kB\n')): self.assertEqual( { 'Size': 100, @@ -1430,14 +1353,36 @@ class DeviceUtilsGetMemoryUsageForPidTest(DeviceUtilsOldImplTest): }, self.device.GetMemoryUsageForPid(1234)) - def testGetMemoryUsageForPid_invalidPid(self): + def testGetMemoryUsageForPid_noSmaps(self): + with self.assertCalls( + (self.call.device.RunShellCommand( + ['showmap', '4321'], as_root=True, check_return=True), + ['cannot open /proc/4321/smaps: No such file or directory']), + (self.call.device.ReadFile('/proc/4321/status', as_root=True), + 'VmHWM: 1024 kb\n')): + self.assertEquals({'VmHWM': 1024}, self.device.GetMemoryUsageForPid(4321)) + + def testGetMemoryUsageForPid_noStatus(self): with self.assertCalls( - "adb -s 0123456789abcdef shell 'showmap 4321'", - 'cannot open /proc/4321/smaps: No such file or directory\r\n'): - self.assertEqual({}, self.device.GetMemoryUsageForPid(4321)) + (self.call.device.RunShellCommand( + ['showmap', '4321'], as_root=True, check_return=True), + ['100 101 102 103 104 105 106 107 TOTAL']), + (self.call.device.ReadFile('/proc/4321/status', as_root=True), + self.CommandError())): + self.assertEquals( + { + 'Size': 100, + 'Rss': 101, + 'Pss': 102, + 'Shared_Clean': 103, + 'Shared_Dirty': 104, + 'Private_Clean': 105, + 'Private_Dirty': 106, + }, + self.device.GetMemoryUsageForPid(4321)) -class DeviceUtilsStrTest(DeviceUtilsNewImplTest): +class DeviceUtilsStrTest(DeviceUtilsTest): def testStr_returnsSerial(self): with self.assertCalls( |