blob: 2490209631075502df03c9f81c035b8da05ef2b6 [file] [log] [blame]
Chris Craikbe1f9092016-03-28 13:54:49 -07001#!/usr/bin/env python
2# Copyright 2014 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""
7Unit tests for the contents of device_utils.py (mostly DeviceUtils).
8"""
9
10# pylint: disable=protected-access
11# pylint: disable=unused-argument
12
Chris Craika23c9e92016-08-19 14:42:29 -070013import json
Chris Craikbe1f9092016-03-28 13:54:49 -070014import logging
Chris Craika23c9e92016-08-19 14:42:29 -070015import os
16import stat
Chris Craikbe1f9092016-03-28 13:54:49 -070017import unittest
18
19from devil import devil_env
20from devil.android import device_errors
21from devil.android import device_signal
22from devil.android import device_utils
23from devil.android.sdk import adb_wrapper
24from devil.android.sdk import intent
Chris Craika0e5c0d2017-03-29 15:00:32 -070025from devil.android.sdk import keyevent
Chris Craikbe1f9092016-03-28 13:54:49 -070026from devil.android.sdk import version_codes
27from devil.utils import cmd_helper
28from devil.utils import mock_calls
29
30with devil_env.SysPath(devil_env.PYMOCK_PATH):
31 import mock # pylint: disable=import-error
32
33
Chris Craika23c9e92016-08-19 14:42:29 -070034class AnyStringWith(object):
35 def __init__(self, value):
36 self._value = value
37
38 def __eq__(self, other):
39 return self._value in other
40
41 def __repr__(self):
42 return '<AnyStringWith: %s>' % self._value
43
44
Chris Craikbe1f9092016-03-28 13:54:49 -070045class _MockApkHelper(object):
46
47 def __init__(self, path, package_name, perms=None):
48 self.path = path
49 self.package_name = package_name
50 self.perms = perms
51
52 def GetPackageName(self):
53 return self.package_name
54
55 def GetPermissions(self):
56 return self.perms
57
58
Chris Craika23c9e92016-08-19 14:42:29 -070059class _MockMultipleDevicesError(Exception):
60 pass
61
62
Chris Craikbe1f9092016-03-28 13:54:49 -070063class DeviceUtilsInitTest(unittest.TestCase):
64
65 def testInitWithStr(self):
66 serial_as_str = str('0123456789abcdef')
67 d = device_utils.DeviceUtils('0123456789abcdef')
68 self.assertEqual(serial_as_str, d.adb.GetDeviceSerial())
69
70 def testInitWithUnicode(self):
71 serial_as_unicode = unicode('fedcba9876543210')
72 d = device_utils.DeviceUtils(serial_as_unicode)
73 self.assertEqual(serial_as_unicode, d.adb.GetDeviceSerial())
74
75 def testInitWithAdbWrapper(self):
76 serial = '123456789abcdef0'
77 a = adb_wrapper.AdbWrapper(serial)
78 d = device_utils.DeviceUtils(a)
79 self.assertEqual(serial, d.adb.GetDeviceSerial())
80
81 def testInitWithMissing_fails(self):
82 with self.assertRaises(ValueError):
83 device_utils.DeviceUtils(None)
84 with self.assertRaises(ValueError):
85 device_utils.DeviceUtils('')
86
87
88class DeviceUtilsGetAVDsTest(mock_calls.TestCase):
89
90 def testGetAVDs(self):
91 mocked_attrs = {
92 'android_sdk': '/my/sdk/path'
93 }
94 with mock.patch('devil.devil_env._Environment.LocalPath',
95 mock.Mock(side_effect=lambda a: mocked_attrs[a])):
96 with self.assertCall(
97 mock.call.devil.utils.cmd_helper.GetCmdOutput(
98 [mock.ANY, 'list', 'avd']),
99 'Available Android Virtual Devices:\n'
100 ' Name: my_android5.0\n'
101 ' Path: /some/path/to/.android/avd/my_android5.0.avd\n'
102 ' Target: Android 5.0 (API level 21)\n'
103 ' Tag/ABI: default/x86\n'
104 ' Skin: WVGA800\n'):
105 self.assertEquals(['my_android5.0'], device_utils.GetAVDs())
106
107
108class DeviceUtilsRestartServerTest(mock_calls.TestCase):
109
110 @mock.patch('time.sleep', mock.Mock())
111 def testRestartServer_succeeds(self):
112 with self.assertCalls(
113 mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.KillServer(),
114 (mock.call.devil.utils.cmd_helper.GetCmdStatusAndOutput(
115 ['pgrep', 'adb']),
116 (1, '')),
117 mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.StartServer(),
118 (mock.call.devil.utils.cmd_helper.GetCmdStatusAndOutput(
119 ['pgrep', 'adb']),
120 (1, '')),
121 (mock.call.devil.utils.cmd_helper.GetCmdStatusAndOutput(
122 ['pgrep', 'adb']),
123 (0, '123\n'))):
124 device_utils.RestartServer()
125
126
127class MockTempFile(object):
128
129 def __init__(self, name='/tmp/some/file'):
130 self.file = mock.MagicMock(spec=file)
131 self.file.name = name
132 self.file.name_quoted = cmd_helper.SingleQuote(name)
133
134 def __enter__(self):
135 return self.file
136
137 def __exit__(self, exc_type, exc_val, exc_tb):
138 pass
139
140 @property
141 def name(self):
142 return self.file.name
143
144
145class _PatchedFunction(object):
146
147 def __init__(self, patched=None, mocked=None):
148 self.patched = patched
149 self.mocked = mocked
150
151
152def _AdbWrapperMock(test_serial, is_ready=True):
153 adb = mock.Mock(spec=adb_wrapper.AdbWrapper)
154 adb.__str__ = mock.Mock(return_value=test_serial)
155 adb.GetDeviceSerial.return_value = test_serial
156 adb.is_ready = is_ready
157 return adb
158
159
160class DeviceUtilsTest(mock_calls.TestCase):
161
162 def setUp(self):
163 self.adb = _AdbWrapperMock('0123456789abcdef')
164 self.device = device_utils.DeviceUtils(
165 self.adb, default_timeout=10, default_retries=0)
166 self.watchMethodCalls(self.call.adb, ignore=['GetDeviceSerial'])
167
168 def AdbCommandError(self, args=None, output=None, status=None, msg=None):
169 if args is None:
170 args = ['[unspecified]']
171 return mock.Mock(side_effect=device_errors.AdbCommandFailedError(
172 args, output, status, msg, str(self.device)))
173
174 def CommandError(self, msg=None):
175 if msg is None:
176 msg = 'Command failed'
177 return mock.Mock(side_effect=device_errors.CommandFailedError(
178 msg, str(self.device)))
179
180 def ShellError(self, output=None, status=1):
181 def action(cmd, *args, **kwargs):
182 raise device_errors.AdbShellCommandFailedError(
183 cmd, output, status, str(self.device))
184 if output is None:
185 output = 'Permission denied\n'
186 return action
187
188 def TimeoutError(self, msg=None):
189 if msg is None:
190 msg = 'Operation timed out'
191 return mock.Mock(side_effect=device_errors.CommandTimeoutError(
192 msg, str(self.device)))
193
Chris Craika23c9e92016-08-19 14:42:29 -0700194 def EnsureCacheInitialized(self, props=None, sdcard='/sdcard'):
195 props = props or []
196 ret = [sdcard, 'TOKEN'] + props
197 return (self.call.device.RunShellCommand(
Chris Craika0e5c0d2017-03-29 15:00:32 -0700198 AnyStringWith('getprop'),
199 shell=True, check_return=True, large_output=True), ret)
Chris Craika23c9e92016-08-19 14:42:29 -0700200
Chris Craikbe1f9092016-03-28 13:54:49 -0700201
202class DeviceUtilsEqTest(DeviceUtilsTest):
203
204 def testEq_equal_deviceUtils(self):
205 other = device_utils.DeviceUtils(_AdbWrapperMock('0123456789abcdef'))
206 self.assertTrue(self.device == other)
207 self.assertTrue(other == self.device)
208
209 def testEq_equal_adbWrapper(self):
210 other = adb_wrapper.AdbWrapper('0123456789abcdef')
211 self.assertTrue(self.device == other)
212 self.assertTrue(other == self.device)
213
214 def testEq_equal_string(self):
215 other = '0123456789abcdef'
216 self.assertTrue(self.device == other)
217 self.assertTrue(other == self.device)
218
219 def testEq_devicesNotEqual(self):
220 other = device_utils.DeviceUtils(_AdbWrapperMock('0123456789abcdee'))
221 self.assertFalse(self.device == other)
222 self.assertFalse(other == self.device)
223
224 def testEq_identity(self):
225 self.assertTrue(self.device == self.device)
226
227 def testEq_serialInList(self):
228 devices = [self.device]
229 self.assertTrue('0123456789abcdef' in devices)
230
231
232class DeviceUtilsLtTest(DeviceUtilsTest):
233
234 def testLt_lessThan(self):
235 other = device_utils.DeviceUtils(_AdbWrapperMock('ffffffffffffffff'))
236 self.assertTrue(self.device < other)
237 self.assertTrue(other > self.device)
238
239 def testLt_greaterThan_lhs(self):
240 other = device_utils.DeviceUtils(_AdbWrapperMock('0000000000000000'))
241 self.assertFalse(self.device < other)
242 self.assertFalse(other > self.device)
243
244 def testLt_equal(self):
245 other = device_utils.DeviceUtils(_AdbWrapperMock('0123456789abcdef'))
246 self.assertFalse(self.device < other)
247 self.assertFalse(other > self.device)
248
249 def testLt_sorted(self):
250 devices = [
251 device_utils.DeviceUtils(_AdbWrapperMock('ffffffffffffffff')),
252 device_utils.DeviceUtils(_AdbWrapperMock('0000000000000000')),
253 ]
254 sorted_devices = sorted(devices)
255 self.assertEquals('0000000000000000',
256 sorted_devices[0].adb.GetDeviceSerial())
257 self.assertEquals('ffffffffffffffff',
258 sorted_devices[1].adb.GetDeviceSerial())
259
260
261class DeviceUtilsStrTest(DeviceUtilsTest):
262
263 def testStr_returnsSerial(self):
264 with self.assertCalls(
265 (self.call.adb.GetDeviceSerial(), '0123456789abcdef')):
266 self.assertEqual('0123456789abcdef', str(self.device))
267
268
269class DeviceUtilsIsOnlineTest(DeviceUtilsTest):
270
271 def testIsOnline_true(self):
272 with self.assertCall(self.call.adb.GetState(), 'device'):
273 self.assertTrue(self.device.IsOnline())
274
275 def testIsOnline_false(self):
276 with self.assertCall(self.call.adb.GetState(), 'offline'):
277 self.assertFalse(self.device.IsOnline())
278
279 def testIsOnline_error(self):
280 with self.assertCall(self.call.adb.GetState(), self.CommandError()):
281 self.assertFalse(self.device.IsOnline())
282
283
284class DeviceUtilsHasRootTest(DeviceUtilsTest):
285
286 def testHasRoot_true(self):
Chris Craika0e5c0d2017-03-29 15:00:32 -0700287 with self.patch_call(self.call.device.product_name,
288 return_value='notasailfish'), (
289 self.assertCall(self.call.adb.Shell('ls /root'), 'foo\n')):
290 self.assertTrue(self.device.HasRoot())
291
292 def testhasRootSpecial_true(self):
293 with self.patch_call(self.call.device.product_name,
294 return_value='sailfish'), (
295 self.assertCall(self.call.adb.Shell('getprop service.adb.root'),
296 '1\n')):
Chris Craikbe1f9092016-03-28 13:54:49 -0700297 self.assertTrue(self.device.HasRoot())
298
299 def testHasRoot_false(self):
Chris Craika0e5c0d2017-03-29 15:00:32 -0700300 with self.patch_call(self.call.device.product_name,
301 return_value='notasailfish'), (
302 self.assertCall(self.call.adb.Shell('ls /root'),
303 self.ShellError())):
304 self.assertFalse(self.device.HasRoot())
305
306 def testHasRootSpecial_false(self):
307 with self.patch_call(self.call.device.product_name,
308 return_value='sailfish'), (
309 self.assertCall(self.call.adb.Shell('getprop service.adb.root'),
310 '\n')):
Chris Craikbe1f9092016-03-28 13:54:49 -0700311 self.assertFalse(self.device.HasRoot())
312
313
314class DeviceUtilsEnableRootTest(DeviceUtilsTest):
315
316 def testEnableRoot_succeeds(self):
317 with self.assertCalls(
318 (self.call.device.IsUserBuild(), False),
319 self.call.adb.Root(),
320 self.call.device.WaitUntilFullyBooted()):
321 self.device.EnableRoot()
322
323 def testEnableRoot_userBuild(self):
324 with self.assertCalls(
325 (self.call.device.IsUserBuild(), True)):
326 with self.assertRaises(device_errors.CommandFailedError):
327 self.device.EnableRoot()
328
329 def testEnableRoot_rootFails(self):
330 with self.assertCalls(
331 (self.call.device.IsUserBuild(), False),
332 (self.call.adb.Root(), self.CommandError())):
333 with self.assertRaises(device_errors.CommandFailedError):
334 self.device.EnableRoot()
335
336
337class DeviceUtilsIsUserBuildTest(DeviceUtilsTest):
338
339 def testIsUserBuild_yes(self):
340 with self.assertCall(
341 self.call.device.GetProp('ro.build.type', cache=True), 'user'):
342 self.assertTrue(self.device.IsUserBuild())
343
344 def testIsUserBuild_no(self):
345 with self.assertCall(
346 self.call.device.GetProp('ro.build.type', cache=True), 'userdebug'):
347 self.assertFalse(self.device.IsUserBuild())
348
349
350class DeviceUtilsGetExternalStoragePathTest(DeviceUtilsTest):
351
352 def testGetExternalStoragePath_succeeds(self):
Chris Craika23c9e92016-08-19 14:42:29 -0700353 with self.assertCalls(
354 self.EnsureCacheInitialized(sdcard='/fake/storage/path')):
Chris Craikbe1f9092016-03-28 13:54:49 -0700355 self.assertEquals('/fake/storage/path',
356 self.device.GetExternalStoragePath())
357
358 def testGetExternalStoragePath_fails(self):
Chris Craika23c9e92016-08-19 14:42:29 -0700359 with self.assertCalls(
360 self.EnsureCacheInitialized(sdcard='')):
Chris Craikbe1f9092016-03-28 13:54:49 -0700361 with self.assertRaises(device_errors.CommandFailedError):
362 self.device.GetExternalStoragePath()
363
364
365class DeviceUtilsGetApplicationPathsInternalTest(DeviceUtilsTest):
366
367 def testGetApplicationPathsInternal_exists(self):
368 with self.assertCalls(
369 (self.call.device.GetProp('ro.build.version.sdk', cache=True), '19'),
370 (self.call.device.RunShellCommand(
371 ['pm', 'path', 'android'], check_return=True),
372 ['package:/path/to/android.apk'])):
373 self.assertEquals(['/path/to/android.apk'],
374 self.device._GetApplicationPathsInternal('android'))
375
376 def testGetApplicationPathsInternal_notExists(self):
377 with self.assertCalls(
378 (self.call.device.GetProp('ro.build.version.sdk', cache=True), '19'),
379 (self.call.device.RunShellCommand(
380 ['pm', 'path', 'not.installed.app'], check_return=True),
381 '')):
382 self.assertEquals([],
383 self.device._GetApplicationPathsInternal('not.installed.app'))
384
John Reck33259e42017-01-18 13:57:49 -0800385 def testGetApplicationPathsInternal_garbageFirstLine(self):
386 with self.assertCalls(
387 (self.call.device.GetProp('ro.build.version.sdk', cache=True), '19'),
388 (self.call.device.RunShellCommand(
389 ['pm', 'path', 'android'], check_return=True),
390 ['garbage first line'])):
391 with self.assertRaises(device_errors.CommandFailedError):
392 self.device._GetApplicationPathsInternal('android')
393
Chris Craikbe1f9092016-03-28 13:54:49 -0700394 def testGetApplicationPathsInternal_fails(self):
395 with self.assertCalls(
396 (self.call.device.GetProp('ro.build.version.sdk', cache=True), '19'),
397 (self.call.device.RunShellCommand(
398 ['pm', 'path', 'android'], check_return=True),
399 self.CommandError('ERROR. Is package manager running?\n'))):
400 with self.assertRaises(device_errors.CommandFailedError):
401 self.device._GetApplicationPathsInternal('android')
402
403
404class DeviceUtils_GetApplicationVersionTest(DeviceUtilsTest):
405
406 def test_GetApplicationVersion_exists(self):
407 with self.assertCalls(
408 (self.call.adb.Shell('dumpsys package com.android.chrome'),
409 'Packages:\n'
410 ' Package [com.android.chrome] (3901ecfb):\n'
411 ' userId=1234 gids=[123, 456, 789]\n'
412 ' pkg=Package{1fecf634 com.android.chrome}\n'
413 ' versionName=45.0.1234.7\n')):
414 self.assertEquals('45.0.1234.7',
415 self.device.GetApplicationVersion('com.android.chrome'))
416
417 def test_GetApplicationVersion_notExists(self):
418 with self.assertCalls(
419 (self.call.adb.Shell('dumpsys package com.android.chrome'), '')):
420 self.assertEquals(None,
421 self.device.GetApplicationVersion('com.android.chrome'))
422
423 def test_GetApplicationVersion_fails(self):
424 with self.assertCalls(
425 (self.call.adb.Shell('dumpsys package com.android.chrome'),
426 'Packages:\n'
427 ' Package [com.android.chrome] (3901ecfb):\n'
428 ' userId=1234 gids=[123, 456, 789]\n'
429 ' pkg=Package{1fecf634 com.android.chrome}\n')):
430 with self.assertRaises(device_errors.CommandFailedError):
431 self.device.GetApplicationVersion('com.android.chrome')
432
433
434class DeviceUtilsGetApplicationDataDirectoryTest(DeviceUtilsTest):
435
436 def testGetApplicationDataDirectory_exists(self):
437 with self.assertCall(
438 self.call.device._RunPipedShellCommand(
439 'pm dump foo.bar.baz | grep dataDir='),
440 ['dataDir=/data/data/foo.bar.baz']):
441 self.assertEquals(
442 '/data/data/foo.bar.baz',
443 self.device.GetApplicationDataDirectory('foo.bar.baz'))
444
445 def testGetApplicationDataDirectory_notExists(self):
446 with self.assertCall(
447 self.call.device._RunPipedShellCommand(
448 'pm dump foo.bar.baz | grep dataDir='),
449 self.ShellError()):
John Reck33259e42017-01-18 13:57:49 -0800450 with self.assertRaises(device_errors.CommandFailedError):
451 self.device.GetApplicationDataDirectory('foo.bar.baz')
Chris Craikbe1f9092016-03-28 13:54:49 -0700452
453
454@mock.patch('time.sleep', mock.Mock())
455class DeviceUtilsWaitUntilFullyBootedTest(DeviceUtilsTest):
456
457 def testWaitUntilFullyBooted_succeedsNoWifi(self):
458 with self.assertCalls(
459 self.call.adb.WaitForDevice(),
460 # sd_card_ready
461 (self.call.device.GetExternalStoragePath(), '/fake/storage/path'),
462 (self.call.adb.Shell('test -d /fake/storage/path'), ''),
463 # pm_ready
464 (self.call.device._GetApplicationPathsInternal('android',
465 skip_cache=True),
466 ['package:/some/fake/path']),
467 # boot_completed
468 (self.call.device.GetProp('sys.boot_completed', cache=False), '1')):
469 self.device.WaitUntilFullyBooted(wifi=False)
470
471 def testWaitUntilFullyBooted_succeedsWithWifi(self):
472 with self.assertCalls(
473 self.call.adb.WaitForDevice(),
474 # sd_card_ready
475 (self.call.device.GetExternalStoragePath(), '/fake/storage/path'),
476 (self.call.adb.Shell('test -d /fake/storage/path'), ''),
477 # pm_ready
478 (self.call.device._GetApplicationPathsInternal('android',
479 skip_cache=True),
480 ['package:/some/fake/path']),
481 # boot_completed
482 (self.call.device.GetProp('sys.boot_completed', cache=False), '1'),
483 # wifi_enabled
484 (self.call.adb.Shell('dumpsys wifi'),
485 'stuff\nWi-Fi is enabled\nmore stuff\n')):
486 self.device.WaitUntilFullyBooted(wifi=True)
487
488 def testWaitUntilFullyBooted_deviceNotInitiallyAvailable(self):
489 with self.assertCalls(
490 self.call.adb.WaitForDevice(),
491 # sd_card_ready
492 (self.call.device.GetExternalStoragePath(), self.AdbCommandError()),
493 # sd_card_ready
494 (self.call.device.GetExternalStoragePath(), self.AdbCommandError()),
495 # sd_card_ready
496 (self.call.device.GetExternalStoragePath(), self.AdbCommandError()),
497 # sd_card_ready
498 (self.call.device.GetExternalStoragePath(), self.AdbCommandError()),
499 # sd_card_ready
500 (self.call.device.GetExternalStoragePath(), '/fake/storage/path'),
501 (self.call.adb.Shell('test -d /fake/storage/path'), ''),
502 # pm_ready
503 (self.call.device._GetApplicationPathsInternal('android',
504 skip_cache=True),
505 ['package:/some/fake/path']),
506 # boot_completed
507 (self.call.device.GetProp('sys.boot_completed', cache=False), '1')):
508 self.device.WaitUntilFullyBooted(wifi=False)
509
Chris Craika23c9e92016-08-19 14:42:29 -0700510 def testWaitUntilFullyBooted_deviceBrieflyOffline(self):
511 with self.assertCalls(
512 self.call.adb.WaitForDevice(),
513 # sd_card_ready
514 (self.call.device.GetExternalStoragePath(), '/fake/storage/path'),
515 (self.call.adb.Shell('test -d /fake/storage/path'), ''),
516 # pm_ready
517 (self.call.device._GetApplicationPathsInternal('android',
518 skip_cache=True),
519 ['package:/some/fake/path']),
520 # boot_completed
521 (self.call.device.GetProp('sys.boot_completed', cache=False),
522 self.AdbCommandError()),
523 # boot_completed
524 (self.call.device.GetProp('sys.boot_completed', cache=False), '1')):
525 self.device.WaitUntilFullyBooted(wifi=False)
526
Chris Craikbe1f9092016-03-28 13:54:49 -0700527 def testWaitUntilFullyBooted_sdCardReadyFails_noPath(self):
528 with self.assertCalls(
529 self.call.adb.WaitForDevice(),
530 # sd_card_ready
531 (self.call.device.GetExternalStoragePath(), self.CommandError())):
532 with self.assertRaises(device_errors.CommandFailedError):
533 self.device.WaitUntilFullyBooted(wifi=False)
534
535 def testWaitUntilFullyBooted_sdCardReadyFails_notExists(self):
536 with self.assertCalls(
537 self.call.adb.WaitForDevice(),
538 # sd_card_ready
539 (self.call.device.GetExternalStoragePath(), '/fake/storage/path'),
540 (self.call.adb.Shell('test -d /fake/storage/path'), self.ShellError()),
541 # sd_card_ready
542 (self.call.device.GetExternalStoragePath(), '/fake/storage/path'),
543 (self.call.adb.Shell('test -d /fake/storage/path'), self.ShellError()),
544 # sd_card_ready
545 (self.call.device.GetExternalStoragePath(), '/fake/storage/path'),
546 (self.call.adb.Shell('test -d /fake/storage/path'),
547 self.TimeoutError())):
548 with self.assertRaises(device_errors.CommandTimeoutError):
549 self.device.WaitUntilFullyBooted(wifi=False)
550
551 def testWaitUntilFullyBooted_devicePmFails(self):
552 with self.assertCalls(
553 self.call.adb.WaitForDevice(),
554 # sd_card_ready
555 (self.call.device.GetExternalStoragePath(), '/fake/storage/path'),
556 (self.call.adb.Shell('test -d /fake/storage/path'), ''),
557 # pm_ready
558 (self.call.device._GetApplicationPathsInternal('android',
559 skip_cache=True),
560 self.CommandError()),
561 # pm_ready
562 (self.call.device._GetApplicationPathsInternal('android',
563 skip_cache=True),
564 self.CommandError()),
565 # pm_ready
566 (self.call.device._GetApplicationPathsInternal('android',
567 skip_cache=True),
568 self.TimeoutError())):
569 with self.assertRaises(device_errors.CommandTimeoutError):
570 self.device.WaitUntilFullyBooted(wifi=False)
571
572 def testWaitUntilFullyBooted_bootFails(self):
573 with self.assertCalls(
574 self.call.adb.WaitForDevice(),
575 # sd_card_ready
576 (self.call.device.GetExternalStoragePath(), '/fake/storage/path'),
577 (self.call.adb.Shell('test -d /fake/storage/path'), ''),
578 # pm_ready
579 (self.call.device._GetApplicationPathsInternal('android',
580 skip_cache=True),
581 ['package:/some/fake/path']),
582 # boot_completed
583 (self.call.device.GetProp('sys.boot_completed', cache=False), '0'),
584 # boot_completed
585 (self.call.device.GetProp('sys.boot_completed', cache=False), '0'),
586 # boot_completed
587 (self.call.device.GetProp('sys.boot_completed', cache=False),
588 self.TimeoutError())):
589 with self.assertRaises(device_errors.CommandTimeoutError):
590 self.device.WaitUntilFullyBooted(wifi=False)
591
592 def testWaitUntilFullyBooted_wifiFails(self):
593 with self.assertCalls(
594 self.call.adb.WaitForDevice(),
595 # sd_card_ready
596 (self.call.device.GetExternalStoragePath(), '/fake/storage/path'),
597 (self.call.adb.Shell('test -d /fake/storage/path'), ''),
598 # pm_ready
599 (self.call.device._GetApplicationPathsInternal('android',
600 skip_cache=True),
601 ['package:/some/fake/path']),
602 # boot_completed
603 (self.call.device.GetProp('sys.boot_completed', cache=False), '1'),
604 # wifi_enabled
605 (self.call.adb.Shell('dumpsys wifi'), 'stuff\nmore stuff\n'),
606 # wifi_enabled
607 (self.call.adb.Shell('dumpsys wifi'), 'stuff\nmore stuff\n'),
608 # wifi_enabled
609 (self.call.adb.Shell('dumpsys wifi'), self.TimeoutError())):
610 with self.assertRaises(device_errors.CommandTimeoutError):
611 self.device.WaitUntilFullyBooted(wifi=True)
612
613
614@mock.patch('time.sleep', mock.Mock())
615class DeviceUtilsRebootTest(DeviceUtilsTest):
616
617 def testReboot_nonBlocking(self):
618 with self.assertCalls(
619 self.call.adb.Reboot(),
620 (self.call.device.IsOnline(), True),
621 (self.call.device.IsOnline(), False)):
622 self.device.Reboot(block=False)
623
624 def testReboot_blocking(self):
625 with self.assertCalls(
626 self.call.adb.Reboot(),
627 (self.call.device.IsOnline(), True),
628 (self.call.device.IsOnline(), False),
629 self.call.device.WaitUntilFullyBooted(wifi=False)):
630 self.device.Reboot(block=True)
631
632 def testReboot_blockUntilWifi(self):
633 with self.assertCalls(
634 self.call.adb.Reboot(),
635 (self.call.device.IsOnline(), True),
636 (self.call.device.IsOnline(), False),
637 self.call.device.WaitUntilFullyBooted(wifi=True)):
638 self.device.Reboot(block=True, wifi=True)
639
640
641class DeviceUtilsInstallTest(DeviceUtilsTest):
642
643 mock_apk = _MockApkHelper('/fake/test/app.apk', 'test.package', ['p1'])
644
645 def testInstall_noPriorInstall(self):
646 with self.patch_call(self.call.device.build_version_sdk, return_value=23):
647 with self.assertCalls(
John Reck33259e42017-01-18 13:57:49 -0800648 (mock.call.os.path.exists('/fake/test/app.apk'), True),
Chris Craikbe1f9092016-03-28 13:54:49 -0700649 (self.call.device._GetApplicationPathsInternal('test.package'), []),
650 self.call.adb.Install('/fake/test/app.apk', reinstall=False,
651 allow_downgrade=False),
652 (self.call.device.GrantPermissions('test.package', ['p1']), [])):
653 self.device.Install(DeviceUtilsInstallTest.mock_apk, retries=0)
654
655 def testInstall_permissionsPreM(self):
656 with self.patch_call(self.call.device.build_version_sdk, return_value=20):
657 with self.assertCalls(
John Reck33259e42017-01-18 13:57:49 -0800658 (mock.call.os.path.exists('/fake/test/app.apk'), True),
Chris Craikbe1f9092016-03-28 13:54:49 -0700659 (self.call.device._GetApplicationPathsInternal('test.package'), []),
660 (self.call.adb.Install('/fake/test/app.apk', reinstall=False,
661 allow_downgrade=False))):
662 self.device.Install(DeviceUtilsInstallTest.mock_apk, retries=0)
663
664 def testInstall_findPermissions(self):
665 with self.patch_call(self.call.device.build_version_sdk, return_value=23):
666 with self.assertCalls(
John Reck33259e42017-01-18 13:57:49 -0800667 (mock.call.os.path.exists('/fake/test/app.apk'), True),
Chris Craikbe1f9092016-03-28 13:54:49 -0700668 (self.call.device._GetApplicationPathsInternal('test.package'), []),
669 (self.call.adb.Install('/fake/test/app.apk', reinstall=False,
670 allow_downgrade=False)),
671 (self.call.device.GrantPermissions('test.package', ['p1']), [])):
672 self.device.Install(DeviceUtilsInstallTest.mock_apk, retries=0)
673
674 def testInstall_passPermissions(self):
675 with self.assertCalls(
John Reck33259e42017-01-18 13:57:49 -0800676 (mock.call.os.path.exists('/fake/test/app.apk'), True),
Chris Craikbe1f9092016-03-28 13:54:49 -0700677 (self.call.device._GetApplicationPathsInternal('test.package'), []),
678 (self.call.adb.Install('/fake/test/app.apk', reinstall=False,
679 allow_downgrade=False)),
680 (self.call.device.GrantPermissions('test.package', ['p1', 'p2']), [])):
681 self.device.Install(DeviceUtilsInstallTest.mock_apk, retries=0,
682 permissions=['p1', 'p2'])
683
684 def testInstall_differentPriorInstall(self):
685 with self.assertCalls(
John Reck33259e42017-01-18 13:57:49 -0800686 (mock.call.os.path.exists('/fake/test/app.apk'), True),
Chris Craikbe1f9092016-03-28 13:54:49 -0700687 (self.call.device._GetApplicationPathsInternal('test.package'),
688 ['/fake/data/app/test.package.apk']),
689 (self.call.device._ComputeStaleApks('test.package',
690 ['/fake/test/app.apk']),
691 (['/fake/test/app.apk'], None)),
692 self.call.device.Uninstall('test.package'),
693 self.call.adb.Install('/fake/test/app.apk', reinstall=False,
694 allow_downgrade=False)):
695 self.device.Install(DeviceUtilsInstallTest.mock_apk, retries=0,
696 permissions=[])
697
698 def testInstall_differentPriorInstall_reinstall(self):
699 with self.assertCalls(
John Reck33259e42017-01-18 13:57:49 -0800700 (mock.call.os.path.exists('/fake/test/app.apk'), True),
Chris Craikbe1f9092016-03-28 13:54:49 -0700701 (self.call.device._GetApplicationPathsInternal('test.package'),
702 ['/fake/data/app/test.package.apk']),
703 (self.call.device._ComputeStaleApks('test.package',
704 ['/fake/test/app.apk']),
705 (['/fake/test/app.apk'], None)),
706 self.call.adb.Install('/fake/test/app.apk', reinstall=True,
707 allow_downgrade=False)):
708 self.device.Install(DeviceUtilsInstallTest.mock_apk,
709 reinstall=True, retries=0, permissions=[])
710
711 def testInstall_identicalPriorInstall_reinstall(self):
712 with self.assertCalls(
John Reck33259e42017-01-18 13:57:49 -0800713 (mock.call.os.path.exists('/fake/test/app.apk'), True),
Chris Craikbe1f9092016-03-28 13:54:49 -0700714 (self.call.device._GetApplicationPathsInternal('test.package'),
715 ['/fake/data/app/test.package.apk']),
716 (self.call.device._ComputeStaleApks('test.package',
717 ['/fake/test/app.apk']),
718 ([], None)),
719 (self.call.device.ForceStop('test.package'))):
720 self.device.Install(DeviceUtilsInstallTest.mock_apk,
721 reinstall=True, retries=0, permissions=[])
722
John Reck33259e42017-01-18 13:57:49 -0800723 def testInstall_missingApk(self):
724 with self.assertCalls(
725 (mock.call.os.path.exists('/fake/test/app.apk'), False)):
726 with self.assertRaises(device_errors.CommandFailedError):
727 self.device.Install(DeviceUtilsInstallTest.mock_apk, retries=0)
728
Chris Craikbe1f9092016-03-28 13:54:49 -0700729 def testInstall_fails(self):
730 with self.assertCalls(
John Reck33259e42017-01-18 13:57:49 -0800731 (mock.call.os.path.exists('/fake/test/app.apk'), True),
Chris Craikbe1f9092016-03-28 13:54:49 -0700732 (self.call.device._GetApplicationPathsInternal('test.package'), []),
733 (self.call.adb.Install('/fake/test/app.apk', reinstall=False,
734 allow_downgrade=False),
735 self.CommandError('Failure\r\n'))):
736 with self.assertRaises(device_errors.CommandFailedError):
737 self.device.Install(DeviceUtilsInstallTest.mock_apk, retries=0)
738
739 def testInstall_downgrade(self):
740 with self.assertCalls(
John Reck33259e42017-01-18 13:57:49 -0800741 (mock.call.os.path.exists('/fake/test/app.apk'), True),
Chris Craikbe1f9092016-03-28 13:54:49 -0700742 (self.call.device._GetApplicationPathsInternal('test.package'),
743 ['/fake/data/app/test.package.apk']),
744 (self.call.device._ComputeStaleApks('test.package',
745 ['/fake/test/app.apk']),
746 (['/fake/test/app.apk'], None)),
747 self.call.adb.Install('/fake/test/app.apk', reinstall=True,
748 allow_downgrade=True)):
749 self.device.Install(DeviceUtilsInstallTest.mock_apk,
750 reinstall=True, retries=0, permissions=[], allow_downgrade=True)
751
752
753class DeviceUtilsInstallSplitApkTest(DeviceUtilsTest):
754
755 mock_apk = _MockApkHelper('base.apk', 'test.package', ['p1'])
756
757 def testInstallSplitApk_noPriorInstall(self):
758 with self.assertCalls(
759 (self.call.device._CheckSdkLevel(21)),
760 (mock.call.devil.android.sdk.split_select.SelectSplits(
761 self.device, 'base.apk',
762 ['split1.apk', 'split2.apk', 'split3.apk'],
763 allow_cached_props=False),
764 ['split2.apk']),
John Reck33259e42017-01-18 13:57:49 -0800765 (mock.call.os.path.exists('base.apk'), True),
766 (mock.call.os.path.exists('split2.apk'), True),
Chris Craikbe1f9092016-03-28 13:54:49 -0700767 (self.call.device._GetApplicationPathsInternal('test.package'), []),
768 (self.call.adb.InstallMultiple(
769 ['base.apk', 'split2.apk'], partial=None, reinstall=False,
770 allow_downgrade=False))):
771 self.device.InstallSplitApk(DeviceUtilsInstallSplitApkTest.mock_apk,
772 ['split1.apk', 'split2.apk', 'split3.apk'], permissions=[], retries=0)
773
774 def testInstallSplitApk_partialInstall(self):
775 with self.assertCalls(
776 (self.call.device._CheckSdkLevel(21)),
777 (mock.call.devil.android.sdk.split_select.SelectSplits(
778 self.device, 'base.apk',
779 ['split1.apk', 'split2.apk', 'split3.apk'],
780 allow_cached_props=False),
781 ['split2.apk']),
John Reck33259e42017-01-18 13:57:49 -0800782 (mock.call.os.path.exists('base.apk'), True),
783 (mock.call.os.path.exists('split2.apk'), True),
Chris Craikbe1f9092016-03-28 13:54:49 -0700784 (self.call.device._GetApplicationPathsInternal('test.package'),
785 ['base-on-device.apk', 'split2-on-device.apk']),
786 (self.call.device._ComputeStaleApks('test.package',
787 ['base.apk', 'split2.apk']),
788 (['split2.apk'], None)),
789 (self.call.adb.InstallMultiple(
790 ['split2.apk'], partial='test.package', reinstall=True,
791 allow_downgrade=False))):
792 self.device.InstallSplitApk(DeviceUtilsInstallSplitApkTest.mock_apk,
793 ['split1.apk', 'split2.apk', 'split3.apk'],
794 reinstall=True, permissions=[], retries=0)
795
796 def testInstallSplitApk_downgrade(self):
797 with self.assertCalls(
798 (self.call.device._CheckSdkLevel(21)),
799 (mock.call.devil.android.sdk.split_select.SelectSplits(
800 self.device, 'base.apk',
801 ['split1.apk', 'split2.apk', 'split3.apk'],
802 allow_cached_props=False),
803 ['split2.apk']),
John Reck33259e42017-01-18 13:57:49 -0800804 (mock.call.os.path.exists('base.apk'), True),
805 (mock.call.os.path.exists('split2.apk'), True),
Chris Craikbe1f9092016-03-28 13:54:49 -0700806 (self.call.device._GetApplicationPathsInternal('test.package'),
807 ['base-on-device.apk', 'split2-on-device.apk']),
808 (self.call.device._ComputeStaleApks('test.package',
809 ['base.apk', 'split2.apk']),
810 (['split2.apk'], None)),
811 (self.call.adb.InstallMultiple(
812 ['split2.apk'], partial='test.package', reinstall=True,
813 allow_downgrade=True))):
814 self.device.InstallSplitApk(DeviceUtilsInstallSplitApkTest.mock_apk,
815 ['split1.apk', 'split2.apk', 'split3.apk'],
816 reinstall=True, permissions=[], retries=0,
817 allow_downgrade=True)
818
John Reck33259e42017-01-18 13:57:49 -0800819 def testInstallSplitApk_missingSplit(self):
820 with self.assertCalls(
821 (self.call.device._CheckSdkLevel(21)),
822 (mock.call.devil.android.sdk.split_select.SelectSplits(
823 self.device, 'base.apk',
824 ['split1.apk', 'split2.apk', 'split3.apk'],
825 allow_cached_props=False),
826 ['split2.apk']),
827 (mock.call.os.path.exists('base.apk'), True),
828 (mock.call.os.path.exists('split2.apk'), False)):
829 with self.assertRaises(device_errors.CommandFailedError):
830 self.device.InstallSplitApk(DeviceUtilsInstallSplitApkTest.mock_apk,
831 ['split1.apk', 'split2.apk', 'split3.apk'], permissions=[],
832 retries=0)
833
Chris Craikbe1f9092016-03-28 13:54:49 -0700834
835class DeviceUtilsUninstallTest(DeviceUtilsTest):
836
837 def testUninstall_callsThrough(self):
838 with self.assertCalls(
839 (self.call.device._GetApplicationPathsInternal('test.package'),
840 ['/path.apk']),
841 self.call.adb.Uninstall('test.package', True)):
842 self.device.Uninstall('test.package', True)
843
844 def testUninstall_noop(self):
845 with self.assertCalls(
846 (self.call.device._GetApplicationPathsInternal('test.package'), [])):
847 self.device.Uninstall('test.package', True)
848
849
850class DeviceUtilsSuTest(DeviceUtilsTest):
851
852 def testSu_preM(self):
853 with self.patch_call(
854 self.call.device.build_version_sdk,
855 return_value=version_codes.LOLLIPOP_MR1):
856 self.assertEquals('su -c foo', self.device._Su('foo'))
857
858 def testSu_mAndAbove(self):
859 with self.patch_call(
860 self.call.device.build_version_sdk,
861 return_value=version_codes.MARSHMALLOW):
862 self.assertEquals('su 0 foo', self.device._Su('foo'))
863
864
865class DeviceUtilsRunShellCommandTest(DeviceUtilsTest):
866
867 def setUp(self):
868 super(DeviceUtilsRunShellCommandTest, self).setUp()
869 self.device.NeedsSU = mock.Mock(return_value=False)
870
871 def testRunShellCommand_commandAsList(self):
872 with self.assertCall(self.call.adb.Shell('pm list packages'), ''):
Chris Craika0e5c0d2017-03-29 15:00:32 -0700873 self.device.RunShellCommand(
874 ['pm', 'list', 'packages'], check_return=True)
Chris Craikbe1f9092016-03-28 13:54:49 -0700875
876 def testRunShellCommand_commandAsListQuoted(self):
877 with self.assertCall(self.call.adb.Shell("echo 'hello world' '$10'"), ''):
Chris Craika0e5c0d2017-03-29 15:00:32 -0700878 self.device.RunShellCommand(
879 ['echo', 'hello world', '$10'], check_return=True)
Chris Craikbe1f9092016-03-28 13:54:49 -0700880
881 def testRunShellCommand_commandAsString(self):
882 with self.assertCall(self.call.adb.Shell('echo "$VAR"'), ''):
Chris Craika0e5c0d2017-03-29 15:00:32 -0700883 self.device.RunShellCommand(
884 'echo "$VAR"', shell=True, check_return=True)
Chris Craikbe1f9092016-03-28 13:54:49 -0700885
886 def testNewRunShellImpl_withEnv(self):
887 with self.assertCall(
888 self.call.adb.Shell('VAR=some_string echo "$VAR"'), ''):
Chris Craika0e5c0d2017-03-29 15:00:32 -0700889 self.device.RunShellCommand(
890 'echo "$VAR"', shell=True, check_return=True,
891 env={'VAR': 'some_string'})
Chris Craikbe1f9092016-03-28 13:54:49 -0700892
893 def testNewRunShellImpl_withEnvQuoted(self):
894 with self.assertCall(
895 self.call.adb.Shell('PATH="$PATH:/other/path" run_this'), ''):
Chris Craika0e5c0d2017-03-29 15:00:32 -0700896 self.device.RunShellCommand(
897 ['run_this'], check_return=True, env={'PATH': '$PATH:/other/path'})
Chris Craikbe1f9092016-03-28 13:54:49 -0700898
899 def testNewRunShellImpl_withEnv_failure(self):
900 with self.assertRaises(KeyError):
Chris Craika0e5c0d2017-03-29 15:00:32 -0700901 self.device.RunShellCommand(
902 ['some_cmd'], check_return=True, env={'INVALID NAME': 'value'})
Chris Craikbe1f9092016-03-28 13:54:49 -0700903
904 def testNewRunShellImpl_withCwd(self):
905 with self.assertCall(self.call.adb.Shell('cd /some/test/path && ls'), ''):
Chris Craika0e5c0d2017-03-29 15:00:32 -0700906 self.device.RunShellCommand(
907 ['ls'], check_return=True, cwd='/some/test/path')
Chris Craikbe1f9092016-03-28 13:54:49 -0700908
909 def testNewRunShellImpl_withCwdQuoted(self):
910 with self.assertCall(
911 self.call.adb.Shell("cd '/some test/path with/spaces' && ls"), ''):
Chris Craika0e5c0d2017-03-29 15:00:32 -0700912 self.device.RunShellCommand(
913 ['ls'], check_return=True, cwd='/some test/path with/spaces')
Chris Craikbe1f9092016-03-28 13:54:49 -0700914
915 def testRunShellCommand_withHugeCmd(self):
916 payload = 'hi! ' * 1024
917 expected_cmd = "echo '%s'" % payload
918 with self.assertCalls(
919 (mock.call.devil.android.device_temp_file.DeviceTempFile(
920 self.adb, suffix='.sh'), MockTempFile('/sdcard/temp-123.sh')),
921 self.call.device._WriteFileWithPush('/sdcard/temp-123.sh', expected_cmd),
922 (self.call.adb.Shell('sh /sdcard/temp-123.sh'), payload + '\n')):
Chris Craika0e5c0d2017-03-29 15:00:32 -0700923 self.assertEquals(
924 [payload],
925 self.device.RunShellCommand(['echo', payload], check_return=True))
Chris Craikbe1f9092016-03-28 13:54:49 -0700926
John Reck33259e42017-01-18 13:57:49 -0800927 def testRunShellCommand_withHugeCmdAndSu(self):
Chris Craikbe1f9092016-03-28 13:54:49 -0700928 payload = 'hi! ' * 1024
929 expected_cmd_without_su = """sh -c 'echo '"'"'%s'"'"''""" % payload
930 expected_cmd = 'su -c %s' % expected_cmd_without_su
931 with self.assertCalls(
932 (self.call.device.NeedsSU(), True),
933 (self.call.device._Su(expected_cmd_without_su), expected_cmd),
934 (mock.call.devil.android.device_temp_file.DeviceTempFile(
935 self.adb, suffix='.sh'), MockTempFile('/sdcard/temp-123.sh')),
936 self.call.device._WriteFileWithPush('/sdcard/temp-123.sh', expected_cmd),
937 (self.call.adb.Shell('sh /sdcard/temp-123.sh'), payload + '\n')):
938 self.assertEquals(
939 [payload],
Chris Craika0e5c0d2017-03-29 15:00:32 -0700940 self.device.RunShellCommand(
941 ['echo', payload], check_return=True, as_root=True))
Chris Craikbe1f9092016-03-28 13:54:49 -0700942
943 def testRunShellCommand_withSu(self):
944 expected_cmd_without_su = "sh -c 'setprop service.adb.root 0'"
945 expected_cmd = 'su -c %s' % expected_cmd_without_su
946 with self.assertCalls(
947 (self.call.device.NeedsSU(), True),
948 (self.call.device._Su(expected_cmd_without_su), expected_cmd),
949 (self.call.adb.Shell(expected_cmd), '')):
Chris Craika0e5c0d2017-03-29 15:00:32 -0700950 self.device.RunShellCommand(
951 ['setprop', 'service.adb.root', '0'],
952 check_return=True, as_root=True)
Chris Craikbe1f9092016-03-28 13:54:49 -0700953
John Reck33259e42017-01-18 13:57:49 -0800954 def testRunShellCommand_withRunAs(self):
955 expected_cmd_without_run_as = "sh -c 'mkdir -p files'"
956 expected_cmd = (
957 'run-as org.devil.test_package %s' % expected_cmd_without_run_as)
958 with self.assertCall(self.call.adb.Shell(expected_cmd), ''):
959 self.device.RunShellCommand(
960 ['mkdir', '-p', 'files'],
Chris Craika0e5c0d2017-03-29 15:00:32 -0700961 check_return=True, run_as='org.devil.test_package')
John Reck33259e42017-01-18 13:57:49 -0800962
963 def testRunShellCommand_withRunAsAndSu(self):
964 expected_cmd_with_nothing = "sh -c 'mkdir -p files'"
965 expected_cmd_with_run_as = (
966 'run-as org.devil.test_package %s' % expected_cmd_with_nothing)
967 expected_cmd_without_su = (
968 'sh -c %s' % cmd_helper.SingleQuote(expected_cmd_with_run_as))
969 expected_cmd = 'su -c %s' % expected_cmd_without_su
970 with self.assertCalls(
971 (self.call.device.NeedsSU(), True),
972 (self.call.device._Su(expected_cmd_without_su), expected_cmd),
973 (self.call.adb.Shell(expected_cmd), '')):
974 self.device.RunShellCommand(
975 ['mkdir', '-p', 'files'],
Chris Craika0e5c0d2017-03-29 15:00:32 -0700976 check_return=True, run_as='org.devil.test_package',
John Reck33259e42017-01-18 13:57:49 -0800977 as_root=True)
978
Chris Craikbe1f9092016-03-28 13:54:49 -0700979 def testRunShellCommand_manyLines(self):
980 cmd = 'ls /some/path'
981 with self.assertCall(self.call.adb.Shell(cmd), 'file1\nfile2\nfile3\n'):
Chris Craika0e5c0d2017-03-29 15:00:32 -0700982 self.assertEquals(
983 ['file1', 'file2', 'file3'],
984 self.device.RunShellCommand(cmd.split(), check_return=True))
Chris Craikbe1f9092016-03-28 13:54:49 -0700985
Chris Craika23c9e92016-08-19 14:42:29 -0700986 def testRunShellCommand_manyLinesRawOutput(self):
987 cmd = 'ls /some/path'
988 with self.assertCall(self.call.adb.Shell(cmd), '\rfile1\nfile2\r\nfile3\n'):
Chris Craika0e5c0d2017-03-29 15:00:32 -0700989 self.assertEquals(
990 '\rfile1\nfile2\r\nfile3\n',
991 self.device.RunShellCommand(
992 cmd.split(), check_return=True, raw_output=True))
Chris Craika23c9e92016-08-19 14:42:29 -0700993
Chris Craikbe1f9092016-03-28 13:54:49 -0700994 def testRunShellCommand_singleLine_success(self):
995 cmd = 'echo $VALUE'
996 with self.assertCall(self.call.adb.Shell(cmd), 'some value\n'):
Chris Craika0e5c0d2017-03-29 15:00:32 -0700997 self.assertEquals(
998 'some value',
999 self.device.RunShellCommand(
1000 cmd, shell=True, check_return=True, single_line=True))
Chris Craikbe1f9092016-03-28 13:54:49 -07001001
1002 def testRunShellCommand_singleLine_successEmptyLine(self):
1003 cmd = 'echo $VALUE'
1004 with self.assertCall(self.call.adb.Shell(cmd), '\n'):
Chris Craika0e5c0d2017-03-29 15:00:32 -07001005 self.assertEquals(
1006 '',
1007 self.device.RunShellCommand(
1008 cmd, shell=True, check_return=True, single_line=True))
Chris Craikbe1f9092016-03-28 13:54:49 -07001009
1010 def testRunShellCommand_singleLine_successWithoutEndLine(self):
1011 cmd = 'echo -n $VALUE'
1012 with self.assertCall(self.call.adb.Shell(cmd), 'some value'):
Chris Craika0e5c0d2017-03-29 15:00:32 -07001013 self.assertEquals(
1014 'some value',
1015 self.device.RunShellCommand(
1016 cmd, shell=True, check_return=True, single_line=True))
Chris Craikbe1f9092016-03-28 13:54:49 -07001017
1018 def testRunShellCommand_singleLine_successNoOutput(self):
1019 cmd = 'echo -n $VALUE'
1020 with self.assertCall(self.call.adb.Shell(cmd), ''):
Chris Craika0e5c0d2017-03-29 15:00:32 -07001021 self.assertEquals(
1022 '',
1023 self.device.RunShellCommand(
1024 cmd, shell=True, check_return=True, single_line=True))
Chris Craikbe1f9092016-03-28 13:54:49 -07001025
1026 def testRunShellCommand_singleLine_failTooManyLines(self):
1027 cmd = 'echo $VALUE'
1028 with self.assertCall(self.call.adb.Shell(cmd),
1029 'some value\nanother value\n'):
1030 with self.assertRaises(device_errors.CommandFailedError):
Chris Craika0e5c0d2017-03-29 15:00:32 -07001031 self.device.RunShellCommand(
1032 cmd, shell=True, check_return=True, single_line=True)
Chris Craikbe1f9092016-03-28 13:54:49 -07001033
1034 def testRunShellCommand_checkReturn_success(self):
1035 cmd = 'echo $ANDROID_DATA'
1036 output = '/data\n'
1037 with self.assertCall(self.call.adb.Shell(cmd), output):
Chris Craika0e5c0d2017-03-29 15:00:32 -07001038 self.assertEquals(
1039 [output.rstrip()],
1040 self.device.RunShellCommand(cmd, shell=True, check_return=True))
Chris Craikbe1f9092016-03-28 13:54:49 -07001041
1042 def testRunShellCommand_checkReturn_failure(self):
1043 cmd = 'ls /root'
1044 output = 'opendir failed, Permission denied\n'
1045 with self.assertCall(self.call.adb.Shell(cmd), self.ShellError(output)):
1046 with self.assertRaises(device_errors.AdbCommandFailedError):
Chris Craika0e5c0d2017-03-29 15:00:32 -07001047 self.device.RunShellCommand(cmd.split(), check_return=True)
Chris Craikbe1f9092016-03-28 13:54:49 -07001048
1049 def testRunShellCommand_checkReturn_disabled(self):
1050 cmd = 'ls /root'
1051 output = 'opendir failed, Permission denied\n'
1052 with self.assertCall(self.call.adb.Shell(cmd), self.ShellError(output)):
Chris Craika0e5c0d2017-03-29 15:00:32 -07001053 self.assertEquals(
1054 [output.rstrip()],
1055 self.device.RunShellCommand(cmd.split(), check_return=False))
Chris Craikbe1f9092016-03-28 13:54:49 -07001056
1057 def testRunShellCommand_largeOutput_enabled(self):
1058 cmd = 'echo $VALUE'
1059 temp_file = MockTempFile('/sdcard/temp-123')
1060 cmd_redirect = '( %s )>%s' % (cmd, temp_file.name)
1061 with self.assertCalls(
1062 (mock.call.devil.android.device_temp_file.DeviceTempFile(self.adb),
1063 temp_file),
1064 (self.call.adb.Shell(cmd_redirect)),
1065 (self.call.device.ReadFile(temp_file.name, force_pull=True),
1066 'something')):
1067 self.assertEquals(
1068 ['something'],
1069 self.device.RunShellCommand(
Chris Craika0e5c0d2017-03-29 15:00:32 -07001070 cmd, shell=True, large_output=True, check_return=True))
Chris Craikbe1f9092016-03-28 13:54:49 -07001071
1072 def testRunShellCommand_largeOutput_disabledNoTrigger(self):
1073 cmd = 'something'
1074 with self.assertCall(self.call.adb.Shell(cmd), self.ShellError('')):
1075 with self.assertRaises(device_errors.AdbCommandFailedError):
Chris Craika0e5c0d2017-03-29 15:00:32 -07001076 self.device.RunShellCommand([cmd], check_return=True)
Chris Craikbe1f9092016-03-28 13:54:49 -07001077
1078 def testRunShellCommand_largeOutput_disabledTrigger(self):
1079 cmd = 'echo $VALUE'
1080 temp_file = MockTempFile('/sdcard/temp-123')
1081 cmd_redirect = '( %s )>%s' % (cmd, temp_file.name)
1082 with self.assertCalls(
1083 (self.call.adb.Shell(cmd), self.ShellError('', None)),
1084 (mock.call.devil.android.device_temp_file.DeviceTempFile(self.adb),
1085 temp_file),
1086 (self.call.adb.Shell(cmd_redirect)),
1087 (self.call.device.ReadFile(mock.ANY, force_pull=True),
1088 'something')):
Chris Craika0e5c0d2017-03-29 15:00:32 -07001089 self.assertEquals(
1090 ['something'],
1091 self.device.RunShellCommand(cmd, shell=True, check_return=True))
Chris Craikbe1f9092016-03-28 13:54:49 -07001092
1093
1094class DeviceUtilsRunPipedShellCommandTest(DeviceUtilsTest):
1095
1096 def testRunPipedShellCommand_success(self):
1097 with self.assertCall(
1098 self.call.device.RunShellCommand(
1099 'ps | grep foo; echo "PIPESTATUS: ${PIPESTATUS[@]}"',
Chris Craika0e5c0d2017-03-29 15:00:32 -07001100 shell=True, check_return=True),
Chris Craikbe1f9092016-03-28 13:54:49 -07001101 ['This line contains foo', 'PIPESTATUS: 0 0']):
1102 self.assertEquals(['This line contains foo'],
1103 self.device._RunPipedShellCommand('ps | grep foo'))
1104
1105 def testRunPipedShellCommand_firstCommandFails(self):
1106 with self.assertCall(
1107 self.call.device.RunShellCommand(
1108 'ps | grep foo; echo "PIPESTATUS: ${PIPESTATUS[@]}"',
Chris Craika0e5c0d2017-03-29 15:00:32 -07001109 shell=True, check_return=True),
Chris Craikbe1f9092016-03-28 13:54:49 -07001110 ['PIPESTATUS: 1 0']):
1111 with self.assertRaises(device_errors.AdbShellCommandFailedError) as ec:
1112 self.device._RunPipedShellCommand('ps | grep foo')
1113 self.assertEquals([1, 0], ec.exception.status)
1114
1115 def testRunPipedShellCommand_secondCommandFails(self):
1116 with self.assertCall(
1117 self.call.device.RunShellCommand(
1118 'ps | grep foo; echo "PIPESTATUS: ${PIPESTATUS[@]}"',
Chris Craika0e5c0d2017-03-29 15:00:32 -07001119 shell=True, check_return=True),
Chris Craikbe1f9092016-03-28 13:54:49 -07001120 ['PIPESTATUS: 0 1']):
1121 with self.assertRaises(device_errors.AdbShellCommandFailedError) as ec:
1122 self.device._RunPipedShellCommand('ps | grep foo')
1123 self.assertEquals([0, 1], ec.exception.status)
1124
1125 def testRunPipedShellCommand_outputCutOff(self):
1126 with self.assertCall(
1127 self.call.device.RunShellCommand(
1128 'ps | grep foo; echo "PIPESTATUS: ${PIPESTATUS[@]}"',
Chris Craika0e5c0d2017-03-29 15:00:32 -07001129 shell=True, check_return=True),
Chris Craikbe1f9092016-03-28 13:54:49 -07001130 ['foo.bar'] * 256 + ['foo.ba']):
1131 with self.assertRaises(device_errors.AdbShellCommandFailedError) as ec:
1132 self.device._RunPipedShellCommand('ps | grep foo')
1133 self.assertIs(None, ec.exception.status)
1134
1135
1136@mock.patch('time.sleep', mock.Mock())
1137class DeviceUtilsKillAllTest(DeviceUtilsTest):
1138
1139 def testKillAll_noMatchingProcessesFailure(self):
1140 with self.assertCall(self.call.device.GetPids('test_process'), {}):
1141 with self.assertRaises(device_errors.CommandFailedError):
1142 self.device.KillAll('test_process')
1143
1144 def testKillAll_noMatchingProcessesQuiet(self):
1145 with self.assertCall(self.call.device.GetPids('test_process'), {}):
1146 self.assertEqual(0, self.device.KillAll('test_process', quiet=True))
1147
1148 def testKillAll_nonblocking(self):
1149 with self.assertCalls(
1150 (self.call.device.GetPids('some.process'),
1151 {'some.process': ['1234'], 'some.processing.thing': ['5678']}),
1152 (self.call.adb.Shell('kill -9 1234 5678'), '')):
1153 self.assertEquals(
1154 2, self.device.KillAll('some.process', blocking=False))
1155
1156 def testKillAll_blocking(self):
1157 with self.assertCalls(
1158 (self.call.device.GetPids('some.process'),
1159 {'some.process': ['1234'], 'some.processing.thing': ['5678']}),
1160 (self.call.adb.Shell('kill -9 1234 5678'), ''),
1161 (self.call.device.GetPids('some.process'),
1162 {'some.processing.thing': ['5678']}),
1163 (self.call.device.GetPids('some.process'),
1164 {'some.process': ['1111']})): # Other instance with different pid.
1165 self.assertEquals(
1166 2, self.device.KillAll('some.process', blocking=True))
1167
1168 def testKillAll_exactNonblocking(self):
1169 with self.assertCalls(
1170 (self.call.device.GetPids('some.process'),
1171 {'some.process': ['1234'], 'some.processing.thing': ['5678']}),
1172 (self.call.adb.Shell('kill -9 1234'), '')):
1173 self.assertEquals(
1174 1, self.device.KillAll('some.process', exact=True, blocking=False))
1175
1176 def testKillAll_exactBlocking(self):
1177 with self.assertCalls(
1178 (self.call.device.GetPids('some.process'),
1179 {'some.process': ['1234'], 'some.processing.thing': ['5678']}),
1180 (self.call.adb.Shell('kill -9 1234'), ''),
1181 (self.call.device.GetPids('some.process'),
1182 {'some.process': ['1234'], 'some.processing.thing': ['5678']}),
1183 (self.call.device.GetPids('some.process'),
1184 {'some.processing.thing': ['5678']})):
1185 self.assertEquals(
1186 1, self.device.KillAll('some.process', exact=True, blocking=True))
1187
1188 def testKillAll_root(self):
1189 with self.assertCalls(
1190 (self.call.device.GetPids('some.process'), {'some.process': ['1234']}),
1191 (self.call.device.NeedsSU(), True),
1192 (self.call.device._Su("sh -c 'kill -9 1234'"),
1193 "su -c sh -c 'kill -9 1234'"),
1194 (self.call.adb.Shell("su -c sh -c 'kill -9 1234'"), '')):
1195 self.assertEquals(
1196 1, self.device.KillAll('some.process', as_root=True))
1197
1198 def testKillAll_sigterm(self):
1199 with self.assertCalls(
1200 (self.call.device.GetPids('some.process'),
1201 {'some.process': ['1234']}),
1202 (self.call.adb.Shell('kill -15 1234'), '')):
1203 self.assertEquals(
1204 1, self.device.KillAll('some.process', signum=device_signal.SIGTERM))
1205
1206 def testKillAll_multipleInstances(self):
1207 with self.assertCalls(
1208 (self.call.device.GetPids('some.process'),
1209 {'some.process': ['1234', '4567']}),
1210 (self.call.adb.Shell('kill -15 1234 4567'), '')):
1211 self.assertEquals(
1212 2, self.device.KillAll('some.process', signum=device_signal.SIGTERM))
1213
1214
1215class DeviceUtilsStartActivityTest(DeviceUtilsTest):
1216
1217 def testStartActivity_actionOnly(self):
1218 test_intent = intent.Intent(action='android.intent.action.VIEW')
1219 with self.assertCall(
1220 self.call.adb.Shell('am start '
1221 '-a android.intent.action.VIEW'),
1222 'Starting: Intent { act=android.intent.action.VIEW }'):
1223 self.device.StartActivity(test_intent)
1224
1225 def testStartActivity_success(self):
1226 test_intent = intent.Intent(action='android.intent.action.VIEW',
1227 package='test.package',
1228 activity='.Main')
1229 with self.assertCall(
1230 self.call.adb.Shell('am start '
1231 '-a android.intent.action.VIEW '
1232 '-n test.package/.Main'),
1233 'Starting: Intent { act=android.intent.action.VIEW }'):
1234 self.device.StartActivity(test_intent)
1235
1236 def testStartActivity_failure(self):
1237 test_intent = intent.Intent(action='android.intent.action.VIEW',
1238 package='test.package',
1239 activity='.Main')
1240 with self.assertCall(
1241 self.call.adb.Shell('am start '
1242 '-a android.intent.action.VIEW '
1243 '-n test.package/.Main'),
1244 'Error: Failed to start test activity'):
1245 with self.assertRaises(device_errors.CommandFailedError):
1246 self.device.StartActivity(test_intent)
1247
1248 def testStartActivity_blocking(self):
1249 test_intent = intent.Intent(action='android.intent.action.VIEW',
1250 package='test.package',
1251 activity='.Main')
1252 with self.assertCall(
1253 self.call.adb.Shell('am start '
1254 '-W '
1255 '-a android.intent.action.VIEW '
1256 '-n test.package/.Main'),
1257 'Starting: Intent { act=android.intent.action.VIEW }'):
1258 self.device.StartActivity(test_intent, blocking=True)
1259
1260 def testStartActivity_withCategory(self):
1261 test_intent = intent.Intent(action='android.intent.action.VIEW',
1262 package='test.package',
1263 activity='.Main',
1264 category='android.intent.category.HOME')
1265 with self.assertCall(
1266 self.call.adb.Shell('am start '
1267 '-a android.intent.action.VIEW '
1268 '-c android.intent.category.HOME '
1269 '-n test.package/.Main'),
1270 'Starting: Intent { act=android.intent.action.VIEW }'):
1271 self.device.StartActivity(test_intent)
1272
1273 def testStartActivity_withMultipleCategories(self):
1274 test_intent = intent.Intent(action='android.intent.action.VIEW',
1275 package='test.package',
1276 activity='.Main',
1277 category=['android.intent.category.HOME',
1278 'android.intent.category.BROWSABLE'])
1279 with self.assertCall(
1280 self.call.adb.Shell('am start '
1281 '-a android.intent.action.VIEW '
1282 '-c android.intent.category.HOME '
1283 '-c android.intent.category.BROWSABLE '
1284 '-n test.package/.Main'),
1285 'Starting: Intent { act=android.intent.action.VIEW }'):
1286 self.device.StartActivity(test_intent)
1287
1288 def testStartActivity_withData(self):
1289 test_intent = intent.Intent(action='android.intent.action.VIEW',
1290 package='test.package',
1291 activity='.Main',
1292 data='http://www.google.com/')
1293 with self.assertCall(
1294 self.call.adb.Shell('am start '
1295 '-a android.intent.action.VIEW '
1296 '-d http://www.google.com/ '
1297 '-n test.package/.Main'),
1298 'Starting: Intent { act=android.intent.action.VIEW }'):
1299 self.device.StartActivity(test_intent)
1300
1301 def testStartActivity_withStringExtra(self):
1302 test_intent = intent.Intent(action='android.intent.action.VIEW',
1303 package='test.package',
1304 activity='.Main',
1305 extras={'foo': 'test'})
1306 with self.assertCall(
1307 self.call.adb.Shell('am start '
1308 '-a android.intent.action.VIEW '
1309 '-n test.package/.Main '
1310 '--es foo test'),
1311 'Starting: Intent { act=android.intent.action.VIEW }'):
1312 self.device.StartActivity(test_intent)
1313
1314 def testStartActivity_withBoolExtra(self):
1315 test_intent = intent.Intent(action='android.intent.action.VIEW',
1316 package='test.package',
1317 activity='.Main',
1318 extras={'foo': True})
1319 with self.assertCall(
1320 self.call.adb.Shell('am start '
1321 '-a android.intent.action.VIEW '
1322 '-n test.package/.Main '
1323 '--ez foo True'),
1324 'Starting: Intent { act=android.intent.action.VIEW }'):
1325 self.device.StartActivity(test_intent)
1326
1327 def testStartActivity_withIntExtra(self):
1328 test_intent = intent.Intent(action='android.intent.action.VIEW',
1329 package='test.package',
1330 activity='.Main',
1331 extras={'foo': 123})
1332 with self.assertCall(
1333 self.call.adb.Shell('am start '
1334 '-a android.intent.action.VIEW '
1335 '-n test.package/.Main '
1336 '--ei foo 123'),
1337 'Starting: Intent { act=android.intent.action.VIEW }'):
1338 self.device.StartActivity(test_intent)
1339
1340 def testStartActivity_withTraceFile(self):
1341 test_intent = intent.Intent(action='android.intent.action.VIEW',
1342 package='test.package',
1343 activity='.Main')
1344 with self.assertCall(
1345 self.call.adb.Shell('am start '
1346 '--start-profiler test_trace_file.out '
1347 '-a android.intent.action.VIEW '
1348 '-n test.package/.Main'),
1349 'Starting: Intent { act=android.intent.action.VIEW }'):
1350 self.device.StartActivity(test_intent,
1351 trace_file_name='test_trace_file.out')
1352
1353 def testStartActivity_withForceStop(self):
1354 test_intent = intent.Intent(action='android.intent.action.VIEW',
1355 package='test.package',
1356 activity='.Main')
1357 with self.assertCall(
1358 self.call.adb.Shell('am start '
1359 '-S '
1360 '-a android.intent.action.VIEW '
1361 '-n test.package/.Main'),
1362 'Starting: Intent { act=android.intent.action.VIEW }'):
1363 self.device.StartActivity(test_intent, force_stop=True)
1364
1365 def testStartActivity_withFlags(self):
1366 test_intent = intent.Intent(action='android.intent.action.VIEW',
1367 package='test.package',
1368 activity='.Main',
Chris Craika23c9e92016-08-19 14:42:29 -07001369 flags=[
1370 intent.FLAG_ACTIVITY_NEW_TASK,
1371 intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
1372 ])
Chris Craikbe1f9092016-03-28 13:54:49 -07001373 with self.assertCall(
1374 self.call.adb.Shell('am start '
1375 '-a android.intent.action.VIEW '
1376 '-n test.package/.Main '
Chris Craika23c9e92016-08-19 14:42:29 -07001377 '-f 0x10200000'),
Chris Craikbe1f9092016-03-28 13:54:49 -07001378 'Starting: Intent { act=android.intent.action.VIEW }'):
1379 self.device.StartActivity(test_intent)
1380
1381
1382class DeviceUtilsStartInstrumentationTest(DeviceUtilsTest):
1383
1384 def testStartInstrumentation_nothing(self):
1385 with self.assertCalls(
1386 self.call.device.RunShellCommand(
1387 'p=test.package;am instrument "$p"/.TestInstrumentation',
Chris Craika0e5c0d2017-03-29 15:00:32 -07001388 shell=True, check_return=True, large_output=True)):
Chris Craikbe1f9092016-03-28 13:54:49 -07001389 self.device.StartInstrumentation(
1390 'test.package/.TestInstrumentation',
1391 finish=False, raw=False, extras=None)
1392
1393 def testStartInstrumentation_finish(self):
1394 with self.assertCalls(
1395 (self.call.device.RunShellCommand(
1396 'p=test.package;am instrument -w "$p"/.TestInstrumentation',
Chris Craika0e5c0d2017-03-29 15:00:32 -07001397 shell=True, check_return=True, large_output=True),
Chris Craikbe1f9092016-03-28 13:54:49 -07001398 ['OK (1 test)'])):
1399 output = self.device.StartInstrumentation(
1400 'test.package/.TestInstrumentation',
1401 finish=True, raw=False, extras=None)
1402 self.assertEquals(['OK (1 test)'], output)
1403
1404 def testStartInstrumentation_raw(self):
1405 with self.assertCalls(
1406 self.call.device.RunShellCommand(
1407 'p=test.package;am instrument -r "$p"/.TestInstrumentation',
Chris Craika0e5c0d2017-03-29 15:00:32 -07001408 shell=True, check_return=True, large_output=True)):
Chris Craikbe1f9092016-03-28 13:54:49 -07001409 self.device.StartInstrumentation(
1410 'test.package/.TestInstrumentation',
1411 finish=False, raw=True, extras=None)
1412
1413 def testStartInstrumentation_extras(self):
1414 with self.assertCalls(
1415 self.call.device.RunShellCommand(
1416 'p=test.package;am instrument -e "$p".foo Foo -e bar \'Val \'"$p" '
1417 '"$p"/.TestInstrumentation',
Chris Craika0e5c0d2017-03-29 15:00:32 -07001418 shell=True, check_return=True, large_output=True)):
Chris Craikbe1f9092016-03-28 13:54:49 -07001419 self.device.StartInstrumentation(
1420 'test.package/.TestInstrumentation',
1421 finish=False, raw=False, extras={'test.package.foo': 'Foo',
1422 'bar': 'Val test.package'})
1423
1424
1425class DeviceUtilsBroadcastIntentTest(DeviceUtilsTest):
1426
1427 def testBroadcastIntent_noExtras(self):
1428 test_intent = intent.Intent(action='test.package.with.an.INTENT')
1429 with self.assertCall(
1430 self.call.adb.Shell('am broadcast -a test.package.with.an.INTENT'),
1431 'Broadcasting: Intent { act=test.package.with.an.INTENT } '):
1432 self.device.BroadcastIntent(test_intent)
1433
1434 def testBroadcastIntent_withExtra(self):
1435 test_intent = intent.Intent(action='test.package.with.an.INTENT',
1436 extras={'foo': 'bar value'})
1437 with self.assertCall(
1438 self.call.adb.Shell(
1439 "am broadcast -a test.package.with.an.INTENT --es foo 'bar value'"),
1440 'Broadcasting: Intent { act=test.package.with.an.INTENT } '):
1441 self.device.BroadcastIntent(test_intent)
1442
1443 def testBroadcastIntent_withExtra_noValue(self):
1444 test_intent = intent.Intent(action='test.package.with.an.INTENT',
1445 extras={'foo': None})
1446 with self.assertCall(
1447 self.call.adb.Shell(
1448 'am broadcast -a test.package.with.an.INTENT --esn foo'),
1449 'Broadcasting: Intent { act=test.package.with.an.INTENT } '):
1450 self.device.BroadcastIntent(test_intent)
1451
1452
1453class DeviceUtilsGoHomeTest(DeviceUtilsTest):
1454
1455 def testGoHome_popupsExist(self):
1456 with self.assertCalls(
1457 (self.call.device.RunShellCommand(
1458 ['dumpsys', 'window', 'windows'], check_return=True,
1459 large_output=True), []),
1460 (self.call.device.RunShellCommand(
1461 ['am', 'start', '-W', '-a', 'android.intent.action.MAIN',
1462 '-c', 'android.intent.category.HOME'], check_return=True),
1463 'Starting: Intent { act=android.intent.action.MAIN }\r\n'''),
1464 (self.call.device.RunShellCommand(
1465 ['dumpsys', 'window', 'windows'], check_return=True,
1466 large_output=True), []),
1467 (self.call.device.RunShellCommand(
1468 ['input', 'keyevent', '66'], check_return=True)),
1469 (self.call.device.RunShellCommand(
1470 ['input', 'keyevent', '4'], check_return=True)),
1471 (self.call.device.RunShellCommand(
1472 ['dumpsys', 'window', 'windows'], check_return=True,
1473 large_output=True),
1474 ['mCurrentFocus Launcher'])):
1475 self.device.GoHome()
1476
1477 def testGoHome_willRetry(self):
1478 with self.assertCalls(
1479 (self.call.device.RunShellCommand(
1480 ['dumpsys', 'window', 'windows'], check_return=True,
1481 large_output=True), []),
1482 (self.call.device.RunShellCommand(
1483 ['am', 'start', '-W', '-a', 'android.intent.action.MAIN',
1484 '-c', 'android.intent.category.HOME'], check_return=True),
1485 'Starting: Intent { act=android.intent.action.MAIN }\r\n'''),
1486 (self.call.device.RunShellCommand(
1487 ['dumpsys', 'window', 'windows'], check_return=True,
1488 large_output=True), []),
1489 (self.call.device.RunShellCommand(
1490 ['input', 'keyevent', '66'], check_return=True,)),
1491 (self.call.device.RunShellCommand(
1492 ['input', 'keyevent', '4'], check_return=True)),
1493 (self.call.device.RunShellCommand(
1494 ['dumpsys', 'window', 'windows'], check_return=True,
1495 large_output=True), []),
1496 (self.call.device.RunShellCommand(
1497 ['input', 'keyevent', '66'], check_return=True)),
1498 (self.call.device.RunShellCommand(
1499 ['input', 'keyevent', '4'], check_return=True)),
1500 (self.call.device.RunShellCommand(
1501 ['dumpsys', 'window', 'windows'], check_return=True,
1502 large_output=True),
1503 self.TimeoutError())):
1504 with self.assertRaises(device_errors.CommandTimeoutError):
1505 self.device.GoHome()
1506
1507 def testGoHome_alreadyFocused(self):
1508 with self.assertCall(
1509 self.call.device.RunShellCommand(
1510 ['dumpsys', 'window', 'windows'], check_return=True,
1511 large_output=True),
1512 ['mCurrentFocus Launcher']):
1513 self.device.GoHome()
1514
1515 def testGoHome_alreadyFocusedAlternateCase(self):
1516 with self.assertCall(
1517 self.call.device.RunShellCommand(
1518 ['dumpsys', 'window', 'windows'], check_return=True,
1519 large_output=True),
1520 [' mCurrentFocus .launcher/.']):
1521 self.device.GoHome()
1522
1523 def testGoHome_obtainsFocusAfterGoingHome(self):
1524 with self.assertCalls(
1525 (self.call.device.RunShellCommand(
1526 ['dumpsys', 'window', 'windows'], check_return=True,
1527 large_output=True), []),
1528 (self.call.device.RunShellCommand(
1529 ['am', 'start', '-W', '-a', 'android.intent.action.MAIN',
1530 '-c', 'android.intent.category.HOME'], check_return=True),
1531 'Starting: Intent { act=android.intent.action.MAIN }\r\n'''),
1532 (self.call.device.RunShellCommand(
1533 ['dumpsys', 'window', 'windows'], check_return=True,
1534 large_output=True),
1535 ['mCurrentFocus Launcher'])):
1536 self.device.GoHome()
1537
1538
1539class DeviceUtilsForceStopTest(DeviceUtilsTest):
1540
1541 def testForceStop(self):
1542 with self.assertCall(
1543 self.call.adb.Shell('p=test.package;if [[ "$(ps)" = *$p* ]]; then '
1544 'am force-stop $p; fi'),
1545 ''):
1546 self.device.ForceStop('test.package')
1547
1548
1549class DeviceUtilsClearApplicationStateTest(DeviceUtilsTest):
1550
1551 def testClearApplicationState_setPermissions(self):
1552 with self.assertCalls(
1553 (self.call.device.GetProp('ro.build.version.sdk', cache=True), '17'),
1554 (self.call.device._GetApplicationPathsInternal('this.package.exists'),
1555 ['/data/app/this.package.exists.apk']),
1556 (self.call.device.RunShellCommand(
1557 ['pm', 'clear', 'this.package.exists'],
1558 check_return=True),
1559 ['Success']),
1560 (self.call.device.GrantPermissions(
1561 'this.package.exists', ['p1']), [])):
1562 self.device.ClearApplicationState(
1563 'this.package.exists', permissions=['p1'])
1564
1565 def testClearApplicationState_packageDoesntExist(self):
1566 with self.assertCalls(
1567 (self.call.device.GetProp('ro.build.version.sdk', cache=True), '11'),
1568 (self.call.device._GetApplicationPathsInternal('does.not.exist'),
1569 [])):
1570 self.device.ClearApplicationState('does.not.exist')
1571
1572 def testClearApplicationState_packageDoesntExistOnAndroidJBMR2OrAbove(self):
1573 with self.assertCalls(
1574 (self.call.device.GetProp('ro.build.version.sdk', cache=True), '18'),
1575 (self.call.device.RunShellCommand(
1576 ['pm', 'clear', 'this.package.does.not.exist'],
1577 check_return=True),
1578 ['Failed'])):
1579 self.device.ClearApplicationState('this.package.does.not.exist')
1580
1581 def testClearApplicationState_packageExists(self):
1582 with self.assertCalls(
1583 (self.call.device.GetProp('ro.build.version.sdk', cache=True), '17'),
1584 (self.call.device._GetApplicationPathsInternal('this.package.exists'),
1585 ['/data/app/this.package.exists.apk']),
1586 (self.call.device.RunShellCommand(
1587 ['pm', 'clear', 'this.package.exists'],
1588 check_return=True),
1589 ['Success'])):
1590 self.device.ClearApplicationState('this.package.exists')
1591
1592 def testClearApplicationState_packageExistsOnAndroidJBMR2OrAbove(self):
1593 with self.assertCalls(
1594 (self.call.device.GetProp('ro.build.version.sdk', cache=True), '18'),
1595 (self.call.device.RunShellCommand(
1596 ['pm', 'clear', 'this.package.exists'],
1597 check_return=True),
1598 ['Success'])):
1599 self.device.ClearApplicationState('this.package.exists')
1600
1601
1602class DeviceUtilsSendKeyEventTest(DeviceUtilsTest):
1603
1604 def testSendKeyEvent(self):
1605 with self.assertCall(self.call.adb.Shell('input keyevent 66'), ''):
1606 self.device.SendKeyEvent(66)
1607
1608
1609class DeviceUtilsPushChangedFilesIndividuallyTest(DeviceUtilsTest):
1610
1611 def testPushChangedFilesIndividually_empty(self):
1612 test_files = []
1613 with self.assertCalls():
1614 self.device._PushChangedFilesIndividually(test_files)
1615
1616 def testPushChangedFilesIndividually_single(self):
1617 test_files = [('/test/host/path', '/test/device/path')]
1618 with self.assertCalls(self.call.adb.Push(*test_files[0])):
1619 self.device._PushChangedFilesIndividually(test_files)
1620
1621 def testPushChangedFilesIndividually_multiple(self):
1622 test_files = [
1623 ('/test/host/path/file1', '/test/device/path/file1'),
1624 ('/test/host/path/file2', '/test/device/path/file2')]
1625 with self.assertCalls(
1626 self.call.adb.Push(*test_files[0]),
1627 self.call.adb.Push(*test_files[1])):
1628 self.device._PushChangedFilesIndividually(test_files)
1629
1630
1631class DeviceUtilsPushChangedFilesZippedTest(DeviceUtilsTest):
1632
1633 def testPushChangedFilesZipped_noUnzipCommand(self):
1634 test_files = [('/test/host/path/file1', '/test/device/path/file1')]
1635 mock_zip_temp = mock.mock_open()
1636 mock_zip_temp.return_value.name = '/test/temp/file/tmp.zip'
1637 with self.assertCalls(
1638 (mock.call.tempfile.NamedTemporaryFile(suffix='.zip'), mock_zip_temp),
1639 (mock.call.multiprocessing.Process(
1640 target=device_utils.DeviceUtils._CreateDeviceZip,
1641 args=('/test/temp/file/tmp.zip', test_files)), mock.Mock()),
1642 (self.call.device._MaybeInstallCommands(), False)):
1643 self.assertFalse(self.device._PushChangedFilesZipped(test_files,
1644 ['/test/dir']))
1645
1646 def _testPushChangedFilesZipped_spec(self, test_files):
1647 mock_zip_temp = mock.mock_open()
1648 mock_zip_temp.return_value.name = '/test/temp/file/tmp.zip'
1649 with self.assertCalls(
1650 (mock.call.tempfile.NamedTemporaryFile(suffix='.zip'), mock_zip_temp),
1651 (mock.call.multiprocessing.Process(
1652 target=device_utils.DeviceUtils._CreateDeviceZip,
1653 args=('/test/temp/file/tmp.zip', test_files)), mock.Mock()),
1654 (self.call.device._MaybeInstallCommands(), True),
1655 (self.call.device.NeedsSU(), True),
1656 (mock.call.devil.android.device_temp_file.DeviceTempFile(self.adb,
1657 suffix='.zip'),
1658 MockTempFile('/test/sdcard/foo123.zip')),
1659 self.call.adb.Push(
1660 '/test/temp/file/tmp.zip', '/test/sdcard/foo123.zip'),
1661 self.call.device.RunShellCommand(
1662 'unzip /test/sdcard/foo123.zip&&chmod -R 777 /test/dir',
Chris Craika0e5c0d2017-03-29 15:00:32 -07001663 shell=True, as_root=True,
Chris Craikbe1f9092016-03-28 13:54:49 -07001664 env={'PATH': '/data/local/tmp/bin:$PATH'},
1665 check_return=True)):
1666 self.assertTrue(self.device._PushChangedFilesZipped(test_files,
1667 ['/test/dir']))
1668
1669 def testPushChangedFilesZipped_single(self):
1670 self._testPushChangedFilesZipped_spec(
1671 [('/test/host/path/file1', '/test/device/path/file1')])
1672
1673 def testPushChangedFilesZipped_multiple(self):
1674 self._testPushChangedFilesZipped_spec(
1675 [('/test/host/path/file1', '/test/device/path/file1'),
1676 ('/test/host/path/file2', '/test/device/path/file2')])
1677
1678
1679class DeviceUtilsPathExistsTest(DeviceUtilsTest):
1680
1681 def testPathExists_pathExists(self):
1682 with self.assertCall(
1683 self.call.device.RunShellCommand(
Chris Craika0e5c0d2017-03-29 15:00:32 -07001684 ['test', '-e', '/path/file exists'],
Chris Craikbe1f9092016-03-28 13:54:49 -07001685 as_root=False, check_return=True, timeout=10, retries=0),
1686 []):
1687 self.assertTrue(self.device.PathExists('/path/file exists'))
1688
1689 def testPathExists_multiplePathExists(self):
1690 with self.assertCall(
1691 self.call.device.RunShellCommand(
Chris Craika0e5c0d2017-03-29 15:00:32 -07001692 ['test', '-e', '/path 1', '-a', '-e', '/path2'],
Chris Craikbe1f9092016-03-28 13:54:49 -07001693 as_root=False, check_return=True, timeout=10, retries=0),
1694 []):
1695 self.assertTrue(self.device.PathExists(('/path 1', '/path2')))
1696
1697 def testPathExists_pathDoesntExist(self):
1698 with self.assertCall(
1699 self.call.device.RunShellCommand(
Chris Craika0e5c0d2017-03-29 15:00:32 -07001700 ['test', '-e', '/path/file.not.exists'],
Chris Craikbe1f9092016-03-28 13:54:49 -07001701 as_root=False, check_return=True, timeout=10, retries=0),
1702 self.ShellError()):
1703 self.assertFalse(self.device.PathExists('/path/file.not.exists'))
1704
1705 def testPathExists_asRoot(self):
1706 with self.assertCall(
1707 self.call.device.RunShellCommand(
Chris Craika0e5c0d2017-03-29 15:00:32 -07001708 ['test', '-e', '/root/path/exists'],
Chris Craikbe1f9092016-03-28 13:54:49 -07001709 as_root=True, check_return=True, timeout=10, retries=0),
1710 self.ShellError()):
1711 self.assertFalse(
1712 self.device.PathExists('/root/path/exists', as_root=True))
1713
1714 def testFileExists_pathDoesntExist(self):
1715 with self.assertCall(
1716 self.call.device.RunShellCommand(
Chris Craika0e5c0d2017-03-29 15:00:32 -07001717 ['test', '-e', '/path/file.not.exists'],
Chris Craikbe1f9092016-03-28 13:54:49 -07001718 as_root=False, check_return=True, timeout=10, retries=0),
1719 self.ShellError()):
1720 self.assertFalse(self.device.FileExists('/path/file.not.exists'))
1721
1722
John Reck33259e42017-01-18 13:57:49 -08001723class DeviceUtilsRemovePathTest(DeviceUtilsTest):
1724
1725 def testRemovePath_regular(self):
1726 with self.assertCall(
1727 self.call.device.RunShellCommand(
1728 ['rm', 'some file'], as_root=False, check_return=True),
1729 []):
1730 self.device.RemovePath('some file')
1731
1732 def testRemovePath_withForce(self):
1733 with self.assertCall(
1734 self.call.device.RunShellCommand(
1735 ['rm', '-f', 'some file'], as_root=False, check_return=True),
1736 []):
1737 self.device.RemovePath('some file', force=True)
1738
1739 def testRemovePath_recursively(self):
1740 with self.assertCall(
1741 self.call.device.RunShellCommand(
1742 ['rm', '-r', '/remove/this/dir'], as_root=False, check_return=True),
1743 []):
1744 self.device.RemovePath('/remove/this/dir', recursive=True)
1745
1746 def testRemovePath_withRoot(self):
1747 with self.assertCall(
1748 self.call.device.RunShellCommand(
1749 ['rm', 'some file'], as_root=True, check_return=True),
1750 []):
1751 self.device.RemovePath('some file', as_root=True)
1752
1753 def testRemovePath_manyPaths(self):
1754 with self.assertCall(
1755 self.call.device.RunShellCommand(
1756 ['rm', 'eeny', 'meeny', 'miny', 'moe'],
1757 as_root=False, check_return=True),
1758 []):
1759 self.device.RemovePath(['eeny', 'meeny', 'miny', 'moe'])
1760
1761
Chris Craikbe1f9092016-03-28 13:54:49 -07001762class DeviceUtilsPullFileTest(DeviceUtilsTest):
1763
1764 def testPullFile_existsOnDevice(self):
1765 with mock.patch('os.path.exists', return_value=True):
1766 with self.assertCall(
1767 self.call.adb.Pull('/data/app/test.file.exists',
1768 '/test/file/host/path')):
1769 self.device.PullFile('/data/app/test.file.exists',
1770 '/test/file/host/path')
1771
1772 def testPullFile_doesntExistOnDevice(self):
1773 with mock.patch('os.path.exists', return_value=True):
1774 with self.assertCall(
1775 self.call.adb.Pull('/data/app/test.file.does.not.exist',
1776 '/test/file/host/path'),
1777 self.CommandError('remote object does not exist')):
1778 with self.assertRaises(device_errors.CommandFailedError):
1779 self.device.PullFile('/data/app/test.file.does.not.exist',
1780 '/test/file/host/path')
1781
1782
1783class DeviceUtilsReadFileTest(DeviceUtilsTest):
1784
1785 def testReadFileWithPull_success(self):
1786 tmp_host_dir = '/tmp/dir/on.host/'
1787 tmp_host = MockTempFile('/tmp/dir/on.host/tmp_ReadFileWithPull')
1788 tmp_host.file.read.return_value = 'some interesting contents'
1789 with self.assertCalls(
1790 (mock.call.tempfile.mkdtemp(), tmp_host_dir),
1791 (self.call.adb.Pull('/path/to/device/file', mock.ANY)),
1792 (mock.call.__builtin__.open(mock.ANY, 'r'), tmp_host),
1793 (mock.call.os.path.exists(tmp_host_dir), True),
1794 (mock.call.shutil.rmtree(tmp_host_dir), None)):
1795 self.assertEquals('some interesting contents',
1796 self.device._ReadFileWithPull('/path/to/device/file'))
1797 tmp_host.file.read.assert_called_once_with()
1798
1799 def testReadFileWithPull_rejected(self):
1800 tmp_host_dir = '/tmp/dir/on.host/'
1801 with self.assertCalls(
1802 (mock.call.tempfile.mkdtemp(), tmp_host_dir),
1803 (self.call.adb.Pull('/path/to/device/file', mock.ANY),
1804 self.CommandError()),
1805 (mock.call.os.path.exists(tmp_host_dir), True),
1806 (mock.call.shutil.rmtree(tmp_host_dir), None)):
1807 with self.assertRaises(device_errors.CommandFailedError):
1808 self.device._ReadFileWithPull('/path/to/device/file')
1809
1810 def testReadFile_exists(self):
1811 with self.assertCalls(
Chris Craika23c9e92016-08-19 14:42:29 -07001812 (self.call.device.FileSize('/read/this/test/file', as_root=False), 256),
Chris Craikbe1f9092016-03-28 13:54:49 -07001813 (self.call.device.RunShellCommand(
1814 ['cat', '/read/this/test/file'],
1815 as_root=False, check_return=True),
1816 ['this is a test file'])):
1817 self.assertEqual('this is a test file\n',
1818 self.device.ReadFile('/read/this/test/file'))
1819
1820 def testReadFile_exists2(self):
1821 # Same as testReadFile_exists, but uses Android N ls output.
1822 with self.assertCalls(
Chris Craika23c9e92016-08-19 14:42:29 -07001823 (self.call.device.FileSize('/read/this/test/file', as_root=False), 256),
Chris Craikbe1f9092016-03-28 13:54:49 -07001824 (self.call.device.RunShellCommand(
1825 ['cat', '/read/this/test/file'],
1826 as_root=False, check_return=True),
1827 ['this is a test file'])):
1828 self.assertEqual('this is a test file\n',
1829 self.device.ReadFile('/read/this/test/file'))
1830
1831 def testReadFile_doesNotExist(self):
1832 with self.assertCall(
Chris Craika23c9e92016-08-19 14:42:29 -07001833 self.call.device.FileSize('/this/file/does.not.exist', as_root=False),
Chris Craikbe1f9092016-03-28 13:54:49 -07001834 self.CommandError('File does not exist')):
1835 with self.assertRaises(device_errors.CommandFailedError):
1836 self.device.ReadFile('/this/file/does.not.exist')
1837
1838 def testReadFile_zeroSize(self):
1839 with self.assertCalls(
Chris Craika23c9e92016-08-19 14:42:29 -07001840 (self.call.device.FileSize('/this/file/has/zero/size', as_root=False),
1841 0),
Chris Craikbe1f9092016-03-28 13:54:49 -07001842 (self.call.device._ReadFileWithPull('/this/file/has/zero/size'),
1843 'but it has contents\n')):
1844 self.assertEqual('but it has contents\n',
1845 self.device.ReadFile('/this/file/has/zero/size'))
1846
1847 def testReadFile_withSU(self):
1848 with self.assertCalls(
Chris Craika23c9e92016-08-19 14:42:29 -07001849 (self.call.device.FileSize(
1850 '/this/file/can.be.read.with.su', as_root=True), 256),
Chris Craikbe1f9092016-03-28 13:54:49 -07001851 (self.call.device.RunShellCommand(
1852 ['cat', '/this/file/can.be.read.with.su'],
1853 as_root=True, check_return=True),
1854 ['this is a test file', 'read with su'])):
1855 self.assertEqual(
1856 'this is a test file\nread with su\n',
1857 self.device.ReadFile('/this/file/can.be.read.with.su',
1858 as_root=True))
1859
1860 def testReadFile_withPull(self):
1861 contents = 'a' * 123456
1862 with self.assertCalls(
Chris Craika23c9e92016-08-19 14:42:29 -07001863 (self.call.device.FileSize('/read/this/big/test/file', as_root=False),
1864 123456),
Chris Craikbe1f9092016-03-28 13:54:49 -07001865 (self.call.device._ReadFileWithPull('/read/this/big/test/file'),
1866 contents)):
1867 self.assertEqual(
1868 contents, self.device.ReadFile('/read/this/big/test/file'))
1869
1870 def testReadFile_withPullAndSU(self):
1871 contents = 'b' * 123456
1872 with self.assertCalls(
Chris Craika23c9e92016-08-19 14:42:29 -07001873 (self.call.device.FileSize(
1874 '/this/big/file/can.be.read.with.su', as_root=True), 123456),
Chris Craikbe1f9092016-03-28 13:54:49 -07001875 (self.call.device.NeedsSU(), True),
1876 (mock.call.devil.android.device_temp_file.DeviceTempFile(self.adb),
1877 MockTempFile('/sdcard/tmp/on.device')),
1878 self.call.device.RunShellCommand(
1879 'SRC=/this/big/file/can.be.read.with.su DEST=/sdcard/tmp/on.device;'
1880 'cp "$SRC" "$DEST" && chmod 666 "$DEST"',
Chris Craika0e5c0d2017-03-29 15:00:32 -07001881 shell=True, as_root=True, check_return=True),
Chris Craikbe1f9092016-03-28 13:54:49 -07001882 (self.call.device._ReadFileWithPull('/sdcard/tmp/on.device'),
1883 contents)):
1884 self.assertEqual(
1885 contents,
1886 self.device.ReadFile('/this/big/file/can.be.read.with.su',
1887 as_root=True))
1888
1889 def testReadFile_forcePull(self):
1890 contents = 'a' * 123456
1891 with self.assertCall(
1892 self.call.device._ReadFileWithPull('/read/this/big/test/file'),
1893 contents):
1894 self.assertEqual(
1895 contents,
1896 self.device.ReadFile('/read/this/big/test/file', force_pull=True))
1897
1898
1899class DeviceUtilsWriteFileTest(DeviceUtilsTest):
1900
1901 def testWriteFileWithPush_success(self):
1902 tmp_host = MockTempFile('/tmp/file/on.host')
1903 contents = 'some interesting contents'
1904 with self.assertCalls(
1905 (mock.call.tempfile.NamedTemporaryFile(), tmp_host),
1906 self.call.adb.Push('/tmp/file/on.host', '/path/to/device/file')):
1907 self.device._WriteFileWithPush('/path/to/device/file', contents)
1908 tmp_host.file.write.assert_called_once_with(contents)
1909
1910 def testWriteFileWithPush_rejected(self):
1911 tmp_host = MockTempFile('/tmp/file/on.host')
1912 contents = 'some interesting contents'
1913 with self.assertCalls(
1914 (mock.call.tempfile.NamedTemporaryFile(), tmp_host),
1915 (self.call.adb.Push('/tmp/file/on.host', '/path/to/device/file'),
1916 self.CommandError())):
1917 with self.assertRaises(device_errors.CommandFailedError):
1918 self.device._WriteFileWithPush('/path/to/device/file', contents)
1919
1920 def testWriteFile_withPush(self):
1921 contents = 'some large contents ' * 26 # 20 * 26 = 520 chars
1922 with self.assertCalls(
1923 self.call.device._WriteFileWithPush('/path/to/device/file', contents)):
1924 self.device.WriteFile('/path/to/device/file', contents)
1925
1926 def testWriteFile_withPushForced(self):
1927 contents = 'tiny contents'
1928 with self.assertCalls(
1929 self.call.device._WriteFileWithPush('/path/to/device/file', contents)):
1930 self.device.WriteFile('/path/to/device/file', contents, force_push=True)
1931
1932 def testWriteFile_withPushAndSU(self):
1933 contents = 'some large contents ' * 26 # 20 * 26 = 520 chars
1934 with self.assertCalls(
1935 (self.call.device.NeedsSU(), True),
1936 (mock.call.devil.android.device_temp_file.DeviceTempFile(self.adb),
1937 MockTempFile('/sdcard/tmp/on.device')),
1938 self.call.device._WriteFileWithPush('/sdcard/tmp/on.device', contents),
1939 self.call.device.RunShellCommand(
1940 ['cp', '/sdcard/tmp/on.device', '/path/to/device/file'],
1941 as_root=True, check_return=True)):
1942 self.device.WriteFile('/path/to/device/file', contents, as_root=True)
1943
1944 def testWriteFile_withEcho(self):
1945 with self.assertCall(self.call.adb.Shell(
1946 "echo -n the.contents > /test/file/to.write"), ''):
1947 self.device.WriteFile('/test/file/to.write', 'the.contents')
1948
1949 def testWriteFile_withEchoAndQuotes(self):
1950 with self.assertCall(self.call.adb.Shell(
1951 "echo -n 'the contents' > '/test/file/to write'"), ''):
1952 self.device.WriteFile('/test/file/to write', 'the contents')
1953
1954 def testWriteFile_withEchoAndSU(self):
1955 expected_cmd_without_su = "sh -c 'echo -n contents > /test/file'"
1956 expected_cmd = 'su -c %s' % expected_cmd_without_su
1957 with self.assertCalls(
1958 (self.call.device.NeedsSU(), True),
1959 (self.call.device._Su(expected_cmd_without_su), expected_cmd),
1960 (self.call.adb.Shell(expected_cmd),
1961 '')):
1962 self.device.WriteFile('/test/file', 'contents', as_root=True)
1963
1964
Chris Craika23c9e92016-08-19 14:42:29 -07001965class DeviceUtilsStatDirectoryTest(DeviceUtilsTest):
1966 # Note: Also tests ListDirectory in testStatDirectory_fileList.
Chris Craikbe1f9092016-03-28 13:54:49 -07001967
Chris Craika23c9e92016-08-19 14:42:29 -07001968 EXAMPLE_LS_OUTPUT = [
1969 'total 12345',
1970 'drwxr-xr-x 19 root root 0 1970-04-06 18:03 .',
1971 'drwxr-xr-x 19 root root 0 1970-04-06 18:03 ..',
1972 'drwxr-xr-x 6 root root 1970-01-01 00:00 some_dir',
1973 '-rw-r--r-- 1 root root 723 1971-01-01 07:04 some_file',
1974 '-rw-r----- 1 root root 327 2009-02-13 23:30 My Music File',
1975 # Older Android versions do not print st_nlink
1976 'lrwxrwxrwx root root 1970-01-01 00:00 lnk -> /some/path',
1977 'srwxrwx--- system system 2016-05-31 17:25 a_socket1',
1978 'drwxrwxrwt system misc 1970-11-23 02:25 tmp',
1979 'drwxr-s--- system shell 1970-11-23 02:24 my_cmd',
1980 'cr--r----- root system 10, 183 1971-01-01 07:04 random',
1981 'brw------- root root 7, 0 1971-01-01 07:04 block_dev',
1982 '-rwS------ root shell 157404 2015-04-13 15:44 silly',
1983 ]
Chris Craikbe1f9092016-03-28 13:54:49 -07001984
Chris Craika23c9e92016-08-19 14:42:29 -07001985 FILENAMES = [
1986 'some_dir', 'some_file', 'My Music File', 'lnk', 'a_socket1',
1987 'tmp', 'my_cmd', 'random', 'block_dev', 'silly']
1988
1989 def getStatEntries(self, path_given='/', path_listed='/'):
1990 with self.assertCall(
1991 self.call.device.RunShellCommand(
1992 ['ls', '-a', '-l', path_listed],
1993 check_return=True, as_root=False, env={'TZ': 'utc'}),
1994 self.EXAMPLE_LS_OUTPUT):
1995 entries = self.device.StatDirectory(path_given)
1996 return {f['filename']: f for f in entries}
1997
1998 def getListEntries(self):
1999 with self.assertCall(
2000 self.call.device.RunShellCommand(
2001 ['ls', '-a', '-l', '/'],
2002 check_return=True, as_root=False, env={'TZ': 'utc'}),
2003 self.EXAMPLE_LS_OUTPUT):
2004 return self.device.ListDirectory('/')
2005
2006 def testStatDirectory_forceTrailingSlash(self):
2007 self.getStatEntries(path_given='/foo/bar/', path_listed='/foo/bar/')
2008 self.getStatEntries(path_given='/foo/bar', path_listed='/foo/bar/')
2009
2010 def testStatDirectory_fileList(self):
2011 self.assertItemsEqual(self.getStatEntries().keys(), self.FILENAMES)
2012 self.assertItemsEqual(self.getListEntries(), self.FILENAMES)
2013
2014 def testStatDirectory_fileModes(self):
2015 expected_modes = (
2016 ('some_dir', stat.S_ISDIR),
2017 ('some_file', stat.S_ISREG),
2018 ('lnk', stat.S_ISLNK),
2019 ('a_socket1', stat.S_ISSOCK),
2020 ('block_dev', stat.S_ISBLK),
2021 ('random', stat.S_ISCHR),
2022 )
2023 entries = self.getStatEntries()
2024 for filename, check in expected_modes:
2025 self.assertTrue(check(entries[filename]['st_mode']))
2026
2027 def testStatDirectory_filePermissions(self):
2028 should_have = (
2029 ('some_file', stat.S_IWUSR), # Owner can write.
2030 ('tmp', stat.S_IXOTH), # Others can execute.
2031 ('tmp', stat.S_ISVTX), # Has sticky bit.
2032 ('my_cmd', stat.S_ISGID), # Has set-group-ID bit.
2033 ('silly', stat.S_ISUID), # Has set UID bit.
2034 )
2035 should_not_have = (
2036 ('some_file', stat.S_IWOTH), # Others can't write.
2037 ('block_dev', stat.S_IRGRP), # Group can't read.
2038 ('silly', stat.S_IXUSR), # Owner can't execute.
2039 )
2040 entries = self.getStatEntries()
2041 for filename, bit in should_have:
2042 self.assertTrue(entries[filename]['st_mode'] & bit)
2043 for filename, bit in should_not_have:
2044 self.assertFalse(entries[filename]['st_mode'] & bit)
2045
2046 def testStatDirectory_numHardLinks(self):
2047 entries = self.getStatEntries()
2048 self.assertEqual(entries['some_dir']['st_nlink'], 6)
2049 self.assertEqual(entries['some_file']['st_nlink'], 1)
2050 self.assertFalse('st_nlink' in entries['tmp'])
2051
2052 def testStatDirectory_fileOwners(self):
2053 entries = self.getStatEntries()
2054 self.assertEqual(entries['some_dir']['st_owner'], 'root')
2055 self.assertEqual(entries['my_cmd']['st_owner'], 'system')
2056 self.assertEqual(entries['my_cmd']['st_group'], 'shell')
2057 self.assertEqual(entries['tmp']['st_group'], 'misc')
2058
2059 def testStatDirectory_fileSize(self):
2060 entries = self.getStatEntries()
2061 self.assertEqual(entries['some_file']['st_size'], 723)
2062 self.assertEqual(entries['My Music File']['st_size'], 327)
2063 # Sizes are sometimes not reported for non-regular files, don't try to
2064 # guess the size in those cases.
2065 self.assertFalse('st_size' in entries['some_dir'])
2066
2067 def testStatDirectory_fileDateTime(self):
2068 entries = self.getStatEntries()
2069 self.assertEqual(entries['some_dir']['st_mtime'], 0) # Epoch!
2070 self.assertEqual(entries['My Music File']['st_mtime'], 1234567800)
2071
2072 def testStatDirectory_deviceType(self):
2073 entries = self.getStatEntries()
2074 self.assertEqual(entries['random']['st_rdev_pair'], (10, 183))
2075 self.assertEqual(entries['block_dev']['st_rdev_pair'], (7, 0))
2076
2077 def testStatDirectory_symbolicLinks(self):
2078 entries = self.getStatEntries()
2079 self.assertEqual(entries['lnk']['symbolic_link_to'], '/some/path')
2080 for d in entries.itervalues():
2081 self.assertEqual('symbolic_link_to' in d, stat.S_ISLNK(d['st_mode']))
Chris Craikbe1f9092016-03-28 13:54:49 -07002082
2083
Chris Craika23c9e92016-08-19 14:42:29 -07002084class DeviceUtilsStatPathTest(DeviceUtilsTest):
Chris Craikbe1f9092016-03-28 13:54:49 -07002085
Chris Craika23c9e92016-08-19 14:42:29 -07002086 EXAMPLE_DIRECTORY = [
2087 {'filename': 'foo.txt', 'st_size': 123, 'st_time': 456},
2088 {'filename': 'some_dir', 'st_time': 0}
2089 ]
2090 INDEX = {e['filename']: e for e in EXAMPLE_DIRECTORY}
Chris Craikbe1f9092016-03-28 13:54:49 -07002091
Chris Craika23c9e92016-08-19 14:42:29 -07002092 def testStatPath_file(self):
2093 with self.assertCall(
2094 self.call.device.StatDirectory('/data/local/tmp', as_root=False),
2095 self.EXAMPLE_DIRECTORY):
2096 self.assertEquals(self.INDEX['foo.txt'],
2097 self.device.StatPath('/data/local/tmp/foo.txt'))
Chris Craikbe1f9092016-03-28 13:54:49 -07002098
Chris Craika23c9e92016-08-19 14:42:29 -07002099 def testStatPath_directory(self):
2100 with self.assertCall(
2101 self.call.device.StatDirectory('/data/local/tmp', as_root=False),
2102 self.EXAMPLE_DIRECTORY):
2103 self.assertEquals(self.INDEX['some_dir'],
2104 self.device.StatPath('/data/local/tmp/some_dir'))
2105
2106 def testStatPath_directoryWithTrailingSlash(self):
2107 with self.assertCall(
2108 self.call.device.StatDirectory('/data/local/tmp', as_root=False),
2109 self.EXAMPLE_DIRECTORY):
2110 self.assertEquals(self.INDEX['some_dir'],
2111 self.device.StatPath('/data/local/tmp/some_dir/'))
2112
2113 def testStatPath_doesNotExist(self):
2114 with self.assertCall(
2115 self.call.device.StatDirectory('/data/local/tmp', as_root=False),
2116 self.EXAMPLE_DIRECTORY):
Chris Craikbe1f9092016-03-28 13:54:49 -07002117 with self.assertRaises(device_errors.CommandFailedError):
Chris Craika23c9e92016-08-19 14:42:29 -07002118 self.device.StatPath('/data/local/tmp/does.not.exist.txt')
2119
2120
2121class DeviceUtilsFileSizeTest(DeviceUtilsTest):
2122
2123 EXAMPLE_DIRECTORY = [
2124 {'filename': 'foo.txt', 'st_size': 123, 'st_mtime': 456},
2125 {'filename': 'some_dir', 'st_mtime': 0}
2126 ]
2127
2128 def testFileSize_file(self):
2129 with self.assertCall(
2130 self.call.device.StatDirectory('/data/local/tmp', as_root=False),
2131 self.EXAMPLE_DIRECTORY):
2132 self.assertEquals(123,
2133 self.device.FileSize('/data/local/tmp/foo.txt'))
2134
2135 def testFileSize_doesNotExist(self):
2136 with self.assertCall(
2137 self.call.device.StatDirectory('/data/local/tmp', as_root=False),
2138 self.EXAMPLE_DIRECTORY):
2139 with self.assertRaises(device_errors.CommandFailedError):
2140 self.device.FileSize('/data/local/tmp/does.not.exist.txt')
2141
2142 def testFileSize_directoryWithNoSize(self):
2143 with self.assertCall(
2144 self.call.device.StatDirectory('/data/local/tmp', as_root=False),
2145 self.EXAMPLE_DIRECTORY):
2146 with self.assertRaises(device_errors.CommandFailedError):
2147 self.device.FileSize('/data/local/tmp/some_dir')
Chris Craikbe1f9092016-03-28 13:54:49 -07002148
2149
2150class DeviceUtilsSetJavaAssertsTest(DeviceUtilsTest):
2151
2152 def testSetJavaAsserts_enable(self):
2153 with self.assertCalls(
2154 (self.call.device.ReadFile(self.device.LOCAL_PROPERTIES_PATH),
2155 'some.example.prop=with an example value\n'
2156 'some.other.prop=value_ok\n'),
2157 self.call.device.WriteFile(
2158 self.device.LOCAL_PROPERTIES_PATH,
2159 'some.example.prop=with an example value\n'
2160 'some.other.prop=value_ok\n'
2161 'dalvik.vm.enableassertions=all\n'),
2162 (self.call.device.GetProp('dalvik.vm.enableassertions'), ''),
2163 self.call.device.SetProp('dalvik.vm.enableassertions', 'all')):
2164 self.assertTrue(self.device.SetJavaAsserts(True))
2165
2166 def testSetJavaAsserts_disable(self):
2167 with self.assertCalls(
2168 (self.call.device.ReadFile(self.device.LOCAL_PROPERTIES_PATH),
2169 'some.example.prop=with an example value\n'
2170 'dalvik.vm.enableassertions=all\n'
2171 'some.other.prop=value_ok\n'),
2172 self.call.device.WriteFile(
2173 self.device.LOCAL_PROPERTIES_PATH,
2174 'some.example.prop=with an example value\n'
2175 'some.other.prop=value_ok\n'),
2176 (self.call.device.GetProp('dalvik.vm.enableassertions'), 'all'),
2177 self.call.device.SetProp('dalvik.vm.enableassertions', '')):
2178 self.assertTrue(self.device.SetJavaAsserts(False))
2179
2180 def testSetJavaAsserts_alreadyEnabled(self):
2181 with self.assertCalls(
2182 (self.call.device.ReadFile(self.device.LOCAL_PROPERTIES_PATH),
2183 'some.example.prop=with an example value\n'
2184 'dalvik.vm.enableassertions=all\n'
2185 'some.other.prop=value_ok\n'),
2186 (self.call.device.GetProp('dalvik.vm.enableassertions'), 'all')):
2187 self.assertFalse(self.device.SetJavaAsserts(True))
2188
2189 def testSetJavaAsserts_malformedLocalProp(self):
2190 with self.assertCalls(
2191 (self.call.device.ReadFile(self.device.LOCAL_PROPERTIES_PATH),
2192 'some.example.prop=with an example value\n'
2193 'malformed_property\n'
2194 'dalvik.vm.enableassertions=all\n'
2195 'some.other.prop=value_ok\n'),
2196 (self.call.device.GetProp('dalvik.vm.enableassertions'), 'all')):
2197 self.assertFalse(self.device.SetJavaAsserts(True))
2198
2199
Chris Craika23c9e92016-08-19 14:42:29 -07002200class DeviceUtilsEnsureCacheInitializedTest(DeviceUtilsTest):
2201
2202 def testEnsureCacheInitialized_noCache_success(self):
2203 self.assertIsNone(self.device._cache['token'])
2204 with self.assertCall(
2205 self.call.device.RunShellCommand(
Chris Craika0e5c0d2017-03-29 15:00:32 -07002206 AnyStringWith('getprop'),
2207 shell=True, check_return=True, large_output=True),
Chris Craika23c9e92016-08-19 14:42:29 -07002208 ['/sdcard', 'TOKEN']):
2209 self.device._EnsureCacheInitialized()
2210 self.assertIsNotNone(self.device._cache['token'])
2211
2212 def testEnsureCacheInitialized_noCache_failure(self):
2213 self.assertIsNone(self.device._cache['token'])
2214 with self.assertCall(
2215 self.call.device.RunShellCommand(
Chris Craika0e5c0d2017-03-29 15:00:32 -07002216 AnyStringWith('getprop'),
2217 shell=True, check_return=True, large_output=True),
Chris Craika23c9e92016-08-19 14:42:29 -07002218 self.TimeoutError()):
2219 with self.assertRaises(device_errors.CommandTimeoutError):
2220 self.device._EnsureCacheInitialized()
2221 self.assertIsNone(self.device._cache['token'])
2222
2223 def testEnsureCacheInitialized_cache(self):
2224 self.device._cache['token'] = 'TOKEN'
2225 with self.assertCalls():
2226 self.device._EnsureCacheInitialized()
2227 self.assertIsNotNone(self.device._cache['token'])
2228
2229
Chris Craikbe1f9092016-03-28 13:54:49 -07002230class DeviceUtilsGetPropTest(DeviceUtilsTest):
2231
2232 def testGetProp_exists(self):
2233 with self.assertCall(
2234 self.call.device.RunShellCommand(
2235 ['getprop', 'test.property'], check_return=True, single_line=True,
2236 timeout=self.device._default_timeout,
2237 retries=self.device._default_retries),
2238 'property_value'):
2239 self.assertEqual('property_value',
2240 self.device.GetProp('test.property'))
2241
2242 def testGetProp_doesNotExist(self):
2243 with self.assertCall(
2244 self.call.device.RunShellCommand(
2245 ['getprop', 'property.does.not.exist'],
2246 check_return=True, single_line=True,
2247 timeout=self.device._default_timeout,
2248 retries=self.device._default_retries),
2249 ''):
2250 self.assertEqual('', self.device.GetProp('property.does.not.exist'))
2251
2252 def testGetProp_cachedRoProp(self):
Chris Craikbe1f9092016-03-28 13:54:49 -07002253 with self.assertCalls(
Chris Craika23c9e92016-08-19 14:42:29 -07002254 self.EnsureCacheInitialized(props=['[ro.build.type]: [userdebug]'])):
Chris Craikbe1f9092016-03-28 13:54:49 -07002255 self.assertEqual('userdebug',
Chris Craika23c9e92016-08-19 14:42:29 -07002256 self.device.GetProp('ro.build.type', cache=True))
Chris Craikbe1f9092016-03-28 13:54:49 -07002257 self.assertEqual('userdebug',
Chris Craika23c9e92016-08-19 14:42:29 -07002258 self.device.GetProp('ro.build.type', cache=True))
Chris Craikbe1f9092016-03-28 13:54:49 -07002259
2260
2261class DeviceUtilsSetPropTest(DeviceUtilsTest):
2262
2263 def testSetProp(self):
2264 with self.assertCall(
2265 self.call.device.RunShellCommand(
2266 ['setprop', 'test.property', 'test value'], check_return=True)):
2267 self.device.SetProp('test.property', 'test value')
2268
2269 def testSetProp_check_succeeds(self):
2270 with self.assertCalls(
2271 (self.call.device.RunShellCommand(
2272 ['setprop', 'test.property', 'new_value'], check_return=True)),
2273 (self.call.device.GetProp('test.property', cache=False), 'new_value')):
2274 self.device.SetProp('test.property', 'new_value', check=True)
2275
2276 def testSetProp_check_fails(self):
2277 with self.assertCalls(
2278 (self.call.device.RunShellCommand(
2279 ['setprop', 'test.property', 'new_value'], check_return=True)),
2280 (self.call.device.GetProp('test.property', cache=False), 'old_value')):
2281 with self.assertRaises(device_errors.CommandFailedError):
2282 self.device.SetProp('test.property', 'new_value', check=True)
2283
2284
2285class DeviceUtilsGetPidsTest(DeviceUtilsTest):
Chris Craika0e5c0d2017-03-29 15:00:32 -07002286 def setUp(self):
2287 super(DeviceUtilsGetPidsTest, self).setUp()
2288 self.sample_output = [
2289 'USER PID PPID VSIZE RSS WCHAN PC NAME',
2290 'user 1001 100 1024 1024 ffffffff 00000000 one.match',
2291 'user 1002 100 1024 1024 ffffffff 00000000 two.match',
2292 'user 1003 100 1024 1024 ffffffff 00000000 three.match',
2293 'user 1234 100 1024 1024 ffffffff 00000000 my$process',
2294 'user 1000 100 1024 1024 ffffffff 00000000 foo',
2295 'user 1236 100 1024 1024 ffffffff 00000000 foo',
2296 ]
2297
2298 def _grepOutput(self, substring):
2299 return [line for line in self.sample_output if substring in line]
2300
2301 def testGetPids_sdkGreaterThanNougatMR1(self):
2302 with self.patch_call(self.call.device.build_version_sdk,
2303 return_value=(version_codes.NOUGAT_MR1 + 1)):
2304 with self.patch_call(self.call.device.build_id,
2305 return_value='ZZZ99Z'):
2306 with self.assertCall(
2307 self.call.device._RunPipedShellCommand(
2308 'ps -e | grep -F example.process'), []):
2309 self.device.GetPids('example.process')
Chris Craikbe1f9092016-03-28 13:54:49 -07002310
2311 def testGetPids_noMatches(self):
Chris Craika0e5c0d2017-03-29 15:00:32 -07002312 with self.patch_call(self.call.device.build_version_sdk,
2313 return_value=version_codes.LOLLIPOP):
2314 with self.assertCall(
2315 self.call.device._RunPipedShellCommand('ps | grep -F does.not.match'),
2316 self._grepOutput('does.not.match')):
2317 self.assertEqual({}, self.device.GetPids('does.not.match'))
Chris Craikbe1f9092016-03-28 13:54:49 -07002318
2319 def testGetPids_oneMatch(self):
Chris Craika0e5c0d2017-03-29 15:00:32 -07002320 with self.patch_call(self.call.device.build_version_sdk,
2321 return_value=version_codes.LOLLIPOP):
2322 with self.assertCall(
2323 self.call.device._RunPipedShellCommand('ps | grep -F one.match'),
2324 self._grepOutput('one.match')):
2325 self.assertEqual(
2326 {'one.match': ['1001']},
2327 self.device.GetPids('one.match'))
Chris Craikbe1f9092016-03-28 13:54:49 -07002328
2329 def testGetPids_multipleMatches(self):
Chris Craika0e5c0d2017-03-29 15:00:32 -07002330 with self.patch_call(self.call.device.build_version_sdk,
2331 return_value=version_codes.LOLLIPOP):
2332 with self.assertCall(
2333 self.call.device._RunPipedShellCommand('ps | grep -F match'),
2334 self._grepOutput('match')):
2335 self.assertEqual(
2336 {'one.match': ['1001'],
2337 'two.match': ['1002'],
2338 'three.match': ['1003']},
2339 self.device.GetPids('match'))
Chris Craikbe1f9092016-03-28 13:54:49 -07002340
2341 def testGetPids_quotable(self):
Chris Craika0e5c0d2017-03-29 15:00:32 -07002342 with self.patch_call(self.call.device.build_version_sdk,
2343 return_value=version_codes.LOLLIPOP):
2344 with self.assertCall(
2345 self.call.device._RunPipedShellCommand("ps | grep -F 'my$process'"),
2346 self._grepOutput('my$process')):
2347 self.assertEqual(
2348 {'my$process': ['1234']}, self.device.GetPids('my$process'))
Chris Craikbe1f9092016-03-28 13:54:49 -07002349
2350 def testGetPids_multipleInstances(self):
Chris Craika0e5c0d2017-03-29 15:00:32 -07002351 with self.patch_call(self.call.device.build_version_sdk,
2352 return_value=version_codes.LOLLIPOP):
2353 with self.assertCall(
2354 self.call.device._RunPipedShellCommand('ps | grep -F foo'),
2355 self._grepOutput('foo')):
2356 self.assertEqual(
2357 {'foo': ['1000', '1236']},
2358 self.device.GetPids('foo'))
2359
2360 def testGetPids_allProcesses(self):
2361 with self.patch_call(self.call.device.build_version_sdk,
2362 return_value=version_codes.LOLLIPOP):
2363 with self.assertCall(
2364 self.call.device.RunShellCommand(
2365 ['ps'], check_return=True, large_output=True),
2366 self.sample_output):
2367 self.assertEqual(
2368 {'one.match': ['1001'],
2369 'two.match': ['1002'],
2370 'three.match': ['1003'],
2371 'my$process': ['1234'],
2372 'foo': ['1000', '1236']},
2373 self.device.GetPids())
2374
2375 def testGetApplicationPids_notFound(self):
2376 with self.patch_call(self.call.device.build_version_sdk,
2377 return_value=version_codes.LOLLIPOP):
2378 with self.assertCall(
2379 self.call.device._RunPipedShellCommand('ps | grep -F match'),
2380 self._grepOutput('match')):
2381 # No PIDs found, process name should be exact match.
2382 self.assertEqual([], self.device.GetApplicationPids('match'))
2383
2384 def testGetApplicationPids_foundOne(self):
2385 with self.patch_call(self.call.device.build_version_sdk,
2386 return_value=version_codes.LOLLIPOP):
2387 with self.assertCall(
2388 self.call.device._RunPipedShellCommand('ps | grep -F one.match'),
2389 self._grepOutput('one.match')):
2390 self.assertEqual(['1001'], self.device.GetApplicationPids('one.match'))
2391
2392 def testGetApplicationPids_foundMany(self):
2393 with self.patch_call(self.call.device.build_version_sdk,
2394 return_value=version_codes.LOLLIPOP):
2395 with self.assertCall(
2396 self.call.device._RunPipedShellCommand('ps | grep -F foo'),
2397 self._grepOutput('foo')):
2398 self.assertEqual(
2399 ['1000', '1236'],
2400 self.device.GetApplicationPids('foo'))
2401
2402 def testGetApplicationPids_atMostOneNotFound(self):
2403 with self.patch_call(self.call.device.build_version_sdk,
2404 return_value=version_codes.LOLLIPOP):
2405 with self.assertCall(
2406 self.call.device._RunPipedShellCommand('ps | grep -F match'),
2407 self._grepOutput('match')):
2408 # No PIDs found, process name should be exact match.
2409 self.assertEqual(
2410 None,
2411 self.device.GetApplicationPids('match', at_most_one=True))
2412
2413 def testGetApplicationPids_atMostOneFound(self):
2414 with self.patch_call(self.call.device.build_version_sdk,
2415 return_value=version_codes.LOLLIPOP):
2416 with self.assertCall(
2417 self.call.device._RunPipedShellCommand('ps | grep -F one.match'),
2418 self._grepOutput('one.match')):
2419 self.assertEqual(
2420 '1001',
2421 self.device.GetApplicationPids('one.match', at_most_one=True))
2422
2423 def testGetApplicationPids_atMostOneFoundTooMany(self):
2424 with self.patch_call(self.call.device.build_version_sdk,
2425 return_value=version_codes.LOLLIPOP):
2426 with self.assertRaises(device_errors.CommandFailedError):
2427 with self.assertCall(
2428 self.call.device._RunPipedShellCommand('ps | grep -F foo'),
2429 self._grepOutput('foo')):
2430 self.device.GetApplicationPids('foo', at_most_one=True)
2431
2432
2433class DeviceUtilsGetSetEnforce(DeviceUtilsTest):
2434
2435 def testGetEnforce_Enforcing(self):
2436 with self.assertCall(self.call.adb.Shell('getenforce'), 'Enforcing'):
2437 self.assertEqual(True, self.device.GetEnforce())
2438
2439 def testGetEnforce_Permissive(self):
2440 with self.assertCall(self.call.adb.Shell('getenforce'), 'Permissive'):
2441 self.assertEqual(False, self.device.GetEnforce())
2442
2443 def testGetEnforce_Disabled(self):
2444 with self.assertCall(self.call.adb.Shell('getenforce'), 'Disabled'):
2445 self.assertEqual(None, self.device.GetEnforce())
2446
2447 def testSetEnforce_Enforcing(self):
2448 with self.assertCalls(
2449 (self.call.device.NeedsSU(), False),
2450 (self.call.adb.Shell('setenforce 1'), '')):
2451 self.device.SetEnforce(enabled=True)
2452
2453 def testSetEnforce_Permissive(self):
2454 with self.assertCalls(
2455 (self.call.device.NeedsSU(), False),
2456 (self.call.adb.Shell('setenforce 0'), '')):
2457 self.device.SetEnforce(enabled=False)
2458
2459 def testSetEnforce_EnforcingWithInt(self):
2460 with self.assertCalls(
2461 (self.call.device.NeedsSU(), False),
2462 (self.call.adb.Shell('setenforce 1'), '')):
2463 self.device.SetEnforce(enabled=1)
2464
2465 def testSetEnforce_PermissiveWithInt(self):
2466 with self.assertCalls(
2467 (self.call.device.NeedsSU(), False),
2468 (self.call.adb.Shell('setenforce 0'), '')):
2469 self.device.SetEnforce(enabled=0)
2470
2471 def testSetEnforce_EnforcingWithStr(self):
2472 with self.assertCalls(
2473 (self.call.device.NeedsSU(), False),
2474 (self.call.adb.Shell('setenforce 1'), '')):
2475 self.device.SetEnforce(enabled='1')
2476
2477 def testSetEnforce_PermissiveWithStr(self):
2478 with self.assertCalls(
2479 (self.call.device.NeedsSU(), False),
2480 (self.call.adb.Shell('setenforce 0'), '')):
2481 self.device.SetEnforce(enabled='0') # Not recommended but it works!
Chris Craikbe1f9092016-03-28 13:54:49 -07002482
2483
2484class DeviceUtilsTakeScreenshotTest(DeviceUtilsTest):
2485
2486 def testTakeScreenshot_fileNameProvided(self):
2487 with self.assertCalls(
2488 (mock.call.devil.android.device_temp_file.DeviceTempFile(
2489 self.adb, suffix='.png'),
2490 MockTempFile('/tmp/path/temp-123.png')),
2491 (self.call.adb.Shell('/system/bin/screencap -p /tmp/path/temp-123.png'),
2492 ''),
2493 self.call.device.PullFile('/tmp/path/temp-123.png',
2494 '/test/host/screenshot.png')):
2495 self.device.TakeScreenshot('/test/host/screenshot.png')
2496
2497
2498class DeviceUtilsGetMemoryUsageForPidTest(DeviceUtilsTest):
2499
2500 def setUp(self):
2501 super(DeviceUtilsGetMemoryUsageForPidTest, self).setUp()
2502
2503 def testGetMemoryUsageForPid_validPid(self):
2504 with self.assertCalls(
2505 (self.call.device._RunPipedShellCommand(
2506 'showmap 1234 | grep TOTAL', as_root=True),
2507 ['100 101 102 103 104 105 106 107 TOTAL']),
2508 (self.call.device.ReadFile('/proc/1234/status', as_root=True),
2509 'VmHWM: 1024 kB\n')):
2510 self.assertEqual(
2511 {
2512 'Size': 100,
2513 'Rss': 101,
2514 'Pss': 102,
2515 'Shared_Clean': 103,
2516 'Shared_Dirty': 104,
2517 'Private_Clean': 105,
2518 'Private_Dirty': 106,
2519 'VmHWM': 1024
2520 },
2521 self.device.GetMemoryUsageForPid(1234))
2522
2523 def testGetMemoryUsageForPid_noSmaps(self):
2524 with self.assertCalls(
2525 (self.call.device._RunPipedShellCommand(
2526 'showmap 4321 | grep TOTAL', as_root=True),
2527 ['cannot open /proc/4321/smaps: No such file or directory']),
2528 (self.call.device.ReadFile('/proc/4321/status', as_root=True),
2529 'VmHWM: 1024 kb\n')):
2530 self.assertEquals({'VmHWM': 1024}, self.device.GetMemoryUsageForPid(4321))
2531
2532 def testGetMemoryUsageForPid_noStatus(self):
2533 with self.assertCalls(
2534 (self.call.device._RunPipedShellCommand(
2535 'showmap 4321 | grep TOTAL', as_root=True),
2536 ['100 101 102 103 104 105 106 107 TOTAL']),
2537 (self.call.device.ReadFile('/proc/4321/status', as_root=True),
2538 self.CommandError())):
2539 self.assertEquals(
2540 {
2541 'Size': 100,
2542 'Rss': 101,
2543 'Pss': 102,
2544 'Shared_Clean': 103,
2545 'Shared_Dirty': 104,
2546 'Private_Clean': 105,
2547 'Private_Dirty': 106,
2548 },
2549 self.device.GetMemoryUsageForPid(4321))
2550
2551
2552class DeviceUtilsDismissCrashDialogIfNeededTest(DeviceUtilsTest):
2553
2554 def testDismissCrashDialogIfNeeded_crashedPageckageNotFound(self):
2555 sample_dumpsys_output = '''
2556WINDOW MANAGER WINDOWS (dumpsys window windows)
2557 Window #11 Window{f8b647a u0 SearchPanel}:
2558 mDisplayId=0 mSession=Session{8 94:122} mClient=android.os.BinderProxy@1ba5
2559 mOwnerUid=100 mShowToOwnerOnly=false package=com.android.systemui appop=NONE
2560 mAttrs=WM.LayoutParams{(0,0)(fillxfill) gr=#53 sim=#31 ty=2024 fl=100
2561 Requested w=1080 h=1920 mLayoutSeq=426
2562 mBaseLayer=211000 mSubLayer=0 mAnimLayer=211000+0=211000 mLastLayer=211000
2563'''
2564 with self.assertCalls(
2565 (self.call.device.RunShellCommand(
2566 ['dumpsys', 'window', 'windows'], check_return=True,
2567 large_output=True), sample_dumpsys_output.split('\n'))):
2568 package_name = self.device.DismissCrashDialogIfNeeded()
2569 self.assertIsNone(package_name)
2570
2571 def testDismissCrashDialogIfNeeded_crashedPageckageFound(self):
2572 sample_dumpsys_output = '''
2573WINDOW MANAGER WINDOWS (dumpsys window windows)
2574 Window #11 Window{f8b647a u0 SearchPanel}:
2575 mDisplayId=0 mSession=Session{8 94:122} mClient=android.os.BinderProxy@1ba5
2576 mOwnerUid=102 mShowToOwnerOnly=false package=com.android.systemui appop=NONE
2577 mAttrs=WM.LayoutParams{(0,0)(fillxfill) gr=#53 sim=#31 ty=2024 fl=100
2578 Requested w=1080 h=1920 mLayoutSeq=426
2579 mBaseLayer=211000 mSubLayer=0 mAnimLayer=211000+0=211000 mLastLayer=211000
2580 mHasPermanentDpad=false
2581 mCurrentFocus=Window{3a27740f u0 Application Error: com.android.chrome}
2582 mFocusedApp=AppWindowToken{470af6f token=Token{272ec24e ActivityRecord{t894}}}
2583'''
2584 with self.assertCalls(
2585 (self.call.device.RunShellCommand(
2586 ['dumpsys', 'window', 'windows'], check_return=True,
2587 large_output=True), sample_dumpsys_output.split('\n')),
2588 (self.call.device.RunShellCommand(
2589 ['input', 'keyevent', '22'], check_return=True)),
2590 (self.call.device.RunShellCommand(
2591 ['input', 'keyevent', '22'], check_return=True)),
2592 (self.call.device.RunShellCommand(
2593 ['input', 'keyevent', '66'], check_return=True)),
2594 (self.call.device.RunShellCommand(
2595 ['dumpsys', 'window', 'windows'], check_return=True,
2596 large_output=True), [])):
2597 package_name = self.device.DismissCrashDialogIfNeeded()
2598 self.assertEqual(package_name, 'com.android.chrome')
2599
2600
2601class DeviceUtilsClientCache(DeviceUtilsTest):
2602
2603 def testClientCache_twoCaches(self):
2604 self.device._cache['test'] = 0
2605 client_cache_one = self.device.GetClientCache('ClientOne')
2606 client_cache_one['test'] = 1
2607 client_cache_two = self.device.GetClientCache('ClientTwo')
2608 client_cache_two['test'] = 2
2609 self.assertEqual(self.device._cache['test'], 0)
2610 self.assertEqual(client_cache_one, {'test': 1})
2611 self.assertEqual(client_cache_two, {'test': 2})
2612 self.device._ClearCache()
2613 self.assertTrue('test' not in self.device._cache)
2614 self.assertEqual(client_cache_one, {})
2615 self.assertEqual(client_cache_two, {})
2616
2617 def testClientCache_multipleInstances(self):
2618 client_cache_one = self.device.GetClientCache('ClientOne')
2619 client_cache_one['test'] = 1
2620 client_cache_two = self.device.GetClientCache('ClientOne')
2621 self.assertEqual(client_cache_one, {'test': 1})
2622 self.assertEqual(client_cache_two, {'test': 1})
2623 self.device._ClearCache()
2624 self.assertEqual(client_cache_one, {})
2625 self.assertEqual(client_cache_two, {})
2626
2627
2628class DeviceUtilsHealthyDevicesTest(mock_calls.TestCase):
2629
Chris Craika23c9e92016-08-19 14:42:29 -07002630 def testHealthyDevices_emptyBlacklist_defaultDeviceArg(self):
Chris Craikbe1f9092016-03-28 13:54:49 -07002631 test_serials = ['0123456789abcdef', 'fedcba9876543210']
2632 with self.assertCalls(
2633 (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(),
2634 [_AdbWrapperMock(s) for s in test_serials])):
2635 blacklist = mock.NonCallableMock(**{'Read.return_value': []})
2636 devices = device_utils.DeviceUtils.HealthyDevices(blacklist)
2637 for serial, device in zip(test_serials, devices):
2638 self.assertTrue(isinstance(device, device_utils.DeviceUtils))
2639 self.assertEquals(serial, device.adb.GetDeviceSerial())
2640
Chris Craika23c9e92016-08-19 14:42:29 -07002641 def testHealthyDevices_blacklist_defaultDeviceArg(self):
Chris Craikbe1f9092016-03-28 13:54:49 -07002642 test_serials = ['0123456789abcdef', 'fedcba9876543210']
2643 with self.assertCalls(
2644 (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(),
2645 [_AdbWrapperMock(s) for s in test_serials])):
2646 blacklist = mock.NonCallableMock(
2647 **{'Read.return_value': ['fedcba9876543210']})
2648 devices = device_utils.DeviceUtils.HealthyDevices(blacklist)
2649 self.assertEquals(1, len(devices))
2650 self.assertTrue(isinstance(devices[0], device_utils.DeviceUtils))
2651 self.assertEquals('0123456789abcdef', devices[0].adb.GetDeviceSerial())
2652
Chris Craika23c9e92016-08-19 14:42:29 -07002653 def testHealthyDevices_noneDeviceArg_multiple_attached(self):
2654 test_serials = ['0123456789abcdef', 'fedcba9876543210']
2655 with self.assertCalls(
2656 (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(),
2657 [_AdbWrapperMock(s) for s in test_serials]),
2658 (mock.call.devil.android.device_errors.MultipleDevicesError(mock.ANY),
2659 _MockMultipleDevicesError())):
2660 with self.assertRaises(_MockMultipleDevicesError):
2661 device_utils.DeviceUtils.HealthyDevices(device_arg=None)
2662
2663 def testHealthyDevices_noneDeviceArg_one_attached(self):
2664 test_serials = ['0123456789abcdef']
2665 with self.assertCalls(
2666 (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(),
2667 [_AdbWrapperMock(s) for s in test_serials])):
2668 devices = device_utils.DeviceUtils.HealthyDevices(device_arg=None)
2669 self.assertEquals(1, len(devices))
2670
2671 def testHealthyDevices_noneDeviceArg_no_attached(self):
2672 test_serials = []
2673 with self.assertCalls(
2674 (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(),
2675 [_AdbWrapperMock(s) for s in test_serials])):
2676 with self.assertRaises(device_errors.NoDevicesError):
2677 device_utils.DeviceUtils.HealthyDevices(device_arg=None)
2678
2679 def testHealthyDevices_noneDeviceArg_multiple_attached_ANDROID_SERIAL(self):
2680 try:
2681 os.environ['ANDROID_SERIAL'] = '0123456789abcdef'
2682 with self.assertCalls(): # Should skip adb devices when device is known.
2683 device_utils.DeviceUtils.HealthyDevices(device_arg=None)
2684 finally:
2685 del os.environ['ANDROID_SERIAL']
2686
2687 def testHealthyDevices_stringDeviceArg(self):
2688 with self.assertCalls(): # Should skip adb devices when device is known.
2689 devices = device_utils.DeviceUtils.HealthyDevices(
2690 device_arg='0123456789abcdef')
2691 self.assertEquals(1, len(devices))
2692
2693 def testHealthyDevices_EmptyListDeviceArg_multiple_attached(self):
2694 test_serials = ['0123456789abcdef', 'fedcba9876543210']
2695 with self.assertCalls(
2696 (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(),
2697 [_AdbWrapperMock(s) for s in test_serials])):
2698 devices = device_utils.DeviceUtils.HealthyDevices(device_arg=())
2699 self.assertEquals(2, len(devices))
2700
2701 def testHealthyDevices_EmptyListDeviceArg_ANDROID_SERIAL(self):
2702 try:
2703 os.environ['ANDROID_SERIAL'] = '0123456789abcdef'
2704 with self.assertCalls(): # Should skip adb devices when device is known.
2705 devices = device_utils.DeviceUtils.HealthyDevices(device_arg=())
2706 finally:
2707 del os.environ['ANDROID_SERIAL']
2708 self.assertEquals(1, len(devices))
2709
2710 def testHealthyDevices_EmptyListDeviceArg_no_attached(self):
2711 test_serials = []
2712 with self.assertCalls(
2713 (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(),
2714 [_AdbWrapperMock(s) for s in test_serials])):
2715 with self.assertRaises(device_errors.NoDevicesError):
2716 device_utils.DeviceUtils.HealthyDevices(device_arg=[])
2717
2718 def testHealthyDevices_ListDeviceArg(self):
2719 device_arg = ['0123456789abcdef', 'fedcba9876543210']
2720 try:
2721 os.environ['ANDROID_SERIAL'] = 'should-not-apply'
2722 with self.assertCalls(): # Should skip adb devices when device is known.
2723 devices = device_utils.DeviceUtils.HealthyDevices(device_arg=device_arg)
2724 finally:
2725 del os.environ['ANDROID_SERIAL']
2726 self.assertEquals(2, len(devices))
2727
Chris Craikbe1f9092016-03-28 13:54:49 -07002728
2729class DeviceUtilsRestartAdbdTest(DeviceUtilsTest):
2730
2731 def testAdbdRestart(self):
2732 mock_temp_file = '/sdcard/temp-123.sh'
2733 with self.assertCalls(
2734 (mock.call.devil.android.device_temp_file.DeviceTempFile(
2735 self.adb, suffix='.sh'), MockTempFile(mock_temp_file)),
2736 self.call.device.WriteFile(mock.ANY, mock.ANY),
2737 (self.call.device.RunShellCommand(
Chris Craika0e5c0d2017-03-29 15:00:32 -07002738 ['source', mock_temp_file], check_return=True, as_root=True)),
Chris Craikbe1f9092016-03-28 13:54:49 -07002739 self.call.adb.WaitForDevice()):
2740 self.device.RestartAdbd()
2741
2742
2743class DeviceUtilsGrantPermissionsTest(DeviceUtilsTest):
2744
2745 def testGrantPermissions_none(self):
2746 self.device.GrantPermissions('package', [])
2747
2748 def testGrantPermissions_underM(self):
2749 with self.patch_call(self.call.device.build_version_sdk,
2750 return_value=version_codes.LOLLIPOP):
2751 self.device.GrantPermissions('package', ['p1'])
2752
2753 def testGrantPermissions_one(self):
2754 permissions_cmd = 'pm grant package p1'
2755 with self.patch_call(self.call.device.build_version_sdk,
2756 return_value=version_codes.MARSHMALLOW):
2757 with self.assertCalls(
2758 (self.call.device.RunShellCommand(
Chris Craika0e5c0d2017-03-29 15:00:32 -07002759 permissions_cmd, shell=True, check_return=True), [])):
Chris Craikbe1f9092016-03-28 13:54:49 -07002760 self.device.GrantPermissions('package', ['p1'])
2761
2762 def testGrantPermissions_multiple(self):
2763 permissions_cmd = 'pm grant package p1&&pm grant package p2'
2764 with self.patch_call(self.call.device.build_version_sdk,
2765 return_value=version_codes.MARSHMALLOW):
2766 with self.assertCalls(
2767 (self.call.device.RunShellCommand(
Chris Craika0e5c0d2017-03-29 15:00:32 -07002768 permissions_cmd, shell=True, check_return=True), [])):
Chris Craikbe1f9092016-03-28 13:54:49 -07002769 self.device.GrantPermissions('package', ['p1', 'p2'])
2770
2771 def testGrantPermissions_WriteExtrnalStorage(self):
2772 permissions_cmd = (
2773 'pm grant package android.permission.WRITE_EXTERNAL_STORAGE&&'
2774 'pm grant package android.permission.READ_EXTERNAL_STORAGE')
2775 with self.patch_call(self.call.device.build_version_sdk,
2776 return_value=version_codes.MARSHMALLOW):
2777 with self.assertCalls(
2778 (self.call.device.RunShellCommand(
Chris Craika0e5c0d2017-03-29 15:00:32 -07002779 permissions_cmd, shell=True, check_return=True), [])):
Chris Craikbe1f9092016-03-28 13:54:49 -07002780 self.device.GrantPermissions(
2781 'package', ['android.permission.WRITE_EXTERNAL_STORAGE'])
2782
2783 def testGrantPermissions_BlackList(self):
2784 with self.patch_call(self.call.device.build_version_sdk,
2785 return_value=version_codes.MARSHMALLOW):
2786 self.device.GrantPermissions(
2787 'package', ['android.permission.ACCESS_MOCK_LOCATION'])
2788
2789
2790class DeviecUtilsIsScreenOn(DeviceUtilsTest):
2791
2792 _L_SCREEN_ON = ['test=test mInteractive=true']
2793 _K_SCREEN_ON = ['test=test mScreenOn=true']
2794 _L_SCREEN_OFF = ['mInteractive=false']
2795 _K_SCREEN_OFF = ['mScreenOn=false']
2796
2797 def testIsScreenOn_onPreL(self):
2798 with self.patch_call(self.call.device.build_version_sdk,
2799 return_value=version_codes.KITKAT):
2800 with self.assertCalls(
2801 (self.call.device._RunPipedShellCommand(
2802 'dumpsys input_method | grep mScreenOn'), self._K_SCREEN_ON)):
2803 self.assertTrue(self.device.IsScreenOn())
2804
2805 def testIsScreenOn_onL(self):
2806 with self.patch_call(self.call.device.build_version_sdk,
2807 return_value=version_codes.LOLLIPOP):
2808 with self.assertCalls(
2809 (self.call.device._RunPipedShellCommand(
2810 'dumpsys input_method | grep mInteractive'), self._L_SCREEN_ON)):
2811 self.assertTrue(self.device.IsScreenOn())
2812
2813 def testIsScreenOn_offPreL(self):
2814 with self.patch_call(self.call.device.build_version_sdk,
2815 return_value=version_codes.KITKAT):
2816 with self.assertCalls(
2817 (self.call.device._RunPipedShellCommand(
2818 'dumpsys input_method | grep mScreenOn'), self._K_SCREEN_OFF)):
2819 self.assertFalse(self.device.IsScreenOn())
2820
2821 def testIsScreenOn_offL(self):
2822 with self.patch_call(self.call.device.build_version_sdk,
2823 return_value=version_codes.LOLLIPOP):
2824 with self.assertCalls(
2825 (self.call.device._RunPipedShellCommand(
2826 'dumpsys input_method | grep mInteractive'), self._L_SCREEN_OFF)):
2827 self.assertFalse(self.device.IsScreenOn())
2828
2829 def testIsScreenOn_noOutput(self):
2830 with self.patch_call(self.call.device.build_version_sdk,
2831 return_value=version_codes.LOLLIPOP):
2832 with self.assertCalls(
2833 (self.call.device._RunPipedShellCommand(
2834 'dumpsys input_method | grep mInteractive'), [])):
2835 with self.assertRaises(device_errors.CommandFailedError):
2836 self.device.IsScreenOn()
2837
2838
2839class DeviecUtilsSetScreen(DeviceUtilsTest):
2840
2841 @mock.patch('time.sleep', mock.Mock())
2842 def testSetScren_alreadySet(self):
2843 with self.assertCalls(
2844 (self.call.device.IsScreenOn(), False)):
2845 self.device.SetScreen(False)
2846
2847 @mock.patch('time.sleep', mock.Mock())
2848 def testSetScreen_on(self):
2849 with self.assertCalls(
2850 (self.call.device.IsScreenOn(), False),
Chris Craika0e5c0d2017-03-29 15:00:32 -07002851 (self.call.device.SendKeyEvent(keyevent.KEYCODE_POWER), None),
Chris Craikbe1f9092016-03-28 13:54:49 -07002852 (self.call.device.IsScreenOn(), True)):
2853 self.device.SetScreen(True)
2854
2855 @mock.patch('time.sleep', mock.Mock())
2856 def testSetScreen_off(self):
2857 with self.assertCalls(
2858 (self.call.device.IsScreenOn(), True),
Chris Craika0e5c0d2017-03-29 15:00:32 -07002859 (self.call.device.SendKeyEvent(keyevent.KEYCODE_POWER), None),
Chris Craikbe1f9092016-03-28 13:54:49 -07002860 (self.call.device.IsScreenOn(), False)):
2861 self.device.SetScreen(False)
2862
2863 @mock.patch('time.sleep', mock.Mock())
2864 def testSetScreen_slow(self):
2865 with self.assertCalls(
2866 (self.call.device.IsScreenOn(), True),
Chris Craika0e5c0d2017-03-29 15:00:32 -07002867 (self.call.device.SendKeyEvent(keyevent.KEYCODE_POWER), None),
Chris Craikbe1f9092016-03-28 13:54:49 -07002868 (self.call.device.IsScreenOn(), True),
2869 (self.call.device.IsScreenOn(), True),
2870 (self.call.device.IsScreenOn(), False)):
2871 self.device.SetScreen(False)
2872
Chris Craika23c9e92016-08-19 14:42:29 -07002873class DeviecUtilsLoadCacheData(DeviceUtilsTest):
2874
2875 def testTokenMissing(self):
2876 with self.assertCalls(
2877 self.EnsureCacheInitialized()):
2878 self.assertFalse(self.device.LoadCacheData('{}'))
2879
2880 def testTokenStale(self):
2881 with self.assertCalls(
2882 self.EnsureCacheInitialized()):
2883 self.assertFalse(self.device.LoadCacheData('{"token":"foo"}'))
2884
2885 def testTokenMatches(self):
2886 with self.assertCalls(
2887 self.EnsureCacheInitialized()):
2888 self.assertTrue(self.device.LoadCacheData('{"token":"TOKEN"}'))
2889
2890 def testDumpThenLoad(self):
2891 with self.assertCalls(
2892 self.EnsureCacheInitialized()):
2893 data = json.loads(self.device.DumpCacheData())
2894 data['token'] = 'TOKEN'
2895 self.assertTrue(self.device.LoadCacheData(json.dumps(data)))
2896
2897
Chris Craikbe1f9092016-03-28 13:54:49 -07002898if __name__ == '__main__':
2899 logging.getLogger().setLevel(logging.DEBUG)
2900 unittest.main(verbosity=2)