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""" 6Unit tests for the contents of device_utils.py (mostly DeviceUtils). 7""" 8 9# pylint: disable=protected-access 10# pylint: disable=unused-argument 11 12import collections 13import contextlib 14import io 15import json 16import logging 17import os 18import posixpath 19import stat 20import sys 21import unittest 22 23import six 24 25from devil import devil_env 26from devil.android import device_errors 27from devil.android import device_signal 28from devil.android import device_utils 29from devil.android.ndk import abis 30from devil.android.sdk import adb_wrapper 31from devil.android.sdk import intent 32from devil.android.sdk import keyevent 33from devil.android.sdk import version_codes 34from devil.utils import cmd_helper 35from devil.utils import mock_calls 36 37with devil_env.SysPath(os.path.join(devil_env.PY_UTILS_PATH)): 38 from py_utils import tempfile_ext 39 40with devil_env.SysPath(devil_env.PYMOCK_PATH): 41 import mock # pylint: disable=import-error 42 43TEST_APK_PATH = '/fake/test/app.apk' 44TEST_PACKAGE = 'test.package' 45 46 47def Process(name, pid, ppid='1'): 48 return device_utils.ProcessInfo(name=name, pid=pid, ppid=ppid) 49 50 51def Processes(*args): 52 return [Process(*arg) for arg in args] 53 54 55class AnyStringWith(object): 56 def __init__(self, value): 57 self._value = value 58 59 def __eq__(self, other): 60 return self._value in other 61 62 def __repr__(self): 63 return '<AnyStringWith: %s>' % self._value 64 65 66class _FakeContextManager(object): 67 def __init__(self, obj): 68 self._obj = obj 69 70 def __enter__(self): 71 return self._obj 72 73 def __exit__(self, type_, value, traceback): 74 pass 75 76 77class _MockApkHelper(object): 78 def __init__(self, path, package_name, perms=None, splits=None): 79 self.path = path 80 self.is_bundle = path.endswith('_bundle') 81 self.package_name = package_name 82 self.perms = perms 83 self.splits = splits if splits else [] 84 self.abis = [abis.ARM] 85 self.version_code = None 86 87 def GetPackageName(self): 88 return self.package_name 89 90 def GetPermissions(self): 91 return self.perms 92 93 def GetVersionCode(self): 94 return self.version_code 95 96 def GetAbis(self): 97 return self.abis 98 99 def GetApkPaths(self, 100 device, 101 modules=None, 102 allow_cached_props=False, 103 additional_locales=None): 104 return _FakeContextManager([self.path] + self.splits) 105 106 #override 107 @staticmethod 108 def SupportsSplits(): 109 return True 110 111 112class _MockMultipleDevicesError(Exception): 113 pass 114 115 116class DeviceUtilsInitTest(unittest.TestCase): 117 def testInitWithStr(self): 118 serial_as_str = str('0123456789abcdef') 119 d = device_utils.DeviceUtils('0123456789abcdef') 120 self.assertEqual(serial_as_str, d.adb.GetDeviceSerial()) 121 122 def testInitWithUnicode(self): 123 if six.PY2: 124 serial_as_unicode = unicode('fedcba9876543210') 125 d = device_utils.DeviceUtils(serial_as_unicode) 126 self.assertEqual(serial_as_unicode, d.adb.GetDeviceSerial()) 127 128 def testInitWithAdbWrapper(self): 129 serial = '123456789abcdef0' 130 a = adb_wrapper.AdbWrapper(serial) 131 d = device_utils.DeviceUtils(a) 132 self.assertEqual(serial, d.adb.GetDeviceSerial()) 133 134 def testInitWithMissing_fails(self): 135 with self.assertRaises(ValueError): 136 device_utils.DeviceUtils(None) 137 with self.assertRaises(ValueError): 138 device_utils.DeviceUtils('') 139 140 141class DeviceUtilsGetAVDsTest(mock_calls.TestCase): 142 def testGetAVDs(self): 143 mocked_attrs = {'android_sdk': '/my/sdk/path'} 144 with mock.patch('devil.devil_env._Environment.LocalPath', 145 mock.Mock(side_effect=lambda a: mocked_attrs[a])): 146 with self.assertCall( 147 mock.call.devil.utils.cmd_helper.GetCmdOutput( 148 [mock.ANY, 'list', 'avd']), 'Available Android Virtual Devices:\n' 149 ' Name: my_android5.0\n' 150 ' Path: /some/path/to/.android/avd/my_android5.0.avd\n' 151 ' Target: Android 5.0 (API level 21)\n' 152 ' Tag/ABI: default/x86\n' 153 ' Skin: WVGA800\n'): 154 self.assertEquals(['my_android5.0'], device_utils.GetAVDs()) 155 156 157class DeviceUtilsRestartServerTest(mock_calls.TestCase): 158 @mock.patch('time.sleep', mock.Mock()) 159 def testRestartServer_succeeds(self): 160 with self.assertCalls( 161 mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.KillServer(), 162 (mock.call.devil.utils.cmd_helper.GetCmdStatusAndOutput( 163 ['pgrep', 'adb']), (1, '')), 164 mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.StartServer(), 165 (mock.call.devil.utils.cmd_helper.GetCmdStatusAndOutput( 166 ['pgrep', 'adb']), 167 (1, '')), (mock.call.devil.utils.cmd_helper.GetCmdStatusAndOutput( 168 ['pgrep', 'adb']), (0, '123\n'))): 169 adb_wrapper.RestartServer() 170 171 172class MockTempFile(object): 173 def __init__(self, name='/tmp/some/file'): 174 self.file = mock.MagicMock(spec=io.BufferedIOBase) 175 self.file.name = name 176 self.file.name_quoted = cmd_helper.SingleQuote(name) 177 178 def __enter__(self): 179 return self.file 180 181 def __exit__(self, exc_type, exc_val, exc_tb): 182 pass 183 184 @property 185 def name(self): 186 return self.file.name 187 188 189class MockLogger(mock.Mock): 190 def __init__(self, *args, **kwargs): 191 super(MockLogger, self).__init__(*args, **kwargs) 192 self.warnings = [] 193 194 def warning(self, message, *args): 195 self.warnings.append(message % args) 196 197 198def PatchLogger(): 199 return mock.patch( 200 'devil.android.device_utils.logger', new_callable=MockLogger) 201 202 203class _PatchedFunction(object): 204 def __init__(self, patched=None, mocked=None): 205 self.patched = patched 206 self.mocked = mocked 207 208 209def _AdbWrapperMock(test_serial, is_ready=True): 210 adb = mock.Mock(spec=adb_wrapper.AdbWrapper) 211 adb.__str__ = mock.Mock(return_value=test_serial) 212 adb.GetDeviceSerial.return_value = test_serial 213 adb.is_ready = is_ready 214 return adb 215 216 217class DeviceUtilsTest(mock_calls.TestCase): 218 def setUp(self): 219 self.adb = _AdbWrapperMock('0123456789abcdef') 220 self.device = device_utils.DeviceUtils( 221 self.adb, default_timeout=10, default_retries=0) 222 self.watchMethodCalls(self.call.adb, ignore=['GetDeviceSerial']) 223 224 def safeAssertItemsEqual(self, expected, actual): 225 if six.PY2: 226 self.assertItemsEqual(expected, actual) 227 else: 228 self.assertCountEqual(expected, actual) # pylint: disable=no-member 229 230 def AdbCommandError(self, args=None, output=None, status=None, msg=None): 231 if args is None: 232 args = ['[unspecified]'] 233 return mock.Mock( 234 side_effect=device_errors.AdbCommandFailedError(args, output, status, 235 msg, str(self.device))) 236 237 def CommandError(self, msg=None): 238 if msg is None: 239 msg = 'Command failed' 240 return mock.Mock( 241 side_effect=device_errors.CommandFailedError(msg, str(self.device))) 242 243 def ShellError(self, output=None, status=1): 244 def action(cmd, *args, **kwargs): 245 raise device_errors.AdbShellCommandFailedError(cmd, output, status, 246 str(self.device)) 247 248 if output is None: 249 output = 'Permission denied\n' 250 return action 251 252 def TimeoutError(self, msg=None): 253 if msg is None: 254 msg = 'Operation timed out' 255 return mock.Mock( 256 side_effect=device_errors.CommandTimeoutError(msg, str(self.device))) 257 258 def EnsureCacheInitialized(self, props=None, sdcard='/sdcard'): 259 props = props or [] 260 ret = [sdcard, 'TOKEN'] + props 261 return (self.call.device.RunShellCommand( 262 AnyStringWith('getprop'), 263 shell=True, 264 check_return=True, 265 large_output=True), ret) 266 267 268class DeviceUtilsEqTest(DeviceUtilsTest): 269 def testEq_equal_deviceUtils(self): 270 other = device_utils.DeviceUtils(_AdbWrapperMock('0123456789abcdef')) 271 self.assertTrue(self.device == other) 272 self.assertTrue(other == self.device) 273 274 def testEq_equal_adbWrapper(self): 275 other = adb_wrapper.AdbWrapper('0123456789abcdef') 276 self.assertTrue(self.device == other) 277 self.assertTrue(other == self.device) 278 279 def testEq_equal_string(self): 280 other = '0123456789abcdef' 281 self.assertTrue(self.device == other) 282 self.assertTrue(other == self.device) 283 284 def testEq_devicesNotEqual(self): 285 other = device_utils.DeviceUtils(_AdbWrapperMock('0123456789abcdee')) 286 self.assertFalse(self.device == other) 287 self.assertFalse(other == self.device) 288 289 def testEq_identity(self): 290 self.assertTrue(self.device == self.device) 291 292 def testEq_serialInList(self): 293 devices = [self.device] 294 self.assertTrue('0123456789abcdef' in devices) 295 296 297class DeviceUtilsLtTest(DeviceUtilsTest): 298 def testLt_lessThan(self): 299 other = device_utils.DeviceUtils(_AdbWrapperMock('ffffffffffffffff')) 300 self.assertTrue(self.device < other) 301 self.assertTrue(other > self.device) 302 303 def testLt_greaterThan_lhs(self): 304 other = device_utils.DeviceUtils(_AdbWrapperMock('0000000000000000')) 305 self.assertFalse(self.device < other) 306 self.assertFalse(other > self.device) 307 308 def testLt_equal(self): 309 other = device_utils.DeviceUtils(_AdbWrapperMock('0123456789abcdef')) 310 self.assertFalse(self.device < other) 311 self.assertFalse(other > self.device) 312 313 def testLt_sorted(self): 314 devices = [ 315 device_utils.DeviceUtils(_AdbWrapperMock('ffffffffffffffff')), 316 device_utils.DeviceUtils(_AdbWrapperMock('0000000000000000')), 317 ] 318 sorted_devices = sorted(devices) 319 self.assertEquals('0000000000000000', 320 sorted_devices[0].adb.GetDeviceSerial()) 321 self.assertEquals('ffffffffffffffff', 322 sorted_devices[1].adb.GetDeviceSerial()) 323 324 325class DeviceUtilsStrTest(DeviceUtilsTest): 326 def testStr_returnsSerial(self): 327 with self.assertCalls((self.call.adb.GetDeviceSerial(), 328 '0123456789abcdef')): 329 self.assertEqual('0123456789abcdef', str(self.device)) 330 331 332class DeviceUtilsIsOnlineTest(DeviceUtilsTest): 333 def testIsOnline_true(self): 334 with self.assertCall(self.call.adb.GetState(), 'device'): 335 self.assertTrue(self.device.IsOnline()) 336 337 def testIsOnline_false(self): 338 with self.assertCall(self.call.adb.GetState(), 'offline'): 339 self.assertFalse(self.device.IsOnline()) 340 341 def testIsOnline_error(self): 342 with self.assertCall(self.call.adb.GetState(), self.CommandError()): 343 self.assertFalse(self.device.IsOnline()) 344 345 346class DeviceUtilsHasRootTest(DeviceUtilsTest): 347 def testHasRoot_true(self): 348 with self.patch_call(self.call.device.build_type, 349 return_value='userdebug'), (self.assertCall( 350 self.call.adb.Shell('id'), 'uid=0(root)\n')): 351 self.assertTrue(self.device.HasRoot()) 352 353 def testHasRootEngBuild_true(self): 354 with self.patch_call(self.call.device.build_type, return_value='eng'): 355 self.assertTrue(self.device.HasRoot()) 356 357 def testHasRoot_false(self): 358 with self.patch_call(self.call.device.build_type, 359 return_value='userdebug'), (self.assertCall( 360 self.call.adb.Shell('id'), 'uid=2000(shell)\n')): 361 self.assertFalse(self.device.HasRoot()) 362 363 364class DeviceUtilsEnableRootTest(DeviceUtilsTest): 365 def testEnableRoot_succeeds(self): 366 with self.assertCalls(self.call.adb.Root(), self.call.adb.WaitForDevice(), 367 (self.call.device.HasRoot(), True)): 368 self.device.EnableRoot() 369 370 def testEnableRoot_userBuild(self): 371 with self.assertCalls((self.call.adb.Root(), self.AdbCommandError()), 372 (self.call.device.IsUserBuild(), True)): 373 with self.assertRaises(device_errors.CommandFailedError): 374 self.device.EnableRoot() 375 376 def testEnableRoot_rootFails(self): 377 with self.assertCalls((self.call.adb.Root(), self.AdbCommandError()), 378 (self.call.device.IsUserBuild(), False)): 379 with self.assertRaises(device_errors.AdbCommandFailedError): 380 self.device.EnableRoot() 381 382 def testEnableRoot_timeoutInWaitForDevice(self): 383 with self.assertCalls( 384 (self.call.adb.Root(), 385 self.AdbCommandError( 386 output='timeout expired while waiting for device')), 387 (self.call.device.IsUserBuild(), False), self.call.adb.WaitForDevice(), 388 (self.call.device.HasRoot(), True)): 389 self.device.EnableRoot() 390 391 392class DeviceUtilsIsUserBuildTest(DeviceUtilsTest): 393 def testIsUserBuild_yes(self): 394 with self.assertCall( 395 self.call.device.GetProp('ro.build.type', cache=True), 'user'): 396 self.assertTrue(self.device.IsUserBuild()) 397 398 def testIsUserBuild_no(self): 399 with self.assertCall( 400 self.call.device.GetProp('ro.build.type', cache=True), 'userdebug'): 401 self.assertFalse(self.device.IsUserBuild()) 402 403 404class DeviceUtilsGetExternalStoragePathTest(DeviceUtilsTest): 405 def testGetExternalStoragePath_succeeds(self): 406 with self.assertCalls( 407 self.EnsureCacheInitialized(sdcard='/fake/storage/path')): 408 self.assertEquals('/fake/storage/path', 409 self.device.GetExternalStoragePath()) 410 411 def testGetExternalStoragePath_fails(self): 412 with self.assertCalls(self.EnsureCacheInitialized(sdcard='')): 413 with self.assertRaises(device_errors.CommandFailedError): 414 self.device.GetExternalStoragePath() 415 416 417class DeviceUtilsGetAppWritablePathTest(DeviceUtilsTest): 418 def testGetAppWritablePath_succeeds_sdk_pre_q(self): 419 with self.assertCalls( 420 (self.call.device.GetProp('ro.build.version.sdk', cache=True), '28'), 421 self.EnsureCacheInitialized(sdcard='/fake/storage/path')): 422 self.assertEquals('/fake/storage/path', 423 self.device.GetAppWritablePath()) 424 425 def testGetAppWritablePath_succeeds_sdk_q(self): 426 with self.assertCalls( 427 (self.call.device.GetProp('ro.build.version.sdk', cache=True), '29'), 428 self.EnsureCacheInitialized(sdcard='/fake/storage/path')): 429 self.assertEquals('/fake/storage/path/Download', 430 self.device.GetAppWritablePath()) 431 432 def testGetAppWritablePath_fails(self): 433 with self.assertCalls( 434 (self.call.device.GetProp('ro.build.version.sdk', cache=True), '29'), 435 self.EnsureCacheInitialized(sdcard='')): 436 with self.assertRaises(device_errors.CommandFailedError): 437 self.device.GetAppWritablePath() 438 439 440class DeviceUtilsIsApplicationInstalledTest(DeviceUtilsTest): 441 def testIsApplicationInstalled_installed(self): 442 with self.assertCalls((self.call.device.RunShellCommand( 443 ['pm', 'list', 'packages', 'some.installed.app'], check_return=True), 444 ['package:some.installed.app'])): 445 self.assertTrue(self.device.IsApplicationInstalled('some.installed.app')) 446 447 def testIsApplicationInstalled_notInstalled(self): 448 with self.assertCalls( 449 (self.call.device.RunShellCommand( 450 ['pm', 'list', 'packages', 'not.installed.app'], check_return=True), 451 ''), 452 (self.call.device.RunShellCommand( 453 ['dumpsys', 'package'], check_return=True, large_output=True), [])): 454 self.assertFalse(self.device.IsApplicationInstalled('not.installed.app')) 455 456 def testIsApplicationInstalled_substringMatch(self): 457 with self.assertCalls( 458 (self.call.device.RunShellCommand( 459 ['pm', 'list', 'packages', 'substring.of.package'], 460 check_return=True), 461 [ 462 'package:first.substring.of.package', 463 'package:second.substring.of.package', 464 ]), 465 (self.call.device.RunShellCommand( 466 ['dumpsys', 'package'], check_return=True, large_output=True), [])): 467 self.assertFalse( 468 self.device.IsApplicationInstalled('substring.of.package')) 469 470 def testIsApplicationInstalled_dumpsysFallback(self): 471 with self.assertCalls( 472 (self.call.device.RunShellCommand( 473 ['pm', 'list', 'packages', 'some.installed.app'], 474 check_return=True), []), 475 (self.call.device.RunShellCommand( 476 ['dumpsys', 'package'], check_return=True, large_output=True), 477 ['Package [some.installed.app] (a12345):'])): 478 self.assertTrue(self.device.IsApplicationInstalled('some.installed.app')) 479 480 def testIsApplicationInstalled_dumpsysFallbackVersioned(self): 481 with self.assertCalls( 482 (self.call.device.RunShellCommand( 483 ['dumpsys', 'package'], check_return=True, large_output=True), 484 ['Package [some.installed.app_1234] (a12345):'])): 485 self.assertTrue( 486 self.device.IsApplicationInstalled('some.installed.app', 1234)) 487 488 def testIsApplicationInstalled_dumpsysFallbackVersionNotNeeded(self): 489 with self.assertCalls( 490 (self.call.device.RunShellCommand( 491 ['dumpsys', 'package'], check_return=True, large_output=True), 492 ['Package [some.installed.app] (a12345):'])): 493 self.assertTrue( 494 self.device.IsApplicationInstalled('some.installed.app', 1234)) 495 496 497class DeviceUtilsGetApplicationPathsInternalTest(DeviceUtilsTest): 498 def testGetApplicationPathsInternal_exists(self): 499 with self.assertCalls( 500 (self.call.device.GetProp('ro.build.version.sdk', cache=True), '19'), 501 (self.call.device.RunShellCommand(['pm', 'path', 'android'], 502 check_return=True), 503 ['package:/path/to/android.apk'])): 504 self.assertEquals(['/path/to/android.apk'], 505 self.device._GetApplicationPathsInternal('android')) 506 507 def testGetApplicationPathsInternal_notExists(self): 508 with self.assertCalls( 509 (self.call.device.GetProp('ro.build.version.sdk', cache=True), '19'), 510 (self.call.device.RunShellCommand(['pm', 'path', 'not.installed.app'], 511 check_return=True), '')): 512 self.assertEquals( 513 [], self.device._GetApplicationPathsInternal('not.installed.app')) 514 515 def testGetApplicationPathsInternal_garbageOutputRaises(self): 516 with self.assertCalls( 517 (self.call.device.GetProp('ro.build.version.sdk', cache=True), '19'), 518 (self.call.device.RunShellCommand(['pm', 'path', 'android'], 519 check_return=True), 520 ['garbage first line'])): 521 with self.assertRaises(device_errors.CommandFailedError): 522 self.device._GetApplicationPathsInternal('android') 523 524 def testGetApplicationPathsInternal_outputWarningsIgnored(self): 525 with self.assertCalls( 526 (self.call.device.GetProp('ro.build.version.sdk', cache=True), '19'), 527 (self.call.device.RunShellCommand(['pm', 'path', 'not.installed.app'], 528 check_return=True), 529 ['WARNING: some warning message from pm'])): 530 self.assertEquals( 531 [], self.device._GetApplicationPathsInternal('not.installed.app')) 532 533 def testGetApplicationPathsInternal_fails(self): 534 with self.assertCalls( 535 (self.call.device.GetProp('ro.build.version.sdk', cache=True), '19'), 536 (self.call.device.RunShellCommand(['pm', 'path', 'android'], 537 check_return=True), 538 self.CommandError('ERROR. Is package manager running?\n'))): 539 with self.assertRaises(device_errors.CommandFailedError): 540 self.device._GetApplicationPathsInternal('android') 541 542 543class DeviceUtils_GetApplicationVersionTest(DeviceUtilsTest): 544 def test_GetApplicationVersion_exists(self): 545 with self.assertCalls( 546 (self.call.adb.Shell('dumpsys package com.android.chrome'), 547 'Packages:\n' 548 ' Package [com.android.chrome] (3901ecfb):\n' 549 ' userId=1234 gids=[123, 456, 789]\n' 550 ' pkg=Package{1fecf634 com.android.chrome}\n' 551 ' versionName=45.0.1234.7\n')): 552 self.assertEquals('45.0.1234.7', 553 self.device.GetApplicationVersion('com.android.chrome')) 554 555 def test_GetApplicationVersion_notExists(self): 556 with self.assertCalls( 557 (self.call.adb.Shell('dumpsys package com.android.chrome'), '')): 558 self.assertEquals(None, 559 self.device.GetApplicationVersion('com.android.chrome')) 560 561 def test_GetApplicationVersion_fails(self): 562 with self.assertCalls( 563 (self.call.adb.Shell('dumpsys package com.android.chrome'), 564 'Packages:\n' 565 ' Package [com.android.chrome] (3901ecfb):\n' 566 ' userId=1234 gids=[123, 456, 789]\n' 567 ' pkg=Package{1fecf634 com.android.chrome}\n')): 568 with self.assertRaises(device_errors.CommandFailedError): 569 self.device.GetApplicationVersion('com.android.chrome') 570 571 572class DeviceUtils_GetApplicationTargetSdkTest(DeviceUtilsTest): 573 def test_GetApplicationTargetSdk_exists(self): 574 with self.assertCalls( 575 (self.call.device.IsApplicationInstalled('com.android.chrome'), True), 576 (self.call.device._GetDumpsysOutput(['package', 'com.android.chrome'], 577 'targetSdk='), 578 [' versionCode=413200001 minSdk=21 targetSdk=29'])): 579 self.assertEquals( 580 '29', self.device.GetApplicationTargetSdk('com.android.chrome')) 581 582 def test_GetApplicationTargetSdk_notExists(self): 583 with self.assertCalls( 584 (self.call.device.IsApplicationInstalled('com.android.chrome'), False)): 585 self.assertIsNone( 586 self.device.GetApplicationTargetSdk('com.android.chrome')) 587 588 def test_GetApplicationTargetSdk_fails(self): 589 with self.assertCalls( 590 (self.call.device.IsApplicationInstalled('com.android.chrome'), True), 591 (self.call.device._GetDumpsysOutput(['package', 'com.android.chrome'], 592 'targetSdk='), [])): 593 with self.assertRaises(device_errors.CommandFailedError): 594 self.device.GetApplicationTargetSdk('com.android.chrome') 595 596 def test_GetApplicationTargetSdk_prefinalizedSdk(self): 597 with self.assertCalls( 598 (self.call.device.IsApplicationInstalled('com.android.chrome'), True), 599 (self.call.device._GetDumpsysOutput(['package', 'com.android.chrome'], 600 'targetSdk='), 601 [' versionCode=410301483 minSdk=10000 targetSdk=10000']), 602 (self.call.device.GetProp('ro.build.version.codename', 603 cache=True), 'R')): 604 self.assertEquals( 605 'R', self.device.GetApplicationTargetSdk('com.android.chrome')) 606 607 608class DeviceUtils_GetPackageArchitectureTest(DeviceUtilsTest): 609 def test_GetPackageArchitecture_exists(self): 610 with self.assertCall( 611 self.call.device._RunPipedShellCommand( 612 'dumpsys package com.android.chrome | grep -F primaryCpuAbi'), 613 [' primaryCpuAbi=armeabi-v7a']): 614 self.assertEquals( 615 abis.ARM, self.device.GetPackageArchitecture('com.android.chrome')) 616 617 def test_GetPackageArchitecture_notExists(self): 618 with self.assertCall( 619 self.call.device._RunPipedShellCommand( 620 'dumpsys package com.android.chrome | grep -F primaryCpuAbi'), []): 621 self.assertEquals( 622 None, self.device.GetPackageArchitecture('com.android.chrome')) 623 624 625class DeviceUtilsGetApplicationDataDirectoryTest(DeviceUtilsTest): 626 def testGetApplicationDataDirectory_exists(self): 627 with self.assertCalls( 628 (self.call.device.IsApplicationInstalled('foo.bar.baz'), True), 629 (self.call.device._RunPipedShellCommand( 630 'pm dump foo.bar.baz | grep dataDir='), 631 ['dataDir=/data/data/foo.bar.baz'])): 632 self.assertEquals('/data/data/foo.bar.baz', 633 self.device.GetApplicationDataDirectory('foo.bar.baz')) 634 635 def testGetApplicationDataDirectory_notInstalled(self): 636 with self.assertCalls( 637 (self.call.device.IsApplicationInstalled('foo.bar.baz'), False)): 638 with self.assertRaises(device_errors.CommandFailedError): 639 self.device.GetApplicationDataDirectory('foo.bar.baz') 640 641 def testGetApplicationDataDirectory_notExists(self): 642 with self.assertCalls( 643 (self.call.device.IsApplicationInstalled('foo.bar.baz'), True), 644 (self.call.device._RunPipedShellCommand( 645 'pm dump foo.bar.baz | grep dataDir='), self.ShellError())): 646 with self.assertRaises(device_errors.CommandFailedError): 647 self.device.GetApplicationDataDirectory('foo.bar.baz') 648 649 650@mock.patch('time.sleep', mock.Mock()) 651class DeviceUtilsWaitUntilFullyBootedTest(DeviceUtilsTest): 652 def testWaitUntilFullyBooted_succeedsWithDefaults(self): 653 with self.assertCalls( 654 self.call.adb.WaitForDevice(), 655 # sd_card_ready 656 (self.call.device.GetExternalStoragePath(), '/fake/storage/path'), 657 (self.call.adb.Shell('test -d /fake/storage/path'), ''), 658 # pm_ready 659 (self.call.device._GetApplicationPathsInternal( 660 'android', skip_cache=True), ['package:/some/fake/path']), 661 # boot_completed 662 (self.call.device.GetProp('sys.boot_completed', cache=False), '1')): 663 self.device.WaitUntilFullyBooted(wifi=False, decrypt=False) 664 665 def testWaitUntilFullyBooted_succeedsWithWifi(self): 666 with self.assertCalls( 667 self.call.adb.WaitForDevice(), 668 # sd_card_ready 669 (self.call.device.GetExternalStoragePath(), '/fake/storage/path'), 670 (self.call.adb.Shell('test -d /fake/storage/path'), ''), 671 # pm_ready 672 (self.call.device._GetApplicationPathsInternal( 673 'android', skip_cache=True), ['package:/some/fake/path']), 674 # boot_completed 675 (self.call.device.GetProp('sys.boot_completed', cache=False), '1'), 676 # wifi_enabled 677 (self.call.adb.Shell('dumpsys wifi'), 678 'stuff\nWi-Fi is enabled\nmore stuff\n')): 679 self.device.WaitUntilFullyBooted(wifi=True, decrypt=False) 680 681 def testWaitUntilFullyBooted_succeedsWithDecryptFDE(self): 682 with self.assertCalls( 683 self.call.adb.WaitForDevice(), 684 # sd_card_ready 685 (self.call.device.GetExternalStoragePath(), '/fake/storage/path'), 686 (self.call.adb.Shell('test -d /fake/storage/path'), ''), 687 # pm_ready 688 (self.call.device._GetApplicationPathsInternal( 689 'android', skip_cache=True), ['package:/some/fake/path']), 690 # boot_completed 691 (self.call.device.GetProp('sys.boot_completed', cache=False), '1'), 692 # decryption_completed 693 (self.call.device.GetProp('vold.decrypt', cache=False), 694 'trigger_restart_framework')): 695 self.device.WaitUntilFullyBooted(wifi=False, decrypt=True) 696 697 def testWaitUntilFullyBooted_succeedsWithDecryptNotFDE(self): 698 with self.assertCalls( 699 self.call.adb.WaitForDevice(), 700 # sd_card_ready 701 (self.call.device.GetExternalStoragePath(), '/fake/storage/path'), 702 (self.call.adb.Shell('test -d /fake/storage/path'), ''), 703 # pm_ready 704 (self.call.device._GetApplicationPathsInternal( 705 'android', skip_cache=True), ['package:/some/fake/path']), 706 # boot_completed 707 (self.call.device.GetProp('sys.boot_completed', cache=False), '1'), 708 # decryption_completed 709 (self.call.device.GetProp('vold.decrypt', cache=False), '')): 710 self.device.WaitUntilFullyBooted(wifi=False, decrypt=True) 711 712 def testWaitUntilFullyBooted_deviceNotInitiallyAvailable(self): 713 with self.assertCalls( 714 self.call.adb.WaitForDevice(), 715 # sd_card_ready 716 (self.call.device.GetExternalStoragePath(), self.AdbCommandError()), 717 # sd_card_ready 718 (self.call.device.GetExternalStoragePath(), self.AdbCommandError()), 719 # sd_card_ready 720 (self.call.device.GetExternalStoragePath(), self.AdbCommandError()), 721 # sd_card_ready 722 (self.call.device.GetExternalStoragePath(), self.AdbCommandError()), 723 # sd_card_ready 724 (self.call.device.GetExternalStoragePath(), '/fake/storage/path'), 725 (self.call.adb.Shell('test -d /fake/storage/path'), ''), 726 # pm_ready 727 (self.call.device._GetApplicationPathsInternal( 728 'android', skip_cache=True), ['package:/some/fake/path']), 729 # boot_completed 730 (self.call.device.GetProp('sys.boot_completed', cache=False), '1')): 731 self.device.WaitUntilFullyBooted(wifi=False, decrypt=False) 732 733 def testWaitUntilFullyBooted_deviceBrieflyOffline(self): 734 with self.assertCalls( 735 self.call.adb.WaitForDevice(), 736 # sd_card_ready 737 (self.call.device.GetExternalStoragePath(), '/fake/storage/path'), 738 (self.call.adb.Shell('test -d /fake/storage/path'), ''), 739 # pm_ready 740 (self.call.device._GetApplicationPathsInternal( 741 'android', skip_cache=True), ['package:/some/fake/path']), 742 # boot_completed 743 (self.call.device.GetProp('sys.boot_completed', cache=False), 744 self.AdbCommandError()), 745 # boot_completed 746 (self.call.device.GetProp('sys.boot_completed', cache=False), '1')): 747 self.device.WaitUntilFullyBooted(wifi=False, decrypt=False) 748 749 def testWaitUntilFullyBooted_sdCardReadyFails_noPath(self): 750 with self.assertCalls( 751 self.call.adb.WaitForDevice(), 752 # sd_card_ready 753 (self.call.device.GetExternalStoragePath(), self.CommandError())): 754 with self.assertRaises(device_errors.CommandFailedError): 755 self.device.WaitUntilFullyBooted(wifi=False, decrypt=False) 756 757 def testWaitUntilFullyBooted_sdCardReadyFails_notExists(self): 758 with self.assertCalls( 759 self.call.adb.WaitForDevice(), 760 # sd_card_ready 761 (self.call.device.GetExternalStoragePath(), '/fake/storage/path'), 762 (self.call.adb.Shell('test -d /fake/storage/path'), self.ShellError()), 763 # sd_card_ready 764 (self.call.device.GetExternalStoragePath(), '/fake/storage/path'), 765 (self.call.adb.Shell('test -d /fake/storage/path'), self.ShellError()), 766 # sd_card_ready 767 (self.call.device.GetExternalStoragePath(), '/fake/storage/path'), 768 (self.call.adb.Shell('test -d /fake/storage/path'), 769 self.TimeoutError())): 770 with self.assertRaises(device_errors.CommandTimeoutError): 771 self.device.WaitUntilFullyBooted(wifi=False, decrypt=False) 772 773 def testWaitUntilFullyBooted_devicePmFails(self): 774 with self.assertCalls( 775 self.call.adb.WaitForDevice(), 776 # sd_card_ready 777 (self.call.device.GetExternalStoragePath(), '/fake/storage/path'), 778 (self.call.adb.Shell('test -d /fake/storage/path'), ''), 779 # pm_ready 780 (self.call.device._GetApplicationPathsInternal( 781 'android', skip_cache=True), self.CommandError()), 782 # pm_ready 783 (self.call.device._GetApplicationPathsInternal( 784 'android', skip_cache=True), self.CommandError()), 785 # pm_ready 786 (self.call.device._GetApplicationPathsInternal( 787 'android', skip_cache=True), self.TimeoutError())): 788 with self.assertRaises(device_errors.CommandTimeoutError): 789 self.device.WaitUntilFullyBooted(wifi=False, decrypt=False) 790 791 def testWaitUntilFullyBooted_bootFails(self): 792 with self.assertCalls( 793 self.call.adb.WaitForDevice(), 794 # sd_card_ready 795 (self.call.device.GetExternalStoragePath(), '/fake/storage/path'), 796 (self.call.adb.Shell('test -d /fake/storage/path'), ''), 797 # pm_ready 798 (self.call.device._GetApplicationPathsInternal( 799 'android', skip_cache=True), ['package:/some/fake/path']), 800 # boot_completed 801 (self.call.device.GetProp('sys.boot_completed', cache=False), '0'), 802 # boot_completed 803 (self.call.device.GetProp('sys.boot_completed', cache=False), '0'), 804 # boot_completed 805 (self.call.device.GetProp('sys.boot_completed', cache=False), 806 self.TimeoutError())): 807 with self.assertRaises(device_errors.CommandTimeoutError): 808 self.device.WaitUntilFullyBooted(wifi=False, decrypt=False) 809 810 def testWaitUntilFullyBooted_wifiFails(self): 811 with self.assertCalls( 812 self.call.adb.WaitForDevice(), 813 # sd_card_ready 814 (self.call.device.GetExternalStoragePath(), '/fake/storage/path'), 815 (self.call.adb.Shell('test -d /fake/storage/path'), ''), 816 # pm_ready 817 (self.call.device._GetApplicationPathsInternal( 818 'android', skip_cache=True), ['package:/some/fake/path']), 819 # boot_completed 820 (self.call.device.GetProp('sys.boot_completed', cache=False), '1'), 821 # wifi_enabled 822 (self.call.adb.Shell('dumpsys wifi'), 'stuff\nmore stuff\n'), 823 # wifi_enabled 824 (self.call.adb.Shell('dumpsys wifi'), 'stuff\nmore stuff\n'), 825 # wifi_enabled 826 (self.call.adb.Shell('dumpsys wifi'), self.TimeoutError())): 827 with self.assertRaises(device_errors.CommandTimeoutError): 828 self.device.WaitUntilFullyBooted(wifi=True, decrypt=False) 829 830 def testWaitUntilFullyBooted_decryptFails(self): 831 with self.assertCalls( 832 self.call.adb.WaitForDevice(), 833 # sd_card_ready 834 (self.call.device.GetExternalStoragePath(), '/fake/storage/path'), 835 (self.call.adb.Shell('test -d /fake/storage/path'), ''), 836 # pm_ready 837 (self.call.device._GetApplicationPathsInternal( 838 'android', skip_cache=True), ['package:/some/fake/path']), 839 # boot_completed 840 (self.call.device.GetProp('sys.boot_completed', cache=False), '1'), 841 # decryption_completed 842 (self.call.device.GetProp('vold.decrypt', cache=False), 843 'trigger_restart_min_framework'), 844 # decryption_completed 845 (self.call.device.GetProp('vold.decrypt', cache=False), 846 'trigger_restart_min_framework'), 847 # decryption_completed 848 (self.call.device.GetProp('vold.decrypt', cache=False), 849 self.TimeoutError())): 850 with self.assertRaises(device_errors.CommandTimeoutError): 851 self.device.WaitUntilFullyBooted(wifi=False, decrypt=True) 852 853 854@mock.patch('time.sleep', mock.Mock()) 855class DeviceUtilsRebootTest(DeviceUtilsTest): 856 def testReboot_nonBlocking(self): 857 with self.assertCalls(self.call.adb.Reboot(), 858 (self.call.device.IsOnline(), True), 859 (self.call.device.IsOnline(), False)): 860 self.device.Reboot(block=False) 861 862 def testReboot_blocking(self): 863 with self.assertCalls( 864 (self.call.device.HasRoot(), False), 865 self.call.adb.Reboot(), (self.call.device.IsOnline(), True), 866 (self.call.device.IsOnline(), False), 867 self.call.device.WaitUntilFullyBooted(wifi=False, decrypt=False)): 868 self.device.Reboot(block=True) 869 870 def testReboot_blockingWithRoot(self): 871 with self.assertCalls( 872 (self.call.device.HasRoot(), True), 873 self.call.adb.Reboot(), (self.call.device.IsOnline(), True), 874 (self.call.device.IsOnline(), False), 875 self.call.device.WaitUntilFullyBooted(wifi=False, decrypt=False), 876 self.call.device.EnableRoot()): 877 self.device.Reboot(block=True) 878 879 def testReboot_blockUntilWifi(self): 880 with self.assertCalls( 881 (self.call.device.HasRoot(), False), 882 self.call.adb.Reboot(), (self.call.device.IsOnline(), True), 883 (self.call.device.IsOnline(), False), 884 self.call.device.WaitUntilFullyBooted(wifi=True, decrypt=False)): 885 self.device.Reboot(block=True, wifi=True, decrypt=False) 886 887 def testReboot_blockUntilDecrypt(self): 888 with self.assertCalls( 889 (self.call.device.HasRoot(), False), 890 self.call.adb.Reboot(), (self.call.device.IsOnline(), True), 891 (self.call.device.IsOnline(), False), 892 self.call.device.WaitUntilFullyBooted(wifi=False, decrypt=True)): 893 self.device.Reboot(block=True, wifi=False, decrypt=True) 894 895 896class DeviceUtilsInstallTest(DeviceUtilsTest): 897 898 mock_apk = _MockApkHelper(TEST_APK_PATH, TEST_PACKAGE, ['p1']) 899 900 def testInstall_noPriorInstall(self): 901 with self.patch_call( 902 self.call.device.product_name, 903 return_value='notflounder'), (self.patch_call( 904 self.call.device.build_version_sdk, return_value=23)): 905 with self.assertCalls( 906 (self.call.device._FakeInstall(set(), None, 'test.package')), 907 (mock.call.os.path.exists(TEST_APK_PATH), True), 908 (self.call.device._GetApplicationPathsInternal(TEST_PACKAGE), []), 909 self.call.adb.Install(TEST_APK_PATH, 910 reinstall=False, 911 streaming=None, 912 allow_downgrade=False), 913 (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True), 914 (self.call.device.GrantPermissions(TEST_PACKAGE, ['p1']), [])): 915 self.device.Install(DeviceUtilsInstallTest.mock_apk, retries=0) 916 917 def testInstall_noStreaming(self): 918 with self.patch_call( 919 self.call.device.product_name, 920 return_value='flounder'), (self.patch_call( 921 self.call.device.build_version_sdk, return_value=23)): 922 with self.assertCalls( 923 (self.call.device._FakeInstall(set(), None, 'test.package')), 924 (mock.call.os.path.exists(TEST_APK_PATH), True), 925 (self.call.device._GetApplicationPathsInternal(TEST_PACKAGE), []), 926 self.call.adb.Install(TEST_APK_PATH, 927 reinstall=False, 928 streaming=False, 929 allow_downgrade=False), 930 (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True), 931 (self.call.device.GrantPermissions(TEST_PACKAGE, ['p1']), [])): 932 self.device.Install(DeviceUtilsInstallTest.mock_apk, retries=0) 933 934 def testInstall_permissionsPreM(self): 935 with self.patch_call( 936 self.call.device.product_name, 937 return_value='notflounder'), (self.patch_call( 938 self.call.device.build_version_sdk, return_value=20)): 939 with self.assertCalls( 940 (self.call.device._FakeInstall(set(), None, 'test.package')), 941 (mock.call.os.path.exists(TEST_APK_PATH), True), 942 (self.call.device._GetApplicationPathsInternal(TEST_PACKAGE), []), 943 (self.call.adb.Install(TEST_APK_PATH, 944 reinstall=False, 945 streaming=None, 946 allow_downgrade=False)), 947 (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True)): 948 self.device.Install(DeviceUtilsInstallTest.mock_apk, retries=0) 949 950 def testInstall_findPermissions(self): 951 with self.patch_call( 952 self.call.device.product_name, 953 return_value='notflounder'), (self.patch_call( 954 self.call.device.build_version_sdk, return_value=23)): 955 with self.assertCalls( 956 (self.call.device._FakeInstall(set(), None, 'test.package')), 957 (mock.call.os.path.exists(TEST_APK_PATH), True), 958 (self.call.device._GetApplicationPathsInternal(TEST_PACKAGE), []), 959 (self.call.adb.Install(TEST_APK_PATH, 960 reinstall=False, 961 streaming=None, 962 allow_downgrade=False)), 963 (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True), 964 (self.call.device.GrantPermissions(TEST_PACKAGE, ['p1']), [])): 965 self.device.Install(DeviceUtilsInstallTest.mock_apk, retries=0) 966 967 def testInstall_passPermissions(self): 968 with self.patch_call( 969 self.call.device.product_name, return_value='notflounder'): 970 with self.assertCalls( 971 (self.call.device._FakeInstall(set(), None, 'test.package')), 972 (mock.call.os.path.exists(TEST_APK_PATH), True), 973 (self.call.device._GetApplicationPathsInternal(TEST_PACKAGE), []), 974 (self.call.adb.Install(TEST_APK_PATH, 975 reinstall=False, 976 streaming=None, 977 allow_downgrade=False)), 978 (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True), 979 (self.call.device.GrantPermissions(TEST_PACKAGE, ['p1', 'p2']), [])): 980 self.device.Install( 981 DeviceUtilsInstallTest.mock_apk, 982 retries=0, 983 permissions=['p1', 'p2']) 984 985 def testInstall_identicalPriorInstall(self): 986 with self.assertCalls( 987 (self.call.device._FakeInstall(set(), None, 'test.package')), 988 (mock.call.os.path.exists(TEST_APK_PATH), True), 989 (self.call.device._GetApplicationPathsInternal(TEST_PACKAGE), 990 ['/fake/data/app/test.package.apk']), 991 (self.call.device._ComputeStaleApks(TEST_PACKAGE, [TEST_APK_PATH]), 992 ([], None)), (self.call.device.ForceStop(TEST_PACKAGE)), 993 (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True)): 994 self.device.Install( 995 DeviceUtilsInstallTest.mock_apk, retries=0, permissions=[]) 996 997 def testInstall_differentPriorInstall(self): 998 with self.patch_call( 999 self.call.device.product_name, return_value='notflounder'): 1000 with self.assertCalls( 1001 (self.call.device._FakeInstall(set(), None, 'test.package')), 1002 (mock.call.os.path.exists(TEST_APK_PATH), True), 1003 (self.call.device._GetApplicationPathsInternal(TEST_PACKAGE), 1004 ['/fake/data/app/test.package.apk']), 1005 (self.call.device._ComputeStaleApks(TEST_PACKAGE, [TEST_APK_PATH]), 1006 ([TEST_APK_PATH], None)), self.call.device.Uninstall(TEST_PACKAGE), 1007 self.call.adb.Install(TEST_APK_PATH, 1008 reinstall=False, 1009 streaming=None, 1010 allow_downgrade=False), 1011 (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True)): 1012 self.device.Install( 1013 DeviceUtilsInstallTest.mock_apk, retries=0, permissions=[]) 1014 1015 def testInstall_differentPriorInstallSplitApk(self): 1016 with self.patch_call( 1017 self.call.device.product_name, return_value='notflounder'): 1018 with self.assertCalls( 1019 (self.call.device._FakeInstall(set(), None, 'test.package')), 1020 (mock.call.os.path.exists(TEST_APK_PATH), True), 1021 (self.call.device._GetApplicationPathsInternal(TEST_PACKAGE), [ 1022 '/fake/data/app/test.package.apk', 1023 '/fake/data/app/test.package2.apk' 1024 ]), self.call.device.Uninstall(TEST_PACKAGE), 1025 self.call.adb.Install(TEST_APK_PATH, 1026 reinstall=False, 1027 streaming=None, 1028 allow_downgrade=False), 1029 (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True)): 1030 self.device.Install( 1031 DeviceUtilsInstallTest.mock_apk, retries=0, permissions=[]) 1032 1033 def testInstall_differentPriorInstall_reinstall(self): 1034 with self.patch_call( 1035 self.call.device.product_name, return_value='notflounder'): 1036 with self.assertCalls( 1037 (self.call.device._FakeInstall(set(), None, 'test.package')), 1038 (mock.call.os.path.exists(TEST_APK_PATH), True), 1039 (self.call.device._GetApplicationPathsInternal(TEST_PACKAGE), 1040 ['/fake/data/app/test.package.apk']), 1041 (self.call.device._ComputeStaleApks(TEST_PACKAGE, [TEST_APK_PATH]), 1042 ([TEST_APK_PATH], None)), 1043 self.call.adb.Install(TEST_APK_PATH, 1044 reinstall=True, 1045 streaming=None, 1046 allow_downgrade=False), 1047 (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True)): 1048 self.device.Install( 1049 DeviceUtilsInstallTest.mock_apk, 1050 reinstall=True, 1051 retries=0, 1052 permissions=[]) 1053 1054 def testInstall_identicalPriorInstall_reinstall(self): 1055 with self.assertCalls( 1056 (self.call.device._FakeInstall(set(), None, 'test.package')), 1057 (mock.call.os.path.exists(TEST_APK_PATH), True), 1058 (self.call.device._GetApplicationPathsInternal(TEST_PACKAGE), 1059 ['/fake/data/app/test.package.apk']), 1060 (self.call.device._ComputeStaleApks(TEST_PACKAGE, [TEST_APK_PATH]), 1061 ([], None)), (self.call.device.ForceStop(TEST_PACKAGE)), 1062 (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True)): 1063 self.device.Install( 1064 DeviceUtilsInstallTest.mock_apk, 1065 reinstall=True, 1066 retries=0, 1067 permissions=[]) 1068 1069 def testInstall_missingApk(self): 1070 with self.assertCalls( 1071 (self.call.device._FakeInstall(set(), None, 'test.package')), 1072 (mock.call.os.path.exists(TEST_APK_PATH), False)): 1073 with self.assertRaises(device_errors.CommandFailedError): 1074 self.device.Install(DeviceUtilsInstallTest.mock_apk, retries=0) 1075 1076 def testInstall_fails(self): 1077 with self.patch_call( 1078 self.call.device.product_name, return_value='notflounder'): 1079 with self.assertCalls( 1080 (self.call.device._FakeInstall(set(), None, 'test.package')), 1081 (mock.call.os.path.exists(TEST_APK_PATH), True), 1082 (self.call.device._GetApplicationPathsInternal(TEST_PACKAGE), []), 1083 (self.call.adb.Install( 1084 TEST_APK_PATH, 1085 reinstall=False, 1086 streaming=None, 1087 allow_downgrade=False), self.CommandError('Failure\r\n'))): 1088 with self.assertRaises(device_errors.CommandFailedError): 1089 self.device.Install(DeviceUtilsInstallTest.mock_apk, retries=0) 1090 1091 def testInstall_downgrade(self): 1092 with self.patch_call( 1093 self.call.device.product_name, return_value='notflounder'): 1094 with self.assertCalls( 1095 (self.call.device._FakeInstall(set(), None, 'test.package')), 1096 (mock.call.os.path.exists(TEST_APK_PATH), True), 1097 (self.call.device._GetApplicationPathsInternal(TEST_PACKAGE), 1098 ['/fake/data/app/test.package.apk']), 1099 (self.call.device._ComputeStaleApks(TEST_PACKAGE, [TEST_APK_PATH]), 1100 ([TEST_APK_PATH], None)), 1101 self.call.adb.Install(TEST_APK_PATH, 1102 reinstall=True, 1103 streaming=None, 1104 allow_downgrade=True), 1105 (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True)): 1106 self.device.Install( 1107 DeviceUtilsInstallTest.mock_apk, 1108 reinstall=True, 1109 retries=0, 1110 permissions=[], 1111 allow_downgrade=True) 1112 1113 def testInstall_pushesFakeModulesToDevice(self): 1114 @contextlib.contextmanager 1115 def mock_zip_temp_dir(): 1116 yield '/test/tmp/dir' 1117 1118 mock_apk_with_fake = _MockApkHelper( 1119 TEST_APK_PATH, TEST_PACKAGE, splits=['fake1-master.apk']) 1120 fake_modules = ['fake1'] 1121 with self.patch_call( 1122 self.call.device.product_name, 1123 return_value='notflounder'), (self.patch_call( 1124 self.call.device.build_version_sdk, return_value=23)): 1125 with self.assertCalls( 1126 (mock.call.py_utils.tempfile_ext.NamedTemporaryDirectory(), 1127 mock_zip_temp_dir), 1128 (mock.call.os.rename('fake1-master.apk', '/test/tmp/dir/fake1.apk')), 1129 (self.call.device.PushChangedFiles( 1130 [('/test/tmp/dir', '/data/local/tmp/modules/test.package')], 1131 delete_device_stale=True)), 1132 (mock.call.os.path.exists(TEST_APK_PATH), True), 1133 (self.call.device._GetApplicationPathsInternal(TEST_PACKAGE), []), 1134 self.call.adb.Install(TEST_APK_PATH, 1135 reinstall=False, 1136 streaming=None, 1137 allow_downgrade=False), 1138 (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True), 1139 (self.call.device.GrantPermissions(TEST_PACKAGE, None), [])): 1140 self.device.Install( 1141 mock_apk_with_fake, fake_modules=fake_modules, retries=0) 1142 1143 def testInstall_packageNotAvailableAfterInstall(self): 1144 with self.patch_call( 1145 self.call.device.product_name, 1146 return_value='notflounder'), (self.patch_call( 1147 self.call.device.build_version_sdk, return_value=23)), ( 1148 self.patch_call(self.call.device.IsApplicationInstalled, 1149 return_value=False)): 1150 with self.assertCalls( 1151 (self.call.device._FakeInstall(set(), None, 'test.package')), 1152 (mock.call.os.path.exists(TEST_APK_PATH), True), 1153 (self.call.device._GetApplicationPathsInternal(TEST_PACKAGE), []), 1154 self.call.adb.Install(TEST_APK_PATH, 1155 reinstall=False, 1156 streaming=None, 1157 allow_downgrade=False)): 1158 with self.assertRaisesRegexp( 1159 device_errors.CommandFailedError, 1160 'not installed on device after explicit install attempt'): 1161 self.device.Install( 1162 DeviceUtilsInstallTest.mock_apk, retries=0) 1163 1164 1165class DeviceUtilsInstallSplitApkTest(DeviceUtilsTest): 1166 1167 mock_apk = _MockApkHelper('base.apk', TEST_PACKAGE, ['p1'], 1168 ['split1.apk', 'split2.apk']) 1169 1170 def testInstallSplitApk_noPriorInstall(self): 1171 with self.patch_call( 1172 self.call.device.product_name, return_value='notflounder'): 1173 with self.assertCalls( 1174 (mock.call.devil.android.apk_helper.ToSplitHelper( 1175 'base.apk', ['split1.apk', 'split2.apk']), 1176 DeviceUtilsInstallSplitApkTest.mock_apk), 1177 (self.call.device._CheckSdkLevel(21)), 1178 (mock.call.os.path.exists('base.apk'), True), 1179 (mock.call.os.path.exists('split1.apk'), True), 1180 (mock.call.os.path.exists('split2.apk'), True), 1181 (self.call.device._GetApplicationPathsInternal(TEST_PACKAGE), []), 1182 (self.call.adb.InstallMultiple( 1183 ['base.apk', 'split1.apk', 'split2.apk'], 1184 partial=None, 1185 reinstall=False, 1186 streaming=None, 1187 allow_downgrade=False)), 1188 (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True)): 1189 self.device.InstallSplitApk( 1190 'base.apk', ['split1.apk', 'split2.apk'], permissions=[], retries=0) 1191 1192 def testInstallSplitApk_noStreaming(self): 1193 with self.patch_call( 1194 self.call.device.product_name, return_value='flounder'): 1195 with self.assertCalls( 1196 (mock.call.devil.android.apk_helper.ToSplitHelper( 1197 'base.apk', ['split1.apk', 'split2.apk']), 1198 DeviceUtilsInstallSplitApkTest.mock_apk), 1199 (self.call.device._CheckSdkLevel(21)), 1200 (mock.call.os.path.exists('base.apk'), True), 1201 (mock.call.os.path.exists('split1.apk'), True), 1202 (mock.call.os.path.exists('split2.apk'), True), 1203 (self.call.device._GetApplicationPathsInternal(TEST_PACKAGE), []), 1204 (self.call.adb.InstallMultiple( 1205 ['base.apk', 'split1.apk', 'split2.apk'], 1206 partial=None, 1207 reinstall=False, 1208 streaming=False, 1209 allow_downgrade=False)), 1210 (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True)): 1211 self.device.InstallSplitApk( 1212 'base.apk', ['split1.apk', 'split2.apk'], permissions=[], retries=0) 1213 1214 def testInstallSplitApk_partialInstall(self): 1215 with self.patch_call( 1216 self.call.device.product_name, return_value='notflounder'): 1217 with self.assertCalls( 1218 (mock.call.devil.android.apk_helper.ToSplitHelper( 1219 DeviceUtilsInstallSplitApkTest.mock_apk, 1220 ['split1.apk', 'split2.apk']), 1221 DeviceUtilsInstallSplitApkTest.mock_apk), 1222 (self.call.device._CheckSdkLevel(21)), 1223 (mock.call.os.path.exists('base.apk'), True), 1224 (mock.call.os.path.exists('split1.apk'), True), 1225 (mock.call.os.path.exists('split2.apk'), True), 1226 (self.call.device._GetApplicationPathsInternal(TEST_PACKAGE), 1227 ['base-on-device.apk', 'split2-on-device.apk']), 1228 (self.call.device._ComputeStaleApks( 1229 TEST_PACKAGE, ['base.apk', 'split1.apk', 'split2.apk']), 1230 (['split2.apk'], None)), 1231 (self.call.adb.InstallMultiple(['split2.apk'], 1232 partial=TEST_PACKAGE, 1233 reinstall=True, 1234 streaming=None, 1235 allow_downgrade=False)), 1236 (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True)): 1237 self.device.InstallSplitApk( 1238 DeviceUtilsInstallSplitApkTest.mock_apk, 1239 ['split1.apk', 'split2.apk'], 1240 reinstall=True, 1241 permissions=[], 1242 retries=0) 1243 1244 def testInstallSplitApk_downgrade(self): 1245 with self.patch_call( 1246 self.call.device.product_name, return_value='notflounder'): 1247 with self.assertCalls( 1248 (mock.call.devil.android.apk_helper.ToSplitHelper( 1249 DeviceUtilsInstallSplitApkTest.mock_apk, 1250 ['split1.apk', 'split2.apk']), 1251 DeviceUtilsInstallSplitApkTest.mock_apk), 1252 (self.call.device._CheckSdkLevel(21)), 1253 (mock.call.os.path.exists('base.apk'), True), 1254 (mock.call.os.path.exists('split1.apk'), True), 1255 (mock.call.os.path.exists('split2.apk'), True), 1256 (self.call.device._GetApplicationPathsInternal(TEST_PACKAGE), 1257 ['base-on-device.apk', 'split2-on-device.apk']), 1258 (self.call.device._ComputeStaleApks( 1259 TEST_PACKAGE, ['base.apk', 'split1.apk', 'split2.apk']), 1260 (['split2.apk'], None)), 1261 (self.call.adb.InstallMultiple(['split2.apk'], 1262 partial=TEST_PACKAGE, 1263 reinstall=True, 1264 streaming=None, 1265 allow_downgrade=True)), 1266 (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True)): 1267 self.device.InstallSplitApk( 1268 DeviceUtilsInstallSplitApkTest.mock_apk, 1269 ['split1.apk', 'split2.apk'], 1270 reinstall=True, 1271 permissions=[], 1272 retries=0, 1273 allow_downgrade=True) 1274 1275 def testInstallSplitApk_missingSplit(self): 1276 with self.assertCalls( 1277 (mock.call.devil.android.apk_helper.ToSplitHelper( 1278 DeviceUtilsInstallSplitApkTest.mock_apk, 1279 ['split1.apk', 'split2.apk']), 1280 DeviceUtilsInstallSplitApkTest.mock_apk), 1281 (self.call.device._CheckSdkLevel(21)), 1282 (mock.call.os.path.exists('base.apk'), True), 1283 (mock.call.os.path.exists('split1.apk'), True), 1284 (mock.call.os.path.exists('split2.apk'), False)),\ 1285 self.assertRaises(device_errors.CommandFailedError): 1286 self.device.InstallSplitApk( 1287 DeviceUtilsInstallSplitApkTest.mock_apk, ['split1.apk', 'split2.apk'], 1288 permissions=[], 1289 retries=0) 1290 1291 def testInstallSplitApk_previouslyNonSplit(self): 1292 with self.patch_call( 1293 self.call.device.product_name, return_value='notflounder'): 1294 with self.assertCalls( 1295 (mock.call.devil.android.apk_helper.ToSplitHelper( 1296 DeviceUtilsInstallSplitApkTest.mock_apk, 1297 ['split1.apk', 'split2.apk']), 1298 DeviceUtilsInstallSplitApkTest.mock_apk), 1299 (self.call.device._CheckSdkLevel(21)), 1300 (mock.call.os.path.exists('base.apk'), True), 1301 (mock.call.os.path.exists('split1.apk'), True), 1302 (mock.call.os.path.exists('split2.apk'), True), 1303 (self.call.device._GetApplicationPathsInternal(TEST_PACKAGE), 1304 ['/fake/data/app/test.package.apk']), 1305 self.call.device.Uninstall(TEST_PACKAGE), 1306 (self.call.adb.InstallMultiple( 1307 ['base.apk', 'split1.apk', 'split2.apk'], 1308 partial=None, 1309 reinstall=False, 1310 streaming=None, 1311 allow_downgrade=False)), 1312 (self.call.device.IsApplicationInstalled(TEST_PACKAGE, None), True)): 1313 self.device.InstallSplitApk( 1314 DeviceUtilsInstallSplitApkTest.mock_apk, 1315 ['split1.apk', 'split2.apk'], 1316 permissions=[], 1317 retries=0) 1318 1319 1320class DeviceUtilsUninstallTest(DeviceUtilsTest): 1321 def testUninstall_callsThrough(self): 1322 with self.assertCalls( 1323 (self.call.device._GetApplicationPathsInternal(TEST_PACKAGE), 1324 ['/path.apk']), self.call.adb.Uninstall(TEST_PACKAGE, True)): 1325 self.device.Uninstall(TEST_PACKAGE, True) 1326 1327 def testUninstall_noop(self): 1328 with self.assertCalls( 1329 (self.call.device._GetApplicationPathsInternal(TEST_PACKAGE), [])): 1330 self.device.Uninstall(TEST_PACKAGE, True) 1331 1332 1333class DeviceUtilsSuTest(DeviceUtilsTest): 1334 def testSu_preM(self): 1335 with self.patch_call( 1336 self.call.device.build_version_sdk, 1337 return_value=version_codes.LOLLIPOP_MR1): 1338 self.assertEquals('su -c foo', self.device._Su('foo')) 1339 1340 def testSu_mAndAbove(self): 1341 with self.patch_call( 1342 self.call.device.build_version_sdk, 1343 return_value=version_codes.MARSHMALLOW): 1344 self.assertEquals('su 0 foo', self.device._Su('foo')) 1345 1346 1347class DeviceUtilsRunShellCommandTest(DeviceUtilsTest): 1348 def setUp(self): 1349 super(DeviceUtilsRunShellCommandTest, self).setUp() 1350 self.device.NeedsSU = mock.Mock(return_value=False) 1351 1352 def testRunShellCommand_commandAsList(self): 1353 with self.assertCall(self.call.adb.Shell('pm list packages'), ''): 1354 self.device.RunShellCommand(['pm', 'list', 'packages'], check_return=True) 1355 1356 def testRunShellCommand_commandAsListQuoted(self): 1357 with self.assertCall(self.call.adb.Shell("echo 'hello world' '$10'"), ''): 1358 self.device.RunShellCommand(['echo', 'hello world', '$10'], 1359 check_return=True) 1360 1361 def testRunShellCommand_commandAsString(self): 1362 with self.assertCall(self.call.adb.Shell('echo "$VAR"'), ''): 1363 self.device.RunShellCommand('echo "$VAR"', shell=True, check_return=True) 1364 1365 def testNewRunShellImpl_withEnv(self): 1366 with self.assertCall( 1367 self.call.adb.Shell('VAR=some_string echo "$VAR"'), ''): 1368 self.device.RunShellCommand( 1369 'echo "$VAR"', 1370 shell=True, 1371 check_return=True, 1372 env={'VAR': 'some_string'}) 1373 1374 def testNewRunShellImpl_withEnvQuoted(self): 1375 with self.assertCall( 1376 self.call.adb.Shell('PATH="$PATH:/other/path" run_this'), ''): 1377 self.device.RunShellCommand(['run_this'], 1378 check_return=True, 1379 env={'PATH': '$PATH:/other/path'}) 1380 1381 def testNewRunShellImpl_withEnv_failure(self): 1382 with self.assertRaises(KeyError): 1383 self.device.RunShellCommand(['some_cmd'], 1384 check_return=True, 1385 env={'INVALID NAME': 'value'}) 1386 1387 def testNewRunShellImpl_withCwd(self): 1388 with self.assertCall(self.call.adb.Shell('cd /some/test/path && ls'), ''): 1389 self.device.RunShellCommand(['ls'], 1390 check_return=True, 1391 cwd='/some/test/path') 1392 1393 def testNewRunShellImpl_withCwdQuoted(self): 1394 with self.assertCall( 1395 self.call.adb.Shell("cd '/some test/path with/spaces' && ls"), ''): 1396 self.device.RunShellCommand(['ls'], 1397 check_return=True, 1398 cwd='/some test/path with/spaces') 1399 1400 def testRunShellCommand_withHugeCmd(self): 1401 payload = 'hi! ' * 1024 1402 expected_cmd = "echo '%s'" % payload 1403 with self.assertCalls( 1404 (mock.call.devil.android.device_temp_file.DeviceTempFile( 1405 self.adb, suffix='.sh'), MockTempFile('/sdcard/temp-123.sh')), 1406 self.call.device._WriteFileWithPush('/sdcard/temp-123.sh', 1407 expected_cmd), 1408 (self.call.adb.Shell('sh /sdcard/temp-123.sh'), payload + '\n')): 1409 self.assertEquals([payload], 1410 self.device.RunShellCommand(['echo', payload], 1411 check_return=True)) 1412 1413 def testRunShellCommand_withHugeCmdAndSu(self): 1414 payload = 'hi! ' * 1024 1415 expected_cmd_without_su = """sh -c 'echo '"'"'%s'"'"''""" % payload 1416 expected_cmd = 'su -c %s' % expected_cmd_without_su 1417 with self.assertCalls( 1418 (self.call.device.NeedsSU(), True), 1419 (self.call.device._Su(expected_cmd_without_su), expected_cmd), 1420 (mock.call.devil.android.device_temp_file.DeviceTempFile( 1421 self.adb, suffix='.sh'), MockTempFile('/sdcard/temp-123.sh')), 1422 self.call.device._WriteFileWithPush('/sdcard/temp-123.sh', 1423 expected_cmd), 1424 (self.call.adb.Shell('sh /sdcard/temp-123.sh'), payload + '\n')): 1425 self.assertEquals([payload], 1426 self.device.RunShellCommand(['echo', payload], 1427 check_return=True, 1428 as_root=True)) 1429 1430 def testRunShellCommand_withSu(self): 1431 expected_cmd_without_su = "sh -c 'setprop service.adb.root 0'" 1432 expected_cmd = 'su -c %s' % expected_cmd_without_su 1433 with self.assertCalls( 1434 (self.call.device.NeedsSU(), True), 1435 (self.call.device._Su(expected_cmd_without_su), expected_cmd), 1436 (self.call.adb.Shell(expected_cmd), '')): 1437 self.device.RunShellCommand(['setprop', 'service.adb.root', '0'], 1438 check_return=True, 1439 as_root=True) 1440 1441 def testRunShellCommand_withRunAs(self): 1442 expected_cmd_without_run_as = "sh -c 'mkdir -p files'" 1443 expected_cmd = ( 1444 'run-as org.devil.test_package %s' % expected_cmd_without_run_as) 1445 with self.assertCall(self.call.adb.Shell(expected_cmd), ''): 1446 self.device.RunShellCommand(['mkdir', '-p', 'files'], 1447 check_return=True, 1448 run_as='org.devil.test_package') 1449 1450 def testRunShellCommand_withRunAsAndSu(self): 1451 expected_cmd_with_nothing = "sh -c 'mkdir -p files'" 1452 expected_cmd_with_run_as = ( 1453 'run-as org.devil.test_package %s' % expected_cmd_with_nothing) 1454 expected_cmd_without_su = ( 1455 'sh -c %s' % cmd_helper.SingleQuote(expected_cmd_with_run_as)) 1456 expected_cmd = 'su -c %s' % expected_cmd_without_su 1457 with self.assertCalls( 1458 (self.call.device.NeedsSU(), True), 1459 (self.call.device._Su(expected_cmd_without_su), expected_cmd), 1460 (self.call.adb.Shell(expected_cmd), '')): 1461 self.device.RunShellCommand(['mkdir', '-p', 'files'], 1462 check_return=True, 1463 run_as='org.devil.test_package', 1464 as_root=True) 1465 1466 def testRunShellCommand_manyLines(self): 1467 cmd = 'ls /some/path' 1468 with self.assertCall(self.call.adb.Shell(cmd), 'file1\nfile2\nfile3\n'): 1469 self.assertEquals(['file1', 'file2', 'file3'], 1470 self.device.RunShellCommand( 1471 cmd.split(), check_return=True)) 1472 1473 def testRunShellCommand_manyLinesRawOutput(self): 1474 cmd = 'ls /some/path' 1475 with self.assertCall(self.call.adb.Shell(cmd), '\rfile1\nfile2\r\nfile3\n'): 1476 self.assertEquals( 1477 '\rfile1\nfile2\r\nfile3\n', 1478 self.device.RunShellCommand( 1479 cmd.split(), check_return=True, raw_output=True)) 1480 1481 def testRunShellCommand_singleLine_success(self): 1482 cmd = 'echo $VALUE' 1483 with self.assertCall(self.call.adb.Shell(cmd), 'some value\n'): 1484 self.assertEquals( 1485 'some value', 1486 self.device.RunShellCommand( 1487 cmd, shell=True, check_return=True, single_line=True)) 1488 1489 def testRunShellCommand_singleLine_successEmptyLine(self): 1490 cmd = 'echo $VALUE' 1491 with self.assertCall(self.call.adb.Shell(cmd), '\n'): 1492 self.assertEquals( 1493 '', 1494 self.device.RunShellCommand( 1495 cmd, shell=True, check_return=True, single_line=True)) 1496 1497 def testRunShellCommand_singleLine_successWithoutEndLine(self): 1498 cmd = 'echo -n $VALUE' 1499 with self.assertCall(self.call.adb.Shell(cmd), 'some value'): 1500 self.assertEquals( 1501 'some value', 1502 self.device.RunShellCommand( 1503 cmd, shell=True, check_return=True, single_line=True)) 1504 1505 def testRunShellCommand_singleLine_successNoOutput(self): 1506 cmd = 'echo -n $VALUE' 1507 with self.assertCall(self.call.adb.Shell(cmd), ''): 1508 self.assertEquals( 1509 '', 1510 self.device.RunShellCommand( 1511 cmd, shell=True, check_return=True, single_line=True)) 1512 1513 def testRunShellCommand_singleLine_failTooManyLines(self): 1514 cmd = 'echo $VALUE' 1515 with self.assertCall( 1516 self.call.adb.Shell(cmd), 'some value\nanother value\n'): 1517 with self.assertRaises(device_errors.CommandFailedError): 1518 self.device.RunShellCommand( 1519 cmd, shell=True, check_return=True, single_line=True) 1520 1521 def testRunShellCommand_checkReturn_success(self): 1522 cmd = 'echo $ANDROID_DATA' 1523 output = '/data\n' 1524 with self.assertCall(self.call.adb.Shell(cmd), output): 1525 self.assertEquals([output.rstrip()], 1526 self.device.RunShellCommand( 1527 cmd, shell=True, check_return=True)) 1528 1529 def testRunShellCommand_checkReturn_failure(self): 1530 cmd = 'ls /root' 1531 output = 'opendir failed, Permission denied\n' 1532 with self.assertCall(self.call.adb.Shell(cmd), self.ShellError(output)): 1533 with self.assertRaises(device_errors.AdbCommandFailedError): 1534 self.device.RunShellCommand(cmd.split(), check_return=True) 1535 1536 def testRunShellCommand_checkReturn_disabled(self): 1537 cmd = 'ls /root' 1538 output = 'opendir failed, Permission denied\n' 1539 with self.assertCall(self.call.adb.Shell(cmd), self.ShellError(output)): 1540 self.assertEquals([output.rstrip()], 1541 self.device.RunShellCommand( 1542 cmd.split(), check_return=False)) 1543 1544 def testRunShellCommand_largeOutput_enabled(self): 1545 cmd = 'echo $VALUE' 1546 temp_file = MockTempFile('/sdcard/temp-123') 1547 cmd_redirect = '( %s )>%s 2>&1' % (cmd, temp_file.name) 1548 with self.assertCalls( 1549 (mock.call.devil.android.device_temp_file.DeviceTempFile(self.adb), 1550 temp_file), 1551 (self.call.adb.Shell(cmd_redirect)), (self.call.device.ReadFile( 1552 temp_file.name, force_pull=True), 'something')): 1553 self.assertEquals(['something'], 1554 self.device.RunShellCommand( 1555 cmd, 1556 shell=True, 1557 large_output=True, 1558 check_return=True)) 1559 1560 def testRunShellCommand_largeOutput_disabledNoTrigger(self): 1561 cmd = 'something' 1562 with self.assertCall(self.call.adb.Shell(cmd), self.ShellError('')): 1563 with self.assertRaises(device_errors.AdbCommandFailedError): 1564 self.device.RunShellCommand([cmd], check_return=True) 1565 1566 def testRunShellCommand_largeOutput_disabledTrigger(self): 1567 cmd = 'echo $VALUE' 1568 temp_file = MockTempFile('/sdcard/temp-123') 1569 cmd_redirect = '( %s )>%s 2>&1' % (cmd, temp_file.name) 1570 with self.assertCalls( 1571 (self.call.adb.Shell(cmd), self.ShellError('', None)), 1572 (mock.call.devil.android.device_temp_file.DeviceTempFile(self.adb), 1573 temp_file), (self.call.adb.Shell(cmd_redirect)), 1574 (self.call.device.ReadFile(mock.ANY, force_pull=True), 'something')): 1575 self.assertEquals(['something'], 1576 self.device.RunShellCommand( 1577 cmd, shell=True, check_return=True)) 1578 1579 1580class DeviceUtilsRunPipedShellCommandTest(DeviceUtilsTest): 1581 def testRunPipedShellCommand_success(self): 1582 with self.assertCall( 1583 self.call.device.RunShellCommand( 1584 'ps | grep foo; echo "PIPESTATUS: ${PIPESTATUS[@]}"', 1585 shell=True, 1586 check_return=True), ['This line contains foo', 'PIPESTATUS: 0 0']): 1587 self.assertEquals(['This line contains foo'], 1588 self.device._RunPipedShellCommand('ps | grep foo')) 1589 1590 def testRunPipedShellCommand_firstCommandFails(self): 1591 with self.assertCall( 1592 self.call.device.RunShellCommand( 1593 'ps | grep foo; echo "PIPESTATUS: ${PIPESTATUS[@]}"', 1594 shell=True, 1595 check_return=True), ['PIPESTATUS: 1 0']): 1596 with self.assertRaises(device_errors.AdbShellCommandFailedError) as ec: 1597 self.device._RunPipedShellCommand('ps | grep foo') 1598 self.assertEquals([1, 0], ec.exception.status) 1599 1600 def testRunPipedShellCommand_secondCommandFails(self): 1601 with self.assertCall( 1602 self.call.device.RunShellCommand( 1603 'ps | grep foo; echo "PIPESTATUS: ${PIPESTATUS[@]}"', 1604 shell=True, 1605 check_return=True), ['PIPESTATUS: 0 1']): 1606 with self.assertRaises(device_errors.AdbShellCommandFailedError) as ec: 1607 self.device._RunPipedShellCommand('ps | grep foo') 1608 self.assertEquals([0, 1], ec.exception.status) 1609 1610 def testRunPipedShellCommand_outputCutOff(self): 1611 with self.assertCall( 1612 self.call.device.RunShellCommand( 1613 'ps | grep foo; echo "PIPESTATUS: ${PIPESTATUS[@]}"', 1614 shell=True, 1615 check_return=True), ['foo.bar'] * 256 + ['foo.ba']): 1616 with self.assertRaises(device_errors.AdbShellCommandFailedError) as ec: 1617 self.device._RunPipedShellCommand('ps | grep foo') 1618 self.assertIs(None, ec.exception.status) 1619 1620 1621@mock.patch('time.sleep', mock.Mock()) 1622class DeviceUtilsKillAllTest(DeviceUtilsTest): 1623 def testKillAll_noMatchingProcessesFailure(self): 1624 with self.assertCall(self.call.device.ListProcesses('test_process'), []): 1625 with self.assertRaises(device_errors.CommandFailedError): 1626 self.device.KillAll('test_process') 1627 1628 def testKillAll_noMatchingProcessesQuiet(self): 1629 with self.assertCall(self.call.device.ListProcesses('test_process'), []): 1630 self.assertEqual(0, self.device.KillAll('test_process', quiet=True)) 1631 1632 def testKillAll_nonblocking(self): 1633 with self.assertCalls((self.call.device.ListProcesses('some.process'), 1634 Processes(('some.process', 1234), 1635 ('some.process.thing', 5678))), 1636 (self.call.adb.Shell('kill -9 1234 5678'), '')): 1637 self.assertEquals(2, self.device.KillAll('some.process', blocking=False)) 1638 1639 def testKillAll_blocking(self): 1640 with self.assertCalls( 1641 (self.call.device.ListProcesses('some.process'), 1642 Processes(('some.process', 1234), ('some.process.thing', 5678))), 1643 (self.call.adb.Shell('kill -9 1234 5678'), ''), 1644 (self.call.device.ListProcesses('some.process'), 1645 Processes(('some.process.thing', 5678))), 1646 ( 1647 self.call.device.ListProcesses('some.process'), 1648 # Other instance with different pid. 1649 Processes(('some.process', 111)))): 1650 self.assertEquals(2, self.device.KillAll('some.process', blocking=True)) 1651 1652 def testKillAll_exactNonblocking(self): 1653 with self.assertCalls((self.call.device.ListProcesses('some.process'), 1654 Processes(('some.process', 1234), 1655 ('some.process.thing', 5678))), 1656 (self.call.adb.Shell('kill -9 1234'), '')): 1657 self.assertEquals( 1658 1, self.device.KillAll('some.process', exact=True, blocking=False)) 1659 1660 def testKillAll_exactBlocking(self): 1661 with self.assertCalls((self.call.device.ListProcesses('some.process'), 1662 Processes(('some.process', 1234), 1663 ('some.process.thing', 5678))), 1664 (self.call.adb.Shell('kill -9 1234'), ''), 1665 (self.call.device.ListProcesses('some.process'), 1666 Processes(('some.process', 1234), 1667 ('some.process.thing', 5678))), 1668 (self.call.device.ListProcesses('some.process'), 1669 Processes(('some.process.thing', 5678)))): 1670 self.assertEquals( 1671 1, self.device.KillAll('some.process', exact=True, blocking=True)) 1672 1673 def testKillAll_root(self): 1674 with self.assertCalls( 1675 (self.call.device.ListProcesses('some.process'), 1676 Processes(('some.process', 1234))), (self.call.device.NeedsSU(), True), 1677 (self.call.device._Su("sh -c 'kill -9 1234'"), 1678 "su -c sh -c 'kill -9 1234'"), 1679 (self.call.adb.Shell("su -c sh -c 'kill -9 1234'"), '')): 1680 self.assertEquals(1, self.device.KillAll('some.process', as_root=True)) 1681 1682 def testKillAll_sigterm(self): 1683 with self.assertCalls((self.call.device.ListProcesses('some.process'), 1684 Processes(('some.process', 1234))), 1685 (self.call.adb.Shell('kill -15 1234'), '')): 1686 self.assertEquals( 1687 1, self.device.KillAll('some.process', signum=device_signal.SIGTERM)) 1688 1689 def testKillAll_multipleInstances(self): 1690 with self.assertCalls((self.call.device.ListProcesses('some.process'), 1691 Processes(('some.process', 1234), 1692 ('some.process', 4567))), 1693 (self.call.adb.Shell('kill -15 1234 4567'), '')): 1694 self.assertEquals( 1695 2, self.device.KillAll('some.process', signum=device_signal.SIGTERM)) 1696 1697 1698class DeviceUtilsStartActivityTest(DeviceUtilsTest): 1699 def testStartActivity_actionOnly(self): 1700 test_intent = intent.Intent(action='android.intent.action.VIEW') 1701 with self.assertCall( 1702 self.call.adb.Shell('am start ' 1703 '-a android.intent.action.VIEW'), 1704 'Starting: Intent { act=android.intent.action.VIEW }'): 1705 self.device.StartActivity(test_intent) 1706 1707 def testStartActivity_success(self): 1708 test_intent = intent.Intent( 1709 action='android.intent.action.VIEW', 1710 package=TEST_PACKAGE, 1711 activity='.Main') 1712 with self.assertCall( 1713 self.call.adb.Shell('am start ' 1714 '-a android.intent.action.VIEW ' 1715 '-n test.package/.Main'), 1716 'Starting: Intent { act=android.intent.action.VIEW }'): 1717 self.device.StartActivity(test_intent) 1718 1719 def testStartActivity_failure(self): 1720 test_intent = intent.Intent( 1721 action='android.intent.action.VIEW', 1722 package=TEST_PACKAGE, 1723 activity='.Main') 1724 with self.assertCall( 1725 self.call.adb.Shell('am start ' 1726 '-a android.intent.action.VIEW ' 1727 '-n test.package/.Main'), 1728 'Error: Failed to start test activity'): 1729 with self.assertRaises(device_errors.CommandFailedError): 1730 self.device.StartActivity(test_intent) 1731 1732 def testStartActivity_blocking(self): 1733 test_intent = intent.Intent( 1734 action='android.intent.action.VIEW', 1735 package=TEST_PACKAGE, 1736 activity='.Main') 1737 with self.assertCall( 1738 self.call.adb.Shell('am start ' 1739 '-W ' 1740 '-a android.intent.action.VIEW ' 1741 '-n test.package/.Main'), 1742 'Starting: Intent { act=android.intent.action.VIEW }'): 1743 self.device.StartActivity(test_intent, blocking=True) 1744 1745 def testStartActivity_withCategory(self): 1746 test_intent = intent.Intent( 1747 action='android.intent.action.VIEW', 1748 package=TEST_PACKAGE, 1749 activity='.Main', 1750 category='android.intent.category.HOME') 1751 with self.assertCall( 1752 self.call.adb.Shell('am start ' 1753 '-a android.intent.action.VIEW ' 1754 '-c android.intent.category.HOME ' 1755 '-n test.package/.Main'), 1756 'Starting: Intent { act=android.intent.action.VIEW }'): 1757 self.device.StartActivity(test_intent) 1758 1759 def testStartActivity_withMultipleCategories(self): 1760 test_intent = intent.Intent( 1761 action='android.intent.action.VIEW', 1762 package=TEST_PACKAGE, 1763 activity='.Main', 1764 category=[ 1765 'android.intent.category.HOME', 'android.intent.category.BROWSABLE' 1766 ]) 1767 with self.assertCall( 1768 self.call.adb.Shell('am start ' 1769 '-a android.intent.action.VIEW ' 1770 '-c android.intent.category.HOME ' 1771 '-c android.intent.category.BROWSABLE ' 1772 '-n test.package/.Main'), 1773 'Starting: Intent { act=android.intent.action.VIEW }'): 1774 self.device.StartActivity(test_intent) 1775 1776 def testStartActivity_withData(self): 1777 test_intent = intent.Intent( 1778 action='android.intent.action.VIEW', 1779 package=TEST_PACKAGE, 1780 activity='.Main', 1781 data='http://www.google.com/') 1782 with self.assertCall( 1783 self.call.adb.Shell('am start ' 1784 '-a android.intent.action.VIEW ' 1785 '-d http://www.google.com/ ' 1786 '-n test.package/.Main'), 1787 'Starting: Intent { act=android.intent.action.VIEW }'): 1788 self.device.StartActivity(test_intent) 1789 1790 def testStartActivity_withStringExtra(self): 1791 test_intent = intent.Intent( 1792 action='android.intent.action.VIEW', 1793 package=TEST_PACKAGE, 1794 activity='.Main', 1795 extras={'foo': 'test'}) 1796 with self.assertCall( 1797 self.call.adb.Shell('am start ' 1798 '-a android.intent.action.VIEW ' 1799 '-n test.package/.Main ' 1800 '--es foo test'), 1801 'Starting: Intent { act=android.intent.action.VIEW }'): 1802 self.device.StartActivity(test_intent) 1803 1804 def testStartActivity_withBoolExtra(self): 1805 test_intent = intent.Intent( 1806 action='android.intent.action.VIEW', 1807 package=TEST_PACKAGE, 1808 activity='.Main', 1809 extras={'foo': True}) 1810 with self.assertCall( 1811 self.call.adb.Shell('am start ' 1812 '-a android.intent.action.VIEW ' 1813 '-n test.package/.Main ' 1814 '--ez foo True'), 1815 'Starting: Intent { act=android.intent.action.VIEW }'): 1816 self.device.StartActivity(test_intent) 1817 1818 def testStartActivity_withIntExtra(self): 1819 test_intent = intent.Intent( 1820 action='android.intent.action.VIEW', 1821 package=TEST_PACKAGE, 1822 activity='.Main', 1823 extras={'foo': 123}) 1824 with self.assertCall( 1825 self.call.adb.Shell('am start ' 1826 '-a android.intent.action.VIEW ' 1827 '-n test.package/.Main ' 1828 '--ei foo 123'), 1829 'Starting: Intent { act=android.intent.action.VIEW }'): 1830 self.device.StartActivity(test_intent) 1831 1832 def testStartActivity_withTraceFile(self): 1833 test_intent = intent.Intent( 1834 action='android.intent.action.VIEW', 1835 package=TEST_PACKAGE, 1836 activity='.Main') 1837 with self.assertCall( 1838 self.call.adb.Shell('am start ' 1839 '--start-profiler test_trace_file.out ' 1840 '-a android.intent.action.VIEW ' 1841 '-n test.package/.Main'), 1842 'Starting: Intent { act=android.intent.action.VIEW }'): 1843 self.device.StartActivity( 1844 test_intent, trace_file_name='test_trace_file.out') 1845 1846 def testStartActivity_withForceStop(self): 1847 test_intent = intent.Intent( 1848 action='android.intent.action.VIEW', 1849 package=TEST_PACKAGE, 1850 activity='.Main') 1851 with self.assertCall( 1852 self.call.adb.Shell('am start ' 1853 '-S ' 1854 '-a android.intent.action.VIEW ' 1855 '-n test.package/.Main'), 1856 'Starting: Intent { act=android.intent.action.VIEW }'): 1857 self.device.StartActivity(test_intent, force_stop=True) 1858 1859 def testStartActivity_withFlags(self): 1860 test_intent = intent.Intent( 1861 action='android.intent.action.VIEW', 1862 package=TEST_PACKAGE, 1863 activity='.Main', 1864 flags=[ 1865 intent.FLAG_ACTIVITY_NEW_TASK, 1866 intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED 1867 ]) 1868 with self.assertCall( 1869 self.call.adb.Shell('am start ' 1870 '-a android.intent.action.VIEW ' 1871 '-n test.package/.Main ' 1872 '-f 0x10200000'), 1873 'Starting: Intent { act=android.intent.action.VIEW }'): 1874 self.device.StartActivity(test_intent) 1875 1876 1877class DeviceUtilsStartServiceTest(DeviceUtilsTest): 1878 def testStartService_success(self): 1879 test_intent = intent.Intent( 1880 action='android.intent.action.START', 1881 package=TEST_PACKAGE, 1882 activity='.Main') 1883 with self.patch_call( 1884 self.call.device.build_version_sdk, return_value=version_codes.NOUGAT): 1885 with self.assertCall( 1886 self.call.adb.Shell('am startservice ' 1887 '-a android.intent.action.START ' 1888 '-n test.package/.Main'), 1889 'Starting service: Intent { act=android.intent.action.START }'): 1890 self.device.StartService(test_intent) 1891 1892 def testStartService_failure(self): 1893 test_intent = intent.Intent( 1894 action='android.intent.action.START', 1895 package=TEST_PACKAGE, 1896 activity='.Main') 1897 with self.patch_call( 1898 self.call.device.build_version_sdk, return_value=version_codes.NOUGAT): 1899 with self.assertCall( 1900 self.call.adb.Shell('am startservice ' 1901 '-a android.intent.action.START ' 1902 '-n test.package/.Main'), 1903 'Error: Failed to start test service'): 1904 with self.assertRaises(device_errors.CommandFailedError): 1905 self.device.StartService(test_intent) 1906 1907 def testStartService_withUser(self): 1908 test_intent = intent.Intent( 1909 action='android.intent.action.START', 1910 package=TEST_PACKAGE, 1911 activity='.Main') 1912 with self.patch_call( 1913 self.call.device.build_version_sdk, return_value=version_codes.NOUGAT): 1914 with self.assertCall( 1915 self.call.adb.Shell('am startservice ' 1916 '--user TestUser ' 1917 '-a android.intent.action.START ' 1918 '-n test.package/.Main'), 1919 'Starting service: Intent { act=android.intent.action.START }'): 1920 self.device.StartService(test_intent, user_id='TestUser') 1921 1922 def testStartService_onOreo(self): 1923 test_intent = intent.Intent( 1924 action='android.intent.action.START', 1925 package=TEST_PACKAGE, 1926 activity='.Main') 1927 with self.patch_call( 1928 self.call.device.build_version_sdk, return_value=version_codes.OREO): 1929 with self.assertCall( 1930 self.call.adb.Shell('am start-service ' 1931 '-a android.intent.action.START ' 1932 '-n test.package/.Main'), 1933 'Starting service: Intent { act=android.intent.action.START }'): 1934 self.device.StartService(test_intent) 1935 1936 1937class DeviceUtilsStartInstrumentationTest(DeviceUtilsTest): 1938 def testStartInstrumentation_nothing(self): 1939 with self.assertCalls( 1940 self.call.device.RunShellCommand( 1941 'p=test.package;am instrument "$p"/.TestInstrumentation', 1942 shell=True, 1943 check_return=True, 1944 large_output=True)): 1945 self.device.StartInstrumentation( 1946 'test.package/.TestInstrumentation', 1947 finish=False, 1948 raw=False, 1949 extras=None) 1950 1951 def testStartInstrumentation_finish(self): 1952 with self.assertCalls((self.call.device.RunShellCommand( 1953 'p=test.package;am instrument -w "$p"/.TestInstrumentation', 1954 shell=True, 1955 check_return=True, 1956 large_output=True), ['OK (1 test)'])): 1957 output = self.device.StartInstrumentation( 1958 'test.package/.TestInstrumentation', 1959 finish=True, 1960 raw=False, 1961 extras=None) 1962 self.assertEquals(['OK (1 test)'], output) 1963 1964 def testStartInstrumentation_raw(self): 1965 with self.assertCalls( 1966 self.call.device.RunShellCommand( 1967 'p=test.package;am instrument -r "$p"/.TestInstrumentation', 1968 shell=True, 1969 check_return=True, 1970 large_output=True)): 1971 self.device.StartInstrumentation( 1972 'test.package/.TestInstrumentation', 1973 finish=False, 1974 raw=True, 1975 extras=None) 1976 1977 def testStartInstrumentation_extras(self): 1978 with self.assertCalls( 1979 self.call.device.RunShellCommand( 1980 'p=test.package;am instrument -e "$p".foo Foo -e bar \'Val \'"$p" ' 1981 '"$p"/.TestInstrumentation', 1982 shell=True, 1983 check_return=True, 1984 large_output=True)): 1985 self.device.StartInstrumentation( 1986 'test.package/.TestInstrumentation', 1987 finish=False, 1988 raw=False, 1989 extras={ 1990 'test.package.foo': 'Foo', 1991 'bar': 'Val test.package' 1992 }) 1993 1994 1995class DeviceUtilsBroadcastIntentTest(DeviceUtilsTest): 1996 def testBroadcastIntent_noExtras(self): 1997 test_intent = intent.Intent(action='test.package.with.an.INTENT') 1998 with self.assertCall( 1999 self.call.adb.Shell('am broadcast -a test.package.with.an.INTENT'), 2000 'Broadcasting: Intent { act=test.package.with.an.INTENT } '): 2001 self.device.BroadcastIntent(test_intent) 2002 2003 def testBroadcastIntent_withExtra(self): 2004 test_intent = intent.Intent( 2005 action='test.package.with.an.INTENT', extras={'foo': 'bar value'}) 2006 with self.assertCall( 2007 self.call.adb.Shell( 2008 "am broadcast -a test.package.with.an.INTENT --es foo 'bar value'"), 2009 'Broadcasting: Intent { act=test.package.with.an.INTENT } '): 2010 self.device.BroadcastIntent(test_intent) 2011 2012 def testBroadcastIntent_withExtra_noValue(self): 2013 test_intent = intent.Intent( 2014 action='test.package.with.an.INTENT', extras={'foo': None}) 2015 with self.assertCall( 2016 self.call.adb.Shell( 2017 'am broadcast -a test.package.with.an.INTENT --esn foo'), 2018 'Broadcasting: Intent { act=test.package.with.an.INTENT } '): 2019 self.device.BroadcastIntent(test_intent) 2020 2021 2022class DeviceUtilsGoHomeTest(DeviceUtilsTest): 2023 def testGoHome_popupsExist(self): 2024 with self.assertCalls( 2025 (self.call.device.RunShellCommand(['dumpsys', 'window', 'windows'], 2026 check_return=True, 2027 large_output=True), []), 2028 (self.call.device.RunShellCommand([ 2029 'am', 'start', '-W', '-a', 'android.intent.action.MAIN', '-c', 2030 'android.intent.category.HOME' 2031 ], 2032 check_return=True), 2033 'Starting: Intent { act=android.intent.action.MAIN }\r\n' 2034 ''), 2035 (self.call.device.RunShellCommand(['dumpsys', 'window', 'windows'], 2036 check_return=True, 2037 large_output=True), []), 2038 (self.call.device.RunShellCommand(['input', 'keyevent', '66'], 2039 check_return=True)), 2040 (self.call.device.RunShellCommand(['input', 'keyevent', '4'], 2041 check_return=True)), 2042 (self.call.device.RunShellCommand(['dumpsys', 'window', 'windows'], 2043 check_return=True, 2044 large_output=True), 2045 ['mCurrentFocus Launcher'])): 2046 self.device.GoHome() 2047 2048 def testGoHome_willRetry(self): 2049 with self.assertCalls( 2050 (self.call.device.RunShellCommand(['dumpsys', 'window', 'windows'], 2051 check_return=True, 2052 large_output=True), []), 2053 (self.call.device.RunShellCommand([ 2054 'am', 'start', '-W', '-a', 'android.intent.action.MAIN', '-c', 2055 'android.intent.category.HOME' 2056 ], 2057 check_return=True), 2058 'Starting: Intent { act=android.intent.action.MAIN }\r\n' 2059 ''), 2060 (self.call.device.RunShellCommand(['dumpsys', 'window', 'windows'], 2061 check_return=True, 2062 large_output=True), []), 2063 (self.call.device.RunShellCommand( 2064 ['input', 'keyevent', '66'], 2065 check_return=True, 2066 )), (self.call.device.RunShellCommand(['input', 'keyevent', '4'], 2067 check_return=True)), 2068 (self.call.device.RunShellCommand(['dumpsys', 'window', 'windows'], 2069 check_return=True, 2070 large_output=True), []), 2071 (self.call.device.RunShellCommand(['input', 'keyevent', '66'], 2072 check_return=True)), 2073 (self.call.device.RunShellCommand(['input', 'keyevent', '4'], 2074 check_return=True)), 2075 (self.call.device.RunShellCommand(['dumpsys', 'window', 'windows'], 2076 check_return=True, 2077 large_output=True), 2078 self.TimeoutError())): 2079 with self.assertRaises(device_errors.CommandTimeoutError): 2080 self.device.GoHome() 2081 2082 def testGoHome_alreadyFocused(self): 2083 with self.assertCall( 2084 self.call.device.RunShellCommand(['dumpsys', 'window', 'windows'], 2085 check_return=True, 2086 large_output=True), 2087 ['mCurrentFocus Launcher']): 2088 self.device.GoHome() 2089 2090 def testGoHome_alreadyFocusedAlternateCase(self): 2091 with self.assertCall( 2092 self.call.device.RunShellCommand(['dumpsys', 'window', 'windows'], 2093 check_return=True, 2094 large_output=True), 2095 [' mCurrentFocus .launcher/.']): 2096 self.device.GoHome() 2097 2098 def testGoHome_obtainsFocusAfterGoingHome(self): 2099 with self.assertCalls( 2100 (self.call.device.RunShellCommand(['dumpsys', 'window', 'windows'], 2101 check_return=True, 2102 large_output=True), []), 2103 (self.call.device.RunShellCommand([ 2104 'am', 'start', '-W', '-a', 'android.intent.action.MAIN', '-c', 2105 'android.intent.category.HOME' 2106 ], 2107 check_return=True), 2108 'Starting: Intent { act=android.intent.action.MAIN }\r\n' 2109 ''), (self.call.device.RunShellCommand( 2110 ['dumpsys', 'window', 'windows'], 2111 check_return=True, 2112 large_output=True), ['mCurrentFocus Launcher'])): 2113 self.device.GoHome() 2114 2115 2116class DeviceUtilsForceStopTest(DeviceUtilsTest): 2117 def testForceStop(self): 2118 with self.assertCalls( 2119 (self.call.device.GetApplicationPids(TEST_PACKAGE), [1111]), 2120 (self.call.device.RunShellCommand(['am', 'force-stop', TEST_PACKAGE], 2121 check_return=True), ['Success'])): 2122 self.device.ForceStop(TEST_PACKAGE) 2123 2124 def testForceStop_NoProcessFound(self): 2125 with self.assertCall(self.call.device.GetApplicationPids(TEST_PACKAGE), []): 2126 self.device.ForceStop(TEST_PACKAGE) 2127 2128 2129class DeviceUtilsClearApplicationStateTest(DeviceUtilsTest): 2130 def testClearApplicationState_setPermissions(self): 2131 with self.assertCalls( 2132 (self.call.device.GetProp('ro.build.version.sdk', cache=True), '17'), 2133 (self.call.device._GetApplicationPathsInternal('this.package.exists'), 2134 ['/data/app/this.package.exists.apk']), 2135 (self.call.device.RunShellCommand( 2136 ['pm', 'clear', 'this.package.exists'], check_return=True), 2137 ['Success']), 2138 (self.call.device.GrantPermissions('this.package.exists', ['p1']), [])): 2139 self.device.ClearApplicationState( 2140 'this.package.exists', permissions=['p1']) 2141 2142 def testClearApplicationState_packageDoesntExist(self): 2143 with self.assertCalls( 2144 (self.call.device.GetProp('ro.build.version.sdk', cache=True), '11'), 2145 (self.call.device._GetApplicationPathsInternal('does.not.exist'), [])): 2146 self.device.ClearApplicationState('does.not.exist') 2147 2148 def testClearApplicationState_packageDoesntExistOnAndroidJBMR2OrAbove(self): 2149 with self.assertCalls( 2150 (self.call.device.GetProp('ro.build.version.sdk', cache=True), '18'), 2151 (self.call.device.RunShellCommand( 2152 ['pm', 'clear', 'this.package.does.not.exist'], check_return=True), 2153 ['Failed'])): 2154 self.device.ClearApplicationState('this.package.does.not.exist') 2155 2156 def testClearApplicationState_packageExists(self): 2157 with self.assertCalls( 2158 (self.call.device.GetProp('ro.build.version.sdk', cache=True), '17'), 2159 (self.call.device._GetApplicationPathsInternal('this.package.exists'), 2160 ['/data/app/this.package.exists.apk']), 2161 (self.call.device.RunShellCommand( 2162 ['pm', 'clear', 'this.package.exists'], check_return=True), 2163 ['Success'])): 2164 self.device.ClearApplicationState('this.package.exists') 2165 2166 def testClearApplicationState_packageExistsOnAndroidJBMR2OrAbove(self): 2167 with self.assertCalls( 2168 (self.call.device.GetProp('ro.build.version.sdk', cache=True), '18'), 2169 (self.call.device.RunShellCommand( 2170 ['pm', 'clear', 'this.package.exists'], check_return=True), 2171 ['Success'])): 2172 self.device.ClearApplicationState('this.package.exists') 2173 2174 2175class DeviceUtilsSendKeyEventTest(DeviceUtilsTest): 2176 def testSendKeyEvent(self): 2177 with self.assertCall(self.call.adb.Shell('input keyevent 66'), ''): 2178 self.device.SendKeyEvent(66) 2179 2180 2181class DeviceUtilsPushChangedFilesIndividuallyTest(DeviceUtilsTest): 2182 def testPushChangedFilesIndividually_empty(self): 2183 test_files = [] 2184 with self.assertCalls(): 2185 self.device._PushChangedFilesIndividually(test_files) 2186 2187 def testPushChangedFilesIndividually_single(self): 2188 test_files = [('/test/host/path', '/test/device/path')] 2189 with self.assertCalls(self.call.adb.Push(*test_files[0])): 2190 self.device._PushChangedFilesIndividually(test_files) 2191 2192 def testPushChangedFilesIndividually_multiple(self): 2193 test_files = [('/test/host/path/file1', '/test/device/path/file1'), 2194 ('/test/host/path/file2', '/test/device/path/file2')] 2195 with self.assertCalls( 2196 self.call.adb.Push(*test_files[0]), self.call.adb.Push(*test_files[1])): 2197 self.device._PushChangedFilesIndividually(test_files) 2198 2199 2200class DeviceUtilsPushChangedFilesZippedTest(DeviceUtilsTest): 2201 def testPushChangedFilesZipped_noUnzipCommand(self): 2202 test_files = [('/test/host/path/file1', '/test/device/path/file1')] 2203 with self.assertCalls((self.call.device._MaybeInstallCommands(), False)): 2204 self.assertFalse( 2205 self.device._PushChangedFilesZipped(test_files, ['/test/dir'])) 2206 2207 def _testPushChangedFilesZipped_spec(self, test_files, test_dirs): 2208 @contextlib.contextmanager 2209 def mock_zip_temp_dir(): 2210 yield '/test/temp/dir' 2211 2212 expected_cmd = ''.join([ 2213 '\n /data/local/tmp/bin/unzip %s &&', 2214 ' (for dir in %s\n do\n chmod -R 777 "$dir" || exit 1\n', 2215 ' done)\n' 2216 ]) % ('/sdcard/foo123.zip', ' '.join(test_dirs)) 2217 with self.assertCalls( 2218 (self.call.device._MaybeInstallCommands(), True), 2219 (mock.call.py_utils.tempfile_ext.NamedTemporaryDirectory(), 2220 mock_zip_temp_dir), (mock.call.devil.utils.zip_utils.WriteZipFile( 2221 '/test/temp/dir/tmp.zip', test_files)), 2222 (mock.call.os.path.getsize('/test/temp/dir/tmp.zip'), 123), 2223 (self.call.device.NeedsSU(), True), 2224 (mock.call.devil.android.device_temp_file.DeviceTempFile( 2225 self.adb, suffix='.zip'), MockTempFile('/sdcard/foo123.zip')), 2226 self.call.adb.Push('/test/temp/dir/tmp.zip', '/sdcard/foo123.zip'), 2227 (mock.call.devil.android.device_temp_file.DeviceTempFile( 2228 self.adb, suffix='.sh'), MockTempFile('/sdcard/temp-123.sh')), 2229 self.call.device.WriteFile('/sdcard/temp-123.sh', expected_cmd), 2230 (self.call.device.RunShellCommand(['source', '/sdcard/temp-123.sh'], 2231 check_return=True, 2232 as_root=True))): 2233 self.assertTrue( 2234 self.device._PushChangedFilesZipped(test_files, test_dirs)) 2235 2236 def testPushChangedFilesZipped_single(self): 2237 self._testPushChangedFilesZipped_spec( 2238 [('/test/host/path/file1', '/test/device/path/file1')], 2239 ['/test/dir1']) 2240 2241 def testPushChangedFilesZipped_multiple(self): 2242 self._testPushChangedFilesZipped_spec( 2243 [('/test/host/path/file1', '/test/device/path/file1'), 2244 ('/test/host/path/file2', '/test/device/path/file2')], 2245 ['/test/dir1', '/test/dir2']) 2246 2247 2248class DeviceUtilsPathExistsTest(DeviceUtilsTest): 2249 def testPathExists_pathExists(self): 2250 with self.assertCall( 2251 self.call.device.RunShellCommand(['test', '-e', '/path/file exists'], 2252 as_root=False, 2253 check_return=True, 2254 timeout=10, 2255 retries=0), []): 2256 self.assertTrue(self.device.PathExists('/path/file exists')) 2257 2258 def testPathExists_multiplePathExists(self): 2259 with self.assertCall( 2260 self.call.device.RunShellCommand( 2261 ['test', '-e', '/path 1', '-a', '-e', '/path2'], 2262 as_root=False, 2263 check_return=True, 2264 timeout=10, 2265 retries=0), []): 2266 self.assertTrue(self.device.PathExists(('/path 1', '/path2'))) 2267 2268 def testPathExists_pathDoesntExist(self): 2269 with self.assertCall( 2270 self.call.device.RunShellCommand( 2271 ['test', '-e', '/path/file.not.exists'], 2272 as_root=False, 2273 check_return=True, 2274 timeout=10, 2275 retries=0), self.ShellError()): 2276 self.assertFalse(self.device.PathExists('/path/file.not.exists')) 2277 2278 def testPathExists_asRoot(self): 2279 with self.assertCall( 2280 self.call.device.RunShellCommand(['test', '-e', '/root/path/exists'], 2281 as_root=True, 2282 check_return=True, 2283 timeout=10, 2284 retries=0), self.ShellError()): 2285 self.assertFalse( 2286 self.device.PathExists('/root/path/exists', as_root=True)) 2287 2288 def testFileExists_pathDoesntExist(self): 2289 with self.assertCall( 2290 self.call.device.RunShellCommand( 2291 ['test', '-e', '/path/file.not.exists'], 2292 as_root=False, 2293 check_return=True, 2294 timeout=10, 2295 retries=0), self.ShellError()): 2296 self.assertFalse(self.device.FileExists('/path/file.not.exists')) 2297 2298 2299class DeviceUtilsRemovePathTest(DeviceUtilsTest): 2300 def testRemovePath_regular(self): 2301 with self.assertCall( 2302 self.call.device.RunShellCommand(['rm', 'some file'], 2303 as_root=False, 2304 check_return=True), []): 2305 self.device.RemovePath('some file') 2306 2307 def testRemovePath_withForce(self): 2308 with self.assertCall( 2309 self.call.device.RunShellCommand(['rm', '-f', 'some file'], 2310 as_root=False, 2311 check_return=True), []): 2312 self.device.RemovePath('some file', force=True) 2313 2314 def testRemovePath_recursively(self): 2315 with self.assertCall( 2316 self.call.device.RunShellCommand(['rm', '-r', '/remove/this/dir'], 2317 as_root=False, 2318 check_return=True), []): 2319 self.device.RemovePath('/remove/this/dir', recursive=True) 2320 2321 def testRemovePath_withRoot(self): 2322 with self.assertCall( 2323 self.call.device.RunShellCommand(['rm', 'some file'], 2324 as_root=True, 2325 check_return=True), []): 2326 self.device.RemovePath('some file', as_root=True) 2327 2328 def testRemovePath_manyPaths(self): 2329 with self.assertCall( 2330 self.call.device.RunShellCommand(['rm', 'eeny', 'meeny', 'miny', 'moe'], 2331 as_root=False, 2332 check_return=True), []): 2333 self.device.RemovePath(['eeny', 'meeny', 'miny', 'moe']) 2334 2335 2336class DeviceUtilsPullFileTest(DeviceUtilsTest): 2337 def testPullFile_existsOnDevice(self): 2338 with mock.patch('os.path.exists', return_value=True): 2339 with self.assertCall( 2340 self.call.adb.Pull('/data/app/test.file.exists', 2341 '/test/file/host/path')): 2342 self.device.PullFile('/data/app/test.file.exists', 2343 '/test/file/host/path') 2344 2345 def testPullFile_doesntExistOnDevice(self): 2346 with mock.patch('os.path.exists', return_value=True): 2347 with self.assertCall( 2348 self.call.adb.Pull('/data/app/test.file.does.not.exist', 2349 '/test/file/host/path'), 2350 self.CommandError('remote object does not exist')): 2351 with self.assertRaises(device_errors.CommandFailedError): 2352 self.device.PullFile('/data/app/test.file.does.not.exist', 2353 '/test/file/host/path') 2354 2355 def testPullFile_asRoot(self): 2356 with mock.patch('os.path.exists', return_value=True): 2357 with self.assertCalls( 2358 (self.call.device.NeedsSU(), True), (self.call.device.PathExists( 2359 '/this/file/can.be.read.with.su', as_root=True), True), 2360 (mock.call.devil.android.device_temp_file.DeviceTempFile(self.adb), 2361 MockTempFile('/sdcard/tmp/on.device')), 2362 self.call.device.RunShellCommand( 2363 'SRC=/this/file/can.be.read.with.su DEST=/sdcard/tmp/on.device;' 2364 'cp "$SRC" "$DEST" && chmod 666 "$DEST"', 2365 shell=True, 2366 as_root=True, 2367 check_return=True), (self.call.adb.Pull('/sdcard/tmp/on.device', 2368 '/test/file/host/path'))): 2369 self.device.PullFile( 2370 '/this/file/can.be.read.with.su', 2371 '/test/file/host/path', 2372 as_root=True) 2373 2374 def testPullFile_asRootDoesntExistOnDevice(self): 2375 with mock.patch('os.path.exists', return_value=True): 2376 with self.assertCalls( 2377 (self.call.device.NeedsSU(), True), (self.call.device.PathExists( 2378 '/data/app/test.file.does.not.exist', as_root=True), False)): 2379 with self.assertRaises(device_errors.CommandFailedError): 2380 self.device.PullFile( 2381 '/data/app/test.file.does.not.exist', 2382 '/test/file/host/path', 2383 as_root=True) 2384 2385 2386class DeviceUtilsReadFileTest(DeviceUtilsTest): 2387 def testReadFileWithPull_success(self): 2388 tmp_host_dir = '/tmp/dir/on.host/' 2389 tmp_host = MockTempFile('/tmp/dir/on.host/tmp_ReadFileWithPull') 2390 tmp_host.file.read.return_value = 'some interesting contents' 2391 with self.assertCalls( 2392 (mock.call.tempfile.mkdtemp(), tmp_host_dir), 2393 (self.call.adb.Pull('/path/to/device/file', mock.ANY)), 2394 (mock.call.__builtin__.open(mock.ANY, 'r'), tmp_host) if six.PY2 else \ 2395 (mock.call.builtins.open(mock.ANY, 'r'), tmp_host), 2396 (mock.call.os.path.exists(tmp_host_dir), True), 2397 (mock.call.shutil.rmtree(tmp_host_dir), None)): 2398 self.assertEquals('some interesting contents', 2399 self.device._ReadFileWithPull('/path/to/device/file')) 2400 tmp_host.file.read.assert_called_once_with() 2401 2402 def testReadFileWithPull_rejected(self): 2403 tmp_host_dir = '/tmp/dir/on.host/' 2404 with self.assertCalls((mock.call.tempfile.mkdtemp(), tmp_host_dir), 2405 (self.call.adb.Pull('/path/to/device/file', mock.ANY), 2406 self.CommandError()), 2407 (mock.call.os.path.exists(tmp_host_dir), True), 2408 (mock.call.shutil.rmtree(tmp_host_dir), None)): 2409 with self.assertRaises(device_errors.CommandFailedError): 2410 self.device._ReadFileWithPull('/path/to/device/file') 2411 2412 def testReadFile_withSU_zeroSize(self): 2413 with self.assertCalls( 2414 (self.call.device.NeedsSU(), True), 2415 (self.call.device.FileSize( 2416 '/this/file/has/zero/size', as_root=True), 0), 2417 (mock.call.devil.android.device_temp_file.DeviceTempFile(self.adb), 2418 MockTempFile('/sdcard/tmp/on.device')), 2419 self.call.device.RunShellCommand( 2420 'SRC=/this/file/has/zero/size DEST=/sdcard/tmp/on.device;' 2421 'cp "$SRC" "$DEST" && chmod 666 "$DEST"', 2422 shell=True, 2423 as_root=True, 2424 check_return=True), 2425 (self.call.device._ReadFileWithPull('/sdcard/tmp/on.device'), 2426 'but it has contents\n')): 2427 self.assertEqual('but it has contents\n', 2428 self.device.ReadFile('/this/file/has/zero/size', 2429 as_root=True)) 2430 2431 def testReadFile_withSU(self): 2432 with self.assertCalls( 2433 (self.call.device.NeedsSU(), True), 2434 (self.call.device.FileSize( 2435 '/this/file/can.be.read.with.su', as_root=True), 256), 2436 (self.call.device.RunShellCommand( 2437 ['cat', '/this/file/can.be.read.with.su'], 2438 as_root=True, 2439 check_return=True), ['this is a test file', 'read with su'])): 2440 self.assertEqual( 2441 'this is a test file\nread with su\n', 2442 self.device.ReadFile('/this/file/can.be.read.with.su', as_root=True)) 2443 2444 def testReadFile_withSU_doesNotExist(self): 2445 with self.assertCalls( 2446 (self.call.device.NeedsSU(), True), 2447 (self.call.device.FileSize('/this/file/does.not.exist', as_root=True), 2448 self.CommandError('File does not exist'))): 2449 with self.assertRaises(device_errors.CommandFailedError): 2450 self.device.ReadFile('/this/file/does.not.exist', as_root=True) 2451 2452 def testReadFile_withPull(self): 2453 contents = 'a' * 123456 2454 with self.assertCalls( 2455 (self.call.device._ReadFileWithPull('/read/this/big/test/file'), 2456 contents)): 2457 self.assertEqual(contents, 2458 self.device.ReadFile('/read/this/big/test/file')) 2459 2460 def testReadFile_withPullAndSU(self): 2461 contents = 'b' * 123456 2462 with self.assertCalls( 2463 (self.call.device.NeedsSU(), True), 2464 (self.call.device.FileSize( 2465 '/this/big/file/can.be.read.with.su', as_root=True), 123456), 2466 (mock.call.devil.android.device_temp_file.DeviceTempFile(self.adb), 2467 MockTempFile('/sdcard/tmp/on.device')), 2468 self.call.device.RunShellCommand( 2469 'SRC=/this/big/file/can.be.read.with.su DEST=/sdcard/tmp/on.device;' 2470 'cp "$SRC" "$DEST" && chmod 666 "$DEST"', 2471 shell=True, 2472 as_root=True, 2473 check_return=True), 2474 (self.call.device._ReadFileWithPull('/sdcard/tmp/on.device'), 2475 contents)): 2476 self.assertEqual( 2477 contents, 2478 self.device.ReadFile( 2479 '/this/big/file/can.be.read.with.su', as_root=True)) 2480 2481 def testReadFile_forcePull(self): 2482 contents = 'a' * 123456 2483 with self.assertCall( 2484 self.call.device._ReadFileWithPull('/read/this/big/test/file'), 2485 contents): 2486 self.assertEqual( 2487 contents, 2488 self.device.ReadFile('/read/this/big/test/file', force_pull=True)) 2489 2490 2491class DeviceUtilsWriteFileTest(DeviceUtilsTest): 2492 def testWriteFileWithPush_success(self): 2493 tmp_host = MockTempFile('/tmp/file/on.host') 2494 contents = 'some interesting contents' 2495 with self.assertCalls((mock.call.tempfile.NamedTemporaryFile(), tmp_host), 2496 self.call.adb.Push('/tmp/file/on.host', 2497 '/path/to/device/file')): 2498 self.device._WriteFileWithPush('/path/to/device/file', contents) 2499 tmp_host.file.write.assert_called_once_with(contents) 2500 2501 def testWriteFileWithPush_rejected(self): 2502 tmp_host = MockTempFile('/tmp/file/on.host') 2503 contents = 'some interesting contents' 2504 with self.assertCalls( 2505 (mock.call.tempfile.NamedTemporaryFile(), tmp_host), 2506 (self.call.adb.Push('/tmp/file/on.host', '/path/to/device/file'), 2507 self.CommandError())): 2508 with self.assertRaises(device_errors.CommandFailedError): 2509 self.device._WriteFileWithPush('/path/to/device/file', contents) 2510 2511 def testWriteFile_withPush(self): 2512 contents = 'some large contents ' * 26 # 20 * 26 = 520 chars 2513 with self.assertCalls( 2514 self.call.device._WriteFileWithPush('/path/to/device/file', contents)): 2515 self.device.WriteFile('/path/to/device/file', contents) 2516 2517 def testWriteFile_withPushForced(self): 2518 contents = 'tiny contents' 2519 with self.assertCalls( 2520 self.call.device._WriteFileWithPush('/path/to/device/file', contents)): 2521 self.device.WriteFile('/path/to/device/file', contents, force_push=True) 2522 2523 def testWriteFile_withPushAndSU(self): 2524 contents = 'some large contents ' * 26 # 20 * 26 = 520 chars 2525 with self.assertCalls( 2526 (self.call.device.NeedsSU(), True), 2527 (mock.call.devil.android.device_temp_file.DeviceTempFile(self.adb), 2528 MockTempFile('/sdcard/tmp/on.device')), 2529 self.call.device._WriteFileWithPush('/sdcard/tmp/on.device', contents), 2530 self.call.device.RunShellCommand( 2531 ['cp', '/sdcard/tmp/on.device', '/path/to/device/file'], 2532 as_root=True, 2533 check_return=True)): 2534 self.device.WriteFile('/path/to/device/file', contents, as_root=True) 2535 2536 def testWriteFile_withEcho(self): 2537 with self.assertCall( 2538 self.call.adb.Shell("echo -n the.contents > /test/file/to.write"), ''): 2539 self.device.WriteFile('/test/file/to.write', 'the.contents') 2540 2541 def testWriteFile_withEchoAndQuotes(self): 2542 with self.assertCall( 2543 self.call.adb.Shell("echo -n 'the contents' > '/test/file/to write'"), 2544 ''): 2545 self.device.WriteFile('/test/file/to write', 'the contents') 2546 2547 def testWriteFile_withEchoAndSU(self): 2548 expected_cmd_without_su = "sh -c 'echo -n contents > /test/file'" 2549 expected_cmd = 'su -c %s' % expected_cmd_without_su 2550 with self.assertCalls( 2551 (self.call.device.NeedsSU(), True), 2552 (self.call.device._Su(expected_cmd_without_su), expected_cmd), 2553 (self.call.adb.Shell(expected_cmd), '')): 2554 self.device.WriteFile('/test/file', 'contents', as_root=True) 2555 2556 2557class DeviceUtilsStatDirectoryTest(DeviceUtilsTest): 2558 # Note: Also tests ListDirectory in testStatDirectory_fileList. 2559 2560 EXAMPLE_LS_OUTPUT = [ 2561 'total 12345', 2562 'drwxr-xr-x 19 root root 0 1970-04-06 18:03 .', 2563 'drwxr-xr-x 19 root root 0 1970-04-06 18:03 ..', 2564 'drwxr-xr-x 6 root root 1970-01-01 00:00 some_dir', 2565 '-rw-r--r-- 1 root root 723 1971-01-01 07:04 some_file', 2566 '-rw-r----- 1 root root 327 2009-02-13 23:30 My Music File', 2567 # Some Android versions escape spaces in file names 2568 '-rw-rw-rw- 1 root root 0 2018-01-11 13:35 Local\\ State', 2569 # Older Android versions do not print st_nlink 2570 'lrwxrwxrwx root root 1970-01-01 00:00 lnk -> /a/path', 2571 'srwxrwx--- system system 2016-05-31 17:25 a_socket1', 2572 'drwxrwxrwt system misc 1970-11-23 02:25 tmp', 2573 'drwxr-s--- system shell 1970-11-23 02:24 my_cmd', 2574 'cr--r----- root system 10, 183 1971-01-01 07:04 random', 2575 'brw------- root root 7, 0 1971-01-01 07:04 block_dev', 2576 '-rwS------ root shell 157404 2015-04-13 15:44 silly', 2577 ] 2578 2579 FILENAMES = [ 2580 'some_dir', 'some_file', 'My Music File', 'Local State', 'lnk', 2581 'a_socket1', 'tmp', 'my_cmd', 'random', 'block_dev', 'silly' 2582 ] 2583 2584 def getStatEntries(self, path_given='/', path_listed='/'): 2585 with self.assertCall( 2586 self.call.device.RunShellCommand(['ls', '-a', '-l', path_listed], 2587 check_return=True, 2588 as_root=False, 2589 env={'TZ': 'utc'}), 2590 self.EXAMPLE_LS_OUTPUT): 2591 entries = self.device.StatDirectory(path_given) 2592 return {f['filename']: f for f in entries} 2593 2594 def getListEntries(self): 2595 with self.assertCall( 2596 self.call.device.RunShellCommand(['ls', '-a', '-l', '/'], 2597 check_return=True, 2598 as_root=False, 2599 env={'TZ': 'utc'}), 2600 self.EXAMPLE_LS_OUTPUT): 2601 return self.device.ListDirectory('/') 2602 2603 def testStatDirectory_forceTrailingSlash(self): 2604 self.getStatEntries(path_given='/foo/bar/', path_listed='/foo/bar/') 2605 self.getStatEntries(path_given='/foo/bar', path_listed='/foo/bar/') 2606 2607 def testStatDirectory_fileList(self): 2608 self.safeAssertItemsEqual(self.getStatEntries().keys(), self.FILENAMES) 2609 self.safeAssertItemsEqual(self.getListEntries(), self.FILENAMES) 2610 2611 def testStatDirectory_fileModes(self): 2612 expected_modes = ( 2613 ('some_dir', stat.S_ISDIR), 2614 ('some_file', stat.S_ISREG), 2615 ('lnk', stat.S_ISLNK), 2616 ('a_socket1', stat.S_ISSOCK), 2617 ('block_dev', stat.S_ISBLK), 2618 ('random', stat.S_ISCHR), 2619 ) 2620 entries = self.getStatEntries() 2621 for filename, check in expected_modes: 2622 self.assertTrue(check(entries[filename]['st_mode'])) 2623 2624 def testStatDirectory_filePermissions(self): 2625 should_have = ( 2626 ('some_file', stat.S_IWUSR), # Owner can write. 2627 ('tmp', stat.S_IXOTH), # Others can execute. 2628 ('tmp', stat.S_ISVTX), # Has sticky bit. 2629 ('my_cmd', stat.S_ISGID), # Has set-group-ID bit. 2630 ('silly', stat.S_ISUID), # Has set UID bit. 2631 ) 2632 should_not_have = ( 2633 ('some_file', stat.S_IWOTH), # Others can't write. 2634 ('block_dev', stat.S_IRGRP), # Group can't read. 2635 ('silly', stat.S_IXUSR), # Owner can't execute. 2636 ) 2637 entries = self.getStatEntries() 2638 for filename, bit in should_have: 2639 self.assertTrue(entries[filename]['st_mode'] & bit) 2640 for filename, bit in should_not_have: 2641 self.assertFalse(entries[filename]['st_mode'] & bit) 2642 2643 def testStatDirectory_numHardLinks(self): 2644 entries = self.getStatEntries() 2645 self.assertEqual(entries['some_dir']['st_nlink'], 6) 2646 self.assertEqual(entries['some_file']['st_nlink'], 1) 2647 self.assertFalse('st_nlink' in entries['tmp']) 2648 2649 def testStatDirectory_fileOwners(self): 2650 entries = self.getStatEntries() 2651 self.assertEqual(entries['some_dir']['st_owner'], 'root') 2652 self.assertEqual(entries['my_cmd']['st_owner'], 'system') 2653 self.assertEqual(entries['my_cmd']['st_group'], 'shell') 2654 self.assertEqual(entries['tmp']['st_group'], 'misc') 2655 2656 def testStatDirectory_fileSize(self): 2657 entries = self.getStatEntries() 2658 self.assertEqual(entries['some_file']['st_size'], 723) 2659 self.assertEqual(entries['My Music File']['st_size'], 327) 2660 # Sizes are sometimes not reported for non-regular files, don't try to 2661 # guess the size in those cases. 2662 self.assertFalse('st_size' in entries['some_dir']) 2663 2664 def testStatDirectory_fileDateTime(self): 2665 entries = self.getStatEntries() 2666 self.assertEqual(entries['some_dir']['st_mtime'], 0) # Epoch! 2667 self.assertEqual(entries['My Music File']['st_mtime'], 1234567800) 2668 2669 def testStatDirectory_deviceType(self): 2670 entries = self.getStatEntries() 2671 self.assertEqual(entries['random']['st_rdev_pair'], (10, 183)) 2672 self.assertEqual(entries['block_dev']['st_rdev_pair'], (7, 0)) 2673 2674 def testStatDirectory_symbolicLinks(self): 2675 entries = self.getStatEntries() 2676 self.assertEqual(entries['lnk']['symbolic_link_to'], '/a/path') 2677 for d in entries.values(): 2678 self.assertEqual('symbolic_link_to' in d, stat.S_ISLNK(d['st_mode'])) 2679 2680 2681class DeviceUtilsStatPathTest(DeviceUtilsTest): 2682 2683 EXAMPLE_DIRECTORY = [{ 2684 'filename': 'foo.txt', 2685 'st_size': 123, 2686 'st_time': 456 2687 }, { 2688 'filename': 'some_dir', 2689 'st_time': 0 2690 }] 2691 INDEX = {e['filename']: e for e in EXAMPLE_DIRECTORY} 2692 2693 def testStatPath_file(self): 2694 with self.assertCall( 2695 self.call.device.StatDirectory('/data/local/tmp', as_root=False), 2696 self.EXAMPLE_DIRECTORY): 2697 self.assertEquals(self.INDEX['foo.txt'], 2698 self.device.StatPath('/data/local/tmp/foo.txt')) 2699 2700 def testStatPath_directory(self): 2701 with self.assertCall( 2702 self.call.device.StatDirectory('/data/local/tmp', as_root=False), 2703 self.EXAMPLE_DIRECTORY): 2704 self.assertEquals(self.INDEX['some_dir'], 2705 self.device.StatPath('/data/local/tmp/some_dir')) 2706 2707 def testStatPath_directoryWithTrailingSlash(self): 2708 with self.assertCall( 2709 self.call.device.StatDirectory('/data/local/tmp', as_root=False), 2710 self.EXAMPLE_DIRECTORY): 2711 self.assertEquals(self.INDEX['some_dir'], 2712 self.device.StatPath('/data/local/tmp/some_dir/')) 2713 2714 def testStatPath_doesNotExist(self): 2715 with self.assertCall( 2716 self.call.device.StatDirectory('/data/local/tmp', as_root=False), 2717 self.EXAMPLE_DIRECTORY): 2718 with self.assertRaises(device_errors.CommandFailedError): 2719 self.device.StatPath('/data/local/tmp/does.not.exist.txt') 2720 2721 2722class DeviceUtilsFileSizeTest(DeviceUtilsTest): 2723 2724 EXAMPLE_DIRECTORY = [{ 2725 'filename': 'foo.txt', 2726 'st_size': 123, 2727 'st_mtime': 456 2728 }, { 2729 'filename': 'some_dir', 2730 'st_mtime': 0 2731 }] 2732 2733 def testFileSize_file(self): 2734 with self.assertCall( 2735 self.call.device.StatDirectory('/data/local/tmp', as_root=False), 2736 self.EXAMPLE_DIRECTORY): 2737 self.assertEquals(123, self.device.FileSize('/data/local/tmp/foo.txt')) 2738 2739 def testFileSize_doesNotExist(self): 2740 with self.assertCall( 2741 self.call.device.StatDirectory('/data/local/tmp', as_root=False), 2742 self.EXAMPLE_DIRECTORY): 2743 with self.assertRaises(device_errors.CommandFailedError): 2744 self.device.FileSize('/data/local/tmp/does.not.exist.txt') 2745 2746 def testFileSize_directoryWithNoSize(self): 2747 with self.assertCall( 2748 self.call.device.StatDirectory('/data/local/tmp', as_root=False), 2749 self.EXAMPLE_DIRECTORY): 2750 with self.assertRaises(device_errors.CommandFailedError): 2751 self.device.FileSize('/data/local/tmp/some_dir') 2752 2753 2754class DeviceUtilsSetJavaAssertsTest(DeviceUtilsTest): 2755 def testSetJavaAsserts_enable(self): 2756 with self.assertCalls( 2757 (self.call.device.ReadFile(self.device.LOCAL_PROPERTIES_PATH), 2758 'some.example.prop=with an example value\n' 2759 'some.other.prop=value_ok\n'), 2760 self.call.device.WriteFile( 2761 self.device.LOCAL_PROPERTIES_PATH, 2762 'some.example.prop=with an example value\n' 2763 'some.other.prop=value_ok\n' 2764 'dalvik.vm.enableassertions=all\n'), 2765 (self.call.device.GetProp('dalvik.vm.enableassertions'), ''), 2766 self.call.device.SetProp('dalvik.vm.enableassertions', 'all')): 2767 self.assertTrue(self.device.SetJavaAsserts(True)) 2768 2769 def testSetJavaAsserts_disable(self): 2770 with self.assertCalls( 2771 (self.call.device.ReadFile(self.device.LOCAL_PROPERTIES_PATH), 2772 'some.example.prop=with an example value\n' 2773 'dalvik.vm.enableassertions=all\n' 2774 'some.other.prop=value_ok\n'), 2775 self.call.device.WriteFile( 2776 self.device.LOCAL_PROPERTIES_PATH, 2777 'some.example.prop=with an example value\n' 2778 'some.other.prop=value_ok\n'), 2779 (self.call.device.GetProp('dalvik.vm.enableassertions'), 'all'), 2780 self.call.device.SetProp('dalvik.vm.enableassertions', '')): 2781 self.assertTrue(self.device.SetJavaAsserts(False)) 2782 2783 def testSetJavaAsserts_alreadyEnabled(self): 2784 with self.assertCalls( 2785 (self.call.device.ReadFile(self.device.LOCAL_PROPERTIES_PATH), 2786 'some.example.prop=with an example value\n' 2787 'dalvik.vm.enableassertions=all\n' 2788 'some.other.prop=value_ok\n'), 2789 (self.call.device.GetProp('dalvik.vm.enableassertions'), 'all')): 2790 self.assertFalse(self.device.SetJavaAsserts(True)) 2791 2792 def testSetJavaAsserts_malformedLocalProp(self): 2793 with self.assertCalls( 2794 (self.call.device.ReadFile(self.device.LOCAL_PROPERTIES_PATH), 2795 'some.example.prop=with an example value\n' 2796 'malformed_property\n' 2797 'dalvik.vm.enableassertions=all\n' 2798 'some.other.prop=value_ok\n'), 2799 (self.call.device.GetProp('dalvik.vm.enableassertions'), 'all')): 2800 self.assertFalse(self.device.SetJavaAsserts(True)) 2801 2802 2803class DeviceUtilsEnsureCacheInitializedTest(DeviceUtilsTest): 2804 def testEnsureCacheInitialized_noCache_success(self): 2805 self.assertIsNone(self.device._cache['token']) 2806 with self.assertCall( 2807 self.call.device.RunShellCommand( 2808 AnyStringWith('getprop'), 2809 shell=True, 2810 check_return=True, 2811 large_output=True), ['/sdcard', 'TOKEN']): 2812 self.device._EnsureCacheInitialized() 2813 self.assertIsNotNone(self.device._cache['token']) 2814 2815 def testEnsureCacheInitialized_noCache_failure(self): 2816 self.assertIsNone(self.device._cache['token']) 2817 with self.assertCall( 2818 self.call.device.RunShellCommand( 2819 AnyStringWith('getprop'), 2820 shell=True, 2821 check_return=True, 2822 large_output=True), self.TimeoutError()): 2823 with self.assertRaises(device_errors.CommandTimeoutError): 2824 self.device._EnsureCacheInitialized() 2825 self.assertIsNone(self.device._cache['token']) 2826 2827 def testEnsureCacheInitialized_cache(self): 2828 self.device._cache['token'] = 'TOKEN' 2829 with self.assertCalls(): 2830 self.device._EnsureCacheInitialized() 2831 self.assertIsNotNone(self.device._cache['token']) 2832 2833 2834class DeviceUtilsGetPropTest(DeviceUtilsTest): 2835 def testGetProp_exists(self): 2836 with self.assertCall( 2837 self.call.device.RunShellCommand(['getprop', 'test.property'], 2838 check_return=True, 2839 single_line=True, 2840 timeout=self.device._default_timeout, 2841 retries=self.device._default_retries), 2842 'property_value'): 2843 self.assertEqual('property_value', self.device.GetProp('test.property')) 2844 2845 def testGetProp_doesNotExist(self): 2846 with self.assertCall( 2847 self.call.device.RunShellCommand(['getprop', 'property.does.not.exist'], 2848 check_return=True, 2849 single_line=True, 2850 timeout=self.device._default_timeout, 2851 retries=self.device._default_retries), 2852 ''): 2853 self.assertEqual('', self.device.GetProp('property.does.not.exist')) 2854 2855 def testGetProp_cachedRoProp(self): 2856 with self.assertCalls( 2857 self.EnsureCacheInitialized(props=['[ro.build.type]: [userdebug]'])): 2858 self.assertEqual('userdebug', 2859 self.device.GetProp('ro.build.type', cache=True)) 2860 self.assertEqual('userdebug', 2861 self.device.GetProp('ro.build.type', cache=True)) 2862 2863 2864class DeviceUtilsSetPropTest(DeviceUtilsTest): 2865 def testSetProp(self): 2866 with self.assertCall( 2867 self.call.device.RunShellCommand( 2868 ['setprop', 'test.property', 'test value'], check_return=True)): 2869 self.device.SetProp('test.property', 'test value') 2870 2871 def testSetProp_check_succeeds(self): 2872 with self.assertCalls( 2873 (self.call.device.RunShellCommand( 2874 ['setprop', 'test.property', 'new_value'], check_return=True)), 2875 (self.call.device.GetProp('test.property', cache=False), 'new_value')): 2876 self.device.SetProp('test.property', 'new_value', check=True) 2877 2878 def testSetProp_check_fails(self): 2879 with self.assertCalls( 2880 (self.call.device.RunShellCommand( 2881 ['setprop', 'test.property', 'new_value'], check_return=True)), 2882 (self.call.device.GetProp('test.property', cache=False), 'old_value')): 2883 with self.assertRaises(device_errors.CommandFailedError): 2884 self.device.SetProp('test.property', 'new_value', check=True) 2885 2886 2887class DeviceUtilsListProcessesTest(DeviceUtilsTest): 2888 def setUp(self): 2889 super(DeviceUtilsListProcessesTest, self).setUp() 2890 self.sample_output = [ 2891 'USER PID PPID VSIZE RSS WCHAN PC NAME', 2892 'user 1001 100 1024 1024 ffffffff 00000000 one.match', 2893 'user 1002 100 1024 1024 ffffffff 00000000 two.match', 2894 'user 1003 101 1024 1024 ffffffff 00000000 three.match', 2895 'user 1234 101 1024 1024 ffffffff 00000000 my$process', 2896 'user 1236 100 1024 1024 ffffffff 00000000 foo', 2897 'user 1578 1236 1024 1024 ffffffff 00000000 foo', 2898 ] 2899 2900 def _grepOutput(self, substring): 2901 return [line for line in self.sample_output if substring in line] 2902 2903 def testListProcesses_sdkGreaterThanNougatMR1(self): 2904 with self.patch_call( 2905 self.call.device.build_version_sdk, 2906 return_value=(version_codes.NOUGAT_MR1 + 1)): 2907 with self.patch_call(self.call.device.build_id, return_value='ZZZ99Z'): 2908 with self.assertCall( 2909 self.call.device._RunPipedShellCommand( 2910 'ps -e | grep -F example.process'), []): 2911 self.device.ListProcesses('example.process') 2912 2913 def testListProcesses_noMatches(self): 2914 with self.patch_call( 2915 self.call.device.build_version_sdk, 2916 return_value=version_codes.LOLLIPOP): 2917 with self.assertCall( 2918 self.call.device._RunPipedShellCommand('ps | grep -F does.not.match'), 2919 self._grepOutput('does.not.match')): 2920 self.assertEqual([], self.device.ListProcesses('does.not.match')) 2921 2922 def testListProcesses_oneMatch(self): 2923 with self.patch_call( 2924 self.call.device.build_version_sdk, 2925 return_value=version_codes.LOLLIPOP): 2926 with self.assertCall( 2927 self.call.device._RunPipedShellCommand('ps | grep -F one.match'), 2928 self._grepOutput('one.match')): 2929 self.assertEqual( 2930 Processes(('one.match', 1001, 100)), 2931 self.device.ListProcesses('one.match')) 2932 2933 def testListProcesses_multipleMatches(self): 2934 with self.patch_call( 2935 self.call.device.build_version_sdk, 2936 return_value=version_codes.LOLLIPOP): 2937 with self.assertCall( 2938 self.call.device._RunPipedShellCommand('ps | grep -F match'), 2939 self._grepOutput('match')): 2940 self.assertEqual( 2941 Processes(('one.match', 1001, 100), ('two.match', 1002, 100), 2942 ('three.match', 1003, 101)), 2943 self.device.ListProcesses('match')) 2944 2945 def testListProcesses_quotable(self): 2946 with self.patch_call( 2947 self.call.device.build_version_sdk, 2948 return_value=version_codes.LOLLIPOP): 2949 with self.assertCall( 2950 self.call.device._RunPipedShellCommand("ps | grep -F 'my$process'"), 2951 self._grepOutput('my$process')): 2952 self.assertEqual( 2953 Processes(('my$process', 1234, 101)), 2954 self.device.ListProcesses('my$process')) 2955 2956 # Tests for the GetPids wrapper interface. 2957 def testGetPids_multipleInstances(self): 2958 with self.patch_call( 2959 self.call.device.build_version_sdk, 2960 return_value=version_codes.LOLLIPOP): 2961 with self.assertCall( 2962 self.call.device._RunPipedShellCommand('ps | grep -F foo'), 2963 self._grepOutput('foo')): 2964 self.assertEqual({'foo': ['1236', '1578']}, self.device.GetPids('foo')) 2965 2966 def testGetPids_allProcesses(self): 2967 with self.patch_call( 2968 self.call.device.build_version_sdk, 2969 return_value=version_codes.LOLLIPOP): 2970 with self.assertCall( 2971 self.call.device.RunShellCommand(['ps'], 2972 check_return=True, 2973 large_output=True), 2974 self.sample_output): 2975 self.assertEqual({ 2976 'one.match': ['1001'], 2977 'two.match': ['1002'], 2978 'three.match': ['1003'], 2979 'my$process': ['1234'], 2980 'foo': ['1236', '1578'] 2981 }, self.device.GetPids()) 2982 2983 # Tests for the GetApplicationPids wrapper interface. 2984 def testGetApplicationPids_notFound(self): 2985 with self.patch_call( 2986 self.call.device.build_version_sdk, 2987 return_value=version_codes.LOLLIPOP): 2988 with self.assertCall( 2989 self.call.device._RunPipedShellCommand('ps | grep -F match'), 2990 self._grepOutput('match')): 2991 # No PIDs found, process name should be exact match. 2992 self.assertEqual([], self.device.GetApplicationPids('match')) 2993 2994 def testGetApplicationPids_foundOne(self): 2995 with self.patch_call( 2996 self.call.device.build_version_sdk, 2997 return_value=version_codes.LOLLIPOP): 2998 with self.assertCall( 2999 self.call.device._RunPipedShellCommand('ps | grep -F one.match'), 3000 self._grepOutput('one.match')): 3001 self.assertEqual([1001], self.device.GetApplicationPids('one.match')) 3002 3003 def testGetApplicationPids_foundMany(self): 3004 with self.patch_call( 3005 self.call.device.build_version_sdk, 3006 return_value=version_codes.LOLLIPOP): 3007 with self.assertCall( 3008 self.call.device._RunPipedShellCommand('ps | grep -F foo'), 3009 self._grepOutput('foo')): 3010 self.assertEqual([1236, 1578], self.device.GetApplicationPids('foo')) 3011 3012 def testGetApplicationPids_atMostOneNotFound(self): 3013 with self.patch_call( 3014 self.call.device.build_version_sdk, 3015 return_value=version_codes.LOLLIPOP): 3016 with self.assertCall( 3017 self.call.device._RunPipedShellCommand('ps | grep -F match'), 3018 self._grepOutput('match')): 3019 # No PIDs found, process name should be exact match. 3020 self.assertEqual( 3021 None, self.device.GetApplicationPids('match', at_most_one=True)) 3022 3023 def testGetApplicationPids_atMostOneFound(self): 3024 with self.patch_call( 3025 self.call.device.build_version_sdk, 3026 return_value=version_codes.LOLLIPOP): 3027 with self.assertCall( 3028 self.call.device._RunPipedShellCommand('ps | grep -F one.match'), 3029 self._grepOutput('one.match')): 3030 self.assertEqual( 3031 1001, self.device.GetApplicationPids('one.match', at_most_one=True)) 3032 3033 def testGetApplicationPids_atMostOneFoundTooMany(self): 3034 with self.patch_call( 3035 self.call.device.build_version_sdk, 3036 return_value=version_codes.LOLLIPOP): 3037 with self.assertRaises(device_errors.CommandFailedError): 3038 with self.assertCall( 3039 self.call.device._RunPipedShellCommand('ps | grep -F foo'), 3040 self._grepOutput('foo')): 3041 self.device.GetApplicationPids('foo', at_most_one=True) 3042 3043 3044class DeviceUtilsGetSetEnforce(DeviceUtilsTest): 3045 def testGetEnforce_Enforcing(self): 3046 with self.assertCall(self.call.adb.Shell('getenforce'), 'Enforcing'): 3047 self.assertEqual(True, self.device.GetEnforce()) 3048 3049 def testGetEnforce_Permissive(self): 3050 with self.assertCall(self.call.adb.Shell('getenforce'), 'Permissive'): 3051 self.assertEqual(False, self.device.GetEnforce()) 3052 3053 def testGetEnforce_Disabled(self): 3054 with self.assertCall(self.call.adb.Shell('getenforce'), 'Disabled'): 3055 self.assertEqual(None, self.device.GetEnforce()) 3056 3057 def testSetEnforce_Enforcing(self): 3058 with self.assertCalls((self.call.device.NeedsSU(), False), 3059 (self.call.adb.Shell('setenforce 1'), '')): 3060 self.device.SetEnforce(enabled=True) 3061 3062 def testSetEnforce_Permissive(self): 3063 with self.assertCalls((self.call.device.NeedsSU(), False), 3064 (self.call.adb.Shell('setenforce 0'), '')): 3065 self.device.SetEnforce(enabled=False) 3066 3067 def testSetEnforce_EnforcingWithInt(self): 3068 with self.assertCalls((self.call.device.NeedsSU(), False), 3069 (self.call.adb.Shell('setenforce 1'), '')): 3070 self.device.SetEnforce(enabled=1) 3071 3072 def testSetEnforce_PermissiveWithInt(self): 3073 with self.assertCalls((self.call.device.NeedsSU(), False), 3074 (self.call.adb.Shell('setenforce 0'), '')): 3075 self.device.SetEnforce(enabled=0) 3076 3077 def testSetEnforce_EnforcingWithStr(self): 3078 with self.assertCalls((self.call.device.NeedsSU(), False), 3079 (self.call.adb.Shell('setenforce 1'), '')): 3080 self.device.SetEnforce(enabled='1') 3081 3082 def testSetEnforce_PermissiveWithStr(self): 3083 with self.assertCalls((self.call.device.NeedsSU(), False), 3084 (self.call.adb.Shell('setenforce 0'), '')): 3085 self.device.SetEnforce(enabled='0') # Not recommended but it works! 3086 3087 3088class DeviceUtilsGetWebViewUpdateServiceDumpTest(DeviceUtilsTest): 3089 def testGetWebViewUpdateServiceDump_success(self): 3090 # Some of the lines of adb shell dumpsys webviewupdate: 3091 dumpsys_lines = [ 3092 'Fallback logic enabled: true', 3093 ('Current WebView package (name, version): ' 3094 '(com.android.chrome, 61.0.3163.98)'), 3095 'Minimum WebView version code: 12345', 3096 'WebView packages:', 3097 ('Valid package com.android.chrome (versionName: ' 3098 '61.0.3163.98, versionCode: 1, targetSdkVersion: 26) is ' 3099 'installed/enabled for all users'), 3100 ('Valid package com.google.android.webview (versionName: ' 3101 '58.0.3029.125, versionCode: 1, targetSdkVersion: 26) is NOT ' 3102 'installed/enabled for all users'), 3103 ('Invalid package com.google.android.apps.chrome (versionName: ' 3104 '56.0.2924.122, versionCode: 2, targetSdkVersion: 25), reason: SDK ' 3105 'version too low'), 3106 ('com.chrome.canary is NOT installed.'), 3107 ] 3108 with self.patch_call( 3109 self.call.device.build_version_sdk, return_value=version_codes.OREO): 3110 with self.assertCall( 3111 self.call.adb.Shell('dumpsys webviewupdate'), 3112 '\n'.join(dumpsys_lines)): 3113 update = self.device.GetWebViewUpdateServiceDump() 3114 self.assertTrue(update['FallbackLogicEnabled']) 3115 self.assertEqual('com.android.chrome', update['CurrentWebViewPackage']) 3116 self.assertEqual(12345, update['MinimumWebViewVersionCode']) 3117 # Order isn't really important, and we shouldn't have duplicates, so we 3118 # convert to sets. 3119 expected = { 3120 'com.android.chrome', 'com.google.android.webview', 3121 'com.google.android.apps.chrome', 'com.chrome.canary' 3122 } 3123 self.assertSetEqual(expected, set(update['WebViewPackages'].keys())) 3124 self.assertEquals('is installed/enabled for all users', 3125 update['WebViewPackages']['com.android.chrome']) 3126 self.assertEquals( 3127 'is NOT installed/enabled for all users', 3128 update['WebViewPackages']['com.google.android.webview']) 3129 self.assertEquals( 3130 'reason: SDK version too low', 3131 update['WebViewPackages']['com.google.android.apps.chrome']) 3132 self.assertEquals('is NOT installed.', 3133 update['WebViewPackages']['com.chrome.canary']) 3134 3135 def testGetWebViewUpdateServiceDump_missingkey(self): 3136 with self.patch_call( 3137 self.call.device.build_version_sdk, return_value=version_codes.OREO): 3138 with self.assertCall( 3139 self.call.adb.Shell('dumpsys webviewupdate'), 3140 'Fallback logic enabled: true'): 3141 update = self.device.GetWebViewUpdateServiceDump() 3142 self.assertEqual(True, update['FallbackLogicEnabled']) 3143 3144 def testGetWebViewUpdateServiceDump_noop(self): 3145 with self.patch_call( 3146 self.call.device.build_version_sdk, 3147 return_value=version_codes.NOUGAT_MR1): 3148 with self.assertCalls(): 3149 self.device.GetWebViewUpdateServiceDump() 3150 3151 def testGetWebViewUpdateServiceDump_noPackage(self): 3152 with self.patch_call( 3153 self.call.device.build_version_sdk, return_value=version_codes.OREO): 3154 with self.assertCall( 3155 self.call.adb.Shell('dumpsys webviewupdate'), 3156 'Fallback logic enabled: true\n' 3157 'Current WebView package is null'): 3158 update = self.device.GetWebViewUpdateServiceDump() 3159 self.assertEqual(True, update['FallbackLogicEnabled']) 3160 self.assertEqual(None, update['CurrentWebViewPackage']) 3161 3162 3163class DeviceUtilsSetWebViewImplementationTest(DeviceUtilsTest): 3164 def testSetWebViewImplementation_success(self): 3165 with self.patch_call( 3166 self.call.device.IsApplicationInstalled, return_value=True): 3167 with self.assertCall( 3168 self.call.adb.Shell( 3169 'cmd webviewupdate set-webview-implementation foo.org'), 3170 'Success'): 3171 self.device.SetWebViewImplementation('foo.org') 3172 3173 def testSetWebViewImplementation_uninstalled(self): 3174 with self.patch_call( 3175 self.call.device.IsApplicationInstalled, return_value=False): 3176 with self.assertRaises(device_errors.CommandFailedError) as cfe: 3177 self.device.SetWebViewImplementation('foo.org') 3178 self.assertIn('is not installed', cfe.exception.message) 3179 3180 def _testSetWebViewImplementationHelper(self, mock_dump_sys, 3181 exception_message_substr): 3182 with self.patch_call( 3183 self.call.device.IsApplicationInstalled, return_value=True): 3184 with self.assertCall( 3185 self.call.adb.Shell( 3186 'cmd webviewupdate set-webview-implementation foo.org'), 'Oops!'): 3187 with self.patch_call( 3188 self.call.device.GetWebViewUpdateServiceDump, 3189 return_value=mock_dump_sys): 3190 with self.assertRaises(device_errors.CommandFailedError) as cfe: 3191 self.device.SetWebViewImplementation('foo.org') 3192 self.assertIn(exception_message_substr, cfe.exception.message) 3193 3194 def testSetWebViewImplementation_notInProviderList(self): 3195 mock_dump_sys = { 3196 'WebViewPackages': { 3197 'some.package': 'any reason', 3198 'other.package': 'any reason', 3199 } 3200 } 3201 self._testSetWebViewImplementationHelper(mock_dump_sys, 'provider list') 3202 3203 def testSetWebViewImplementation_notEnabled(self): 3204 mock_dump_sys = { 3205 'WebViewPackages': { 3206 'foo.org': 'is NOT installed/enabled for all users', 3207 } 3208 } 3209 self._testSetWebViewImplementationHelper(mock_dump_sys, 'is disabled') 3210 3211 def testSetWebViewImplementation_missingManifestTag(self): 3212 mock_dump_sys = { 3213 'WebViewPackages': { 3214 'foo.org': 'No WebView-library manifest flag', 3215 } 3216 } 3217 self._testSetWebViewImplementationHelper(mock_dump_sys, 3218 'WebView native library') 3219 3220 def testSetWebViewImplementation_lowTargetSdkVersion_finalizedSdk(self): 3221 mock_dump_sys = {'WebViewPackages': {'foo.org': 'SDK version too low', }} 3222 with self.assertCalls( 3223 (self.call.device.GetApplicationTargetSdk('foo.org'), '29'), 3224 (self.call.device.GetProp('ro.build.version.preview_sdk'), '0')): 3225 with self.patch_call(self.call.device.build_version_sdk, return_value=30): 3226 self._testSetWebViewImplementationHelper( 3227 mock_dump_sys, 3228 "has targetSdkVersion '29', but valid WebView providers must " 3229 "target >= 30 on this device") 3230 3231 def testSetWebViewImplementation_lowTargetSdkVersion_prefinalizedSdk(self): 3232 mock_dump_sys = {'WebViewPackages': {'foo.org': 'SDK version too low', }} 3233 with self.assertCalls( 3234 (self.call.device.GetApplicationTargetSdk('foo.org'), '29'), 3235 (self.call.device.GetProp('ro.build.version.preview_sdk'), '1'), 3236 (self.call.device.GetProp('ro.build.version.codename'), 'R')): 3237 with self.patch_call(self.call.device.build_version_sdk, return_value=29): 3238 self._testSetWebViewImplementationHelper( 3239 mock_dump_sys, 3240 "targets a finalized SDK ('29'), but valid WebView providers must " 3241 "target a pre-finalized SDK ('R') on this device") 3242 3243 def testSetWebViewImplementation_lowVersionCode(self): 3244 mock_dump_sys = { 3245 'MinimumWebViewVersionCode': 12345, 3246 'WebViewPackages': { 3247 'foo.org': 'Version code too low', 3248 } 3249 } 3250 self._testSetWebViewImplementationHelper(mock_dump_sys, 3251 'higher versionCode') 3252 3253 def testSetWebViewImplementation_invalidSignature(self): 3254 mock_dump_sys = {'WebViewPackages': {'foo.org': 'Incorrect signature'}} 3255 self._testSetWebViewImplementationHelper(mock_dump_sys, 3256 'signed with release keys') 3257 3258 3259class DeviceUtilsSetWebViewFallbackLogicTest(DeviceUtilsTest): 3260 def testSetWebViewFallbackLogic_False_success(self): 3261 with self.patch_call( 3262 self.call.device.build_version_sdk, return_value=version_codes.NOUGAT): 3263 with self.assertCall( 3264 self.call.adb.Shell('cmd webviewupdate enable-redundant-packages'), 3265 'Success'): 3266 self.device.SetWebViewFallbackLogic(False) 3267 3268 def testSetWebViewFallbackLogic_True_success(self): 3269 with self.patch_call( 3270 self.call.device.build_version_sdk, return_value=version_codes.NOUGAT): 3271 with self.assertCall( 3272 self.call.adb.Shell('cmd webviewupdate disable-redundant-packages'), 3273 'Success'): 3274 self.device.SetWebViewFallbackLogic(True) 3275 3276 def testSetWebViewFallbackLogic_failure(self): 3277 with self.patch_call( 3278 self.call.device.build_version_sdk, return_value=version_codes.NOUGAT): 3279 with self.assertCall( 3280 self.call.adb.Shell('cmd webviewupdate enable-redundant-packages'), 3281 'Oops!'): 3282 with self.assertRaises(device_errors.CommandFailedError): 3283 self.device.SetWebViewFallbackLogic(False) 3284 3285 def testSetWebViewFallbackLogic_beforeNougat(self): 3286 with self.patch_call( 3287 self.call.device.build_version_sdk, 3288 return_value=version_codes.MARSHMALLOW): 3289 with self.assertCalls(): 3290 self.device.SetWebViewFallbackLogic(False) 3291 3292 def testSetWebViewFallbackLogic_afterPie(self): 3293 with self.patch_call( 3294 self.call.device.build_version_sdk, return_value=version_codes.Q): 3295 with self.assertCalls(): 3296 self.device.SetWebViewFallbackLogic(False) 3297 3298 3299class DeviceUtilsTakeScreenshotTest(DeviceUtilsTest): 3300 def testTakeScreenshot_fileNameProvided(self): 3301 with self.assertCalls( 3302 (mock.call.devil.android.device_temp_file.DeviceTempFile( 3303 self.adb, suffix='.png'), MockTempFile('/tmp/path/temp-123.png')), 3304 (self.call.adb.Shell('/system/bin/screencap -p /tmp/path/temp-123.png'), 3305 ''), 3306 self.call.device.PullFile('/tmp/path/temp-123.png', 3307 '/test/host/screenshot.png')): 3308 self.device.TakeScreenshot('/test/host/screenshot.png') 3309 3310 3311class DeviceUtilsDismissCrashDialogIfNeededTest(DeviceUtilsTest): 3312 def testDismissCrashDialogIfNeeded_crashedPageckageNotFound(self): 3313 sample_dumpsys_output = ''' 3314WINDOW MANAGER WINDOWS (dumpsys window windows) 3315 Window #11 Window{f8b647a u0 SearchPanel}: 3316 mDisplayId=0 mSession=Session{8 94:122} mClient=android.os.BinderProxy@1ba5 3317 mOwnerUid=100 mShowToOwnerOnly=false package=com.android.systemui appop=NONE 3318 mAttrs=WM.LayoutParams{(0,0)(fillxfill) gr=#53 sim=#31 ty=2024 fl=100 3319 Requested w=1080 h=1920 mLayoutSeq=426 3320 mBaseLayer=211000 mSubLayer=0 mAnimLayer=211000+0=211000 mLastLayer=211000 3321''' 3322 with self.assertCalls( 3323 (self.call.device.RunShellCommand(['dumpsys', 'window', 'windows'], 3324 check_return=True, 3325 large_output=True), 3326 sample_dumpsys_output.split('\n'))): 3327 package_name = self.device.DismissCrashDialogIfNeeded() 3328 self.assertIsNone(package_name) 3329 3330 def testDismissCrashDialogIfNeeded_crashedPageckageFound(self): 3331 sample_dumpsys_output = ''' 3332WINDOW MANAGER WINDOWS (dumpsys window windows) 3333 Window #11 Window{f8b647a u0 SearchPanel}: 3334 mDisplayId=0 mSession=Session{8 94:122} mClient=android.os.BinderProxy@1ba5 3335 mOwnerUid=102 mShowToOwnerOnly=false package=com.android.systemui appop=NONE 3336 mAttrs=WM.LayoutParams{(0,0)(fillxfill) gr=#53 sim=#31 ty=2024 fl=100 3337 Requested w=1080 h=1920 mLayoutSeq=426 3338 mBaseLayer=211000 mSubLayer=0 mAnimLayer=211000+0=211000 mLastLayer=211000 3339 mHasPermanentDpad=false 3340 mCurrentFocus=Window{3a27740f u0 Application Error: com.android.chrome} 3341 mFocusedApp=AppWindowToken{470af6f token=Token{272ec24e ActivityRecord{t894}}} 3342''' 3343 with self.assertCalls( 3344 (self.call.device.RunShellCommand(['dumpsys', 'window', 'windows'], 3345 check_return=True, 3346 large_output=True), 3347 sample_dumpsys_output.split('\n')), (self.call.device.RunShellCommand( 3348 ['input', 'keyevent', '22'], check_return=True)), 3349 (self.call.device.RunShellCommand(['input', 'keyevent', '22'], 3350 check_return=True)), 3351 (self.call.device.RunShellCommand(['input', 'keyevent', '66'], 3352 check_return=True)), 3353 (self.call.device.RunShellCommand(['dumpsys', 'window', 'windows'], 3354 check_return=True, 3355 large_output=True), [])): 3356 package_name = self.device.DismissCrashDialogIfNeeded() 3357 self.assertEqual(package_name, 'com.android.chrome') 3358 3359 3360class DeviceUtilsClientCache(DeviceUtilsTest): 3361 def testClientCache_twoCaches(self): 3362 self.device._cache['test'] = 0 3363 client_cache_one = self.device.GetClientCache('ClientOne') 3364 client_cache_one['test'] = 1 3365 client_cache_two = self.device.GetClientCache('ClientTwo') 3366 client_cache_two['test'] = 2 3367 self.assertEqual(self.device._cache['test'], 0) 3368 self.assertEqual(client_cache_one, {'test': 1}) 3369 self.assertEqual(client_cache_two, {'test': 2}) 3370 self.device.ClearCache() 3371 self.assertTrue('test' not in self.device._cache) 3372 self.assertEqual(client_cache_one, {}) 3373 self.assertEqual(client_cache_two, {}) 3374 3375 def testClientCache_multipleInstances(self): 3376 client_cache_one = self.device.GetClientCache('ClientOne') 3377 client_cache_one['test'] = 1 3378 client_cache_two = self.device.GetClientCache('ClientOne') 3379 self.assertEqual(client_cache_one, {'test': 1}) 3380 self.assertEqual(client_cache_two, {'test': 1}) 3381 self.device.ClearCache() 3382 self.assertEqual(client_cache_one, {}) 3383 self.assertEqual(client_cache_two, {}) 3384 3385 3386class DeviceUtilsHealthyDevicesTest(mock_calls.TestCase): 3387 def testHealthyDevices_emptyDenylist_defaultDeviceArg(self): 3388 test_serials = ['0123456789abcdef', 'fedcba9876543210'] 3389 with self.assertCalls( 3390 (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(), 3391 [_AdbWrapperMock(s) for s in test_serials]), 3392 (mock.call.devil.android.device_utils.DeviceUtils.GetABI(), abis.ARM), 3393 (mock.call.devil.android.device_utils.DeviceUtils.GetABI(), abis.ARM)): 3394 denylist = mock.NonCallableMock(**{'Read.return_value': []}) 3395 devices = device_utils.DeviceUtils.HealthyDevices(denylist) 3396 for serial, device in zip(test_serials, devices): 3397 self.assertTrue(isinstance(device, device_utils.DeviceUtils)) 3398 self.assertEquals(serial, device.adb.GetDeviceSerial()) 3399 3400 def testHealthyDevices_denylist_defaultDeviceArg(self): 3401 test_serials = ['0123456789abcdef', 'fedcba9876543210'] 3402 with self.assertCalls( 3403 (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(), 3404 [_AdbWrapperMock(s) for s in test_serials]), 3405 (mock.call.devil.android.device_utils.DeviceUtils.GetABI(), abis.ARM)): 3406 denylist = mock.NonCallableMock( 3407 **{'Read.return_value': ['fedcba9876543210']}) 3408 devices = device_utils.DeviceUtils.HealthyDevices(denylist) 3409 self.assertEquals(1, len(devices)) 3410 self.assertTrue(isinstance(devices[0], device_utils.DeviceUtils)) 3411 self.assertEquals('0123456789abcdef', devices[0].adb.GetDeviceSerial()) 3412 3413 def testHealthyDevices_noneDeviceArg_multiple_attached(self): 3414 test_serials = ['0123456789abcdef', 'fedcba9876543210'] 3415 with self.assertCalls( 3416 (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(), 3417 [_AdbWrapperMock(s) for s in test_serials]), 3418 (mock.call.devil.android.device_utils.DeviceUtils.GetABI(), abis.ARM), 3419 (mock.call.devil.android.device_utils.DeviceUtils.GetABI(), abis.ARM), 3420 (mock.call.devil.android.device_errors.MultipleDevicesError(mock.ANY), 3421 _MockMultipleDevicesError())): 3422 with self.assertRaises(_MockMultipleDevicesError): 3423 device_utils.DeviceUtils.HealthyDevices(device_arg=None) 3424 3425 def testHealthyDevices_noneDeviceArg_one_attached(self): 3426 test_serials = ['0123456789abcdef'] 3427 with self.assertCalls( 3428 (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(), 3429 [_AdbWrapperMock(s) for s in test_serials]), 3430 (mock.call.devil.android.device_utils.DeviceUtils.GetABI(), abis.ARM)): 3431 devices = device_utils.DeviceUtils.HealthyDevices(device_arg=None) 3432 self.assertEquals(1, len(devices)) 3433 3434 def testHealthyDevices_noneDeviceArg_no_attached(self): 3435 test_serials = [] 3436 with self.assertCalls( 3437 (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(), 3438 [_AdbWrapperMock(s) for s in test_serials])): 3439 with self.assertRaises(device_errors.NoDevicesError): 3440 device_utils.DeviceUtils.HealthyDevices(device_arg=None, retries=0) 3441 3442 def testHealthyDevices_noneDeviceArg_multiple_attached_ANDROID_SERIAL(self): 3443 try: 3444 os.environ['ANDROID_SERIAL'] = '0123456789abcdef' 3445 with self.assertCalls(): # Should skip adb devices when device is known. 3446 device_utils.DeviceUtils.HealthyDevices(device_arg=None) 3447 finally: 3448 del os.environ['ANDROID_SERIAL'] 3449 3450 def testHealthyDevices_stringDeviceArg(self): 3451 with self.assertCalls(): # Should skip adb devices when device is known. 3452 devices = device_utils.DeviceUtils.HealthyDevices( 3453 device_arg='0123456789abcdef') 3454 self.assertEquals(1, len(devices)) 3455 3456 def testHealthyDevices_EmptyListDeviceArg_multiple_attached(self): 3457 test_serials = ['0123456789abcdef', 'fedcba9876543210'] 3458 with self.assertCalls( 3459 (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(), 3460 [_AdbWrapperMock(s) for s in test_serials]), 3461 (mock.call.devil.android.device_utils.DeviceUtils.GetABI(), abis.ARM), 3462 (mock.call.devil.android.device_utils.DeviceUtils.GetABI(), abis.ARM)): 3463 devices = device_utils.DeviceUtils.HealthyDevices(device_arg=()) 3464 self.assertEquals(2, len(devices)) 3465 3466 def testHealthyDevices_EmptyListDeviceArg_ANDROID_SERIAL(self): 3467 try: 3468 os.environ['ANDROID_SERIAL'] = '0123456789abcdef' 3469 with self.assertCalls(): # Should skip adb devices when device is known. 3470 devices = device_utils.DeviceUtils.HealthyDevices(device_arg=()) 3471 finally: 3472 del os.environ['ANDROID_SERIAL'] 3473 self.assertEquals(1, len(devices)) 3474 3475 def testHealthyDevices_EmptyListDeviceArg_no_attached(self): 3476 test_serials = [] 3477 with self.assertCalls( 3478 (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(), 3479 [_AdbWrapperMock(s) for s in test_serials])): 3480 with self.assertRaises(device_errors.NoDevicesError): 3481 device_utils.DeviceUtils.HealthyDevices(device_arg=[], retries=0) 3482 3483 @mock.patch('time.sleep') 3484 @mock.patch('devil.android.sdk.adb_wrapper.RestartServer') 3485 def testHealthyDevices_EmptyListDeviceArg_no_attached_with_retry( 3486 self, mock_restart, mock_sleep): 3487 with self.assertCalls( 3488 (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(), []), 3489 (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(), []), 3490 (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(), []), 3491 (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(), []), 3492 (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(), [])): 3493 with self.assertRaises(device_errors.NoDevicesError): 3494 device_utils.DeviceUtils.HealthyDevices(device_arg=[], retries=4) 3495 self.assertEquals(mock_restart.call_count, 4) 3496 self.assertEquals( 3497 mock_sleep.call_args_list, 3498 [mock.call(2), mock.call(4), 3499 mock.call(8), mock.call(16)]) 3500 3501 @mock.patch('time.sleep') 3502 @mock.patch('devil.android.sdk.adb_wrapper.RestartServer') 3503 def testHealthyDevices_EmptyListDeviceArg_no_attached_with_resets( 3504 self, mock_restart, mock_sleep): 3505 # The reset_usb import fails on windows. Mock the full import here so it can 3506 # succeed like it would on linux. 3507 mock_reset_import = mock.MagicMock() 3508 sys.modules['devil.utils.reset_usb'] = mock_reset_import 3509 with self.assertCalls( 3510 (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(), []), 3511 (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(), []), 3512 (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(), []), 3513 (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(), []), 3514 (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(), [])): 3515 with self.assertRaises(device_errors.NoDevicesError): 3516 with mock.patch.object(mock_reset_import, 3517 'reset_all_android_devices') as mock_reset: 3518 device_utils.DeviceUtils.HealthyDevices( 3519 device_arg=[], retries=4, enable_usb_resets=True) 3520 self.assertEquals(mock_reset.call_count, 1) 3521 self.assertEquals(mock_restart.call_count, 4) 3522 self.assertEquals( 3523 mock_sleep.call_args_list, 3524 [mock.call(2), mock.call(4), 3525 mock.call(8), mock.call(16)]) 3526 3527 def testHealthyDevices_ListDeviceArg(self): 3528 device_arg = ['0123456789abcdef', 'fedcba9876543210'] 3529 try: 3530 os.environ['ANDROID_SERIAL'] = 'should-not-apply' 3531 with self.assertCalls(): # Should skip adb devices when device is known. 3532 devices = device_utils.DeviceUtils.HealthyDevices(device_arg=device_arg) 3533 finally: 3534 del os.environ['ANDROID_SERIAL'] 3535 self.assertEquals(2, len(devices)) 3536 3537 def testHealthyDevices_abisArg_no_matching_abi(self): 3538 test_serials = ['0123456789abcdef', 'fedcba9876543210'] 3539 with self.assertCalls( 3540 (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(), 3541 [_AdbWrapperMock(s) for s in test_serials]), 3542 (mock.call.devil.android.device_utils.DeviceUtils.GetABI(), abis.ARM), 3543 (mock.call.devil.android.device_utils.DeviceUtils.GetABI(), abis.ARM)): 3544 with self.assertRaises(device_errors.NoDevicesError): 3545 device_utils.DeviceUtils.HealthyDevices( 3546 device_arg=[], retries=0, abis=[abis.ARM_64]) 3547 3548 def testHealthyDevices_abisArg_filter_on_abi(self): 3549 test_serials = ['0123456789abcdef', 'fedcba9876543210'] 3550 with self.assertCalls( 3551 (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(), 3552 [_AdbWrapperMock(s) for s in test_serials]), 3553 (mock.call.devil.android.device_utils.DeviceUtils.GetABI(), 3554 abis.ARM_64), 3555 (mock.call.devil.android.device_utils.DeviceUtils.GetABI(), abis.ARM)): 3556 devices = device_utils.DeviceUtils.HealthyDevices( 3557 device_arg=[], retries=0, abis=[abis.ARM_64]) 3558 self.assertEquals(1, len(devices)) 3559 3560 3561class DeviceUtilsRestartAdbdTest(DeviceUtilsTest): 3562 def testAdbdRestart(self): 3563 mock_temp_file = '/sdcard/temp-123.sh' 3564 with self.assertCalls( 3565 (mock.call.devil.android.device_temp_file.DeviceTempFile( 3566 self.adb, suffix='.sh'), MockTempFile(mock_temp_file)), 3567 self.call.device.WriteFile(mock.ANY, mock.ANY), 3568 (self.call.device.RunShellCommand( 3569 ['source', mock_temp_file], check_return=True, as_root=True)), 3570 self.call.adb.WaitForDevice()): 3571 self.device.RestartAdbd() 3572 3573 3574class DeviceUtilsGrantPermissionsTest(DeviceUtilsTest): 3575 def _PmGrantShellCall(self, package, permissions): 3576 fragment = 'p=%s;for q in %s;' % (package, ' '.join(sorted(permissions))) 3577 results = [] 3578 for permission, result in sorted(permissions.items()): 3579 if result: 3580 output, status = result + '\n', 1 3581 else: 3582 output, status = '', 0 3583 results.append('{output}{sep}{permission}{sep}{status}{sep}\n'.format( 3584 output=output, 3585 permission=permission, 3586 status=status, 3587 sep=device_utils._SHELL_OUTPUT_SEPARATOR)) 3588 return (self.call.device.RunShellCommand( 3589 AnyStringWith(fragment), 3590 shell=True, 3591 raw_output=True, 3592 large_output=True, 3593 check_return=True), ''.join(results)) 3594 3595 def testGrantPermissions_none(self): 3596 self.device.GrantPermissions('package', []) 3597 3598 def testGrantPermissions_one(self): 3599 with self.patch_call( 3600 self.call.device.build_version_sdk, 3601 return_value=version_codes.MARSHMALLOW): 3602 with self.assertCalls(self._PmGrantShellCall('package', {'p1': 0})): 3603 self.device.GrantPermissions('package', ['p1']) 3604 3605 def testGrantPermissions_multiple(self): 3606 with self.patch_call( 3607 self.call.device.build_version_sdk, 3608 return_value=version_codes.MARSHMALLOW): 3609 with self.assertCalls( 3610 self._PmGrantShellCall('package', { 3611 'p1': 0, 3612 'p2': 0 3613 })): 3614 self.device.GrantPermissions('package', ['p1', 'p2']) 3615 3616 def testGrantPermissions_WriteExtrnalStorage(self): 3617 WRITE = 'android.permission.WRITE_EXTERNAL_STORAGE' 3618 READ = 'android.permission.READ_EXTERNAL_STORAGE' 3619 with PatchLogger() as logger: 3620 with self.patch_call( 3621 self.call.device.build_version_sdk, 3622 return_value=version_codes.MARSHMALLOW): 3623 with self.assertCalls( 3624 self._PmGrantShellCall('package', { 3625 READ: 0, 3626 WRITE: 0 3627 })): 3628 self.device.GrantPermissions('package', [WRITE]) 3629 self.assertEqual(logger.warnings, []) 3630 3631 def testGrantPermissions_ManageExtrnalStorage(self): 3632 with PatchLogger() as logger: 3633 with self.patch_call(self.call.device.build_version_sdk, 3634 return_value=version_codes.R): 3635 with self.assertCalls( 3636 (self.call.device.RunShellCommand( 3637 AnyStringWith('appops set pkg MANAGE_EXTERNAL_STORAGE allow'), 3638 shell=True, 3639 raw_output=True, 3640 large_output=True, 3641 check_return=True), 3642 '{sep}MANAGE_EXTERNAL_STORAGE{sep}0{sep}\n'.format( 3643 sep=device_utils._SHELL_OUTPUT_SEPARATOR))): 3644 self.device.GrantPermissions( 3645 'pkg', ['android.permission.MANAGE_EXTERNAL_STORAGE']) 3646 self.assertEqual(logger.warnings, []) 3647 3648 def testGrantPermissions_DenyList(self): 3649 with PatchLogger() as logger: 3650 with self.patch_call( 3651 self.call.device.build_version_sdk, 3652 return_value=version_codes.MARSHMALLOW): 3653 with self.assertCalls(self._PmGrantShellCall('package', {'p1': 0})): 3654 self.device.GrantPermissions('package', 3655 ['p1', 'foo.permission.C2D_MESSAGE']) 3656 self.assertEqual(logger.warnings, []) 3657 3658 def testGrantPermissions_unchangeablePermision(self): 3659 error_message = ( 3660 'Operation not allowed: java.lang.SecurityException: ' 3661 'Permission UNCHANGEABLE is not a changeable permission type') 3662 with PatchLogger() as logger: 3663 with self.patch_call( 3664 self.call.device.build_version_sdk, 3665 return_value=version_codes.MARSHMALLOW): 3666 with self.assertCalls( 3667 self._PmGrantShellCall('package', {'UNCHANGEABLE': error_message})): 3668 self.device.GrantPermissions('package', ['UNCHANGEABLE']) 3669 self.assertEqual(logger.warnings, 3670 [mock.ANY, AnyStringWith('UNCHANGEABLE')]) 3671 3672 3673class DeviecUtilsIsScreenOn(DeviceUtilsTest): 3674 3675 _L_SCREEN_ON = ['test=test mInteractive=true'] 3676 _K_SCREEN_ON = ['test=test mScreenOn=true'] 3677 _L_SCREEN_OFF = ['mInteractive=false'] 3678 _K_SCREEN_OFF = ['mScreenOn=false'] 3679 3680 def testIsScreenOn_onPreL(self): 3681 with self.patch_call( 3682 self.call.device.build_version_sdk, return_value=version_codes.KITKAT): 3683 with self.assertCalls((self.call.device._RunPipedShellCommand( 3684 'dumpsys input_method | grep mScreenOn'), self._K_SCREEN_ON)): 3685 self.assertTrue(self.device.IsScreenOn()) 3686 3687 def testIsScreenOn_onL(self): 3688 with self.patch_call( 3689 self.call.device.build_version_sdk, 3690 return_value=version_codes.LOLLIPOP): 3691 with self.assertCalls((self.call.device._RunPipedShellCommand( 3692 'dumpsys input_method | grep mInteractive'), self._L_SCREEN_ON)): 3693 self.assertTrue(self.device.IsScreenOn()) 3694 3695 def testIsScreenOn_offPreL(self): 3696 with self.patch_call( 3697 self.call.device.build_version_sdk, return_value=version_codes.KITKAT): 3698 with self.assertCalls((self.call.device._RunPipedShellCommand( 3699 'dumpsys input_method | grep mScreenOn'), self._K_SCREEN_OFF)): 3700 self.assertFalse(self.device.IsScreenOn()) 3701 3702 def testIsScreenOn_offL(self): 3703 with self.patch_call( 3704 self.call.device.build_version_sdk, 3705 return_value=version_codes.LOLLIPOP): 3706 with self.assertCalls((self.call.device._RunPipedShellCommand( 3707 'dumpsys input_method | grep mInteractive'), self._L_SCREEN_OFF)): 3708 self.assertFalse(self.device.IsScreenOn()) 3709 3710 def testIsScreenOn_noOutput(self): 3711 with self.patch_call( 3712 self.call.device.build_version_sdk, 3713 return_value=version_codes.LOLLIPOP): 3714 with self.assertCalls((self.call.device._RunPipedShellCommand( 3715 'dumpsys input_method | grep mInteractive'), [])): 3716 with self.assertRaises(device_errors.CommandFailedError): 3717 self.device.IsScreenOn() 3718 3719 3720class DeviecUtilsSetScreen(DeviceUtilsTest): 3721 @mock.patch('time.sleep', mock.Mock()) 3722 def testSetScren_alreadySet(self): 3723 with self.assertCalls((self.call.device.IsScreenOn(), False)): 3724 self.device.SetScreen(False) 3725 3726 @mock.patch('time.sleep', mock.Mock()) 3727 def testSetScreen_on(self): 3728 with self.assertCalls( 3729 (self.call.device.IsScreenOn(), False), 3730 (self.call.device.SendKeyEvent(keyevent.KEYCODE_POWER), None), 3731 (self.call.device.IsScreenOn(), True)): 3732 self.device.SetScreen(True) 3733 3734 @mock.patch('time.sleep', mock.Mock()) 3735 def testSetScreen_off(self): 3736 with self.assertCalls( 3737 (self.call.device.IsScreenOn(), True), 3738 (self.call.device.SendKeyEvent(keyevent.KEYCODE_POWER), None), 3739 (self.call.device.IsScreenOn(), False)): 3740 self.device.SetScreen(False) 3741 3742 @mock.patch('time.sleep', mock.Mock()) 3743 def testSetScreen_slow(self): 3744 with self.assertCalls( 3745 (self.call.device.IsScreenOn(), True), 3746 (self.call.device.SendKeyEvent(keyevent.KEYCODE_POWER), None), 3747 (self.call.device.IsScreenOn(), True), 3748 (self.call.device.IsScreenOn(), True), 3749 (self.call.device.IsScreenOn(), False)): 3750 self.device.SetScreen(False) 3751 3752 3753class DeviecUtilsLoadCacheData(DeviceUtilsTest): 3754 def testInvalidJson(self): 3755 self.assertFalse(self.device.LoadCacheData('')) 3756 3757 def testTokenMissing(self): 3758 with self.assertCalls(self.EnsureCacheInitialized()): 3759 self.assertFalse(self.device.LoadCacheData('{}')) 3760 3761 def testTokenStale(self): 3762 with self.assertCalls(self.EnsureCacheInitialized()): 3763 self.assertFalse(self.device.LoadCacheData('{"token":"foo"}')) 3764 3765 def testTokenMatches(self): 3766 with self.assertCalls(self.EnsureCacheInitialized()): 3767 self.assertTrue(self.device.LoadCacheData('{"token":"TOKEN"}')) 3768 3769 def testDumpThenLoad(self): 3770 with self.assertCalls(self.EnsureCacheInitialized()): 3771 data = json.loads(self.device.DumpCacheData()) 3772 data['token'] = 'TOKEN' 3773 self.assertTrue(self.device.LoadCacheData(json.dumps(data))) 3774 3775 3776class DeviceUtilsGetIMEITest(DeviceUtilsTest): 3777 def testSuccessfulDumpsys(self): 3778 dumpsys_output = ('Phone Subscriber Info:' 3779 ' Phone Type = GSM' 3780 ' Device ID = 123454321') 3781 with self.assertCalls( 3782 (self.call.device.GetProp('ro.build.version.sdk', cache=True), '19'), 3783 (self.call.adb.Shell('dumpsys iphonesubinfo'), dumpsys_output)): 3784 self.assertEquals(self.device.GetIMEI(), '123454321') 3785 3786 def testSuccessfulServiceCall(self): 3787 service_output = """ 3788 Result: Parcel(\n' 3789 0x00000000: 00000000 0000000f 00350033 00360033 '........7.6.5.4.' 3790 0x00000010: 00360032 00370030 00300032 00300039 '3.2.1.0.1.2.3.4.' 3791 0x00000020: 00380033 00000039 '5.6.7... ') 3792 """ 3793 with self.assertCalls( 3794 (self.call.device.GetProp('ro.build.version.sdk', cache=True), '24'), 3795 (self.call.adb.Shell('service call iphonesubinfo 1'), service_output)): 3796 self.assertEquals(self.device.GetIMEI(), '765432101234567') 3797 3798 def testNoIMEI(self): 3799 with self.assertCalls( 3800 (self.call.device.GetProp('ro.build.version.sdk', cache=True), '19'), 3801 (self.call.adb.Shell('dumpsys iphonesubinfo'), 'no device id')): 3802 with self.assertRaises(device_errors.CommandFailedError): 3803 self.device.GetIMEI() 3804 3805 def testAdbError(self): 3806 with self.assertCalls( 3807 (self.call.device.GetProp('ro.build.version.sdk', cache=True), '24'), 3808 (self.call.adb.Shell('service call iphonesubinfo 1'), 3809 self.ShellError())): 3810 with self.assertRaises(device_errors.CommandFailedError): 3811 self.device.GetIMEI() 3812 3813 3814class DeviceUtilsChangeOwner(DeviceUtilsTest): 3815 def testChangeOwner(self): 3816 with self.assertCalls( 3817 (self.call.device.RunShellCommand( 3818 ['chown', 'user.group', '/path/to/file1', 'file2'], 3819 check_return=True))): 3820 self.device.ChangeOwner('user.group', ['/path/to/file1', 'file2']) 3821 3822 3823class DeviceUtilsChangeSecurityContext(DeviceUtilsTest): 3824 def testChangeSecurityContext(self): 3825 with self.assertCalls((self.call.device.RunShellCommand( 3826 ['chcon', 'u:object_r:system_data_file:s0', '/path', '/path2'], 3827 as_root=device_utils._FORCE_SU, 3828 check_return=True))): 3829 self.device.ChangeSecurityContext('u:object_r:system_data_file:s0', 3830 ['/path', '/path2']) 3831 3832 3833class DeviceUtilsLocale(DeviceUtilsTest): 3834 def testLocaleLegacy(self): 3835 with self.assertCalls( 3836 (self.call.device.GetProp('persist.sys.locale', cache=False), ''), 3837 (self.call.device.GetProp('persist.sys.language', cache=False), 'en'), 3838 (self.call.device.GetProp('persist.sys.country', cache=False), 'US')): 3839 self.assertEquals(self.device.GetLocale(), ('en', 'US')) 3840 3841 def testLocale(self): 3842 with self.assertCalls( 3843 (self.call.device.GetProp('persist.sys.locale', cache=False), 'en-US'), 3844 (self.call.device.GetProp('persist.sys.locale', cache=False), 3845 'en-US-sw')): 3846 self.assertEquals(self.device.GetLocale(), ('en', 'US')) 3847 self.assertEquals(self.device.GetLocale(), ('en', 'US-sw')) 3848 3849 def testBadLocale(self): 3850 with self.assertCalls((self.call.device.GetProp( 3851 'persist.sys.locale', cache=False), 'en')): 3852 self.assertEquals(self.device.GetLocale(), ('', '')) 3853 3854 def testLanguageAndCountryLegacy(self): 3855 with self.assertCalls( 3856 (self.call.device.GetProp('persist.sys.locale', cache=False), ''), 3857 (self.call.device.GetProp('persist.sys.language', cache=False), 'en'), 3858 (self.call.device.GetProp('persist.sys.country', cache=False), 'US'), 3859 (self.call.device.GetProp('persist.sys.locale', cache=False), ''), 3860 (self.call.device.GetProp('persist.sys.language', cache=False), 'en'), 3861 (self.call.device.GetProp('persist.sys.country', cache=False), 'US')): 3862 self.assertEquals(self.device.GetLanguage(), 'en') 3863 self.assertEquals(self.device.GetCountry(), 'US') 3864 3865 def testLanguageAndCountry(self): 3866 with self.assertCalls( 3867 (self.call.device.GetProp('persist.sys.locale', cache=False), 'en-US'), 3868 (self.call.device.GetProp('persist.sys.locale', cache=False), 'en-US')): 3869 self.assertEquals(self.device.GetLanguage(), 'en') 3870 self.assertEquals(self.device.GetCountry(), 'US') 3871 3872 3873class IterPushableComponentsTest(unittest.TestCase): 3874 @classmethod 3875 @contextlib.contextmanager 3876 def sampleLayout(cls): 3877 Layout = collections.namedtuple('Layout', [ 3878 'root', 'basic_file', 'symlink_file', 'symlink_dir', 3879 'dir_with_symlinks', 'dir_without_symlinks' 3880 ]) 3881 3882 with tempfile_ext.NamedTemporaryDirectory() as layout_root: 3883 dir1 = os.path.join(layout_root, 'dir1') 3884 os.makedirs(dir1) 3885 3886 basic_file = os.path.join(dir1, 'file1.txt') 3887 with open(basic_file, 'w') as f: 3888 f.write('hello world') 3889 3890 symlink = os.path.join(dir1, 'symlink.txt') 3891 os.symlink(basic_file, symlink) 3892 3893 dir2 = os.path.join(layout_root, 'dir2') 3894 os.makedirs(dir2) 3895 3896 with open(os.path.join(dir2, 'file2.txt'), 'w') as f: 3897 f.write('goodnight moon') 3898 3899 symlink_dir = os.path.join(layout_root, 'dir3') 3900 os.symlink(dir2, symlink_dir) 3901 3902 yield Layout(layout_root, basic_file, symlink, symlink_dir, dir1, dir2) 3903 3904 def safeAssertItemsEqual(self, expected, actual): 3905 if six.PY2: 3906 self.assertItemsEqual(expected, actual) 3907 else: 3908 self.assertCountEqual(expected, actual) # pylint: disable=no-member 3909 3910 def testFile(self): 3911 with self.sampleLayout() as layout: 3912 device_path = '/sdcard/basic_file' 3913 3914 expected = [(layout.basic_file, device_path, True)] 3915 actual = list( 3916 device_utils._IterPushableComponents(layout.basic_file, device_path)) 3917 self.safeAssertItemsEqual(expected, actual) 3918 3919 def testSymlinkFile(self): 3920 with self.sampleLayout() as layout: 3921 device_path = '/sdcard/basic_symlink' 3922 3923 expected = [(os.path.realpath(layout.symlink_file), device_path, False)] 3924 actual = list( 3925 device_utils._IterPushableComponents(layout.symlink_file, 3926 device_path)) 3927 self.safeAssertItemsEqual(expected, actual) 3928 3929 def testDirectoryWithNoSymlink(self): 3930 with self.sampleLayout() as layout: 3931 device_path = '/sdcard/basic_directory' 3932 3933 expected = [(layout.dir_without_symlinks, device_path, True)] 3934 actual = list( 3935 device_utils._IterPushableComponents(layout.dir_without_symlinks, 3936 device_path)) 3937 self.safeAssertItemsEqual(expected, actual) 3938 3939 def testDirectoryWithSymlink(self): 3940 with self.sampleLayout() as layout: 3941 device_path = '/sdcard/directory' 3942 3943 expected = [ 3944 (layout.basic_file, 3945 posixpath.join(device_path, os.path.basename(layout.basic_file)), 3946 True), 3947 (os.path.realpath(layout.symlink_file), 3948 posixpath.join(device_path, os.path.basename(layout.symlink_file)), 3949 False), 3950 ] 3951 actual = list( 3952 device_utils._IterPushableComponents(layout.dir_with_symlinks, 3953 device_path)) 3954 self.safeAssertItemsEqual(expected, actual) 3955 3956 def testSymlinkDirectory(self): 3957 with self.sampleLayout() as layout: 3958 device_path = '/sdcard/directory' 3959 3960 expected = [(os.path.realpath(layout.symlink_dir), device_path, False)] 3961 actual = list( 3962 device_utils._IterPushableComponents(layout.symlink_dir, device_path)) 3963 self.safeAssertItemsEqual(expected, actual) 3964 3965 def testDirectoryWithNestedSymlink(self): 3966 with self.sampleLayout() as layout: 3967 device_path = '/sdcard/directory' 3968 3969 expected = [ 3970 (layout.dir_without_symlinks, 3971 posixpath.join(device_path, 3972 os.path.basename(layout.dir_without_symlinks)), True), 3973 (layout.basic_file, 3974 posixpath.join( 3975 device_path, 3976 *os.path.split(os.path.relpath(layout.basic_file, layout.root))), 3977 True), 3978 (os.path.realpath(layout.symlink_file), 3979 posixpath.join( 3980 device_path, 3981 *os.path.split( 3982 os.path.relpath(layout.symlink_file, layout.root))), False), 3983 (os.path.realpath(layout.symlink_dir), 3984 posixpath.join( 3985 device_path, 3986 *os.path.split(os.path.relpath(layout.symlink_dir, 3987 layout.root))), False), 3988 ] 3989 actual = list( 3990 device_utils._IterPushableComponents(layout.root, device_path)) 3991 self.safeAssertItemsEqual(expected, actual) 3992 3993 3994class DeviceUtilsGetTracingPathTest(DeviceUtilsTest): 3995 def testGetTracingPath_hasDebugfs(self): 3996 with self.assertCalls( 3997 (self.call.device.RunShellCommand(['mount'], retries=0, 3998 timeout=10, check_return=True), 3999 ['debugfs on /sys/kernel/debug', 'proc on /proc'])): 4000 self.assertEquals('/sys/kernel/debug/tracing', 4001 self.device.GetTracingPath()) 4002 4003 def testGetTracingPath_noDebugfs(self): 4004 with self.assertCalls( 4005 (self.call.device.RunShellCommand(['mount'], retries=0, 4006 timeout=10, check_return=True), 4007 ['proc on /proc'])): 4008 self.assertEquals('/sys/kernel/tracing', self.device.GetTracingPath()) 4009 4010 4011if __name__ == '__main__': 4012 logging.getLogger().setLevel(logging.DEBUG) 4013 unittest.main(verbosity=2) 4014