Home | History | Annotate | Download | only in android
      1 #!/usr/bin/env python
      2 # Copyright 2015 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 """
      7 Unit tests for the contents of fastboot_utils.py
      8 """
      9 
     10 # pylint: disable=protected-access,unused-argument
     11 
     12 import collections
     13 import io
     14 import logging
     15 import unittest
     16 
     17 from devil import devil_env
     18 from devil.android import device_errors
     19 from devil.android import device_utils
     20 from devil.android import fastboot_utils
     21 from devil.android.sdk import fastboot
     22 from devil.utils import mock_calls
     23 
     24 with devil_env.SysPath(devil_env.PYMOCK_PATH):
     25   import mock  # pylint: disable=import-error
     26 
     27 _BOARD = 'board_type'
     28 _SERIAL = '0123456789abcdef'
     29 _PARTITIONS = [
     30     'bootloader', 'radio', 'boot', 'recovery', 'system', 'userdata', 'cache']
     31 _IMAGES = collections.OrderedDict([
     32     ('bootloader', 'bootloader.img'),
     33     ('radio', 'radio.img'),
     34     ('boot', 'boot.img'),
     35     ('recovery', 'recovery.img'),
     36     ('system', 'system.img'),
     37     ('userdata', 'userdata.img'),
     38     ('cache', 'cache.img')
     39 ])
     40 _VALID_FILES = [_BOARD + '.zip', 'android-info.txt']
     41 _INVALID_FILES = ['test.zip', 'android-info.txt']
     42 
     43 
     44 class MockFile(object):
     45 
     46   def __init__(self, name='/tmp/some/file'):
     47     self.file = mock.MagicMock(spec=file)
     48     self.file.name = name
     49 
     50   def __enter__(self):
     51     return self.file
     52 
     53   def __exit__(self, exc_type, exc_val, exc_tb):
     54     pass
     55 
     56   @property
     57   def name(self):
     58     return self.file.name
     59 
     60 
     61 def _FastbootWrapperMock(test_serial):
     62   fastbooter = mock.Mock(spec=fastboot.Fastboot)
     63   fastbooter.__str__ = mock.Mock(return_value=test_serial)
     64   fastbooter.Devices.return_value = [test_serial]
     65   return fastbooter
     66 
     67 
     68 def _DeviceUtilsMock(test_serial):
     69   device = mock.Mock(spec=device_utils.DeviceUtils)
     70   device.__str__ = mock.Mock(return_value=test_serial)
     71   device.product_board = mock.Mock(return_value=_BOARD)
     72   device.adb = mock.Mock()
     73   return device
     74 
     75 
     76 class FastbootUtilsTest(mock_calls.TestCase):
     77 
     78   def setUp(self):
     79     self.device_utils_mock = _DeviceUtilsMock(_SERIAL)
     80     self.fastboot_wrapper = _FastbootWrapperMock(_SERIAL)
     81     self.fastboot = fastboot_utils.FastbootUtils(
     82         self.device_utils_mock, fastbooter=self.fastboot_wrapper,
     83         default_timeout=2, default_retries=0)
     84     self.fastboot._board = _BOARD
     85 
     86 
     87 class FastbootUtilsInitTest(FastbootUtilsTest):
     88 
     89   def testInitWithDeviceUtil(self):
     90     f = fastboot_utils.FastbootUtils(self.device_utils_mock)
     91     self.assertEqual(str(self.device_utils_mock), str(f._device))
     92 
     93   def testInitWithMissing_fails(self):
     94     with self.assertRaises(AttributeError):
     95       fastboot_utils.FastbootUtils(None)
     96     with self.assertRaises(AttributeError):
     97       fastboot_utils.FastbootUtils('')
     98 
     99   def testPartitionOrdering(self):
    100     parts = ['bootloader', 'radio', 'boot', 'recovery', 'system', 'userdata',
    101              'cache', 'vendor']
    102     self.assertListEqual(fastboot_utils.ALL_PARTITIONS, parts)
    103 
    104 
    105 class FastbootUtilsWaitForFastbootMode(FastbootUtilsTest):
    106 
    107   # If this test fails by timing out after 1 second.
    108   @mock.patch('time.sleep', mock.Mock())
    109   def testWaitForFastbootMode(self):
    110     self.fastboot.WaitForFastbootMode()
    111 
    112 
    113 class FastbootUtilsEnableFastbootMode(FastbootUtilsTest):
    114 
    115   def testEnableFastbootMode(self):
    116     with self.assertCalls(
    117         self.call.fastboot._device.EnableRoot(),
    118         self.call.fastboot._device.adb.Reboot(to_bootloader=True),
    119         self.call.fastboot.WaitForFastbootMode()):
    120       self.fastboot.EnableFastbootMode()
    121 
    122 
    123 class FastbootUtilsReboot(FastbootUtilsTest):
    124 
    125   def testReboot_bootloader(self):
    126     with self.assertCalls(
    127         self.call.fastboot.fastboot.RebootBootloader(),
    128         self.call.fastboot.WaitForFastbootMode()):
    129       self.fastboot.Reboot(bootloader=True)
    130 
    131   def testReboot_normal(self):
    132     with self.assertCalls(
    133         self.call.fastboot.fastboot.Reboot(),
    134         self.call.fastboot._device.WaitUntilFullyBooted(timeout=mock.ANY)):
    135       self.fastboot.Reboot()
    136 
    137 
    138 class FastbootUtilsFlashPartitions(FastbootUtilsTest):
    139 
    140   def testFlashPartitions_wipe(self):
    141     with self.assertCalls(
    142         (self.call.fastboot._VerifyBoard('test'), True),
    143         (mock.call.devil.android.fastboot_utils.
    144             _FindAndVerifyPartitionsAndImages(_PARTITIONS, 'test'), _IMAGES),
    145         (self.call.fastboot.fastboot.Flash('bootloader', 'bootloader.img')),
    146         (self.call.fastboot.Reboot(bootloader=True)),
    147         (self.call.fastboot.fastboot.Flash('radio', 'radio.img')),
    148         (self.call.fastboot.Reboot(bootloader=True)),
    149         (self.call.fastboot.fastboot.Flash('boot', 'boot.img')),
    150         (self.call.fastboot.fastboot.Flash('recovery', 'recovery.img')),
    151         (self.call.fastboot.fastboot.Flash('system', 'system.img')),
    152         (self.call.fastboot.fastboot.Flash('userdata', 'userdata.img')),
    153         (self.call.fastboot.fastboot.Flash('cache', 'cache.img'))):
    154       self.fastboot._FlashPartitions(_PARTITIONS, 'test', wipe=True)
    155 
    156   def testFlashPartitions_noWipe(self):
    157     with self.assertCalls(
    158         (self.call.fastboot._VerifyBoard('test'), True),
    159         (mock.call.devil.android.fastboot_utils.
    160             _FindAndVerifyPartitionsAndImages(_PARTITIONS, 'test'), _IMAGES),
    161         (self.call.fastboot.fastboot.Flash('bootloader', 'bootloader.img')),
    162         (self.call.fastboot.Reboot(bootloader=True)),
    163         (self.call.fastboot.fastboot.Flash('radio', 'radio.img')),
    164         (self.call.fastboot.Reboot(bootloader=True)),
    165         (self.call.fastboot.fastboot.Flash('boot', 'boot.img')),
    166         (self.call.fastboot.fastboot.Flash('recovery', 'recovery.img')),
    167         (self.call.fastboot.fastboot.Flash('system', 'system.img'))):
    168       self.fastboot._FlashPartitions(_PARTITIONS, 'test')
    169 
    170 
    171 class FastbootUtilsFastbootMode(FastbootUtilsTest):
    172 
    173   def testFastbootMode_goodWait(self):
    174     with self.assertCalls(
    175         self.call.fastboot.EnableFastbootMode(),
    176         self.call.fastboot.fastboot.SetOemOffModeCharge(False),
    177         self.call.fastboot.fastboot.SetOemOffModeCharge(True),
    178         self.call.fastboot.Reboot(wait_for_reboot=True)):
    179       with self.fastboot.FastbootMode() as fbm:
    180         self.assertEqual(self.fastboot, fbm)
    181 
    182   def testFastbootMode_goodNoWait(self):
    183     with self.assertCalls(
    184         self.call.fastboot.EnableFastbootMode(),
    185         self.call.fastboot.fastboot.SetOemOffModeCharge(False),
    186         self.call.fastboot.fastboot.SetOemOffModeCharge(True),
    187         self.call.fastboot.Reboot(wait_for_reboot=False)):
    188       with self.fastboot.FastbootMode(wait_for_reboot=False) as fbm:
    189         self.assertEqual(self.fastboot, fbm)
    190 
    191   def testFastbootMode_exception(self):
    192     with self.assertCalls(
    193         self.call.fastboot.EnableFastbootMode(),
    194         self.call.fastboot.fastboot.SetOemOffModeCharge(False),
    195         self.call.fastboot.fastboot.SetOemOffModeCharge(True),
    196         self.call.fastboot.Reboot(wait_for_reboot=True)):
    197       with self.assertRaises(NotImplementedError):
    198         with self.fastboot.FastbootMode() as fbm:
    199           self.assertEqual(self.fastboot, fbm)
    200           raise NotImplementedError
    201 
    202   def testFastbootMode_exceptionInEnableFastboot(self):
    203     self.fastboot.EnableFastbootMode = mock.Mock()
    204     self.fastboot.EnableFastbootMode.side_effect = NotImplementedError
    205     with self.assertRaises(NotImplementedError):
    206       with self.fastboot.FastbootMode():
    207         pass
    208 
    209 
    210 class FastbootUtilsVerifyBoard(FastbootUtilsTest):
    211 
    212   def testVerifyBoard_bothValid(self):
    213     mock_file = io.StringIO(u'require board=%s\n' % _BOARD)
    214     with mock.patch('__builtin__.open', return_value=mock_file, create=True):
    215       with mock.patch('os.listdir', return_value=_VALID_FILES):
    216         self.assertTrue(self.fastboot._VerifyBoard('test'))
    217 
    218   def testVerifyBoard_BothNotValid(self):
    219     mock_file = io.StringIO(u'abc')
    220     with mock.patch('__builtin__.open', return_value=mock_file, create=True):
    221       with mock.patch('os.listdir', return_value=_INVALID_FILES):
    222         self.assertFalse(self.assertFalse(self.fastboot._VerifyBoard('test')))
    223 
    224   def testVerifyBoard_FileNotFoundZipValid(self):
    225     with mock.patch('os.listdir', return_value=[_BOARD + '.zip']):
    226       self.assertTrue(self.fastboot._VerifyBoard('test'))
    227 
    228   def testVerifyBoard_ZipNotFoundFileValid(self):
    229     mock_file = io.StringIO(u'require board=%s\n' % _BOARD)
    230     with mock.patch('__builtin__.open', return_value=mock_file, create=True):
    231       with mock.patch('os.listdir', return_value=['android-info.txt']):
    232         self.assertTrue(self.fastboot._VerifyBoard('test'))
    233 
    234   def testVerifyBoard_zipNotValidFileIs(self):
    235     mock_file = io.StringIO(u'require board=%s\n' % _BOARD)
    236     with mock.patch('__builtin__.open', return_value=mock_file, create=True):
    237       with mock.patch('os.listdir', return_value=_INVALID_FILES):
    238         self.assertTrue(self.fastboot._VerifyBoard('test'))
    239 
    240   def testVerifyBoard_fileNotValidZipIs(self):
    241     mock_file = io.StringIO(u'require board=WrongBoard')
    242     with mock.patch('__builtin__.open', return_value=mock_file, create=True):
    243       with mock.patch('os.listdir', return_value=_VALID_FILES):
    244         self.assertFalse(self.fastboot._VerifyBoard('test'))
    245 
    246   def testVerifyBoard_noBoardInFileValidZip(self):
    247     mock_file = io.StringIO(u'Regex wont match')
    248     with mock.patch('__builtin__.open', return_value=mock_file, create=True):
    249       with mock.patch('os.listdir', return_value=_VALID_FILES):
    250         self.assertTrue(self.fastboot._VerifyBoard('test'))
    251 
    252   def testVerifyBoard_noBoardInFileInvalidZip(self):
    253     mock_file = io.StringIO(u'Regex wont match')
    254     with mock.patch('__builtin__.open', return_value=mock_file, create=True):
    255       with mock.patch('os.listdir', return_value=_INVALID_FILES):
    256         self.assertFalse(self.fastboot._VerifyBoard('test'))
    257 
    258 
    259 class FastbootUtilsFindAndVerifyPartitionsAndImages(FastbootUtilsTest):
    260 
    261   def testFindAndVerifyPartitionsAndImages_validNoVendor(self):
    262     PARTITIONS = [
    263         'bootloader', 'radio', 'boot', 'recovery', 'system', 'userdata',
    264         'cache', 'vendor'
    265     ]
    266     files = [
    267         'bootloader-test-.img',
    268         'radio123.img',
    269         'boot.img',
    270         'recovery.img',
    271         'system.img',
    272         'userdata.img',
    273         'cache.img'
    274     ]
    275     img_check = collections.OrderedDict([
    276       ('bootloader', 'test/bootloader-test-.img'),
    277       ('radio', 'test/radio123.img'),
    278       ('boot', 'test/boot.img'),
    279       ('recovery', 'test/recovery.img'),
    280       ('system', 'test/system.img'),
    281       ('userdata', 'test/userdata.img'),
    282       ('cache', 'test/cache.img'),
    283     ])
    284     parts_check = [
    285         'bootloader', 'radio', 'boot', 'recovery', 'system', 'userdata',
    286         'cache'
    287     ]
    288     with mock.patch('os.listdir', return_value=files):
    289       imgs = fastboot_utils._FindAndVerifyPartitionsAndImages(
    290           PARTITIONS, 'test')
    291       parts = imgs.keys()
    292       self.assertDictEqual(imgs, img_check)
    293       self.assertListEqual(parts, parts_check)
    294 
    295   def testFindAndVerifyPartitionsAndImages_validVendor(self):
    296     PARTITIONS = [
    297         'bootloader', 'radio', 'boot', 'recovery', 'system', 'userdata',
    298         'cache', 'vendor'
    299     ]
    300     files = [
    301         'bootloader-test-.img',
    302         'radio123.img',
    303         'boot.img',
    304         'recovery.img',
    305         'system.img',
    306         'userdata.img',
    307         'cache.img',
    308         'vendor.img'
    309     ]
    310     img_check = {
    311       'bootloader': 'test/bootloader-test-.img',
    312       'radio': 'test/radio123.img',
    313       'boot': 'test/boot.img',
    314       'recovery': 'test/recovery.img',
    315       'system': 'test/system.img',
    316       'userdata': 'test/userdata.img',
    317       'cache': 'test/cache.img',
    318       'vendor': 'test/vendor.img',
    319     }
    320     parts_check = [
    321         'bootloader', 'radio', 'boot', 'recovery', 'system', 'userdata',
    322         'cache', 'vendor'
    323     ]
    324 
    325     with mock.patch('os.listdir', return_value=files):
    326       imgs = fastboot_utils._FindAndVerifyPartitionsAndImages(
    327           PARTITIONS, 'test')
    328       parts = imgs.keys()
    329       self.assertDictEqual(imgs, img_check)
    330       self.assertListEqual(parts, parts_check)
    331 
    332   def testFindAndVerifyPartitionsAndImages_badPartition(self):
    333     with mock.patch('os.listdir', return_value=['test']):
    334       with self.assertRaises(KeyError):
    335         fastboot_utils._FindAndVerifyPartitionsAndImages(['test'], 'test')
    336 
    337   def testFindAndVerifyPartitionsAndImages_noFile(self):
    338     with mock.patch('os.listdir', return_value=['test']):
    339       with self.assertRaises(device_errors.FastbootCommandFailedError):
    340         fastboot_utils._FindAndVerifyPartitionsAndImages(['cache'], 'test')
    341 
    342 
    343 class FastbootUtilsFlashDevice(FastbootUtilsTest):
    344 
    345   def testFlashDevice_wipe(self):
    346     with self.assertCalls(
    347         self.call.fastboot.EnableFastbootMode(),
    348         self.call.fastboot.fastboot.SetOemOffModeCharge(False),
    349         self.call.fastboot._FlashPartitions(mock.ANY, 'test', wipe=True),
    350         self.call.fastboot.fastboot.SetOemOffModeCharge(True),
    351         self.call.fastboot.Reboot(wait_for_reboot=False)):
    352       self.fastboot.FlashDevice('test', wipe=True)
    353 
    354   def testFlashDevice_noWipe(self):
    355     with self.assertCalls(
    356         self.call.fastboot.EnableFastbootMode(),
    357         self.call.fastboot.fastboot.SetOemOffModeCharge(False),
    358         self.call.fastboot._FlashPartitions(mock.ANY, 'test', wipe=False),
    359         self.call.fastboot.fastboot.SetOemOffModeCharge(True),
    360         self.call.fastboot.Reboot(wait_for_reboot=True)):
    361       self.fastboot.FlashDevice('test', wipe=False)
    362 
    363   def testFlashDevice_partitions(self):
    364     with self.assertCalls(
    365         self.call.fastboot.EnableFastbootMode(),
    366         self.call.fastboot.fastboot.SetOemOffModeCharge(False),
    367         self.call.fastboot._FlashPartitions(['boot'], 'test', wipe=False),
    368         self.call.fastboot.fastboot.SetOemOffModeCharge(True),
    369         self.call.fastboot.Reboot(wait_for_reboot=True)):
    370       self.fastboot.FlashDevice('test', partitions=['boot'], wipe=False)
    371 
    372 
    373 if __name__ == '__main__':
    374   logging.getLogger().setLevel(logging.DEBUG)
    375   unittest.main(verbosity=2)
    376