blob: ae3ed85206f084574618a934617ba15879b0afda [file] [log] [blame]
#!/usr/bin/python
# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""This module tests the cros flash command."""
from __future__ import print_function
import mock
import os
import sys
sys.path.insert(0, os.path.abspath('%s/../../..' % os.path.dirname(__file__)))
from chromite.cros.commands import cros_flash
from chromite.cros.commands import init_unittest
from chromite.lib import cros_build_lib
from chromite.lib import cros_test_lib
from chromite.lib import dev_server_wrapper
from chromite.lib import partial_mock
from chromite.lib import remote_access
# pylint: disable=W0212
class TestXbuddyHelpers(cros_test_lib.MockTempDirTestCase):
"""Test xbuddy helper functions."""
def testGenerateXbuddyRequestForUpdate(self):
"""Test we generate correct xbuddy requests."""
# Use the latest build when 'latest' is given.
req = 'xbuddy/latest?for_update=true&return_dir=true'
self.assertEqual(
cros_flash.GenerateXbuddyRequest('latest', 'update'), req)
# Convert the path starting with 'xbuddy://' to 'xbuddy/'
path = 'xbuddy://remote/stumpy/version'
req = 'xbuddy/remote/stumpy/version?for_update=true&return_dir=true'
self.assertEqual(cros_flash.GenerateXbuddyRequest(path, 'update'), req)
def testGenerateXbuddyRequestForImage(self):
"""Tests that we generate correct requests to get images."""
image_path = 'foo/bar/taco'
self.assertEqual(cros_flash.GenerateXbuddyRequest(image_path, 'image'),
'xbuddy/foo/bar/taco?return_dir=true')
image_path = 'xbuddy://foo/bar/taco'
self.assertEqual(cros_flash.GenerateXbuddyRequest(image_path, 'image'),
'xbuddy/foo/bar/taco?return_dir=true')
def testGenerateXbuddyRequestForTranslate(self):
"""Tests that we generate correct requests for translation."""
image_path = 'foo/bar/taco'
self.assertEqual(cros_flash.GenerateXbuddyRequest(image_path, 'translate'),
'xbuddy_translate/foo/bar/taco')
image_path = 'xbuddy://foo/bar/taco'
self.assertEqual(cros_flash.GenerateXbuddyRequest(image_path, 'translate'),
'xbuddy_translate/foo/bar/taco')
def testConvertTranslatedPath(self):
"""Tests that we convert a translated path to a usable xbuddy path."""
path = 'remote/latest-canary'
translated_path = 'taco-release/R36-5761.0.0/chromiumos_test_image.bin'
self.assertEqual(cros_flash.ConvertTranslatedPath(path, translated_path),
'remote/taco-release/R36-5761.0.0/test')
path = 'latest'
translated_path = 'taco/R36-5600.0.0/chromiumos_image.bin'
self.assertEqual(cros_flash.ConvertTranslatedPath(path, translated_path),
'local/taco/R36-5600.0.0/dev')
@mock.patch('chromite.lib.cros_build_lib.IsInsideChroot', return_value=True)
def testTranslatedPathToLocalPath(self, _mock1):
"""Tests that we convert a translated path to a local path correctly."""
translated_path = 'peppy-release/R33-5116.87.0/chromiumos_image.bin'
base_path = os.path.join(self.tempdir, 'peppy-release/R33-5116.87.0')
local_path = os.path.join(base_path, 'chromiumos_image.bin')
self.assertEqual(
cros_flash.TranslatedPathToLocalPath(translated_path, self.tempdir),
local_path)
class MockFlashCommand(init_unittest.MockCommand):
"""Mock out the flash command."""
TARGET = 'chromite.cros.commands.cros_flash.FlashCommand'
TARGET_CLASS = cros_flash.FlashCommand
COMMAND = 'flash'
def __init__(self, *args, **kwargs):
init_unittest.MockCommand.__init__(self, *args, **kwargs)
def Run(self, inst):
init_unittest.MockCommand.Run(self, inst)
class RemoteDeviceUpdaterMock(partial_mock.PartialCmdMock):
"""Mock out RemoteDeviceUpdater."""
TARGET = 'chromite.cros.commands.cros_flash.RemoteDeviceUpdater'
ATTRS = ('UpdateStateful', 'UpdateRootfs', 'GetUpdatePayloads',
'SetupRootfsUpdate', 'Verify')
def __init__(self):
partial_mock.PartialCmdMock.__init__(self)
def GetUpdatePayloads(self, _inst, *_args, **_kwargs):
"""Mock out GetUpdatePayloads."""
def UpdateStateful(self, _inst, *_args, **_kwargs):
"""Mock out UpdateStateful."""
def UpdateRootfs(self, _inst, *_args, **_kwargs):
"""Mock out UpdateRootfs."""
def SetupRootfsUpdate(self, _inst, *_args, **_kwargs):
"""Mock out SetupRootfsUpdate."""
def Verify(self, _inst, *_args, **_kwargs):
"""Mock out SetupRootfsUpdate."""
class UpdateRunThroughTest(cros_test_lib.MockTempDirTestCase,
cros_test_lib.LoggingTestCase):
"""Test the flow of FlashCommand.run with the update methods mocked out."""
IMAGE = '/path/to/image'
DEVICE = '1.1.1.1'
def SetupCommandMock(self, cmd_args):
"""Setup comand mock."""
self.cmd_mock = MockFlashCommand(
cmd_args, base_args=['--cache-dir', self.tempdir])
self.StartPatcher(self.cmd_mock)
def setUp(self):
"""Patches objects."""
self.cmd_mock = None
self.updater_mock = self.StartPatcher(RemoteDeviceUpdaterMock())
self.PatchObject(cros_flash, 'GenerateXbuddyRequest',
return_value='xbuddy/local/latest')
self.PatchObject(dev_server_wrapper, 'DevServerWrapper')
self.PatchObject(cros_flash, 'GetImagePathWithXbuddy',
return_value='taco-paladin/R36/chromiumos_test_image.bin')
self.PatchObject(remote_access, 'CHECK_INTERVAL', new=0)
self.PatchObject(remote_access, 'ChromiumOSDevice')
def testUpdateAll(self):
"""Tests that update methods are called correctly."""
self.SetupCommandMock([self.DEVICE, self.IMAGE])
with mock.patch('os.path.exists', return_value=True):
self.cmd_mock.inst.Run()
self.assertTrue(self.updater_mock.patched['UpdateStateful'].called)
self.assertTrue(self.updater_mock.patched['UpdateRootfs'].called)
def testUpdateStateful(self):
"""Tests that update methods are called correctly."""
self.SetupCommandMock(['--no-rootfs-update', self.DEVICE, self.IMAGE])
with mock.patch('os.path.exists', return_value=True):
self.cmd_mock.inst.Run()
self.assertTrue(self.updater_mock.patched['UpdateStateful'].called)
self.assertFalse(self.updater_mock.patched['UpdateRootfs'].called)
def testUpdateRootfs(self):
"""Tests that update methods are called correctly."""
self.SetupCommandMock(['--no-stateful-update', self.DEVICE, self.IMAGE])
with mock.patch('os.path.exists', return_value=True):
self.cmd_mock.inst.Run()
self.assertFalse(self.updater_mock.patched['UpdateStateful'].called)
self.assertTrue(self.updater_mock.patched['UpdateRootfs'].called)
def testMissingPayloads(self):
"""Tests we exit when payloads are missing."""
self.SetupCommandMock([self.DEVICE, self.IMAGE])
with mock.patch('os.path.exists', return_value=False):
self.assertRaises(cros_build_lib.DieSystemExit, self.cmd_mock.inst.Run)
class USBImagerMock(partial_mock.PartialCmdMock):
"""Mock out USBImager."""
TARGET = 'chromite.cros.commands.cros_flash.USBImager'
ATTRS = ('CopyImageToDevice', 'InstallImageToDevice',
'ChooseRemovableDevice', 'ListAllRemovableDevices',
'GetRemovableDeviceDescription', 'IsFilePathGPTDiskImage')
VALID_IMAGE = True
def __init__(self):
partial_mock.PartialCmdMock.__init__(self)
def CopyImageToDevice(self, _inst, *_args, **_kwargs):
"""Mock out CopyImageToDevice."""
def InstallImageToDevice(self, _inst, *_args, **_kwargs):
"""Mock out InstallImageToDevice."""
def ChooseRemovableDevice(self, _inst, *_args, **_kwargs):
"""Mock out ChooseRemovableDevice."""
def ListAllRemovableDevices(self, _inst, *_args, **_kwargs):
"""Mock out ListAllRemovableDevices."""
return ['foo', 'taco', 'milk']
def GetRemovableDeviceDescription(self, _inst, *_args, **_kwargs):
"""Mock out GetRemovableDeviceDescription."""
def IsFilePathGPTDiskImage(self, _inst, *_args, **_kwargs):
"""Mock out IsFilePathGPTDiskImage."""
return self.VALID_IMAGE
class ImagingRunThroughTest(cros_test_lib.MockTempDirTestCase,
cros_test_lib.LoggingTestCase):
"""Test the flow of FlashCommand.run with the imaging methods mocked out."""
IMAGE = '/path/to/image'
def SetupCommandMock(self, cmd_args):
"""Setup comand mock."""
self.cmd_mock = MockFlashCommand(
cmd_args, base_args=['--cache-dir', self.tempdir])
self.StartPatcher(self.cmd_mock)
def setUp(self):
"""Patches objects."""
self.cmd_mock = None
self.usb_mock = USBImagerMock()
self.imager_mock = self.StartPatcher(self.usb_mock)
self.PatchObject(cros_flash, 'GenerateXbuddyRequest',
return_value='xbuddy/local/latest')
self.PatchObject(dev_server_wrapper, 'DevServerWrapper')
self.PatchObject(cros_flash, 'GetImagePathWithXbuddy',
return_value='taco-paladin/R36/chromiumos_test_image.bin')
self.PatchObject(os.path, 'exists', return_value=True)
def testLocalImagePathCopy(self):
"""Tests that imaging methods are called correctly."""
self.SetupCommandMock(['usb:///dev/foo', self.IMAGE])
with mock.patch('os.path.isfile', return_value=True):
self.cmd_mock.inst.Run()
self.assertTrue(self.imager_mock.patched['CopyImageToDevice'].called)
def testLocalImagePathInstall(self):
"""Tests that imaging methods are called correctly."""
self.SetupCommandMock(['--board=taco', '--install', 'usb:///dev/foo',
self.IMAGE])
with mock.patch('os.path.isfile', return_value=True):
self.cmd_mock.inst.Run()
self.assertTrue(self.imager_mock.patched['InstallImageToDevice'].called)
def testLocalBadImagePath(self):
"""Tests that using an image not having the magic bytes has prompt."""
self.usb_mock.VALID_IMAGE = False
self.SetupCommandMock(['usb:///dev/foo', self.IMAGE])
with mock.patch('os.path.isfile', return_value=True):
with mock.patch.object(cros_build_lib, 'BooleanPrompt') as mock_prompt:
mock_prompt.return_value = False
self.cmd_mock.inst.Run()
self.assertTrue(mock_prompt.called)
def testNonLocalImagePath(self):
"""Tests that we try to get the image path using xbuddy."""
self.SetupCommandMock(['usb:///dev/foo', self.IMAGE])
with mock.patch.object(cros_flash, 'GetImagePathWithXbuddy') as mock_xbuddy:
with mock.patch('os.path.isfile', return_value=False):
with mock.patch('os.path.isdir', return_value=False):
self.cmd_mock.inst.Run()
self.assertTrue(mock_xbuddy.called)
def testConfirmNonRemovableDevice(self):
"""Tests that we ask user to confirm if the device is not removable."""
with mock.patch.object(cros_build_lib, 'BooleanPrompt') as mock_prompt:
self.SetupCommandMock(['usb:///dev/dummy', self.IMAGE])
self.cmd_mock.inst.Run()
self.assertTrue(mock_prompt.called)
def testSkipPromptNonRemovableDevice(self):
"""Tests that we skip the prompt for non-removable with --yes."""
with mock.patch.object(cros_build_lib, 'BooleanPrompt') as mock_prompt:
self.SetupCommandMock(['--yes', 'usb:///dev/dummy', self.IMAGE])
self.cmd_mock.inst.Run()
self.assertFalse(mock_prompt.called)
def testChooseRemovableDevice(self):
"""Tests that we ask user to choose a device if none is given."""
self.SetupCommandMock(['usb://', self.IMAGE])
self.cmd_mock.inst.Run()
self.assertTrue(self.imager_mock.patched['ChooseRemovableDevice'].called)
if __name__ == '__main__':
cros_test_lib.main()