[Android] Switch to DeviceUtils versions of GetPid, TakeScreenshot, and GetIoStats.

BUG=267773

Review URL: https://codereview.chromium.org/386053002

git-svn-id: http://src.chromium.org/svn/trunk/src/build@283731 4ff67af0-8c30-449e-8e8b-ad334ec8d88c
This commit is contained in:
jbudorick@chromium.org 2014-07-17 09:54:06 +00:00
Родитель c4afee99f3
Коммит 494c5b76a1
7 изменённых файлов: 377 добавлений и 166 удалений

Просмотреть файл

@ -81,12 +81,12 @@ class DeviceUtils(object):
"""Checks whether the device is online.
Args:
timeout: An integer containing the number of seconds to wait for the
operation to complete.
retries: An integer containing the number of times the operation should
be retried if it fails.
timeout: timeout in seconds
retries: number of retries
Returns:
True if the device is online, False otherwise.
Raises:
CommandTimeoutError on timeout.
"""
return self.old_interface.IsOnline()
@ -95,21 +95,26 @@ class DeviceUtils(object):
"""Checks whether or not adbd has root privileges.
Args:
timeout: Same as for |IsOnline|.
retries: Same as for |IsOnline|.
timeout: timeout in seconds
retries: number of retries
Returns:
True if adbd has root privileges, False otherwise.
Raises:
CommandTimeoutError on timeout.
DeviceUnreachableError on missing device.
"""
return self._HasRootImpl()
def _HasRootImpl(self):
""" Implementation of HasRoot.
"""Implementation of HasRoot.
This is split from HasRoot to allow other DeviceUtils methods to call
HasRoot without spawning a new timeout thread.
Returns:
Same as for |HasRoot|.
Raises:
Same as for |HasRoot|.
"""
return self.old_interface.IsRootEnabled()
@ -118,10 +123,11 @@ class DeviceUtils(object):
"""Restarts adbd with root privileges.
Args:
timeout: Same as for |IsOnline|.
retries: Same as for |IsOnline|.
timeout: timeout in seconds
retries: number of retries
Raises:
CommandFailedError if root could not be enabled.
CommandTimeoutError on timeout.
"""
if not self.old_interface.EnableAdbRoot():
raise device_errors.CommandFailedError(
@ -132,10 +138,14 @@ class DeviceUtils(object):
"""Get the device's path to its SD card.
Args:
timeout: Same as for |IsOnline|.
retries: Same as for |IsOnline|.
timeout: timeout in seconds
retries: number of retries
Returns:
The device's path to its SD card.
Raises:
CommandFailedError if the external storage path could not be determined.
CommandTimeoutError on timeout.
DeviceUnreachableError on missing device.
"""
try:
return self.old_interface.GetExternalStorage()
@ -153,16 +163,17 @@ class DeviceUtils(object):
Args:
wifi: A boolean indicating if we should wait for wifi to come up or not.
timeout: Same as for |IsOnline|.
retries: Same as for |IsOnline|.
timeout: timeout in seconds
retries: number of retries
Raises:
CommandFailedError on failure.
CommandTimeoutError if one of the component waits times out.
DeviceUnreachableError if the device becomes unresponsive.
"""
self._WaitUntilFullyBootedImpl(wifi=wifi, timeout=timeout)
def _WaitUntilFullyBootedImpl(self, wifi=False, timeout=None):
""" Implementation of WaitUntilFullyBooted.
"""Implementation of WaitUntilFullyBooted.
This is split from WaitUntilFullyBooted to allow other DeviceUtils methods
to call WaitUntilFullyBooted without spawning a new timeout thread.
@ -172,7 +183,7 @@ class DeviceUtils(object):
Args:
wifi: Same as for |WaitUntilFullyBooted|.
timeout: Same as for |IsOnline|.
timeout: timeout in seconds
Raises:
Same as for |WaitUntilFullyBooted|.
"""
@ -197,8 +208,11 @@ class DeviceUtils(object):
Args:
block: A boolean indicating if we should wait for the reboot to complete.
timeout: Same as for |IsOnline|.
retries: Same as for |IsOnline|.
timeout: timeout in seconds
retries: number of retries
Raises:
CommandTimeoutError on timeout.
DeviceUnreachableError on missing device.
"""
self.old_interface.Reboot()
if block:
@ -218,11 +232,12 @@ class DeviceUtils(object):
Args:
apk_path: A string containing the path to the APK to install.
reinstall: A boolean indicating if we should keep any existing app data.
timeout: Same as for |IsOnline|.
retries: Same as for |IsOnline|.
timeout: timeout in seconds
retries: number of retries
Raises:
CommandFailedError if the installation fails.
CommandTimeoutError if the installation times out.
DeviceUnreachableError on missing device.
"""
package_name = apk_helper.GetPackageName(apk_path)
device_path = self.old_interface.GetApplicationPath(package_name)
@ -266,12 +281,14 @@ class DeviceUtils(object):
be checked.
as_root: A boolean indicating whether the shell command should be run
with root privileges.
timeout: Same as for |IsOnline|.
retries: Same as for |IsOnline|.
Raises:
CommandFailedError if check_return is True and the return code is nozero.
timeout: timeout in seconds
retries: number of retries
Returns:
The output of the command.
Raises:
CommandFailedError if check_return is True and the return code is nozero.
CommandTimeoutError on timeout.
DeviceUnreachableError on missing device.
"""
return self._RunShellCommandImpl(cmd, check_return=check_return,
as_root=as_root, timeout=timeout)
@ -290,7 +307,7 @@ class DeviceUtils(object):
cmd: Same as for |RunShellCommand|.
check_return: Same as for |RunShellCommand|.
as_root: Same as for |RunShellCommand|.
timeout: Same as for |IsOnline|.
timeout: timeout in seconds
Raises:
Same as for |RunShellCommand|.
Returns:
@ -323,10 +340,12 @@ class DeviceUtils(object):
root privileges.
blocking: A boolean indicating whether we should wait until all processes
with the given |process_name| are dead.
timeout: Same as for |IsOnline|.
retries: Same as for |IsOnline|.
timeout: timeout in seconds
retries: number of retries
Raises:
CommandFailedError if no process was killed.
CommandTimeoutError on timeout.
DeviceUnreachableError on missing device.
"""
pids = self.old_interface.ExtractPid(process_name)
if len(pids) == 0:
@ -357,10 +376,12 @@ class DeviceUtils(object):
trace should be saved.
force_stop: A boolean indicating whether we should stop the activity
before starting it.
timeout: Same as for |IsOnline|.
retries: Same as for |IsOnline|.
timeout: timeout in seconds
retries: number of retries
Raises:
CommandFailedError if the activity could not be started.
CommandTimeoutError on timeout.
DeviceUnreachableError on missing device.
"""
single_category = (intent.category[0] if isinstance(intent.category, list)
else intent.category)
@ -379,8 +400,11 @@ class DeviceUtils(object):
Args:
intent: An Intent to broadcast.
timeout: Same as for |IsOnline|.
retries: Same as for |IsOnline|.
timeout: timeout in seconds
retries: number of retries
Raises:
CommandTimeoutError on timeout.
DeviceUnreachableError on missing device.
"""
package, old_intent = intent.action.rsplit('.', 1)
if intent.extras is None:
@ -395,8 +419,11 @@ class DeviceUtils(object):
"""Return to the home screen.
Args:
timeout: Same as for |IsOnline|.
retries: Same as for |IsOnline|.
timeout: timeout in seconds
retries: number of retries
Raises:
CommandTimeoutError on timeout.
DeviceUnreachableError on missing device.
"""
self.old_interface.GoHome()
@ -406,8 +433,11 @@ class DeviceUtils(object):
Args:
package: A string containing the name of the package to stop.
timeout: Same as for |IsOnline|.
retries: Same as for |IsOnline|.
timeout: timeout in seconds
retries: number of retries
Raises:
CommandTimeoutError on timeout.
DeviceUnreachableError on missing device.
"""
self.old_interface.CloseApplication(package)
@ -417,8 +447,11 @@ class DeviceUtils(object):
Args:
package: A string containing the name of the package to stop.
timeout: Same as for |IsOnline|.
retries: Same as for |IsOnline|.
timeout: timeout in seconds
retries: number of retries
Raises:
CommandTimeoutError on timeout.
DeviceUnreachableError on missing device.
"""
self.old_interface.ClearApplicationState(package)
@ -430,8 +463,11 @@ class DeviceUtils(object):
Args:
keycode: A integer keycode to send to the device.
timeout: Same as for |IsOnline|.
retries: Same as for |IsOnline|.
timeout: timeout in seconds
retries: number of retries
Raises:
CommandTimeoutError on timeout.
DeviceUnreachableError on missing device.
"""
self.old_interface.SendKeyEvent(keycode)
@ -450,8 +486,12 @@ class DeviceUtils(object):
on the host that should be minimally pushed to the device.
device_path: A string containing the absolute path of the destination on
the device.
timeout: Same as for |IsOnline|.
retries: Same as for |IsOnline|.
timeout: timeout in seconds
retries: number of retries
Raises:
CommandFailedError on failure.
CommandTimeoutError on timeout.
DeviceUnreachableError on missing device.
"""
self.old_interface.PushIfNeeded(host_path, device_path)
@ -462,10 +502,13 @@ class DeviceUtils(object):
Args:
device_path: A string containing the absolute path to the file on the
device.
timeout: Same as for |IsOnline|.
retries: Same as for |IsOnline|.
timeout: timeout in seconds
retries: number of retries
Returns:
True if the file exists on the device, False otherwise.
Raises:
CommandTimeoutError on timeout.
DeviceUnreachableError on missing device.
"""
return self._FileExistsImpl(device_path)
@ -479,6 +522,8 @@ class DeviceUtils(object):
device_path: Same as for |FileExists|.
Returns:
True if the file exists on the device, False otherwise.
Raises:
Same as for |FileExists|.
"""
return self.old_interface.FileExistsOnDevice(device_path)
@ -491,10 +536,17 @@ class DeviceUtils(object):
from the device.
host_path: A string containing the absolute path of the destination on
the host.
timeout: Same as for |IsOnline|.
retries: Same as for |IsOnline|.
timeout: timeout in seconds
retries: number of retries
Raises:
CommandFailedError on failure.
CommandTimeoutError on timeout.
"""
self.old_interface.PullFileFromDevice(device_path, host_path)
try:
self.old_interface.PullFileFromDevice(device_path, host_path)
except AssertionError as e:
raise device_errors.CommandFailedError(
str(e), device=str(self)), None, sys.exc_info()[2]
@decorators.WithTimeoutAndRetriesFromInstance()
def ReadFile(self, device_path, as_root=False, timeout=None, retries=None):
@ -505,12 +557,14 @@ class DeviceUtils(object):
from the device.
as_root: A boolean indicating whether the read should be executed with
root privileges.
timeout: Same as for |IsOnline|.
retries: Same as for |IsOnline|.
timeout: timeout in seconds
retries: number of retries
Returns:
The contents of the file at |device_path| as a list of lines.
Raises:
CommandFailedError if the file can't be read.
CommandTimeoutError on timeout.
DeviceUnreachableError on missing device.
"""
# TODO(jbudorick) Evaluate whether we actually want to return a list of
# lines after the implementation switch.
@ -533,10 +587,12 @@ class DeviceUtils(object):
contents: A string containing the data to write to the device.
as_root: A boolean indicating whether the write should be executed with
root privileges.
timeout: Same as for |IsOnline|.
retries: Same as for |IsOnline|.
timeout: timeout in seconds
retries: number of retries
Raises:
CommandFailedError if the file could not be written on the device.
CommandTimeoutError on timeout.
DeviceUnreachableError on missing device.
"""
if as_root:
if not self.old_interface.CanAccessProtectedFileContents():
@ -553,10 +609,13 @@ class DeviceUtils(object):
Args:
device_path: A string containing the path of the directory on the device
to list.
timeout: Same as for |IsOnline|.
retries: Same as for |IsOnline|.
timeout: timeout in seconds
retries: number of retries
Returns:
The contents of the directory specified by |device_path|.
Raises:
CommandTimeoutError on timeout.
DeviceUnreachableError on missing device.
"""
return self.old_interface.ListPathContents(device_path)
@ -567,8 +626,10 @@ class DeviceUtils(object):
Args:
enabled: A boolean indicating whether Java asserts should be enabled
or disabled.
timeout: Same as for |IsOnline|.
retries: Same as for |IsOnline|.
timeout: timeout in seconds
retries: number of retries
Raises:
CommandTimeoutError on timeout.
"""
self.old_interface.SetJavaAssertsEnabled(enabled)
@ -579,10 +640,12 @@ class DeviceUtils(object):
Args:
property_name: A string containing the name of the property to get from
the device.
timeout: Same as for |IsOnline|.
retries: Same as for |IsOnline|.
timeout: timeout in seconds
retries: number of retries
Returns:
The value of the device's |property_name| property.
Raises:
CommandTimeoutError on timeout.
"""
return self.old_interface.system_properties[property_name]
@ -595,11 +658,73 @@ class DeviceUtils(object):
the device.
value: A string containing the value to set to the property on the
device.
timeout: Same as for |IsOnline|.
retries: Same as for |IsOnline|.
timeout: timeout in seconds
retries: number of retries
Raises:
CommandTimeoutError on timeout.
"""
self.old_interface.system_properties[property_name] = value
@decorators.WithTimeoutAndRetriesFromInstance()
def GetPids(self, process_name, timeout=None, retries=None):
"""Returns the PIDs of processes with the given name.
Note that the |process_name| is often the package name.
Args:
process_name: A string containing the process name to get the PIDs for.
timeout: timeout in seconds
retries: number of retries
Returns:
A dict mapping process name to PID for each process that contained the
provided |process_name|.
Raises:
CommandTimeoutError on timeout.
DeviceUnreachableError on missing device.
"""
procs_pids = {}
for line in self._RunShellCommandImpl('ps'):
try:
ps_data = line.split()
if process_name in ps_data[-1]:
procs_pids[ps_data[-1]] = ps_data[1]
except IndexError:
pass
return procs_pids
@decorators.WithTimeoutAndRetriesFromInstance()
def TakeScreenshot(self, host_path=None, timeout=None, retries=None):
"""Takes a screenshot of the device.
Args:
host_path: A string containing the path on the host to save the
screenshot to. If None, a file name will be generated.
timeout: timeout in seconds
retries: number of retries
Returns:
The name of the file on the host to which the screenshot was saved.
Raises:
CommandFailedError on failure.
CommandTimeoutError on timeout.
DeviceUnreachableError on missing device.
"""
return self.old_interface.TakeScreenshot(host_path)
@decorators.WithTimeoutAndRetriesFromInstance()
def GetIOStats(self, timeout=None, retries=None):
"""Gets cumulative disk IO stats since boot for all processes.
Args:
timeout: timeout in seconds
retries: number of retries
Returns:
A dict containing |num_reads|, |num_writes|, |read_ms|, and |write_ms|.
Raises:
CommandTimeoutError on timeout.
DeviceUnreachableError on missing device.
"""
return self.old_interface.GetIoStats()
def __str__(self):
"""Returns the device serial."""
return self.old_interface.GetDevice()

