blob: 4d464197d806c7a7d26069968e9c7d6d7e4d85aa [file] [log] [blame]
David Pursellf1d16a62015-03-25 13:31:04 -07001# Copyright 2015 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Unit tests for the flash module."""
6
7from __future__ import print_function
8
9import mock
10import os
11
12from chromite.cli import flash
13from chromite.lib import brick_lib
14from chromite.lib import commandline
15from chromite.lib import cros_build_lib
16from chromite.lib import cros_test_lib
17from chromite.lib import dev_server_wrapper
18from chromite.lib import partial_mock
19from chromite.lib import remote_access
20
21
22class RemoteDeviceUpdaterMock(partial_mock.PartialCmdMock):
23 """Mock out RemoteDeviceUpdater."""
24 TARGET = 'chromite.cli.flash.RemoteDeviceUpdater'
25 ATTRS = ('UpdateStateful', 'UpdateRootfs', 'SetupRootfsUpdate', 'Verify')
26
27 def __init__(self):
28 partial_mock.PartialCmdMock.__init__(self)
29
30 def UpdateStateful(self, _inst, *_args, **_kwargs):
31 """Mock out UpdateStateful."""
32
33 def UpdateRootfs(self, _inst, *_args, **_kwargs):
34 """Mock out UpdateRootfs."""
35
36 def SetupRootfsUpdate(self, _inst, *_args, **_kwargs):
37 """Mock out SetupRootfsUpdate."""
38
39 def Verify(self, _inst, *_args, **_kwargs):
40 """Mock out SetupRootfsUpdate."""
41
42
David Pursellf1d16a62015-03-25 13:31:04 -070043class RemoteDeviceUpdaterTest(cros_test_lib.MockTempDirTestCase):
44 """Test the flow of flash.Flash() with RemoteDeviceUpdater."""
45
46 IMAGE = '/path/to/image'
47 DEVICE = commandline.Device(scheme=commandline.DEVICE_SCHEME_SSH,
48 hostname='1.1.1.1')
49
50 def setUp(self):
51 """Patches objects."""
52 self.updater_mock = self.StartPatcher(RemoteDeviceUpdaterMock())
53 self.PatchObject(dev_server_wrapper, 'GenerateXbuddyRequest',
54 return_value='xbuddy/local/latest')
55 self.PatchObject(dev_server_wrapper, 'DevServerWrapper')
56 self.PatchObject(dev_server_wrapper, 'GetImagePathWithXbuddy',
Gilad Arnolde62ec902015-04-24 14:41:02 -070057 return_value=('taco-paladin/R36/chromiumos_test_image.bin',
58 'remote/taco-paladin/R36/test'))
David Pursellf1d16a62015-03-25 13:31:04 -070059 self.PatchObject(dev_server_wrapper, 'GetUpdatePayloads')
60 self.PatchObject(remote_access, 'CHECK_INTERVAL', new=0)
61 self.PatchObject(remote_access, 'ChromiumOSDevice')
62
63 def testUpdateAll(self):
64 """Tests that update methods are called correctly."""
David Pursellf1d16a62015-03-25 13:31:04 -070065 with mock.patch('os.path.exists', return_value=True):
Bertrand SIMONNETb34a98b2015-04-22 14:30:04 -070066 flash.Flash(self.DEVICE, self.IMAGE)
67 self.assertTrue(self.updater_mock.patched['UpdateStateful'].called)
68 self.assertTrue(self.updater_mock.patched['UpdateRootfs'].called)
David Pursellf1d16a62015-03-25 13:31:04 -070069
70 def testUpdateStateful(self):
71 """Tests that update methods are called correctly."""
David Pursellf1d16a62015-03-25 13:31:04 -070072 with mock.patch('os.path.exists', return_value=True):
Bertrand SIMONNETb34a98b2015-04-22 14:30:04 -070073 flash.Flash(self.DEVICE, self.IMAGE, rootfs_update=False)
74 self.assertTrue(self.updater_mock.patched['UpdateStateful'].called)
75 self.assertFalse(self.updater_mock.patched['UpdateRootfs'].called)
David Pursellf1d16a62015-03-25 13:31:04 -070076
77 def testUpdateRootfs(self):
78 """Tests that update methods are called correctly."""
David Pursellf1d16a62015-03-25 13:31:04 -070079 with mock.patch('os.path.exists', return_value=True):
Bertrand SIMONNETb34a98b2015-04-22 14:30:04 -070080 flash.Flash(self.DEVICE, self.IMAGE, stateful_update=False)
81 self.assertFalse(self.updater_mock.patched['UpdateStateful'].called)
82 self.assertTrue(self.updater_mock.patched['UpdateRootfs'].called)
David Pursellf1d16a62015-03-25 13:31:04 -070083
84 def testMissingPayloads(self):
85 """Tests we raise FlashError when payloads are missing."""
86 with mock.patch('os.path.exists', return_value=False):
87 self.assertRaises(flash.FlashError, flash.Flash, self.DEVICE, self.IMAGE)
88
89 def testProjectSdk(self):
90 """Tests that Project SDK flashing invoked as expected."""
David Pursellf1d16a62015-03-25 13:31:04 -070091 with mock.patch('os.path.exists', return_value=True):
Bertrand SIMONNETb34a98b2015-04-22 14:30:04 -070092 with mock.patch('chromite.lib.project_sdk.FindVersion',
93 return_value='1.2.3'):
94 flash.Flash(self.DEVICE, self.IMAGE, project_sdk_image=True)
95 dev_server_wrapper.GetImagePathWithXbuddy.assert_called_with(
96 'project_sdk', mock.ANY, version='1.2.3', static_dir=mock.ANY,
97 lookup_only=True)
98 self.assertTrue(self.updater_mock.patched['UpdateStateful'].called)
99 self.assertTrue(self.updater_mock.patched['UpdateRootfs'].called)
David Pursellf1d16a62015-03-25 13:31:04 -0700100
101
102class USBImagerMock(partial_mock.PartialCmdMock):
103 """Mock out USBImager."""
104 TARGET = 'chromite.cli.flash.USBImager'
105 ATTRS = ('CopyImageToDevice', 'InstallImageToDevice',
106 'ChooseRemovableDevice', 'ListAllRemovableDevices',
107 'GetRemovableDeviceDescription', 'IsFilePathGPTDiskImage')
108 VALID_IMAGE = True
109
110 def __init__(self):
111 partial_mock.PartialCmdMock.__init__(self)
112
113 def CopyImageToDevice(self, _inst, *_args, **_kwargs):
114 """Mock out CopyImageToDevice."""
115
116 def InstallImageToDevice(self, _inst, *_args, **_kwargs):
117 """Mock out InstallImageToDevice."""
118
119 def ChooseRemovableDevice(self, _inst, *_args, **_kwargs):
120 """Mock out ChooseRemovableDevice."""
121
122 def ListAllRemovableDevices(self, _inst, *_args, **_kwargs):
123 """Mock out ListAllRemovableDevices."""
124 return ['foo', 'taco', 'milk']
125
126 def GetRemovableDeviceDescription(self, _inst, *_args, **_kwargs):
127 """Mock out GetRemovableDeviceDescription."""
128
129 def IsFilePathGPTDiskImage(self, _inst, *_args, **_kwargs):
130 """Mock out IsFilePathGPTDiskImage."""
131 return self.VALID_IMAGE
132
133
134class USBImagerTest(cros_test_lib.MockTempDirTestCase):
135 """Test the flow of flash.Flash() with USBImager."""
136 IMAGE = '/path/to/image'
137
138 def Device(self, path):
139 """Create a USB device for passing to flash.Flash()."""
140 return commandline.Device(scheme=commandline.DEVICE_SCHEME_USB,
141 path=path)
142
143 def setUp(self):
144 """Patches objects."""
145 self.usb_mock = USBImagerMock()
146 self.imager_mock = self.StartPatcher(self.usb_mock)
147 self.PatchObject(dev_server_wrapper, 'GenerateXbuddyRequest',
148 return_value='xbuddy/local/latest')
149 self.PatchObject(dev_server_wrapper, 'DevServerWrapper')
150 self.PatchObject(dev_server_wrapper, 'GetImagePathWithXbuddy',
Gilad Arnolde62ec902015-04-24 14:41:02 -0700151 return_value=('taco-paladin/R36/chromiumos_test_image.bin',
152 'remote/taco-paladin/R36/test'))
David Pursellf1d16a62015-03-25 13:31:04 -0700153 self.PatchObject(os.path, 'exists', return_value=True)
154 self.PatchObject(brick_lib, 'FindBrickInPath', return_value=None)
155
156 def testLocalImagePathCopy(self):
157 """Tests that imaging methods are called correctly."""
158 with mock.patch('os.path.isfile', return_value=True):
159 flash.Flash(self.Device('/dev/foo'), self.IMAGE)
160 self.assertTrue(self.imager_mock.patched['CopyImageToDevice'].called)
161
162 def testLocalImagePathInstall(self):
163 """Tests that imaging methods are called correctly."""
164 with mock.patch('os.path.isfile', return_value=True):
165 flash.Flash(self.Device('/dev/foo'), self.IMAGE, board='taco',
166 install=True)
167 self.assertTrue(self.imager_mock.patched['InstallImageToDevice'].called)
168
169 def testLocalBadImagePath(self):
170 """Tests that using an image not having the magic bytes has prompt."""
171 self.usb_mock.VALID_IMAGE = False
172 with mock.patch('os.path.isfile', return_value=True):
173 with mock.patch.object(cros_build_lib, 'BooleanPrompt') as mock_prompt:
174 mock_prompt.return_value = False
175 flash.Flash(self.Device('/dev/foo'), self.IMAGE)
176 self.assertTrue(mock_prompt.called)
177
178 def testNonLocalImagePath(self):
179 """Tests that we try to get the image path using xbuddy."""
180 with mock.patch.object(
181 dev_server_wrapper,
182 'GetImagePathWithXbuddy',
Gilad Arnolde62ec902015-04-24 14:41:02 -0700183 return_value=('translated/xbuddy/path',
184 'resolved/xbuddy/path')) as mock_xbuddy:
David Pursellf1d16a62015-03-25 13:31:04 -0700185 with mock.patch('os.path.isfile', return_value=False):
186 with mock.patch('os.path.isdir', return_value=False):
187 flash.Flash(self.Device('/dev/foo'), self.IMAGE)
188 self.assertTrue(mock_xbuddy.called)
189
190 def testConfirmNonRemovableDevice(self):
191 """Tests that we ask user to confirm if the device is not removable."""
192 with mock.patch.object(cros_build_lib, 'BooleanPrompt') as mock_prompt:
193 flash.Flash(self.Device('/dev/dummy'), self.IMAGE)
194 self.assertTrue(mock_prompt.called)
195
196 def testSkipPromptNonRemovableDevice(self):
197 """Tests that we skip the prompt for non-removable with --yes."""
198 with mock.patch.object(cros_build_lib, 'BooleanPrompt') as mock_prompt:
199 flash.Flash(self.Device('/dev/dummy'), self.IMAGE, yes=True)
200 self.assertFalse(mock_prompt.called)
201
202 def testChooseRemovableDevice(self):
203 """Tests that we ask user to choose a device if none is given."""
204 flash.Flash(self.Device(''), self.IMAGE)
205 self.assertTrue(self.imager_mock.patched['ChooseRemovableDevice'].called)