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