Просмотреть файл

@ -72,6 +72,75 @@ class _PatchedFunction(object):
self.mocked = mocked
class MockFileSystem(object):
@staticmethod
def osStatResult(
st_mode=None, st_ino=None, st_dev=None, st_nlink=None, st_uid=None,
st_gid=None, st_size=None, st_atime=None, st_mtime=None, st_ctime=None):
MockOSStatResult = collections.namedtuple('MockOSStatResult', [
'st_mode', 'st_ino', 'st_dev', 'st_nlink', 'st_uid', 'st_gid',
'st_size', 'st_atime', 'st_mtime', 'st_ctime'])
return MockOSStatResult(st_mode, st_ino, st_dev, st_nlink, st_uid, st_gid,
st_size, st_atime, st_mtime, st_ctime)
MOCKED_FUNCTIONS = [
('os.path.abspath', ''),
('os.path.dirname', ''),
('os.path.exists', False),
('os.path.getsize', 0),
('os.path.isdir', False),
('os.stat', osStatResult.__func__()),
('os.walk', []),
]
def _get(self, mocked, path, default_val):
if self._verbose:
logging.debug('%s(%s)' % (mocked, path))
return (self.mock_file_info[path][mocked]
if path in self.mock_file_info
else default_val)
def _patched(self, target, default_val=None):
r = lambda f: self._get(target, f, default_val)
return _PatchedFunction(patched=mock.patch(target, side_effect=r))
def __init__(self, verbose=False):
self.mock_file_info = {}
self._patched_functions = [
self._patched(m, d) for m, d in type(self).MOCKED_FUNCTIONS]
self._verbose = verbose
def addMockFile(self, path, **kw):
self._addMockThing(path, False, **kw)
def addMockDirectory(self, path, **kw):
self._addMockThing(path, True, **kw)
def _addMockThing(self, path, is_dir, size=0, stat=None, walk=None):
if stat is None:
stat = self.osStatResult()
if walk is None:
walk = []
self.mock_file_info[path] = {
'os.path.abspath': path,
'os.path.dirname': '/' + '/'.join(path.strip('/').split('/')[:-1]),
'os.path.exists': True,
'os.path.isdir': is_dir,
'os.path.getsize': size,
'os.stat': stat,
'os.walk': walk,
}
def __enter__(self):
for p in self._patched_functions:
p.mocked = p.patched.__enter__()
def __exit__(self, exc_type, exc_val, exc_tb):
for p in self._patched_functions:
p.patched.__exit__()
class DeviceUtilsOldImplTest(unittest.TestCase):
class AndroidCommandsCalls(object):
@ -787,68 +856,6 @@ class DeviceUtilsSendKeyEventTest(DeviceUtilsOldImplTest):
class DeviceUtilsPushChangedFilesTest(DeviceUtilsOldImplTest):
class MockFileSystem(object):
@staticmethod
def osStatResult(
st_mode=None, st_ino=None, st_dev=None, st_nlink=None, st_uid=None,
st_gid=None, st_size=None, st_atime=None, st_mtime=None, st_ctime=None):
MockOSStatResult = collections.namedtuple('MockOSStatResult', [
'st_mode', 'st_ino', 'st_dev', 'st_nlink', 'st_uid', 'st_gid',
'st_size', 'st_atime', 'st_mtime', 'st_ctime'])
return MockOSStatResult(st_mode, st_ino, st_dev, st_nlink, st_uid, st_gid,
st_size, st_atime, st_mtime, st_ctime)
def _get(self, mocked, path, default_val):
return (self.mock_file_info[path][mocked]
if path in self.mock_file_info
else default_val)
def _patched(self, target, default_val=None):
r = lambda f: self._get(target, f, default_val)
return _PatchedFunction(patched=mock.patch(target, side_effect=r))
def __init__(self):
self.mock_file_info = {}
self._os_path_exists = self._patched('os.path.exists', default_val=False)
self._os_path_getsize = self._patched('os.path.getsize', default_val=0)
self._os_path_isdir = self._patched('os.path.isdir', default_val=False)
self._os_stat = self._patched('os.stat', default_val=self.osStatResult())
self._os_walk = self._patched('os.walk', default_val=[])
def addMockFile(self, path, size, **kw):
self._addMockThing(path, size, False, **kw)
def addMockDirectory(self, path, size, **kw):
self._addMockThing(path, size, True, **kw)
def _addMockThing(self, path, size, is_dir, stat=None, walk=None):
if stat is None:
stat = self.osStatResult()
if walk is None:
walk = []
self.mock_file_info[path] = {
'os.path.exists': True,
'os.path.isdir': is_dir,
'os.path.getsize': size,
'os.stat': stat,
'os.walk': walk,
}
def __enter__(self):
self._os_path_exists.mocked = self._os_path_exists.patched.__enter__()
self._os_path_getsize.mocked = self._os_path_getsize.patched.__enter__()
self._os_path_isdir.mocked = self._os_path_isdir.patched.__enter__()
self._os_stat.mocked = self._os_stat.patched.__enter__()
self._os_walk.mocked = self._os_walk.patched.__enter__()
def __exit__(self, exc_type, exc_val, exc_tb):
self._os_walk.patched.__exit__()
self._os_stat.patched.__exit__()
self._os_path_isdir.patched.__exit__(exc_type, exc_val, exc_tb)
self._os_path_getsize.patched.__exit__(exc_type, exc_val, exc_tb)
self._os_path_exists.patched.__exit__(exc_type, exc_val, exc_tb)
def testPushChangedFiles_noHostPath(self):
with mock.patch('os.path.exists', return_value=False):
@ -861,8 +868,8 @@ class DeviceUtilsPushChangedFilesTest(DeviceUtilsOldImplTest):
host_file_path = '/test/host/path'
device_file_path = '/test/device/path'
mock_fs = self.MockFileSystem()
mock_fs.addMockFile(host_file_path, 100)
mock_fs = MockFileSystem()
mock_fs.addMockFile(host_file_path, size=100)
self.device.old_interface.GetFilesChanged = mock.Mock(return_value=[])
@ -877,10 +884,10 @@ class DeviceUtilsPushChangedFilesTest(DeviceUtilsOldImplTest):
host_file_path = '/test/host/path'
device_file_path = '/test/device/path'
mock_fs = self.MockFileSystem()
mock_fs = MockFileSystem()
mock_fs.addMockFile(
host_file_path, 100,
stat=self.MockFileSystem.osStatResult(st_mtime=1000000000))
host_file_path, size=100,
stat=MockFileSystem.osStatResult(st_mtime=1000000000))
self.device.old_interface.GetFilesChanged = mock.Mock(
return_value=[('/test/host/path', '/test/device/path')])
@ -896,16 +903,16 @@ class DeviceUtilsPushChangedFilesTest(DeviceUtilsOldImplTest):
host_file_path = '/test/host/path'
device_file_path = '/test/device/path'
mock_fs = self.MockFileSystem()
mock_fs = MockFileSystem()
mock_fs.addMockDirectory(
host_file_path, 256,
stat=self.MockFileSystem.osStatResult(st_mtime=1000000000))
host_file_path, size=256,
stat=MockFileSystem.osStatResult(st_mtime=1000000000))
mock_fs.addMockFile(
host_file_path + '/file1', 251,
stat=self.MockFileSystem.osStatResult(st_mtime=1000000001))
host_file_path + '/file1', size=251,
stat=MockFileSystem.osStatResult(st_mtime=1000000001))
mock_fs.addMockFile(
host_file_path + '/file2', 252,
stat=self.MockFileSystem.osStatResult(st_mtime=1000000002))
host_file_path + '/file2', size=252,
stat=MockFileSystem.osStatResult(st_mtime=1000000002))
self.device.old_interface.GetFilesChanged = mock.Mock(return_value=[])
@ -921,17 +928,17 @@ class DeviceUtilsPushChangedFilesTest(DeviceUtilsOldImplTest):
host_file_path = '/test/host/path'
device_file_path = '/test/device/path'
mock_fs = self.MockFileSystem()
mock_fs = MockFileSystem()
mock_fs.addMockDirectory(
host_file_path, 256,
stat=self.MockFileSystem.osStatResult(st_mtime=1000000000),
host_file_path, size=256,
stat=MockFileSystem.osStatResult(st_mtime=1000000000),
walk=[('/test/host/path', [], ['file1', 'file2'])])
mock_fs.addMockFile(
host_file_path + '/file1', 256,
stat=self.MockFileSystem.osStatResult(st_mtime=1000000001))
host_file_path + '/file1', size=256,
stat=MockFileSystem.osStatResult(st_mtime=1000000001))
mock_fs.addMockFile(
host_file_path + '/file2', 256,
stat=self.MockFileSystem.osStatResult(st_mtime=1000000002))
host_file_path + '/file2', size=256,
stat=MockFileSystem.osStatResult(st_mtime=1000000002))
self.device.old_interface.GetFilesChanged = mock.Mock(
return_value=[('/test/host/path/file1', '/test/device/path/file1')])
@ -951,16 +958,16 @@ class DeviceUtilsPushChangedFilesTest(DeviceUtilsOldImplTest):
host_file_path = '/test/host/path'
device_file_path = '/test/device/path'
mock_fs = self.MockFileSystem()
mock_fs = MockFileSystem()
mock_fs.addMockDirectory(
host_file_path, 256,
stat=self.MockFileSystem.osStatResult(st_mtime=1000000000))
host_file_path, size=256,
stat=MockFileSystem.osStatResult(st_mtime=1000000000))
mock_fs.addMockFile(
host_file_path + '/file1', 256,
stat=self.MockFileSystem.osStatResult(st_mtime=1000000001))
host_file_path + '/file1', size=256,
stat=MockFileSystem.osStatResult(st_mtime=1000000001))
mock_fs.addMockFile(
host_file_path + '/file2', 256,
stat=self.MockFileSystem.osStatResult(st_mtime=1000000002))
host_file_path + '/file2', size=256,
stat=MockFileSystem.osStatResult(st_mtime=1000000002))
self.device.old_interface.GetFilesChanged = mock.Mock(
return_value=[('/test/host/path/file1', '/test/device/path/file1'),
@ -1356,6 +1363,86 @@ class DeviceUtilsSetPropTest(DeviceUtilsOldImplTest):
self.device.SetProp('this.is.a.test.property', 'test_property_value')
class DeviceUtilsGetPidsTest(DeviceUtilsOldImplTest):
def testGetPids_noMatches(self):
with self.assertCalls(
"adb -s 0123456789abcdef shell 'ps'",
'USER PID PPID VSIZE RSS WCHAN PC NAME\r\n'
'user 1000 100 1024 1024 ffffffff 00000000 no.match\r\n'):
self.assertEqual({}, self.device.GetPids('does.not.match'))
def testGetPids_oneMatch(self):
with self.assertCalls(
"adb -s 0123456789abcdef shell 'ps'",
'USER PID PPID VSIZE RSS WCHAN PC NAME\r\n'
'user 1000 100 1024 1024 ffffffff 00000000 not.a.match\r\n'
'user 1001 100 1024 1024 ffffffff 00000000 one.match\r\n'):
self.assertEqual({'one.match': '1001'}, self.device.GetPids('one.match'))
def testGetPids_mutlipleMatches(self):
with self.assertCalls(
"adb -s 0123456789abcdef shell 'ps'",
'USER PID PPID VSIZE RSS WCHAN PC NAME\r\n'
'user 1000 100 1024 1024 ffffffff 00000000 not\r\n'
'user 1001 100 1024 1024 ffffffff 00000000 one.match\r\n'
'user 1002 100 1024 1024 ffffffff 00000000 two.match\r\n'
'user 1003 100 1024 1024 ffffffff 00000000 three.match\r\n'):
self.assertEqual(
{'one.match': '1001', 'two.match': '1002', 'three.match': '1003'},
self.device.GetPids('match'))
def testGetPids_exactMatch(self):
with self.assertCalls(
"adb -s 0123456789abcdef shell 'ps'",
'USER PID PPID VSIZE RSS WCHAN PC NAME\r\n'
'user 1000 100 1024 1024 ffffffff 00000000 not.exact.match\r\n'
'user 1234 100 1024 1024 ffffffff 00000000 exact.match\r\n'):
self.assertEqual(
{'not.exact.match': '1000', 'exact.match': '1234'},
self.device.GetPids('exact.match'))
class DeviceUtilsTakeScreenshotTest(DeviceUtilsOldImplTest):
def testTakeScreenshot_fileNameProvided(self):
mock_fs = MockFileSystem()
mock_fs.addMockDirectory('/test/host')
mock_fs.addMockFile('/test/host/screenshot.png')
with mock_fs:
with self.assertCallsSequence(
cmd_ret=[
(r"adb -s 0123456789abcdef shell 'echo \$EXTERNAL_STORAGE'",
'/test/external/storage\r\n'),
(r"adb -s 0123456789abcdef shell '/system/bin/screencap -p \S+'",
''),
(r"adb -s 0123456789abcdef shell ls \S+",
'/test/external/storage/screenshot.png\r\n'),
(r'adb -s 0123456789abcdef pull \S+ /test/host/screenshot.png',
'100 B/s (100 B in 1.000s)\r\n'),
(r"adb -s 0123456789abcdef shell 'rm -f \S+'", '')
],
comp=re.match):
self.device.TakeScreenshot('/test/host/screenshot.png')
class DeviceUtilsGetIOStatsTest(DeviceUtilsOldImplTest):
def testGetIOStats(self):
with self.assertCalls(
"adb -s 0123456789abcdef shell 'cat \"/proc/diskstats\" 2>/dev/null'",
'179 0 mmcblk0 1 2 3 4 5 6 7 8 9 10 11\r\n'):
self.assertEqual(
{
'num_reads': 1,
'num_writes': 5,
'read_ms': 4,
'write_ms': 8,
},
self.device.GetIOStats())
if __name__ == '__main__':
logging.getLogger().setLevel(logging.DEBUG)
unittest.main(verbosity=2)

Просмотреть файл

@ -341,9 +341,7 @@ class Forwarder(object):
# 'kill-server') is not running on the bots anymore.
timeout_sec = 5
try:
device.KillAll(
'device_forwarder', blocking=True, timeout=timeout_sec)
device.KillAll('device_forwarder', blocking=True, timeout=timeout_sec)
except device_errors.CommandFailedError:
pids = device.old_interface.ExtractPid('device_forwarder')
if pids:
if device.GetPids('device_forwarder'):
raise

Просмотреть файл

@ -142,7 +142,7 @@ class TestRunner(base_test_runner.BaseTestRunner):
"""Takes a screenshot from the device."""
screenshot_name = os.path.join(constants.SCREENSHOTS_DIR, '%s.png' % test)
logging.info('Taking screenshot named %s', screenshot_name)
self.device.old_interface.TakeScreenshot(screenshot_name)
self.device.TakeScreenshot(screenshot_name)
def SetUp(self):
"""Sets up the test harness and device before all tests are run."""

Просмотреть файл

@ -58,22 +58,22 @@ class TestRunner(base_test_runner.BaseTestRunner):
# Chrome crashes are not always caught by Monkey test runner.
# Verify Chrome has the same PID before and after the test.
before_pids = self.device.old_interface.ExtractPid(self._package)
before_pids = self.device.GetPids(self._package)
# Run the test.
output = ''
if before_pids:
output = '\n'.join(self._LaunchMonkeyTest())
after_pids = self.device.old_interface.ExtractPid(self._package)
after_pids = self.device.GetPids(self._package)
crashed = True
if not before_pids:
if not self._package in before_pids:
logging.error('Failed to start the process.')
elif not after_pids:
logging.error('Process %s has died.', before_pids[0])
elif before_pids[0] != after_pids[0]:
elif not self._package in after_pids:
logging.error('Process %s has died.', before_pids[self._package])
elif before_pids[self._package] != after_pids[self._package]:
logging.error('Detected process restart %s -> %s',
before_pids[0], after_pids[0])
before_pids[self._package], after_pids[self._package])
else:
crashed = False

Просмотреть файл

@ -3,6 +3,7 @@
# found in the LICENSE file.
import os
import signal
import tempfile
from pylib import cmd_helper
@ -33,7 +34,6 @@ class VideoRecorder(object):
self._device_file = (
'%s/screen-recording.mp4' % device.GetExternalStoragePath())
self._recorder = None
self._recorder_pids = None
self._recorder_stdout = None
self._is_started = False
@ -53,8 +53,7 @@ class VideoRecorder(object):
self._recorder_stdout = tempfile.mkstemp()[1]
self._recorder = cmd_helper.Popen(
self._args, stdout=open(self._recorder_stdout, 'w'))
self._recorder_pids = self._device.old_interface.ExtractPid('screenrecord')
if not self._recorder_pids:
if not self._device.GetPids('screenrecord'):
raise RuntimeError('Recording failed. Is your device running Android '
'KitKat or later?')
@ -70,17 +69,18 @@ class VideoRecorder(object):
"""Stop recording video."""
os.remove(self._recorder_stdout)
self._is_started = False
if not self._recorder or not self._recorder_pids:
if not self._recorder:
return
self._device.RunShellCommand(
'kill -SIGINT ' + ' '.join(self._recorder_pids))
self._device.KillAll('screenrecord', signum=signal.SIGINT)
self._recorder.wait()
def Pull(self, host_file):
def Pull(self, host_file=None):
"""Pull resulting video file from the device.
Args:
host_file: Path to the video file to store on the host.
Returns:
Output video file name on the host.
"""
host_file_name = host_file or ('screen-recording-%s.mp4' %
self._device.old_interface.GetTimestamp())
@ -88,3 +88,4 @@ class VideoRecorder(object):
self._device.old_interface.EnsureHostDirectory(host_file_name)
self._device.PullFile(self._device_file, host_file_name)
self._device.RunShellCommand('rm -f "%s"' % self._device_file)
return host_file_name

Просмотреть файл

@ -21,7 +21,7 @@ def _PrintMessage(heading, eol='\n'):
def _CaptureScreenshot(device, host_file):
host_file = device.old_interface.TakeScreenshot(host_file)
host_file = device.TakeScreenshot(host_file)
_PrintMessage('Screenshot written to %s' % os.path.abspath(host_file))
@ -37,7 +37,7 @@ def _CaptureVideo(device, host_file, options):
raw_input()
finally:
recorder.Stop()
recorder.Pull(host_file)
host_file = recorder.Pull(host_file)
_PrintMessage('Video written to %s' % os.path.abspath(host_file))