1#!/usr/bin/env python 2# Copyright 2014 The Chromium Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6""" 7Unit tests for the contents of device_utils.py (mostly DeviceUtils). 8""" 9 10# pylint: disable=C0321 11# pylint: disable=W0212 12# pylint: disable=W0613 13 14import collections 15import datetime 16import logging 17import os 18import re 19import signal 20import sys 21import unittest 22 23from pylib import android_commands 24from pylib import constants 25from pylib.device import adb_wrapper 26from pylib.device import device_errors 27from pylib.device import device_utils 28from pylib.device import intent 29 30# RunCommand from third_party/android_testrunner/run_command.py is mocked 31# below, so its path needs to be in sys.path. 32sys.path.append(os.path.join( 33 constants.DIR_SOURCE_ROOT, 'third_party', 'android_testrunner')) 34 35sys.path.append(os.path.join( 36 constants.DIR_SOURCE_ROOT, 'third_party', 'pymock')) 37import mock # pylint: disable=F0401 38 39 40class DeviceUtilsTest(unittest.TestCase): 41 42 def testInitWithStr(self): 43 serial_as_str = str('0123456789abcdef') 44 d = device_utils.DeviceUtils('0123456789abcdef') 45 self.assertEqual(serial_as_str, d.old_interface.GetDevice()) 46 47 def testInitWithUnicode(self): 48 serial_as_unicode = unicode('fedcba9876543210') 49 d = device_utils.DeviceUtils(serial_as_unicode) 50 self.assertEqual(serial_as_unicode, d.old_interface.GetDevice()) 51 52 def testInitWithAdbWrapper(self): 53 serial = '123456789abcdef0' 54 a = adb_wrapper.AdbWrapper(serial) 55 d = device_utils.DeviceUtils(a) 56 self.assertEqual(serial, d.old_interface.GetDevice()) 57 58 def testInitWithAndroidCommands(self): 59 serial = '0fedcba987654321' 60 a = android_commands.AndroidCommands(device=serial) 61 d = device_utils.DeviceUtils(a) 62 self.assertEqual(serial, d.old_interface.GetDevice()) 63 64 def testInitWithNone(self): 65 d = device_utils.DeviceUtils(None) 66 self.assertIsNone(d.old_interface.GetDevice()) 67 68 69class _PatchedFunction(object): 70 def __init__(self, patched=None, mocked=None): 71 self.patched = patched 72 self.mocked = mocked 73 74 75class MockFileSystem(object): 76 77 @staticmethod 78 def osStatResult( 79 st_mode=None, st_ino=None, st_dev=None, st_nlink=None, st_uid=None, 80 st_gid=None, st_size=None, st_atime=None, st_mtime=None, st_ctime=None): 81 MockOSStatResult = collections.namedtuple('MockOSStatResult', [ 82 'st_mode', 'st_ino', 'st_dev', 'st_nlink', 'st_uid', 'st_gid', 83 'st_size', 'st_atime', 'st_mtime', 'st_ctime']) 84 return MockOSStatResult(st_mode, st_ino, st_dev, st_nlink, st_uid, st_gid, 85 st_size, st_atime, st_mtime, st_ctime) 86 87 MOCKED_FUNCTIONS = [ 88 ('os.path.abspath', ''), 89 ('os.path.dirname', ''), 90 ('os.path.exists', False), 91 ('os.path.getsize', 0), 92 ('os.path.isdir', False), 93 ('os.stat', osStatResult.__func__()), 94 ('os.walk', []), 95 ] 96 97 def _get(self, mocked, path, default_val): 98 if self._verbose: 99 logging.debug('%s(%s)' % (mocked, path)) 100 return (self.mock_file_info[path][mocked] 101 if path in self.mock_file_info 102 else default_val) 103 104 def _patched(self, target, default_val=None): 105 r = lambda f: self._get(target, f, default_val) 106 return _PatchedFunction(patched=mock.patch(target, side_effect=r)) 107 108 def __init__(self, verbose=False): 109 self.mock_file_info = {} 110 self._patched_functions = [ 111 self._patched(m, d) for m, d in type(self).MOCKED_FUNCTIONS] 112 self._verbose = verbose 113 114 def addMockFile(self, path, **kw): 115 self._addMockThing(path, False, **kw) 116 117 def addMockDirectory(self, path, **kw): 118 self._addMockThing(path, True, **kw) 119 120 def _addMockThing(self, path, is_dir, size=0, stat=None, walk=None): 121 if stat is None: 122 stat = self.osStatResult() 123 if walk is None: 124 walk = [] 125 self.mock_file_info[path] = { 126 'os.path.abspath': path, 127 'os.path.dirname': '/' + '/'.join(path.strip('/').split('/')[:-1]), 128 'os.path.exists': True, 129 'os.path.isdir': is_dir, 130 'os.path.getsize': size, 131 'os.stat': stat, 132 'os.walk': walk, 133 } 134 135 def __enter__(self): 136 for p in self._patched_functions: 137 p.mocked = p.patched.__enter__() 138 139 def __exit__(self, exc_type, exc_val, exc_tb): 140 for p in self._patched_functions: 141 p.patched.__exit__() 142 143 144class DeviceUtilsOldImplTest(unittest.TestCase): 145 146 class AndroidCommandsCalls(object): 147 148 def __init__(self, test_case, cmd_ret, comp): 149 self._cmds = cmd_ret 150 self._comp = comp 151 self._run_command = _PatchedFunction() 152 self._test_case = test_case 153 self._total_received = 0 154 155 def __enter__(self): 156 self._run_command.patched = mock.patch( 157 'run_command.RunCommand', 158 side_effect=lambda c, **kw: self._ret(c)) 159 self._run_command.mocked = self._run_command.patched.__enter__() 160 161 def _ret(self, actual_cmd): 162 if sys.exc_info()[0] is None: 163 on_failure_fmt = ('\n' 164 ' received command: %s\n' 165 ' expected command: %s') 166 self._test_case.assertGreater( 167 len(self._cmds), self._total_received, 168 msg=on_failure_fmt % (actual_cmd, None)) 169 expected_cmd, ret = self._cmds[self._total_received] 170 self._total_received += 1 171 self._test_case.assertTrue( 172 self._comp(expected_cmd, actual_cmd), 173 msg=on_failure_fmt % (actual_cmd, expected_cmd)) 174 return ret 175 return '' 176 177 def __exit__(self, exc_type, exc_val, exc_tb): 178 self._run_command.patched.__exit__(exc_type, exc_val, exc_tb) 179 if exc_type is None: 180 on_failure = "adb commands don't match.\nExpected:%s\nActual:%s" % ( 181 ''.join('\n %s' % c for c, _ in self._cmds), 182 ''.join('\n %s' % a[0] 183 for _, a, kw in self._run_command.mocked.mock_calls)) 184 self._test_case.assertEqual( 185 len(self._cmds), len(self._run_command.mocked.mock_calls), 186 msg=on_failure) 187 for (expected_cmd, _r), (_n, actual_args, actual_kwargs) in zip( 188 self._cmds, self._run_command.mocked.mock_calls): 189 self._test_case.assertEqual(1, len(actual_args), msg=on_failure) 190 self._test_case.assertTrue(self._comp(expected_cmd, actual_args[0]), 191 msg=on_failure) 192 self._test_case.assertTrue('timeout_time' in actual_kwargs, 193 msg=on_failure) 194 self._test_case.assertTrue('retry_count' in actual_kwargs, 195 msg=on_failure) 196 197 def assertNoAdbCalls(self): 198 return type(self).AndroidCommandsCalls(self, [], str.__eq__) 199 200 def assertCalls(self, cmd, ret, comp=str.__eq__): 201 return type(self).AndroidCommandsCalls(self, [(cmd, ret)], comp) 202 203 def assertCallsSequence(self, cmd_ret, comp=str.__eq__): 204 return type(self).AndroidCommandsCalls(self, cmd_ret, comp) 205 206 def setUp(self): 207 self.device = device_utils.DeviceUtils( 208 '0123456789abcdef', default_timeout=1, default_retries=0) 209 210 211class DeviceUtilsIsOnlineTest(DeviceUtilsOldImplTest): 212 213 def testIsOnline_true(self): 214 with self.assertCalls('adb -s 0123456789abcdef devices', 215 '00123456789abcdef device\r\n'): 216 self.assertTrue(self.device.IsOnline()) 217 218 def testIsOnline_false(self): 219 with self.assertCalls('adb -s 0123456789abcdef devices', '\r\n'): 220 self.assertFalse(self.device.IsOnline()) 221 222 223class DeviceUtilsHasRootTest(DeviceUtilsOldImplTest): 224 225 def testHasRoot_true(self): 226 with self.assertCalls("adb -s 0123456789abcdef shell 'ls /root'", 227 'foo\r\n'): 228 self.assertTrue(self.device.HasRoot()) 229 230 def testHasRoot_false(self): 231 with self.assertCalls("adb -s 0123456789abcdef shell 'ls /root'", 232 'Permission denied\r\n'): 233 self.assertFalse(self.device.HasRoot()) 234 235 236class DeviceUtilsEnableRootTest(DeviceUtilsOldImplTest): 237 238 def testEnableRoot_succeeds(self): 239 with self.assertCallsSequence([ 240 ('adb -s 0123456789abcdef shell getprop ro.build.type', 241 'userdebug\r\n'), 242 ('adb -s 0123456789abcdef root', 'restarting adbd as root\r\n'), 243 ('adb -s 0123456789abcdef wait-for-device', ''), 244 ('adb -s 0123456789abcdef wait-for-device', '')]): 245 self.device.EnableRoot() 246 247 def testEnableRoot_userBuild(self): 248 with self.assertCallsSequence([ 249 ('adb -s 0123456789abcdef shell getprop ro.build.type', 'user\r\n')]): 250 with self.assertRaises(device_errors.CommandFailedError): 251 self.device.EnableRoot() 252 253 def testEnableRoot_rootFails(self): 254 with self.assertCallsSequence([ 255 ('adb -s 0123456789abcdef shell getprop ro.build.type', 256 'userdebug\r\n'), 257 ('adb -s 0123456789abcdef root', 'no\r\n'), 258 ('adb -s 0123456789abcdef wait-for-device', '')]): 259 with self.assertRaises(device_errors.CommandFailedError): 260 self.device.EnableRoot() 261 262 263class DeviceUtilsGetExternalStoragePathTest(DeviceUtilsOldImplTest): 264 265 def testGetExternalStoragePath_succeeds(self): 266 fakeStoragePath = '/fake/storage/path' 267 with self.assertCalls( 268 "adb -s 0123456789abcdef shell 'echo $EXTERNAL_STORAGE'", 269 '%s\r\n' % fakeStoragePath): 270 self.assertEquals(fakeStoragePath, 271 self.device.GetExternalStoragePath()) 272 273 def testGetExternalStoragePath_fails(self): 274 with self.assertCalls( 275 "adb -s 0123456789abcdef shell 'echo $EXTERNAL_STORAGE'", '\r\n'): 276 with self.assertRaises(device_errors.CommandFailedError): 277 self.device.GetExternalStoragePath() 278 279 280class DeviceUtilsWaitUntilFullyBootedTest(DeviceUtilsOldImplTest): 281 282 def testWaitUntilFullyBooted_succeedsNoWifi(self): 283 with self.assertCallsSequence([ 284 # AndroidCommands.WaitForSystemBootCompleted 285 ('adb -s 0123456789abcdef wait-for-device', ''), 286 ('adb -s 0123456789abcdef shell getprop sys.boot_completed', '1\r\n'), 287 # AndroidCommands.WaitForDevicePm 288 ('adb -s 0123456789abcdef wait-for-device', ''), 289 ('adb -s 0123456789abcdef shell pm path android', 290 'package:this.is.a.test.package'), 291 # AndroidCommands.WaitForSdCardReady 292 ("adb -s 0123456789abcdef shell 'echo $EXTERNAL_STORAGE'", 293 '/fake/storage/path'), 294 ("adb -s 0123456789abcdef shell 'ls /fake/storage/path'", 295 'nothing\r\n') 296 ]): 297 self.device.WaitUntilFullyBooted(wifi=False) 298 299 def testWaitUntilFullyBooted_succeedsWithWifi(self): 300 with self.assertCallsSequence([ 301 # AndroidCommands.WaitForSystemBootCompleted 302 ('adb -s 0123456789abcdef wait-for-device', ''), 303 ('adb -s 0123456789abcdef shell getprop sys.boot_completed', '1\r\n'), 304 # AndroidCommands.WaitForDevicePm 305 ('adb -s 0123456789abcdef wait-for-device', ''), 306 ('adb -s 0123456789abcdef shell pm path android', 307 'package:this.is.a.test.package'), 308 # AndroidCommands.WaitForSdCardReady 309 ("adb -s 0123456789abcdef shell 'echo $EXTERNAL_STORAGE'", 310 '/fake/storage/path'), 311 ("adb -s 0123456789abcdef shell 'ls /fake/storage/path'", 312 'nothing\r\n'), 313 # wait for wifi 314 ("adb -s 0123456789abcdef shell 'dumpsys wifi'", 'Wi-Fi is enabled')]): 315 self.device.WaitUntilFullyBooted(wifi=True) 316 317 def testWaitUntilFullyBooted_bootFails(self): 318 with mock.patch('time.sleep'): 319 with self.assertCallsSequence([ 320 # AndroidCommands.WaitForSystemBootCompleted 321 ('adb -s 0123456789abcdef wait-for-device', ''), 322 ('adb -s 0123456789abcdef shell getprop sys.boot_completed', 323 '0\r\n')]): 324 with self.assertRaises(device_errors.CommandTimeoutError): 325 self.device.WaitUntilFullyBooted(wifi=False) 326 327 def testWaitUntilFullyBooted_devicePmFails(self): 328 with mock.patch('time.sleep'): 329 with self.assertCallsSequence([ 330 # AndroidCommands.WaitForSystemBootCompleted 331 ('adb -s 0123456789abcdef wait-for-device', ''), 332 ('adb -s 0123456789abcdef shell getprop sys.boot_completed', 333 '1\r\n')] 334 # AndroidCommands.WaitForDevicePm 335 + 3 * ([('adb -s 0123456789abcdef wait-for-device', '')] 336 + 24 * [('adb -s 0123456789abcdef shell pm path android', '\r\n')] 337 + [("adb -s 0123456789abcdef shell 'stop'", '\r\n'), 338 ("adb -s 0123456789abcdef shell 'start'", '\r\n')])): 339 with self.assertRaises(device_errors.CommandTimeoutError): 340 self.device.WaitUntilFullyBooted(wifi=False) 341 342 def testWaitUntilFullyBooted_sdCardReadyFails_noPath(self): 343 with mock.patch('time.sleep'): 344 with self.assertCallsSequence([ 345 # AndroidCommands.WaitForSystemBootCompleted 346 ('adb -s 0123456789abcdef wait-for-device', ''), 347 ('adb -s 0123456789abcdef shell getprop sys.boot_completed', 348 '1\r\n'), 349 # AndroidCommands.WaitForDevicePm 350 ('adb -s 0123456789abcdef wait-for-device', ''), 351 ('adb -s 0123456789abcdef shell pm path android', 352 'package:this.is.a.test.package'), 353 ("adb -s 0123456789abcdef shell 'echo $EXTERNAL_STORAGE'", '\r\n')]): 354 with self.assertRaises(device_errors.CommandFailedError): 355 self.device.WaitUntilFullyBooted(wifi=False) 356 357 def testWaitUntilFullyBooted_sdCardReadyFails_emptyPath(self): 358 with mock.patch('time.sleep'): 359 with self.assertCallsSequence([ 360 # AndroidCommands.WaitForSystemBootCompleted 361 ('adb -s 0123456789abcdef wait-for-device', ''), 362 ('adb -s 0123456789abcdef shell getprop sys.boot_completed', 363 '1\r\n'), 364 # AndroidCommands.WaitForDevicePm 365 ('adb -s 0123456789abcdef wait-for-device', ''), 366 ('adb -s 0123456789abcdef shell pm path android', 367 'package:this.is.a.test.package'), 368 ("adb -s 0123456789abcdef shell 'echo $EXTERNAL_STORAGE'", 369 '/fake/storage/path\r\n'), 370 ("adb -s 0123456789abcdef shell 'ls /fake/storage/path'", '')]): 371 with self.assertRaises(device_errors.CommandTimeoutError): 372 self.device.WaitUntilFullyBooted(wifi=False) 373 374 375class DeviceUtilsRebootTest(DeviceUtilsOldImplTest): 376 377 def testReboot_nonBlocking(self): 378 with mock.patch('time.sleep'): 379 with self.assertCallsSequence([ 380 ('adb -s 0123456789abcdef reboot', ''), 381 ('adb -s 0123456789abcdef devices', 'unknown\r\n'), 382 ('adb -s 0123456789abcdef wait-for-device', ''), 383 ('adb -s 0123456789abcdef shell pm path android', 384 'package:this.is.a.test.package'), 385 ("adb -s 0123456789abcdef shell 'echo $EXTERNAL_STORAGE'", 386 '/fake/storage/path\r\n'), 387 ("adb -s 0123456789abcdef shell 'ls /fake/storage/path'", 388 'nothing\r\n')]): 389 self.device.Reboot(block=False) 390 391 def testReboot_blocking(self): 392 with mock.patch('time.sleep'): 393 with self.assertCallsSequence([ 394 ('adb -s 0123456789abcdef reboot', ''), 395 ('adb -s 0123456789abcdef devices', 'unknown\r\n'), 396 ('adb -s 0123456789abcdef wait-for-device', ''), 397 ('adb -s 0123456789abcdef shell pm path android', 398 'package:this.is.a.test.package'), 399 ("adb -s 0123456789abcdef shell 'echo $EXTERNAL_STORAGE'", 400 '/fake/storage/path\r\n'), 401 ("adb -s 0123456789abcdef shell 'ls /fake/storage/path'", 402 'nothing\r\n'), 403 ('adb -s 0123456789abcdef wait-for-device', ''), 404 ('adb -s 0123456789abcdef shell getprop sys.boot_completed', 405 '1\r\n'), 406 ('adb -s 0123456789abcdef wait-for-device', ''), 407 ('adb -s 0123456789abcdef shell pm path android', 408 'package:this.is.a.test.package'), 409 ("adb -s 0123456789abcdef shell 'ls /fake/storage/path'", 410 'nothing\r\n')]): 411 self.device.Reboot(block=True) 412 413 414class DeviceUtilsInstallTest(DeviceUtilsOldImplTest): 415 416 def testInstall_noPriorInstall(self): 417 with mock.patch('os.path.isfile', return_value=True), ( 418 mock.patch('pylib.utils.apk_helper.GetPackageName', 419 return_value='this.is.a.test.package')): 420 with self.assertCallsSequence([ 421 ("adb -s 0123456789abcdef shell 'pm path this.is.a.test.package'", 422 ''), 423 ("adb -s 0123456789abcdef install /fake/test/app.apk", 424 'Success\r\n')]): 425 self.device.Install('/fake/test/app.apk', retries=0) 426 427 def testInstall_differentPriorInstall(self): 428 def mockGetFilesChanged(host_path, device_path, ignore_filenames): 429 return [(host_path, device_path)] 430 431 # Pylint raises a false positive "operator not preceded by a space" 432 # warning below. 433 # pylint: disable=C0322 434 with mock.patch('os.path.isfile', return_value=True), ( 435 mock.patch('os.path.exists', return_value=True)), ( 436 mock.patch('pylib.utils.apk_helper.GetPackageName', 437 return_value='this.is.a.test.package')), ( 438 mock.patch('pylib.constants.GetOutDirectory', 439 return_value='/fake/test/out')), ( 440 mock.patch('pylib.android_commands.AndroidCommands.GetFilesChanged', 441 side_effect=mockGetFilesChanged)): 442 # pylint: enable=C0322 443 with self.assertCallsSequence([ 444 ("adb -s 0123456789abcdef shell 'pm path this.is.a.test.package'", 445 'package:/fake/data/app/this.is.a.test.package.apk\r\n'), 446 # GetFilesChanged is mocked, so its adb calls are omitted. 447 ('adb -s 0123456789abcdef uninstall this.is.a.test.package', 448 'Success\r\n'), 449 ('adb -s 0123456789abcdef install /fake/test/app.apk', 450 'Success\r\n')]): 451 self.device.Install('/fake/test/app.apk', retries=0) 452 453 def testInstall_differentPriorInstall_reinstall(self): 454 def mockGetFilesChanged(host_path, device_path, ignore_filenames): 455 return [(host_path, device_path)] 456 457 # Pylint raises a false positive "operator not preceded by a space" 458 # warning below. 459 # pylint: disable=C0322 460 with mock.patch('os.path.isfile', return_value=True), ( 461 mock.patch('pylib.utils.apk_helper.GetPackageName', 462 return_value='this.is.a.test.package')), ( 463 mock.patch('pylib.constants.GetOutDirectory', 464 return_value='/fake/test/out')), ( 465 mock.patch('pylib.android_commands.AndroidCommands.GetFilesChanged', 466 side_effect=mockGetFilesChanged)): 467 # pylint: enable=C0322 468 with self.assertCallsSequence([ 469 ("adb -s 0123456789abcdef shell 'pm path this.is.a.test.package'", 470 'package:/fake/data/app/this.is.a.test.package.apk\r\n'), 471 # GetFilesChanged is mocked, so its adb calls are omitted. 472 ('adb -s 0123456789abcdef install -r /fake/test/app.apk', 473 'Success\r\n')]): 474 self.device.Install('/fake/test/app.apk', reinstall=True, retries=0) 475 476 def testInstall_identicalPriorInstall(self): 477 def mockGetFilesChanged(host_path, device_path, ignore_filenames): 478 return [] 479 480 with mock.patch('pylib.utils.apk_helper.GetPackageName', 481 return_value='this.is.a.test.package'), ( 482 mock.patch('pylib.android_commands.AndroidCommands.GetFilesChanged', 483 side_effect=mockGetFilesChanged)): 484 with self.assertCallsSequence([ 485 ("adb -s 0123456789abcdef shell 'pm path this.is.a.test.package'", 486 'package:/fake/data/app/this.is.a.test.package.apk\r\n') 487 # GetFilesChanged is mocked, so its adb calls are omitted. 488 ]): 489 self.device.Install('/fake/test/app.apk', retries=0) 490 491 def testInstall_fails(self): 492 with mock.patch('os.path.isfile', return_value=True), ( 493 mock.patch('pylib.utils.apk_helper.GetPackageName', 494 return_value='this.is.a.test.package')): 495 with self.assertCallsSequence([ 496 ("adb -s 0123456789abcdef shell 'pm path this.is.a.test.package'", 497 ''), 498 ("adb -s 0123456789abcdef install /fake/test/app.apk", 499 'Failure\r\n')]): 500 with self.assertRaises(device_errors.CommandFailedError): 501 self.device.Install('/fake/test/app.apk', retries=0) 502 503 504class DeviceUtilsRunShellCommandTest(DeviceUtilsOldImplTest): 505 506 def testRunShellCommand_commandAsList(self): 507 with self.assertCalls( 508 "adb -s 0123456789abcdef shell 'pm list packages'", 509 'pacakge:android\r\n'): 510 self.device.RunShellCommand(['pm', 'list', 'packages']) 511 512 def testRunShellCommand_commandAsString(self): 513 with self.assertCalls( 514 "adb -s 0123456789abcdef shell 'dumpsys wifi'", 515 'Wi-Fi is enabled\r\n'): 516 self.device.RunShellCommand('dumpsys wifi') 517 518 def testRunShellCommand_withSu(self): 519 with self.assertCallsSequence([ 520 ("adb -s 0123456789abcdef shell 'ls /root'", 'Permission denied\r\n'), 521 ("adb -s 0123456789abcdef shell 'su -c setprop service.adb.root 0'", 522 '')]): 523 self.device.RunShellCommand('setprop service.adb.root 0', as_root=True) 524 525 def testRunShellCommand_withRoot(self): 526 with self.assertCallsSequence([ 527 ("adb -s 0123456789abcdef shell 'ls /root'", 'hello\r\nworld\r\n'), 528 ("adb -s 0123456789abcdef shell 'setprop service.adb.root 0'", '')]): 529 self.device.RunShellCommand('setprop service.adb.root 0', as_root=True) 530 531 def testRunShellCommand_checkReturn_success(self): 532 with self.assertCalls( 533 "adb -s 0123456789abcdef shell 'echo $ANDROID_DATA; echo %$?'", 534 '/data\r\n%0\r\n'): 535 self.device.RunShellCommand('echo $ANDROID_DATA', check_return=True) 536 537 def testRunShellCommand_checkReturn_failure(self): 538 with self.assertCalls( 539 "adb -s 0123456789abcdef shell 'echo $ANDROID_DATA; echo %$?'", 540 '\r\n%1\r\n'): 541 with self.assertRaises(device_errors.CommandFailedError): 542 self.device.RunShellCommand('echo $ANDROID_DATA', check_return=True) 543 544 545class DeviceUtilsKillAllTest(DeviceUtilsOldImplTest): 546 547 def testKillAll_noMatchingProcesses(self): 548 with self.assertCalls( 549 "adb -s 0123456789abcdef shell 'ps'", 550 'USER PID PPID VSIZE RSS WCHAN PC NAME\r\n'): 551 with self.assertRaises(device_errors.CommandFailedError): 552 self.device.KillAll('test_process') 553 554 def testKillAll_nonblocking(self): 555 with self.assertCallsSequence([ 556 ("adb -s 0123456789abcdef shell 'ps'", 557 'USER PID PPID VSIZE RSS WCHAN PC NAME\r\n' 558 'u0_a1 1234 174 123456 54321 ffffffff 456789ab ' 559 'this.is.a.test.process\r\n'), 560 ("adb -s 0123456789abcdef shell 'kill -9 1234'", '')]): 561 self.assertEquals(1, 562 self.device.KillAll('this.is.a.test.process', blocking=False)) 563 564 def testKillAll_blocking(self): 565 with mock.patch('time.sleep'): 566 with self.assertCallsSequence([ 567 ("adb -s 0123456789abcdef shell 'ps'", 568 'USER PID PPID VSIZE RSS WCHAN PC NAME\r\n' 569 'u0_a1 1234 174 123456 54321 ffffffff 456789ab ' 570 'this.is.a.test.process\r\n'), 571 ("adb -s 0123456789abcdef shell 'kill -9 1234'", ''), 572 ("adb -s 0123456789abcdef shell 'ps'", 573 'USER PID PPID VSIZE RSS WCHAN PC NAME\r\n' 574 'u0_a1 1234 174 123456 54321 ffffffff 456789ab ' 575 'this.is.a.test.process\r\n'), 576 ("adb -s 0123456789abcdef shell 'ps'", 577 'USER PID PPID VSIZE RSS WCHAN PC NAME\r\n')]): 578 self.assertEquals(1, 579 self.device.KillAll('this.is.a.test.process', blocking=True)) 580 581 def testKillAll_root(self): 582 with self.assertCallsSequence([ 583 ("adb -s 0123456789abcdef shell 'ps'", 584 'USER PID PPID VSIZE RSS WCHAN PC NAME\r\n' 585 'u0_a1 1234 174 123456 54321 ffffffff 456789ab ' 586 'this.is.a.test.process\r\n'), 587 ("adb -s 0123456789abcdef shell 'ls /root'", 'Permission denied\r\n'), 588 ("adb -s 0123456789abcdef shell 'su -c kill -9 1234'", '')]): 589 self.assertEquals(1, 590 self.device.KillAll('this.is.a.test.process', as_root=True)) 591 592 def testKillAll_sigterm(self): 593 with self.assertCallsSequence([ 594 ("adb -s 0123456789abcdef shell 'ps'", 595 'USER PID PPID VSIZE RSS WCHAN PC NAME\r\n' 596 'u0_a1 1234 174 123456 54321 ffffffff 456789ab ' 597 'this.is.a.test.process\r\n'), 598 ("adb -s 0123456789abcdef shell 'kill -15 1234'", '')]): 599 self.assertEquals(1, 600 self.device.KillAll('this.is.a.test.process', signum=signal.SIGTERM)) 601 602 603class DeviceUtilsStartActivityTest(DeviceUtilsOldImplTest): 604 605 def testStartActivity_actionOnly(self): 606 test_intent = intent.Intent(action='android.intent.action.VIEW') 607 with self.assertCalls( 608 "adb -s 0123456789abcdef shell 'am start " 609 "-a android.intent.action.VIEW'", 610 'Starting: Intent { act=android.intent.action.VIEW }'): 611 self.device.StartActivity(test_intent) 612 613 def testStartActivity_success(self): 614 test_intent = intent.Intent(action='android.intent.action.VIEW', 615 package='this.is.a.test.package', 616 activity='.Main') 617 with self.assertCalls( 618 "adb -s 0123456789abcdef shell 'am start " 619 "-a android.intent.action.VIEW " 620 "-n this.is.a.test.package/.Main'", 621 'Starting: Intent { act=android.intent.action.VIEW }'): 622 self.device.StartActivity(test_intent) 623 624 def testStartActivity_failure(self): 625 test_intent = intent.Intent(action='android.intent.action.VIEW', 626 package='this.is.a.test.package', 627 activity='.Main') 628 with self.assertCalls( 629 "adb -s 0123456789abcdef shell 'am start " 630 "-a android.intent.action.VIEW " 631 "-n this.is.a.test.package/.Main'", 632 'Error: Failed to start test activity'): 633 with self.assertRaises(device_errors.CommandFailedError): 634 self.device.StartActivity(test_intent) 635 636 def testStartActivity_blocking(self): 637 test_intent = intent.Intent(action='android.intent.action.VIEW', 638 package='this.is.a.test.package', 639 activity='.Main') 640 with self.assertCalls( 641 "adb -s 0123456789abcdef shell 'am start " 642 "-a android.intent.action.VIEW " 643 "-W " 644 "-n this.is.a.test.package/.Main'", 645 'Starting: Intent { act=android.intent.action.VIEW }'): 646 self.device.StartActivity(test_intent, blocking=True) 647 648 def testStartActivity_withCategory(self): 649 test_intent = intent.Intent(action='android.intent.action.VIEW', 650 package='this.is.a.test.package', 651 activity='.Main', 652 category='android.intent.category.HOME') 653 with self.assertCalls( 654 "adb -s 0123456789abcdef shell 'am start " 655 "-a android.intent.action.VIEW " 656 "-c android.intent.category.HOME " 657 "-n this.is.a.test.package/.Main'", 658 'Starting: Intent { act=android.intent.action.VIEW }'): 659 self.device.StartActivity(test_intent) 660 661 def testStartActivity_withMultipleCategories(self): 662 # The new implementation will start the activity with all provided 663 # categories. The old one only uses the first category. 664 test_intent = intent.Intent(action='android.intent.action.VIEW', 665 package='this.is.a.test.package', 666 activity='.Main', 667 category=['android.intent.category.HOME', 668 'android.intent.category.BROWSABLE']) 669 with self.assertCalls( 670 "adb -s 0123456789abcdef shell 'am start " 671 "-a android.intent.action.VIEW " 672 "-c android.intent.category.HOME " 673 "-n this.is.a.test.package/.Main'", 674 'Starting: Intent { act=android.intent.action.VIEW }'): 675 self.device.StartActivity(test_intent) 676 677 def testStartActivity_withData(self): 678 test_intent = intent.Intent(action='android.intent.action.VIEW', 679 package='this.is.a.test.package', 680 activity='.Main', 681 data='http://www.google.com/') 682 with self.assertCalls( 683 "adb -s 0123456789abcdef shell 'am start " 684 "-a android.intent.action.VIEW " 685 "-n this.is.a.test.package/.Main " 686 "-d \"http://www.google.com/\"'", 687 'Starting: Intent { act=android.intent.action.VIEW }'): 688 self.device.StartActivity(test_intent) 689 690 def testStartActivity_withStringExtra(self): 691 test_intent = intent.Intent(action='android.intent.action.VIEW', 692 package='this.is.a.test.package', 693 activity='.Main', 694 extras={'foo': 'test'}) 695 with self.assertCalls( 696 "adb -s 0123456789abcdef shell 'am start " 697 "-a android.intent.action.VIEW " 698 "-n this.is.a.test.package/.Main " 699 "--es foo test'", 700 'Starting: Intent { act=android.intent.action.VIEW }'): 701 self.device.StartActivity(test_intent) 702 703 def testStartActivity_withBoolExtra(self): 704 test_intent = intent.Intent(action='android.intent.action.VIEW', 705 package='this.is.a.test.package', 706 activity='.Main', 707 extras={'foo': True}) 708 with self.assertCalls( 709 "adb -s 0123456789abcdef shell 'am start " 710 "-a android.intent.action.VIEW " 711 "-n this.is.a.test.package/.Main " 712 "--ez foo True'", 713 'Starting: Intent { act=android.intent.action.VIEW }'): 714 self.device.StartActivity(test_intent) 715 716 def testStartActivity_withIntExtra(self): 717 test_intent = intent.Intent(action='android.intent.action.VIEW', 718 package='this.is.a.test.package', 719 activity='.Main', 720 extras={'foo': 123}) 721 with self.assertCalls( 722 "adb -s 0123456789abcdef shell 'am start " 723 "-a android.intent.action.VIEW " 724 "-n this.is.a.test.package/.Main " 725 "--ei foo 123'", 726 'Starting: Intent { act=android.intent.action.VIEW }'): 727 self.device.StartActivity(test_intent) 728 729 def testStartActivity_withTraceFile(self): 730 test_intent = intent.Intent(action='android.intent.action.VIEW', 731 package='this.is.a.test.package', 732 activity='.Main') 733 with self.assertCalls( 734 "adb -s 0123456789abcdef shell 'am start " 735 "-a android.intent.action.VIEW " 736 "-n this.is.a.test.package/.Main " 737 "--start-profiler test_trace_file.out'", 738 'Starting: Intent { act=android.intent.action.VIEW }'): 739 self.device.StartActivity(test_intent, 740 trace_file_name='test_trace_file.out') 741 742 def testStartActivity_withForceStop(self): 743 test_intent = intent.Intent(action='android.intent.action.VIEW', 744 package='this.is.a.test.package', 745 activity='.Main') 746 with self.assertCalls( 747 "adb -s 0123456789abcdef shell 'am start " 748 "-a android.intent.action.VIEW " 749 "-S " 750 "-n this.is.a.test.package/.Main'", 751 'Starting: Intent { act=android.intent.action.VIEW }'): 752 self.device.StartActivity(test_intent, force_stop=True) 753 754 def testStartActivity_withFlags(self): 755 test_intent = intent.Intent(action='android.intent.action.VIEW', 756 package='this.is.a.test.package', 757 activity='.Main', 758 flags='0x10000000') 759 with self.assertCalls( 760 "adb -s 0123456789abcdef shell 'am start " 761 "-a android.intent.action.VIEW " 762 "-n this.is.a.test.package/.Main " 763 "-f 0x10000000'", 764 'Starting: Intent { act=android.intent.action.VIEW }'): 765 self.device.StartActivity(test_intent) 766 767 768class DeviceUtilsBroadcastIntentTest(DeviceUtilsOldImplTest): 769 770 def testBroadcastIntent_noExtras(self): 771 test_intent = intent.Intent(action='test.package.with.an.INTENT') 772 with self.assertCalls( 773 "adb -s 0123456789abcdef shell 'am broadcast " 774 "-a test.package.with.an.INTENT '", 775 'Broadcasting: Intent { act=test.package.with.an.INTENT } '): 776 self.device.BroadcastIntent(test_intent) 777 778 def testBroadcastIntent_withExtra(self): 779 test_intent = intent.Intent(action='test.package.with.an.INTENT', 780 extras={'foo': 'bar'}) 781 with self.assertCalls( 782 "adb -s 0123456789abcdef shell 'am broadcast " 783 "-a test.package.with.an.INTENT " 784 "-e foo \"bar\"'", 785 'Broadcasting: Intent { act=test.package.with.an.INTENT } '): 786 self.device.BroadcastIntent(test_intent) 787 788 def testBroadcastIntent_withExtra_noValue(self): 789 test_intent = intent.Intent(action='test.package.with.an.INTENT', 790 extras={'foo': None}) 791 with self.assertCalls( 792 "adb -s 0123456789abcdef shell 'am broadcast " 793 "-a test.package.with.an.INTENT " 794 "-e foo'", 795 'Broadcasting: Intent { act=test.package.with.an.INTENT } '): 796 self.device.BroadcastIntent(test_intent) 797 798 799class DeviceUtilsGoHomeTest(DeviceUtilsOldImplTest): 800 801 def testGoHome(self): 802 with self.assertCalls( 803 "adb -s 0123456789abcdef shell 'am start " 804 "-W " 805 "-a android.intent.action.MAIN " 806 "-c android.intent.category.HOME'", 807 'Starting: Intent { act=android.intent.action.MAIN }\r\n'): 808 self.device.GoHome() 809 810 811class DeviceUtilsForceStopTest(DeviceUtilsOldImplTest): 812 813 def testForceStop(self): 814 with self.assertCalls( 815 "adb -s 0123456789abcdef shell 'am force-stop this.is.a.test.package'", 816 ''): 817 self.device.ForceStop('this.is.a.test.package') 818 819 820class DeviceUtilsClearApplicationStateTest(DeviceUtilsOldImplTest): 821 822 def testClearApplicationState_packageExists(self): 823 with self.assertCalls( 824 "adb -s 0123456789abcdef shell 'pm path this.package.does.not.exist'", 825 ''): 826 self.device.ClearApplicationState('this.package.does.not.exist') 827 828 def testClearApplicationState_packageDoesntExist(self): 829 with self.assertCallsSequence([ 830 ("adb -s 0123456789abcdef shell 'pm path this.package.exists'", 831 'package:/data/app/this.package.exists.apk'), 832 ("adb -s 0123456789abcdef shell 'pm clear this.package.exists'", 833 'Success\r\n')]): 834 self.device.ClearApplicationState('this.package.exists') 835 836 837class DeviceUtilsSendKeyEventTest(DeviceUtilsOldImplTest): 838 839 def testSendKeyEvent(self): 840 with self.assertCalls( 841 "adb -s 0123456789abcdef shell 'input keyevent 66'", 842 ''): 843 self.device.SendKeyEvent(66) 844 845 846class DeviceUtilsPushChangedFilesTest(DeviceUtilsOldImplTest): 847 848 849 def testPushChangedFiles_noHostPath(self): 850 with mock.patch('os.path.exists', return_value=False): 851 with self.assertRaises(device_errors.CommandFailedError): 852 self.device.PushChangedFiles('/test/host/path', '/test/device/path') 853 854 def testPushChangedFiles_file_noChange(self): 855 self.device.old_interface._push_if_needed_cache = {} 856 857 host_file_path = '/test/host/path' 858 device_file_path = '/test/device/path' 859 860 mock_fs = MockFileSystem() 861 mock_fs.addMockFile(host_file_path, size=100) 862 863 self.device.old_interface.GetFilesChanged = mock.Mock(return_value=[]) 864 865 with mock_fs: 866 # GetFilesChanged is mocked, so its adb calls are omitted. 867 with self.assertNoAdbCalls(): 868 self.device.PushChangedFiles(host_file_path, device_file_path) 869 870 def testPushChangedFiles_file_changed(self): 871 self.device.old_interface._push_if_needed_cache = {} 872 873 host_file_path = '/test/host/path' 874 device_file_path = '/test/device/path' 875 876 mock_fs = MockFileSystem() 877 mock_fs.addMockFile( 878 host_file_path, size=100, 879 stat=MockFileSystem.osStatResult(st_mtime=1000000000)) 880 881 self.device.old_interface.GetFilesChanged = mock.Mock( 882 return_value=[('/test/host/path', '/test/device/path')]) 883 884 with mock_fs: 885 with self.assertCalls('adb -s 0123456789abcdef push ' 886 '/test/host/path /test/device/path', '100 B/s (100 B in 1.000s)\r\n'): 887 self.device.PushChangedFiles(host_file_path, device_file_path) 888 889 def testPushChangedFiles_directory_nothingChanged(self): 890 self.device.old_interface._push_if_needed_cache = {} 891 892 host_file_path = '/test/host/path' 893 device_file_path = '/test/device/path' 894 895 mock_fs = MockFileSystem() 896 mock_fs.addMockDirectory( 897 host_file_path, size=256, 898 stat=MockFileSystem.osStatResult(st_mtime=1000000000)) 899 mock_fs.addMockFile( 900 host_file_path + '/file1', size=251, 901 stat=MockFileSystem.osStatResult(st_mtime=1000000001)) 902 mock_fs.addMockFile( 903 host_file_path + '/file2', size=252, 904 stat=MockFileSystem.osStatResult(st_mtime=1000000002)) 905 906 self.device.old_interface.GetFilesChanged = mock.Mock(return_value=[]) 907 908 with mock_fs: 909 with self.assertCallsSequence([ 910 ("adb -s 0123456789abcdef shell 'mkdir -p \"/test/device/path\"'", 911 '')]): 912 self.device.PushChangedFiles(host_file_path, device_file_path) 913 914 def testPushChangedFiles_directory_somethingChanged(self): 915 self.device.old_interface._push_if_needed_cache = {} 916 917 host_file_path = '/test/host/path' 918 device_file_path = '/test/device/path' 919 920 mock_fs = MockFileSystem() 921 mock_fs.addMockDirectory( 922 host_file_path, size=256, 923 stat=MockFileSystem.osStatResult(st_mtime=1000000000), 924 walk=[('/test/host/path', [], ['file1', 'file2'])]) 925 mock_fs.addMockFile( 926 host_file_path + '/file1', size=256, 927 stat=MockFileSystem.osStatResult(st_mtime=1000000001)) 928 mock_fs.addMockFile( 929 host_file_path + '/file2', size=256, 930 stat=MockFileSystem.osStatResult(st_mtime=1000000002)) 931 932 self.device.old_interface.GetFilesChanged = mock.Mock( 933 return_value=[('/test/host/path/file1', '/test/device/path/file1')]) 934 935 with mock_fs: 936 with self.assertCallsSequence([ 937 ("adb -s 0123456789abcdef shell 'mkdir -p \"/test/device/path\"'", 938 ''), 939 ('adb -s 0123456789abcdef push ' 940 '/test/host/path/file1 /test/device/path/file1', 941 '256 B/s (256 B in 1.000s)\r\n')]): 942 self.device.PushChangedFiles(host_file_path, device_file_path) 943 944 def testPushChangedFiles_directory_everythingChanged(self): 945 self.device.old_interface._push_if_needed_cache = {} 946 947 host_file_path = '/test/host/path' 948 device_file_path = '/test/device/path' 949 950 mock_fs = MockFileSystem() 951 mock_fs.addMockDirectory( 952 host_file_path, size=256, 953 stat=MockFileSystem.osStatResult(st_mtime=1000000000)) 954 mock_fs.addMockFile( 955 host_file_path + '/file1', size=256, 956 stat=MockFileSystem.osStatResult(st_mtime=1000000001)) 957 mock_fs.addMockFile( 958 host_file_path + '/file2', size=256, 959 stat=MockFileSystem.osStatResult(st_mtime=1000000002)) 960 961 self.device.old_interface.GetFilesChanged = mock.Mock( 962 return_value=[('/test/host/path/file1', '/test/device/path/file1'), 963 ('/test/host/path/file2', '/test/device/path/file2')]) 964 965 with mock_fs: 966 with self.assertCallsSequence([ 967 ("adb -s 0123456789abcdef shell 'mkdir -p \"/test/device/path\"'", 968 ''), 969 ('adb -s 0123456789abcdef push /test/host/path /test/device/path', 970 '768 B/s (768 B in 1.000s)\r\n')]): 971 self.device.PushChangedFiles(host_file_path, device_file_path) 972 973 974class DeviceUtilsFileExistsTest(DeviceUtilsOldImplTest): 975 976 def testFileExists_usingTest_fileExists(self): 977 with self.assertCalls( 978 "adb -s 0123456789abcdef shell " 979 "'test -e \"/data/app/test.file.exists\"; echo $?'", 980 '0\r\n'): 981 self.assertTrue(self.device.FileExists('/data/app/test.file.exists')) 982 983 def testFileExists_usingTest_fileDoesntExist(self): 984 with self.assertCalls( 985 "adb -s 0123456789abcdef shell " 986 "'test -e \"/data/app/test.file.does.not.exist\"; echo $?'", 987 '1\r\n'): 988 self.assertFalse(self.device.FileExists( 989 '/data/app/test.file.does.not.exist')) 990 991 def testFileExists_usingLs_fileExists(self): 992 with self.assertCallsSequence([ 993 ("adb -s 0123456789abcdef shell " 994 "'test -e \"/data/app/test.file.exists\"; echo $?'", 995 'test: not found\r\n'), 996 ("adb -s 0123456789abcdef shell " 997 "'ls \"/data/app/test.file.exists\" >/dev/null 2>&1; echo $?'", 998 '0\r\n')]): 999 self.assertTrue(self.device.FileExists('/data/app/test.file.exists')) 1000 1001 def testFileExists_usingLs_fileDoesntExist(self): 1002 with self.assertCallsSequence([ 1003 ("adb -s 0123456789abcdef shell " 1004 "'test -e \"/data/app/test.file.does.not.exist\"; echo $?'", 1005 'test: not found\r\n'), 1006 ("adb -s 0123456789abcdef shell " 1007 "'ls \"/data/app/test.file.does.not.exist\" " 1008 ">/dev/null 2>&1; echo $?'", 1009 '1\r\n')]): 1010 self.assertFalse(self.device.FileExists( 1011 '/data/app/test.file.does.not.exist')) 1012 1013 1014class DeviceUtilsPullFileTest(DeviceUtilsOldImplTest): 1015 1016 def testPullFile_existsOnDevice(self): 1017 with mock.patch('os.path.exists', return_value=True): 1018 with self.assertCallsSequence([ 1019 ('adb -s 0123456789abcdef shell ' 1020 'ls /data/app/test.file.exists', 1021 '/data/app/test.file.exists'), 1022 ('adb -s 0123456789abcdef pull ' 1023 '/data/app/test.file.exists /test/file/host/path', 1024 '100 B/s (100 bytes in 1.000s)\r\n')]): 1025 self.device.PullFile('/data/app/test.file.exists', 1026 '/test/file/host/path') 1027 1028 def testPullFile_doesntExistOnDevice(self): 1029 with mock.patch('os.path.exists', return_value=True): 1030 with self.assertCalls( 1031 'adb -s 0123456789abcdef shell ' 1032 'ls /data/app/test.file.does.not.exist', 1033 '/data/app/test.file.does.not.exist: No such file or directory\r\n'): 1034 with self.assertRaises(device_errors.CommandFailedError): 1035 self.device.PullFile('/data/app/test.file.does.not.exist', 1036 '/test/file/host/path') 1037 1038 1039class DeviceUtilsReadFileTest(DeviceUtilsOldImplTest): 1040 1041 def testReadFile_exists(self): 1042 with self.assertCallsSequence([ 1043 ("adb -s 0123456789abcdef shell " 1044 "'cat \"/read/this/test/file\" 2>/dev/null'", 1045 'this is a test file')]): 1046 self.assertEqual(['this is a test file'], 1047 self.device.ReadFile('/read/this/test/file')) 1048 1049 def testReadFile_doesNotExist(self): 1050 with self.assertCalls( 1051 "adb -s 0123456789abcdef shell " 1052 "'cat \"/this/file/does.not.exist\" 2>/dev/null'", 1053 ''): 1054 self.device.ReadFile('/this/file/does.not.exist') 1055 1056 def testReadFile_asRoot_withRoot(self): 1057 self.device.old_interface._privileged_command_runner = ( 1058 self.device.old_interface.RunShellCommand) 1059 self.device.old_interface._protected_file_access_method_initialized = True 1060 with self.assertCallsSequence([ 1061 ("adb -s 0123456789abcdef shell " 1062 "'cat \"/this/file/must.be.read.by.root\" 2> /dev/null'", 1063 'this is a test file\nread by root')]): 1064 self.assertEqual( 1065 ['this is a test file', 'read by root'], 1066 self.device.ReadFile('/this/file/must.be.read.by.root', 1067 as_root=True)) 1068 1069 def testReadFile_asRoot_withSu(self): 1070 self.device.old_interface._privileged_command_runner = ( 1071 self.device.old_interface.RunShellCommandWithSU) 1072 self.device.old_interface._protected_file_access_method_initialized = True 1073 with self.assertCallsSequence([ 1074 ("adb -s 0123456789abcdef shell " 1075 "'su -c cat \"/this/file/can.be.read.with.su\" 2> /dev/null'", 1076 'this is a test file\nread with su')]): 1077 self.assertEqual( 1078 ['this is a test file', 'read with su'], 1079 self.device.ReadFile('/this/file/can.be.read.with.su', 1080 as_root=True)) 1081 1082 def testReadFile_asRoot_rejected(self): 1083 self.device.old_interface._privileged_command_runner = None 1084 self.device.old_interface._protected_file_access_method_initialized = True 1085 with self.assertRaises(device_errors.CommandFailedError): 1086 self.device.ReadFile('/this/file/cannot.be.read.by.user', 1087 as_root=True) 1088 1089 1090class DeviceUtilsWriteFileTest(DeviceUtilsOldImplTest): 1091 1092 def testWriteFile_basic(self): 1093 mock_file = mock.MagicMock(spec=file) 1094 mock_file.name = '/tmp/file/to.be.pushed' 1095 mock_file.__enter__.return_value = mock_file 1096 with mock.patch('tempfile.NamedTemporaryFile', 1097 return_value=mock_file): 1098 with self.assertCalls( 1099 'adb -s 0123456789abcdef push ' 1100 '/tmp/file/to.be.pushed /test/file/written.to.device', 1101 '100 B/s (100 bytes in 1.000s)\r\n'): 1102 self.device.WriteFile('/test/file/written.to.device', 1103 'new test file contents') 1104 mock_file.write.assert_called_once_with('new test file contents') 1105 1106 def testWriteFile_asRoot_withRoot(self): 1107 self.device.old_interface._external_storage = '/fake/storage/path' 1108 self.device.old_interface._privileged_command_runner = ( 1109 self.device.old_interface.RunShellCommand) 1110 self.device.old_interface._protected_file_access_method_initialized = True 1111 1112 mock_file = mock.MagicMock(spec=file) 1113 mock_file.name = '/tmp/file/to.be.pushed' 1114 mock_file.__enter__.return_value = mock_file 1115 with mock.patch('tempfile.NamedTemporaryFile', 1116 return_value=mock_file): 1117 with self.assertCallsSequence( 1118 cmd_ret=[ 1119 # Create temporary contents file 1120 (r"adb -s 0123456789abcdef shell " 1121 "'test -e \"/fake/storage/path/temp_file-\d+-\d+\"; " 1122 "echo \$\?'", 1123 '1\r\n'), 1124 # Create temporary script file 1125 (r"adb -s 0123456789abcdef shell " 1126 "'test -e \"/fake/storage/path/temp_file-\d+-\d+\.sh\"; " 1127 "echo \$\?'", 1128 '1\r\n'), 1129 # Set contents file 1130 (r'adb -s 0123456789abcdef push /tmp/file/to\.be\.pushed ' 1131 '/fake/storage/path/temp_file-\d+\d+', 1132 '100 B/s (100 bytes in 1.000s)\r\n'), 1133 # Set script file 1134 (r'adb -s 0123456789abcdef push /tmp/file/to\.be\.pushed ' 1135 '/fake/storage/path/temp_file-\d+\d+', 1136 '100 B/s (100 bytes in 1.000s)\r\n'), 1137 # Call script 1138 (r"adb -s 0123456789abcdef shell " 1139 "'sh /fake/storage/path/temp_file-\d+-\d+\.sh'", ''), 1140 # Remove device temporaries 1141 (r"adb -s 0123456789abcdef shell " 1142 "'rm /fake/storage/path/temp_file-\d+-\d+\.sh'", ''), 1143 (r"adb -s 0123456789abcdef shell " 1144 "'rm /fake/storage/path/temp_file-\d+-\d+'", '')], 1145 comp=re.match): 1146 self.device.WriteFile('/test/file/written.to.device', 1147 'new test file contents', as_root=True) 1148 1149 def testWriteFile_asRoot_withSu(self): 1150 self.device.old_interface._external_storage = '/fake/storage/path' 1151 self.device.old_interface._privileged_command_runner = ( 1152 self.device.old_interface.RunShellCommandWithSU) 1153 self.device.old_interface._protected_file_access_method_initialized = True 1154 1155 mock_file = mock.MagicMock(spec=file) 1156 mock_file.name = '/tmp/file/to.be.pushed' 1157 mock_file.__enter__.return_value = mock_file 1158 with mock.patch('tempfile.NamedTemporaryFile', 1159 return_value=mock_file): 1160 with self.assertCallsSequence( 1161 cmd_ret=[ 1162 # Create temporary contents file 1163 (r"adb -s 0123456789abcdef shell " 1164 "'test -e \"/fake/storage/path/temp_file-\d+-\d+\"; " 1165 "echo \$\?'", 1166 '1\r\n'), 1167 # Create temporary script file 1168 (r"adb -s 0123456789abcdef shell " 1169 "'test -e \"/fake/storage/path/temp_file-\d+-\d+\.sh\"; " 1170 "echo \$\?'", 1171 '1\r\n'), 1172 # Set contents file 1173 (r'adb -s 0123456789abcdef push /tmp/file/to\.be\.pushed ' 1174 '/fake/storage/path/temp_file-\d+\d+', 1175 '100 B/s (100 bytes in 1.000s)\r\n'), 1176 # Set script file 1177 (r'adb -s 0123456789abcdef push /tmp/file/to\.be\.pushed ' 1178 '/fake/storage/path/temp_file-\d+\d+', 1179 '100 B/s (100 bytes in 1.000s)\r\n'), 1180 # Call script 1181 (r"adb -s 0123456789abcdef shell " 1182 "'su -c sh /fake/storage/path/temp_file-\d+-\d+\.sh'", ''), 1183 # Remove device temporaries 1184 (r"adb -s 0123456789abcdef shell " 1185 "'rm /fake/storage/path/temp_file-\d+-\d+\.sh'", ''), 1186 (r"adb -s 0123456789abcdef shell " 1187 "'rm /fake/storage/path/temp_file-\d+-\d+'", '')], 1188 comp=re.match): 1189 self.device.WriteFile('/test/file/written.to.device', 1190 'new test file contents', as_root=True) 1191 1192 def testWriteFile_asRoot_rejected(self): 1193 self.device.old_interface._privileged_command_runner = None 1194 self.device.old_interface._protected_file_access_method_initialized = True 1195 with self.assertRaises(device_errors.CommandFailedError): 1196 self.device.WriteFile('/test/file/no.permissions.to.write', 1197 'new test file contents', as_root=True) 1198 1199class DeviceUtilsWriteTextFileTest(DeviceUtilsOldImplTest): 1200 1201 def testWriteTextFileTest_basic(self): 1202 with self.assertCalls( 1203 "adb -s 0123456789abcdef shell 'echo some.string" 1204 " > /test/file/to.write; echo %$?'", '%0\r\n'): 1205 self.device.WriteTextFile('/test/file/to.write', 'some.string') 1206 1207 def testWriteTextFileTest_stringWithSpaces(self): 1208 with self.assertCalls( 1209 "adb -s 0123456789abcdef shell 'echo '\\''some other string'\\''" 1210 " > /test/file/to.write; echo %$?'", '%0\r\n'): 1211 self.device.WriteTextFile('/test/file/to.write', 'some other string') 1212 1213 def testWriteTextFileTest_asRoot_withSu(self): 1214 with self.assertCallsSequence([ 1215 ("adb -s 0123456789abcdef shell 'ls /root'", 'Permission denied\r\n'), 1216 ("adb -s 0123456789abcdef shell 'su -c echo some.string" 1217 " > /test/file/to.write; echo %$?'", '%0\r\n')]): 1218 self.device.WriteTextFile('/test/file/to.write', 'some.string', 1219 as_root=True) 1220 1221 def testWriteTextFileTest_asRoot_withRoot(self): 1222 with self.assertCallsSequence([ 1223 ("adb -s 0123456789abcdef shell 'ls /root'", 'hello\r\nworld\r\n'), 1224 ("adb -s 0123456789abcdef shell 'echo some.string" 1225 " > /test/file/to.write; echo %$?'", '%0\r\n')]): 1226 self.device.WriteTextFile('/test/file/to.write', 'some.string', 1227 as_root=True) 1228 1229 def testWriteTextFileTest_asRoot_rejected(self): 1230 with self.assertCallsSequence([ 1231 ("adb -s 0123456789abcdef shell 'ls /root'", 'Permission denied\r\n'), 1232 ("adb -s 0123456789abcdef shell 'su -c echo some.string" 1233 " > /test/file/to.write; echo %$?'", '%1\r\n')]): 1234 with self.assertRaises(device_errors.CommandFailedError): 1235 self.device.WriteTextFile('/test/file/to.write', 'some.string', 1236 as_root=True) 1237 1238class DeviceUtilsLsTest(DeviceUtilsOldImplTest): 1239 1240 def testLs_nothing(self): 1241 with self.assertCallsSequence([ 1242 ("adb -s 0123456789abcdef shell 'ls -lR /this/file/does.not.exist'", 1243 '/this/file/does.not.exist: No such file or directory\r\n'), 1244 ("adb -s 0123456789abcdef shell 'date +%z'", '+0000')]): 1245 self.assertEqual({}, self.device.Ls('/this/file/does.not.exist')) 1246 1247 def testLs_file(self): 1248 with self.assertCallsSequence([ 1249 ("adb -s 0123456789abcdef shell 'ls -lR /this/is/a/test.file'", 1250 '-rw-rw---- testuser testgroup 4096 1970-01-01 00:00 test.file\r\n'), 1251 ("adb -s 0123456789abcdef shell 'date +%z'", '+0000')]): 1252 self.assertEqual( 1253 {'test.file': (4096, datetime.datetime(1970, 1, 1))}, 1254 self.device.Ls('/this/is/a/test.file')) 1255 1256 def testLs_directory(self): 1257 with self.assertCallsSequence([ 1258 ("adb -s 0123456789abcdef shell 'ls -lR /this/is/a/test.directory'", 1259 '\r\n' 1260 '/this/is/a/test.directory:\r\n' 1261 '-rw-rw---- testuser testgroup 4096 1970-01-01 18:19 test.file\r\n'), 1262 ("adb -s 0123456789abcdef shell 'date +%z'", '+0000')]): 1263 self.assertEqual( 1264 {'test.file': (4096, datetime.datetime(1970, 1, 1, 18, 19))}, 1265 self.device.Ls('/this/is/a/test.directory')) 1266 1267 def testLs_directories(self): 1268 with self.assertCallsSequence([ 1269 ("adb -s 0123456789abcdef shell 'ls -lR /this/is/a/test.directory'", 1270 '\r\n' 1271 '/this/is/a/test.directory:\r\n' 1272 'drwxr-xr-x testuser testgroup 1970-01-01 00:00 test.subdirectory\r\n' 1273 '\r\n' 1274 '/this/is/a/test.directory/test.subdirectory:\r\n' 1275 '-rw-rw---- testuser testgroup 4096 1970-01-01 00:00 test.file\r\n'), 1276 ("adb -s 0123456789abcdef shell 'date +%z'", '-0700')]): 1277 self.assertEqual( 1278 {'test.subdirectory/test.file': 1279 (4096, datetime.datetime(1970, 1, 1, 7, 0, 0))}, 1280 self.device.Ls('/this/is/a/test.directory')) 1281 1282 1283class DeviceUtilsSetJavaAssertsTest(DeviceUtilsOldImplTest): 1284 1285 @staticmethod 1286 def mockNamedTemporary(name='/tmp/file/property.file', 1287 read_contents=''): 1288 mock_file = mock.MagicMock(spec=file) 1289 mock_file.name = name 1290 mock_file.__enter__.return_value = mock_file 1291 mock_file.read.return_value = read_contents 1292 return mock_file 1293 1294 def testSetJavaAsserts_enable(self): 1295 mock_file = self.mockNamedTemporary() 1296 with mock.patch('tempfile.NamedTemporaryFile', 1297 return_value=mock_file), ( 1298 mock.patch('__builtin__.open', return_value=mock_file)): 1299 with self.assertCallsSequence( 1300 [('adb -s 0123456789abcdef shell ls %s' % 1301 constants.DEVICE_LOCAL_PROPERTIES_PATH, 1302 '%s\r\n' % constants.DEVICE_LOCAL_PROPERTIES_PATH), 1303 ('adb -s 0123456789abcdef pull %s %s' % 1304 (constants.DEVICE_LOCAL_PROPERTIES_PATH, mock_file.name), 1305 '100 B/s (100 bytes in 1.000s)\r\n'), 1306 ('adb -s 0123456789abcdef push %s %s' % 1307 (mock_file.name, constants.DEVICE_LOCAL_PROPERTIES_PATH), 1308 '100 B/s (100 bytes in 1.000s)\r\n'), 1309 ('adb -s 0123456789abcdef shell ' 1310 'getprop dalvik.vm.enableassertions', 1311 '\r\n'), 1312 ('adb -s 0123456789abcdef shell ' 1313 'setprop dalvik.vm.enableassertions "all"', 1314 '')]): 1315 self.assertTrue(self.device.SetJavaAsserts(True)) 1316 1317 def testSetJavaAsserts_disable(self): 1318 mock_file = self.mockNamedTemporary( 1319 read_contents='dalvik.vm.enableassertions=all\n') 1320 with mock.patch('tempfile.NamedTemporaryFile', 1321 return_value=mock_file), ( 1322 mock.patch('__builtin__.open', return_value=mock_file)): 1323 with self.assertCallsSequence( 1324 [('adb -s 0123456789abcdef shell ls %s' % 1325 constants.DEVICE_LOCAL_PROPERTIES_PATH, 1326 '%s\r\n' % constants.DEVICE_LOCAL_PROPERTIES_PATH), 1327 ('adb -s 0123456789abcdef pull %s %s' % 1328 (constants.DEVICE_LOCAL_PROPERTIES_PATH, mock_file.name), 1329 '100 B/s (100 bytes in 1.000s)\r\n'), 1330 ('adb -s 0123456789abcdef push %s %s' % 1331 (mock_file.name, constants.DEVICE_LOCAL_PROPERTIES_PATH), 1332 '100 B/s (100 bytes in 1.000s)\r\n'), 1333 ('adb -s 0123456789abcdef shell ' 1334 'getprop dalvik.vm.enableassertions', 1335 'all\r\n'), 1336 ('adb -s 0123456789abcdef shell ' 1337 'setprop dalvik.vm.enableassertions ""', 1338 '')]): 1339 self.assertTrue(self.device.SetJavaAsserts(False)) 1340 1341 def testSetJavaAsserts_alreadyEnabled(self): 1342 mock_file = self.mockNamedTemporary( 1343 read_contents='dalvik.vm.enableassertions=all\n') 1344 with mock.patch('tempfile.NamedTemporaryFile', 1345 return_value=mock_file), ( 1346 mock.patch('__builtin__.open', return_value=mock_file)): 1347 with self.assertCallsSequence( 1348 [('adb -s 0123456789abcdef shell ls %s' % 1349 constants.DEVICE_LOCAL_PROPERTIES_PATH, 1350 '%s\r\n' % constants.DEVICE_LOCAL_PROPERTIES_PATH), 1351 ('adb -s 0123456789abcdef pull %s %s' % 1352 (constants.DEVICE_LOCAL_PROPERTIES_PATH, mock_file.name), 1353 '100 B/s (100 bytes in 1.000s)\r\n'), 1354 ('adb -s 0123456789abcdef shell ' 1355 'getprop dalvik.vm.enableassertions', 1356 'all\r\n')]): 1357 self.assertFalse(self.device.SetJavaAsserts(True)) 1358 1359 1360class DeviceUtilsGetPropTest(DeviceUtilsOldImplTest): 1361 1362 def testGetProp_exists(self): 1363 with self.assertCalls( 1364 'adb -s 0123456789abcdef shell getprop this.is.a.test.property', 1365 'test_property_value\r\n'): 1366 self.assertEqual('test_property_value', 1367 self.device.GetProp('this.is.a.test.property')) 1368 1369 def testGetProp_doesNotExist(self): 1370 with self.assertCalls( 1371 'adb -s 0123456789abcdef shell ' 1372 'getprop this.property.does.not.exist', ''): 1373 self.assertEqual('', self.device.GetProp('this.property.does.not.exist')) 1374 1375 def testGetProp_cachedRoProp(self): 1376 with self.assertCalls( 1377 'adb -s 0123456789abcdef shell ' 1378 'getprop ro.build.type', 'userdebug'): 1379 self.assertEqual('userdebug', self.device.GetProp('ro.build.type')) 1380 self.assertEqual('userdebug', self.device.GetProp('ro.build.type')) 1381 1382 1383class DeviceUtilsSetPropTest(DeviceUtilsOldImplTest): 1384 1385 def testSetProp(self): 1386 with self.assertCalls( 1387 'adb -s 0123456789abcdef shell ' 1388 'setprop this.is.a.test.property "test_property_value"', 1389 ''): 1390 self.device.SetProp('this.is.a.test.property', 'test_property_value') 1391 1392 1393class DeviceUtilsGetPidsTest(DeviceUtilsOldImplTest): 1394 1395 def testGetPids_noMatches(self): 1396 with self.assertCalls( 1397 "adb -s 0123456789abcdef shell 'ps'", 1398 'USER PID PPID VSIZE RSS WCHAN PC NAME\r\n' 1399 'user 1000 100 1024 1024 ffffffff 00000000 no.match\r\n'): 1400 self.assertEqual({}, self.device.GetPids('does.not.match')) 1401 1402 def testGetPids_oneMatch(self): 1403 with self.assertCalls( 1404 "adb -s 0123456789abcdef shell 'ps'", 1405 'USER PID PPID VSIZE RSS WCHAN PC NAME\r\n' 1406 'user 1000 100 1024 1024 ffffffff 00000000 not.a.match\r\n' 1407 'user 1001 100 1024 1024 ffffffff 00000000 one.match\r\n'): 1408 self.assertEqual({'one.match': '1001'}, self.device.GetPids('one.match')) 1409 1410 def testGetPids_mutlipleMatches(self): 1411 with self.assertCalls( 1412 "adb -s 0123456789abcdef shell 'ps'", 1413 'USER PID PPID VSIZE RSS WCHAN PC NAME\r\n' 1414 'user 1000 100 1024 1024 ffffffff 00000000 not\r\n' 1415 'user 1001 100 1024 1024 ffffffff 00000000 one.match\r\n' 1416 'user 1002 100 1024 1024 ffffffff 00000000 two.match\r\n' 1417 'user 1003 100 1024 1024 ffffffff 00000000 three.match\r\n'): 1418 self.assertEqual( 1419 {'one.match': '1001', 'two.match': '1002', 'three.match': '1003'}, 1420 self.device.GetPids('match')) 1421 1422 def testGetPids_exactMatch(self): 1423 with self.assertCalls( 1424 "adb -s 0123456789abcdef shell 'ps'", 1425 'USER PID PPID VSIZE RSS WCHAN PC NAME\r\n' 1426 'user 1000 100 1024 1024 ffffffff 00000000 not.exact.match\r\n' 1427 'user 1234 100 1024 1024 ffffffff 00000000 exact.match\r\n'): 1428 self.assertEqual( 1429 {'not.exact.match': '1000', 'exact.match': '1234'}, 1430 self.device.GetPids('exact.match')) 1431 1432 1433class DeviceUtilsTakeScreenshotTest(DeviceUtilsOldImplTest): 1434 1435 def testTakeScreenshot_fileNameProvided(self): 1436 mock_fs = MockFileSystem() 1437 mock_fs.addMockDirectory('/test/host') 1438 mock_fs.addMockFile('/test/host/screenshot.png') 1439 1440 with mock_fs: 1441 with self.assertCallsSequence( 1442 cmd_ret=[ 1443 (r"adb -s 0123456789abcdef shell 'echo \$EXTERNAL_STORAGE'", 1444 '/test/external/storage\r\n'), 1445 (r"adb -s 0123456789abcdef shell '/system/bin/screencap -p \S+'", 1446 ''), 1447 (r"adb -s 0123456789abcdef shell ls \S+", 1448 '/test/external/storage/screenshot.png\r\n'), 1449 (r'adb -s 0123456789abcdef pull \S+ /test/host/screenshot.png', 1450 '100 B/s (100 B in 1.000s)\r\n'), 1451 (r"adb -s 0123456789abcdef shell 'rm -f \S+'", '') 1452 ], 1453 comp=re.match): 1454 self.device.TakeScreenshot('/test/host/screenshot.png') 1455 1456 1457class DeviceUtilsGetIOStatsTest(DeviceUtilsOldImplTest): 1458 1459 def testGetIOStats(self): 1460 with self.assertCalls( 1461 "adb -s 0123456789abcdef shell 'cat \"/proc/diskstats\" 2>/dev/null'", 1462 '179 0 mmcblk0 1 2 3 4 5 6 7 8 9 10 11\r\n'): 1463 self.assertEqual( 1464 { 1465 'num_reads': 1, 1466 'num_writes': 5, 1467 'read_ms': 4, 1468 'write_ms': 8, 1469 }, 1470 self.device.GetIOStats()) 1471 1472 1473class DeviceUtilsGetMemoryUsageForPidTest(DeviceUtilsOldImplTest): 1474 1475 def setUp(self): 1476 super(DeviceUtilsGetMemoryUsageForPidTest, self).setUp() 1477 self.device.old_interface._privileged_command_runner = ( 1478 self.device.old_interface.RunShellCommand) 1479 self.device.old_interface._protected_file_access_method_initialized = True 1480 1481 def testGetMemoryUsageForPid_validPid(self): 1482 with self.assertCallsSequence([ 1483 ("adb -s 0123456789abcdef shell 'showmap 1234'", 1484 '100 101 102 103 104 105 106 107 TOTAL\r\n'), 1485 ("adb -s 0123456789abcdef shell " 1486 "'cat \"/proc/1234/status\" 2> /dev/null'", 1487 'VmHWM: 1024 kB') 1488 ]): 1489 self.assertEqual( 1490 { 1491 'Size': 100, 1492 'Rss': 101, 1493 'Pss': 102, 1494 'Shared_Clean': 103, 1495 'Shared_Dirty': 104, 1496 'Private_Clean': 105, 1497 'Private_Dirty': 106, 1498 'VmHWM': 1024 1499 }, 1500 self.device.GetMemoryUsageForPid(1234)) 1501 1502 def testGetMemoryUsageForPid_invalidPid(self): 1503 with self.assertCalls( 1504 "adb -s 0123456789abcdef shell 'showmap 4321'", 1505 'cannot open /proc/4321/smaps: No such file or directory\r\n'): 1506 self.assertEqual({}, self.device.GetMemoryUsageForPid(4321)) 1507 1508 1509class DeviceUtilsStrTest(DeviceUtilsOldImplTest): 1510 def testStr_noAdbCalls(self): 1511 with self.assertNoAdbCalls(): 1512 self.assertEqual('0123456789abcdef', str(self.device)) 1513 1514 def testStr_noSerial(self): 1515 self.device = device_utils.DeviceUtils(None) 1516 with self.assertCalls('adb get-serialno', '0123456789abcdef'): 1517 self.assertEqual('0123456789abcdef', str(self.device)) 1518 1519 def testStr_noSerial_noDevices(self): 1520 self.device = device_utils.DeviceUtils(None) 1521 with self.assertCalls('adb get-serialno', 'unknown'), ( 1522 self.assertRaises(device_errors.NoDevicesError)): 1523 str(self.device) 1524 1525 1526if __name__ == '__main__': 1527 logging.getLogger().setLevel(logging.DEBUG) 1528 unittest.main(verbosity=2) 1529 1530