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