blob: d390fe3281729bf8816b99c6f75bbdb05f8b5ae8 [file] [log] [blame]
Mike Frysingere58c0e22017-10-04 15:43:30 -04001# -*- coding: utf-8 -*-
Ryan Cuiafd6c5c2012-07-30 17:48:22 -07002# Copyright (c) 2012 The Chromium OS 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
Steve Funge984a532013-11-25 17:09:25 -08006"""Unit tests for the deploy_chrome script."""
Ryan Cuiafd6c5c2012-07-30 17:48:22 -07007
Mike Frysinger383367e2014-09-16 15:06:17 -04008from __future__ import print_function
9
Anushruth8d797672019-10-17 12:22:31 -070010import errno
Ryan Cuiafd6c5c2012-07-30 17:48:22 -070011import os
Mike Frysinger6165cdc2020-02-21 02:38:07 -050012import sys
David James88e6f032013-03-02 08:13:20 -080013import time
Ryan Cuiafd6c5c2012-07-30 17:48:22 -070014
Mike Frysinger6db648e2018-07-24 19:57:58 -040015import mock
16
David Pursellcfd58872015-03-19 09:15:48 -070017from chromite.cli.cros import cros_chrome_sdk_unittest
Ryan Cuief91e702013-02-04 12:06:36 -080018from chromite.lib import chrome_util
Ryan Cuiafd6c5c2012-07-30 17:48:22 -070019from chromite.lib import cros_build_lib
20from chromite.lib import cros_test_lib
Ryan Cui686ec052013-02-12 16:39:41 -080021from chromite.lib import osutils
Erik Chen75a2f492020-08-06 19:15:11 -070022from chromite.lib import parallel_unittest
Ryan Cuiafd6c5c2012-07-30 17:48:22 -070023from chromite.lib import partial_mock
Robert Flack1dc7ea82014-11-26 13:50:24 -050024from chromite.lib import remote_access
Ryan Cuiafd6c5c2012-07-30 17:48:22 -070025from chromite.lib import remote_access_unittest
26from chromite.scripts import deploy_chrome
27
Ryan Cuief91e702013-02-04 12:06:36 -080028
Mike Frysinger6165cdc2020-02-21 02:38:07 -050029assert sys.version_info >= (3, 6), 'This module requires Python 3.6+'
30
31
Mike Frysinger27e21b72018-07-12 14:20:21 -040032# pylint: disable=protected-access
33
Ryan Cuiafd6c5c2012-07-30 17:48:22 -070034
35_REGULAR_TO = ('--to', 'monkey')
Avery Musbach3edff0e2020-03-27 13:35:53 -070036_TARGET_BOARD = 'eve'
Ryan Cuiafd6c5c2012-07-30 17:48:22 -070037_GS_PATH = 'gs://foon'
38
39
40def _ParseCommandLine(argv):
41 return deploy_chrome._ParseCommandLine(['--log-level', 'debug'] + argv)
42
43
44class InterfaceTest(cros_test_lib.OutputTestCase):
45 """Tests the commandline interface of the script."""
46
47 def testGsLocalPathUnSpecified(self):
48 """Test no chrome path specified."""
49 with self.OutputCapturer():
Avery Musbach3edff0e2020-03-27 13:35:53 -070050 self.assertRaises2(SystemExit, _ParseCommandLine,
51 list(_REGULAR_TO) + ['--board', _TARGET_BOARD],
Ryan Cuiafd6c5c2012-07-30 17:48:22 -070052 check_attrs={'code': 2})
53
54 def testGsPathSpecified(self):
55 """Test case of GS path specified."""
Avery Musbach3edff0e2020-03-27 13:35:53 -070056 argv = list(_REGULAR_TO) + ['--board', _TARGET_BOARD, '--gs-path', _GS_PATH]
Ryan Cuiafd6c5c2012-07-30 17:48:22 -070057 _ParseCommandLine(argv)
58
59 def testLocalPathSpecified(self):
60 """Test case of local path specified."""
Avery Musbach3edff0e2020-03-27 13:35:53 -070061 argv = list(_REGULAR_TO) + ['--board', _TARGET_BOARD, '--local-pkg-path',
62 '/path/to/chrome']
Ryan Cuiafd6c5c2012-07-30 17:48:22 -070063 _ParseCommandLine(argv)
64
65 def testNoTarget(self):
66 """Test no target specified."""
Avery Musbach3edff0e2020-03-27 13:35:53 -070067 argv = ['--board', _TARGET_BOARD, '--gs-path', _GS_PATH]
Ryan Cuief91e702013-02-04 12:06:36 -080068 self.assertParseError(argv)
69
Ben Pastene3bd3e5e2020-08-10 14:40:43 -070070 def testToAndDevice(self):
71 """Test no target specified."""
72 argv = ['--board', _TARGET_BOARD, '--build-dir', '/path/to/nowhere',
73 '--to', 'localhost', '--device', 'localhost']
74 self.assertParseError(argv)
75
Erik Chen75a2f492020-08-06 19:15:11 -070076 def testLacros(self):
77 """Test basic lacros invocation."""
78 argv = ['--lacros', '--nostrip', '--build-dir', '/path/to/nowhere',
79 '--to', 'localhost']
80 options = _ParseCommandLine(argv)
81 self.assertTrue(options.lacros)
82 self.assertEqual(options.target_dir, deploy_chrome.LACROS_DIR)
83
84 def testLacrosRequiresNostrip(self):
85 """Lacros requires --nostrip"""
86 argv = ['--lacros', '--build-dir', '/path/to/nowhere', '--to', 'localhost']
87 self.assertRaises2(SystemExit, _ParseCommandLine, argv,
88 check_attrs={'code': 2})
89
Ryan Cuief91e702013-02-04 12:06:36 -080090 def assertParseError(self, argv):
Ryan Cuiafd6c5c2012-07-30 17:48:22 -070091 with self.OutputCapturer():
92 self.assertRaises2(SystemExit, _ParseCommandLine, argv,
93 check_attrs={'code': 2})
94
Thiago Goncales12793312013-05-23 11:26:17 -070095 def testMountOptionSetsTargetDir(self):
Avery Musbach3edff0e2020-03-27 13:35:53 -070096 argv = list(_REGULAR_TO) + ['--board', _TARGET_BOARD, '--gs-path', _GS_PATH,
97 '--mount']
Mike Frysingerc3061a62015-06-04 04:16:18 -040098 options = _ParseCommandLine(argv)
Thiago Goncales12793312013-05-23 11:26:17 -070099 self.assertIsNot(options.target_dir, None)
100
101 def testMountOptionSetsMountDir(self):
Avery Musbach3edff0e2020-03-27 13:35:53 -0700102 argv = list(_REGULAR_TO) + ['--board', _TARGET_BOARD, '--gs-path', _GS_PATH,
103 '--mount']
Mike Frysingerc3061a62015-06-04 04:16:18 -0400104 options = _ParseCommandLine(argv)
Thiago Goncales12793312013-05-23 11:26:17 -0700105 self.assertIsNot(options.mount_dir, None)
106
107 def testMountOptionDoesNotOverrideTargetDir(self):
Avery Musbach3edff0e2020-03-27 13:35:53 -0700108 argv = list(_REGULAR_TO) + ['--board', _TARGET_BOARD, '--gs-path', _GS_PATH,
109 '--mount', '--target-dir', '/foo/bar/cow']
Mike Frysingerc3061a62015-06-04 04:16:18 -0400110 options = _ParseCommandLine(argv)
Thiago Goncales12793312013-05-23 11:26:17 -0700111 self.assertEqual(options.target_dir, '/foo/bar/cow')
112
113 def testMountOptionDoesNotOverrideMountDir(self):
Avery Musbach3edff0e2020-03-27 13:35:53 -0700114 argv = list(_REGULAR_TO) + ['--board', _TARGET_BOARD, '--gs-path', _GS_PATH,
115 '--mount', '--mount-dir', '/foo/bar/cow']
Mike Frysingerc3061a62015-06-04 04:16:18 -0400116 options = _ParseCommandLine(argv)
Thiago Goncales12793312013-05-23 11:26:17 -0700117 self.assertEqual(options.mount_dir, '/foo/bar/cow')
118
Adrian Eldera2c548a2017-11-07 19:01:29 -0500119 def testSshIdentityOptionSetsOption(self):
Avery Musbach3edff0e2020-03-27 13:35:53 -0700120 argv = list(_REGULAR_TO) + ['--board', _TARGET_BOARD,
121 '--private-key', '/foo/bar/key',
Bernie Thompson93b9ee62018-02-21 14:56:16 -0800122 '--build-dir', '/path/to/nowhere']
Adrian Eldera2c548a2017-11-07 19:01:29 -0500123 options = _ParseCommandLine(argv)
124 self.assertEqual(options.private_key, '/foo/bar/key')
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700125
126class DeployChromeMock(partial_mock.PartialMock):
Steve Funge984a532013-11-25 17:09:25 -0800127 """Deploy Chrome Mock Class."""
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700128
129 TARGET = 'chromite.scripts.deploy_chrome.DeployChrome'
Erik Chen75a2f492020-08-06 19:15:11 -0700130 ATTRS = ('_KillAshChromeIfNeeded', '_DisableRootfsVerification')
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700131
David James88e6f032013-03-02 08:13:20 -0800132 def __init__(self):
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700133 partial_mock.PartialMock.__init__(self)
Robert Flack1dc7ea82014-11-26 13:50:24 -0500134 self.remote_device_mock = remote_access_unittest.RemoteDeviceMock()
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700135 # Target starts off as having rootfs verification enabled.
Ryan Cuie18f24f2012-12-03 18:39:55 -0800136 self.rsh_mock = remote_access_unittest.RemoteShMock()
David James88e6f032013-03-02 08:13:20 -0800137 self.rsh_mock.SetDefaultCmdResult(0)
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700138 self.MockMountCmd(1)
David Haddock3151d912017-10-24 03:50:32 +0000139 self.rsh_mock.AddCmdResult(
Anushruth8d797672019-10-17 12:22:31 -0700140 deploy_chrome.LSOF_COMMAND_CHROME % (deploy_chrome._CHROME_DIR,), 1)
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700141
142 def MockMountCmd(self, returnvalue):
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700143 self.rsh_mock.AddCmdResult(deploy_chrome.MOUNT_RW_COMMAND,
David James88e6f032013-03-02 08:13:20 -0800144 returnvalue)
145
146 def _DisableRootfsVerification(self, inst):
147 with mock.patch.object(time, 'sleep'):
148 self.backup['_DisableRootfsVerification'](inst)
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700149
Ryan Cui4d6fca92012-12-13 16:41:56 -0800150 def PreStart(self):
Robert Flack1dc7ea82014-11-26 13:50:24 -0500151 self.remote_device_mock.start()
Ryan Cui4d6fca92012-12-13 16:41:56 -0800152 self.rsh_mock.start()
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700153
Ryan Cui4d6fca92012-12-13 16:41:56 -0800154 def PreStop(self):
155 self.rsh_mock.stop()
Robert Flack1dc7ea82014-11-26 13:50:24 -0500156 self.remote_device_mock.stop()
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700157
Erik Chen75a2f492020-08-06 19:15:11 -0700158 def _KillAshChromeIfNeeded(self, _inst):
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700159 # Fully stub out for now.
160 pass
161
162
Ryan Cuief91e702013-02-04 12:06:36 -0800163class DeployTest(cros_test_lib.MockTempDirTestCase):
Steve Funge984a532013-11-25 17:09:25 -0800164 """Setup a deploy object with a GS-path for use in tests."""
165
Ryan Cuief91e702013-02-04 12:06:36 -0800166 def _GetDeployChrome(self, args):
Mike Frysingerc3061a62015-06-04 04:16:18 -0400167 options = _ParseCommandLine(args)
Ryan Cuia56a71e2012-10-18 18:40:35 -0700168 return deploy_chrome.DeployChrome(
169 options, self.tempdir, os.path.join(self.tempdir, 'staging'))
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700170
171 def setUp(self):
Ryan Cuif1416f32013-01-22 18:43:41 -0800172 self.deploy_mock = self.StartPatcher(DeployChromeMock())
Avery Musbach3edff0e2020-03-27 13:35:53 -0700173 self.deploy = self._GetDeployChrome(list(_REGULAR_TO) +
174 ['--board', _TARGET_BOARD, '--gs-path',
175 _GS_PATH, '--force', '--mount'])
Luigi Semenzato1bc79b22016-11-22 16:32:17 -0800176 self.remote_reboot_mock = \
177 self.PatchObject(remote_access.RemoteAccess, 'RemoteReboot',
178 return_value=True)
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700179
Avery Musbach3edff0e2020-03-27 13:35:53 -0700180
181class TestCheckIfBoardMatches(DeployTest):
182 """Testing checking whether the DUT board matches the target board."""
183
184 def testMatchedBoard(self):
185 """Test the case where the DUT board matches the target board."""
186 self.PatchObject(remote_access.ChromiumOSDevice, 'board', _TARGET_BOARD)
187 self.assertTrue(self.deploy.options.force)
188 self.deploy._CheckBoard()
189 self.deploy.options.force = False
190 self.deploy._CheckBoard()
191
192 def testMismatchedBoard(self):
193 """Test the case where the DUT board does not match the target board."""
194 self.PatchObject(remote_access.ChromiumOSDevice, 'board', 'cedar')
195 self.assertTrue(self.deploy.options.force)
196 self.deploy._CheckBoard()
197 self.deploy.options.force = False
198 self.PatchObject(cros_build_lib, 'BooleanPrompt', return_value=True)
199 self.deploy._CheckBoard()
200 self.PatchObject(cros_build_lib, 'BooleanPrompt', return_value=False)
201 self.assertRaises(deploy_chrome.DeployFailure, self.deploy._CheckBoard)
202
203
David James88e6f032013-03-02 08:13:20 -0800204class TestDisableRootfsVerification(DeployTest):
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700205 """Testing disabling of rootfs verification and RO mode."""
206
David James88e6f032013-03-02 08:13:20 -0800207 def testDisableRootfsVerificationSuccess(self):
208 """Test the working case, disabling rootfs verification."""
209 self.deploy_mock.MockMountCmd(0)
210 self.deploy._DisableRootfsVerification()
Steven Bennettsca73efa2018-07-10 13:36:56 -0700211 self.assertFalse(self.deploy._root_dir_is_still_readonly.is_set())
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700212
213 def testDisableRootfsVerificationFailure(self):
214 """Test failure to disable rootfs verification."""
Mike Frysinger27e21b72018-07-12 14:20:21 -0400215 # pylint: disable=unused-argument
Shuqian Zhao14e61092017-11-17 00:02:16 +0000216 def RaiseRunCommandError(timeout_sec=None):
Mike Frysinger929f3ba2019-09-12 03:24:59 -0400217 raise cros_build_lib.RunCommandError('Mock RunCommandError')
Luigi Semenzato1bc79b22016-11-22 16:32:17 -0800218 self.remote_reboot_mock.side_effect = RaiseRunCommandError
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700219 self.assertRaises(cros_build_lib.RunCommandError,
David James88e6f032013-03-02 08:13:20 -0800220 self.deploy._DisableRootfsVerification)
Luigi Semenzato1bc79b22016-11-22 16:32:17 -0800221 self.remote_reboot_mock.side_effect = None
Steven Bennettsca73efa2018-07-10 13:36:56 -0700222 self.assertFalse(self.deploy._root_dir_is_still_readonly.is_set())
David James88e6f032013-03-02 08:13:20 -0800223
224
225class TestMount(DeployTest):
226 """Testing mount success and failure."""
227
228 def testSuccess(self):
229 """Test case where we are able to mount as writable."""
Steven Bennettsca73efa2018-07-10 13:36:56 -0700230 self.assertFalse(self.deploy._root_dir_is_still_readonly.is_set())
David James88e6f032013-03-02 08:13:20 -0800231 self.deploy_mock.MockMountCmd(0)
232 self.deploy._MountRootfsAsWritable()
Steven Bennettsca73efa2018-07-10 13:36:56 -0700233 self.assertFalse(self.deploy._root_dir_is_still_readonly.is_set())
David James88e6f032013-03-02 08:13:20 -0800234
235 def testMountError(self):
236 """Test that mount failure doesn't raise an exception by default."""
Steven Bennettsca73efa2018-07-10 13:36:56 -0700237 self.assertFalse(self.deploy._root_dir_is_still_readonly.is_set())
Avery Musbach3edff0e2020-03-27 13:35:53 -0700238 self.PatchObject(remote_access.ChromiumOSDevice, 'IsDirWritable',
Robert Flack1dc7ea82014-11-26 13:50:24 -0500239 return_value=False, autospec=True)
David James88e6f032013-03-02 08:13:20 -0800240 self.deploy._MountRootfsAsWritable()
Steven Bennettsca73efa2018-07-10 13:36:56 -0700241 self.assertTrue(self.deploy._root_dir_is_still_readonly.is_set())
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700242
243 def testMountRwFailure(self):
Mike Frysingerf5a3b2d2019-12-12 14:36:17 -0500244 """Test that mount failure raises an exception if check=True."""
David James88e6f032013-03-02 08:13:20 -0800245 self.assertRaises(cros_build_lib.RunCommandError,
Mike Frysingerf5a3b2d2019-12-12 14:36:17 -0500246 self.deploy._MountRootfsAsWritable, check=True)
Steven Bennettsca73efa2018-07-10 13:36:56 -0700247 self.assertFalse(self.deploy._root_dir_is_still_readonly.is_set())
Robert Flack1dc7ea82014-11-26 13:50:24 -0500248
249 def testMountTempDir(self):
250 """Test that mount succeeds if target dir is writable."""
Steven Bennettsca73efa2018-07-10 13:36:56 -0700251 self.assertFalse(self.deploy._root_dir_is_still_readonly.is_set())
Avery Musbach3edff0e2020-03-27 13:35:53 -0700252 self.PatchObject(remote_access.ChromiumOSDevice, 'IsDirWritable',
Robert Flack1dc7ea82014-11-26 13:50:24 -0500253 return_value=True, autospec=True)
254 self.deploy._MountRootfsAsWritable()
Steven Bennettsca73efa2018-07-10 13:36:56 -0700255 self.assertFalse(self.deploy._root_dir_is_still_readonly.is_set())
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700256
257
Anushruth8d797672019-10-17 12:22:31 -0700258class TestMountTarget(DeployTest):
Mike Frysingerdf1d0b02019-11-12 17:44:12 -0500259 """Testing mount and umount command handling."""
Anushruth8d797672019-10-17 12:22:31 -0700260
261 def testMountTargetUmountFailure(self):
262 """Test error being thrown if umount fails.
263
264 Test that 'lsof' is run on mount-dir and 'mount -rbind' command is not run
265 if 'umount' cmd fails.
266 """
267 mount_dir = self.deploy.options.mount_dir
268 target_dir = self.deploy.options.target_dir
269 self.deploy_mock.rsh_mock.AddCmdResult(
270 deploy_chrome._UMOUNT_DIR_IF_MOUNTPOINT_CMD %
271 {'dir': mount_dir}, returncode=errno.EBUSY, stderr='Target is Busy')
272 self.deploy_mock.rsh_mock.AddCmdResult(deploy_chrome.LSOF_COMMAND %
273 (mount_dir,), returncode=0,
274 stdout='process ' + mount_dir)
275 # Check for RunCommandError being thrown.
276 self.assertRaises(cros_build_lib.RunCommandError,
277 self.deploy._MountTarget)
278 # Check for the 'mount -rbind' command not run.
279 self.deploy_mock.rsh_mock.assertCommandContains(
280 (deploy_chrome._BIND_TO_FINAL_DIR_CMD % (target_dir, mount_dir)),
281 expected=False)
282 # Check for lsof command being called.
283 self.deploy_mock.rsh_mock.assertCommandContains(
284 (deploy_chrome.LSOF_COMMAND % (mount_dir,)))
285
286
Ryan Cuief91e702013-02-04 12:06:36 -0800287class TestUiJobStarted(DeployTest):
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700288 """Test detection of a running 'ui' job."""
289
Ryan Cuif2d1a582013-02-19 14:08:13 -0800290 def MockStatusUiCmd(self, **kwargs):
David Haddock3151d912017-10-24 03:50:32 +0000291 self.deploy_mock.rsh_mock.AddCmdResult('status ui', **kwargs)
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700292
293 def testUiJobStartedFalse(self):
294 """Correct results with a stopped job."""
Ryan Cuif2d1a582013-02-19 14:08:13 -0800295 self.MockStatusUiCmd(output='ui stop/waiting')
296 self.assertFalse(self.deploy._CheckUiJobStarted())
297
298 def testNoUiJob(self):
299 """Correct results when the job doesn't exist."""
300 self.MockStatusUiCmd(error='start: Unknown job: ui', returncode=1)
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700301 self.assertFalse(self.deploy._CheckUiJobStarted())
302
303 def testCheckRootfsWriteableTrue(self):
304 """Correct results with a running job."""
Ryan Cuif2d1a582013-02-19 14:08:13 -0800305 self.MockStatusUiCmd(output='ui start/running, process 297')
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700306 self.assertTrue(self.deploy._CheckUiJobStarted())
307
308
Ryan Cuief91e702013-02-04 12:06:36 -0800309class StagingTest(cros_test_lib.MockTempDirTestCase):
310 """Test user-mode and ebuild-mode staging functionality."""
311
312 def setUp(self):
Ryan Cuief91e702013-02-04 12:06:36 -0800313 self.staging_dir = os.path.join(self.tempdir, 'staging')
314 self.build_dir = os.path.join(self.tempdir, 'build_dir')
Avery Musbach3edff0e2020-03-27 13:35:53 -0700315 self.common_flags = ['--board', _TARGET_BOARD,
316 '--build-dir', self.build_dir, '--staging-only',
317 '--cache-dir', self.tempdir]
Ryan Cuia0215a72013-02-14 16:20:45 -0800318 self.sdk_mock = self.StartPatcher(cros_chrome_sdk_unittest.SDKFetcherMock())
Ryan Cui686ec052013-02-12 16:39:41 -0800319 self.PatchObject(
320 osutils, 'SourceEnvironment', autospec=True,
321 return_value={'STRIP': 'x86_64-cros-linux-gnu-strip'})
Ryan Cuief91e702013-02-04 12:06:36 -0800322
David Jamesa6e08892013-03-01 13:34:11 -0800323 def testSingleFileDeployFailure(self):
324 """Default staging enforces that mandatory files are copied"""
Mike Frysingerc3061a62015-06-04 04:16:18 -0400325 options = _ParseCommandLine(self.common_flags)
David Jamesa6e08892013-03-01 13:34:11 -0800326 osutils.Touch(os.path.join(self.build_dir, 'chrome'), makedirs=True)
327 self.assertRaises(
328 chrome_util.MissingPathError, deploy_chrome._PrepareStagingDir,
Daniel Eratc89829c2014-05-12 17:24:21 -0700329 options, self.tempdir, self.staging_dir, chrome_util._COPY_PATHS_CHROME)
Ryan Cuief91e702013-02-04 12:06:36 -0800330
David Jamesa6e08892013-03-01 13:34:11 -0800331 def testSloppyDeployFailure(self):
332 """Sloppy staging enforces that at least one file is copied."""
Mike Frysingerc3061a62015-06-04 04:16:18 -0400333 options = _ParseCommandLine(self.common_flags + ['--sloppy'])
David Jamesa6e08892013-03-01 13:34:11 -0800334 self.assertRaises(
335 chrome_util.MissingPathError, deploy_chrome._PrepareStagingDir,
Daniel Eratc89829c2014-05-12 17:24:21 -0700336 options, self.tempdir, self.staging_dir, chrome_util._COPY_PATHS_CHROME)
David Jamesa6e08892013-03-01 13:34:11 -0800337
338 def testSloppyDeploySuccess(self):
339 """Sloppy staging - stage one file."""
Mike Frysingerc3061a62015-06-04 04:16:18 -0400340 options = _ParseCommandLine(self.common_flags + ['--sloppy'])
David Jamesa6e08892013-03-01 13:34:11 -0800341 osutils.Touch(os.path.join(self.build_dir, 'chrome'), makedirs=True)
Steve Funge984a532013-11-25 17:09:25 -0800342 deploy_chrome._PrepareStagingDir(options, self.tempdir, self.staging_dir,
Daniel Eratc89829c2014-05-12 17:24:21 -0700343 chrome_util._COPY_PATHS_CHROME)
David Jamesa6e08892013-03-01 13:34:11 -0800344
Steve Funge984a532013-11-25 17:09:25 -0800345
346class DeployTestBuildDir(cros_test_lib.MockTempDirTestCase):
Daniel Erat1ae46382014-08-14 10:23:39 -0700347 """Set up a deploy object with a build-dir for use in deployment type tests"""
Steve Funge984a532013-11-25 17:09:25 -0800348
349 def _GetDeployChrome(self, args):
Mike Frysingerc3061a62015-06-04 04:16:18 -0400350 options = _ParseCommandLine(args)
Steve Funge984a532013-11-25 17:09:25 -0800351 return deploy_chrome.DeployChrome(
352 options, self.tempdir, os.path.join(self.tempdir, 'staging'))
353
354 def setUp(self):
355 self.staging_dir = os.path.join(self.tempdir, 'staging')
356 self.build_dir = os.path.join(self.tempdir, 'build_dir')
357 self.deploy_mock = self.StartPatcher(DeployChromeMock())
358 self.deploy = self._GetDeployChrome(
Avery Musbach3edff0e2020-03-27 13:35:53 -0700359 list(_REGULAR_TO) + ['--board', _TARGET_BOARD,
360 '--build-dir', self.build_dir, '--staging-only',
361 '--cache-dir', self.tempdir, '--sloppy'])
Steve Funge984a532013-11-25 17:09:25 -0800362
Daniel Erat1ae46382014-08-14 10:23:39 -0700363 def getCopyPath(self, source_path):
364 """Return a chrome_util.Path or None if not present."""
365 paths = [p for p in self.deploy.copy_paths if p.src == source_path]
366 return paths[0] if paths else None
Steve Funge984a532013-11-25 17:09:25 -0800367
Daniel Erat1ae46382014-08-14 10:23:39 -0700368class TestDeploymentType(DeployTestBuildDir):
Steve Funge984a532013-11-25 17:09:25 -0800369 """Test detection of deployment type using build dir."""
370
Daniel Erat1ae46382014-08-14 10:23:39 -0700371 def testAppShellDetection(self):
372 """Check for an app_shell deployment"""
373 osutils.Touch(os.path.join(self.deploy.options.build_dir, 'app_shell'),
Steve Funge984a532013-11-25 17:09:25 -0800374 makedirs=True)
375 self.deploy._CheckDeployType()
Daniel Erat1ae46382014-08-14 10:23:39 -0700376 self.assertTrue(self.getCopyPath('app_shell'))
377 self.assertFalse(self.getCopyPath('chrome'))
Steve Funge984a532013-11-25 17:09:25 -0800378
Daniel Erat1ae46382014-08-14 10:23:39 -0700379 def testChromeAndAppShellDetection(self):
Daniel Eratf53bd3a2016-12-02 11:28:36 -0700380 """Check for a chrome deployment when app_shell also exists."""
Steve Fung63d705d2014-03-16 03:14:03 -0700381 osutils.Touch(os.path.join(self.deploy.options.build_dir, 'chrome'),
382 makedirs=True)
Daniel Erat1ae46382014-08-14 10:23:39 -0700383 osutils.Touch(os.path.join(self.deploy.options.build_dir, 'app_shell'),
Steve Fung63d705d2014-03-16 03:14:03 -0700384 makedirs=True)
385 self.deploy._CheckDeployType()
Daniel Erat1ae46382014-08-14 10:23:39 -0700386 self.assertTrue(self.getCopyPath('chrome'))
Daniel Erat9813f0e2014-11-12 11:00:28 -0700387 self.assertFalse(self.getCopyPath('app_shell'))
Steve Fung63d705d2014-03-16 03:14:03 -0700388
Steve Funge984a532013-11-25 17:09:25 -0800389 def testChromeDetection(self):
390 """Check for a regular chrome deployment"""
391 osutils.Touch(os.path.join(self.deploy.options.build_dir, 'chrome'),
392 makedirs=True)
393 self.deploy._CheckDeployType()
Daniel Erat1ae46382014-08-14 10:23:39 -0700394 self.assertTrue(self.getCopyPath('chrome'))
Daniel Erat9813f0e2014-11-12 11:00:28 -0700395 self.assertFalse(self.getCopyPath('app_shell'))
Ben Pastenee484b342020-06-30 18:29:27 -0700396
397
398class TestDeployTestBinaries(cros_test_lib.RunCommandTempDirTestCase):
399 """Tests _DeployTestBinaries()."""
400
401 def setUp(self):
402 options = _ParseCommandLine(list(_REGULAR_TO) + [
403 '--board', _TARGET_BOARD, '--force', '--mount',
404 '--build-dir', os.path.join(self.tempdir, 'build_dir'),
405 '--nostrip'])
406 self.deploy = deploy_chrome.DeployChrome(
407 options, self.tempdir, os.path.join(self.tempdir, 'staging'))
408
409 def testFindError(self):
410 """Ensure an error is thrown if we can't inspect the device."""
411 self.rc.AddCmdResult(
412 partial_mock.In(deploy_chrome._FIND_TEST_BIN_CMD), 1)
413 self.assertRaises(
414 deploy_chrome.DeployFailure, self.deploy._DeployTestBinaries)
415
416 def testSuccess(self):
417 """Ensure the staging dir contains the right binaries to copy over."""
418 test_binaries = [
419 'run_a_tests',
420 'run_b_tests',
421 'run_c_tests',
422 ]
423 # Simulate having the binaries both on the device and in our local build
424 # dir.
425 self.rc.AddCmdResult(
426 partial_mock.In(deploy_chrome._FIND_TEST_BIN_CMD),
427 stdout='\n'.join(test_binaries))
428 for binary in test_binaries:
429 osutils.Touch(os.path.join(self.deploy.options.build_dir, binary),
430 makedirs=True, mode=0o700)
431
432 self.deploy._DeployTestBinaries()
433
434 # Ensure the binaries were placed in the staging dir used to copy them over.
435 staging_dir = os.path.join(
436 self.tempdir, os.path.basename(deploy_chrome._CHROME_TEST_BIN_DIR))
437 for binary in test_binaries:
438 self.assertIn(binary, os.listdir(staging_dir))
Erik Chen75a2f492020-08-06 19:15:11 -0700439
440
441class LacrosPerformTest(cros_test_lib.RunCommandTempDirTestCase):
442 """Line coverage for Perform() method with --lacros option."""
443
444 def setUp(self):
445 options = _ParseCommandLine([
446 '--lacros', '--nostrip', '--build-dir', '/path/to/nowhere',
447 '--to', 'localhost'])
448 self.deploy = deploy_chrome.DeployChrome(
449 options, self.tempdir, os.path.join(self.tempdir, 'staging'))
450
451 # These methods being mocked are all side effects expected for a --lacros
452 # deploy.
453 self.deploy._EnsureTargetDir = mock.Mock()
454 self.deploy._GetDeviceInfo = mock.Mock()
455 self.deploy._CheckConnection = mock.Mock()
456 self.deploy._MountRootfsAsWritable = mock.Mock()
457 self.deploy._PrepareStagingDir = mock.Mock()
458 self.deploy._CheckDeviceFreeSpace = mock.Mock()
459
460 self._ran_start_command = False
461
462 self.StartPatcher(parallel_unittest.ParallelMock())
463
464 # Common mocking shared between tests.
465 def kill_procs_side_effect():
466 self.deploy._stopped_ui = True
467 self.deploy._KillAshChromeIfNeeded = mock.Mock(
468 side_effect=kill_procs_side_effect)
469
470 def start_ui_side_effect(*args, **kwargs):
471 # pylint: disable=unused-argument
472 self._ran_start_command = True
473 self.rc.AddCmdResult(partial_mock.In('start ui'),
474 side_effect=start_ui_side_effect)
475
476 def testConfNotModified(self):
477 """When the conf file is not modified we don't restart chrome ."""
478 self.deploy.Perform()
479 self.deploy._KillAshChromeIfNeeded.assert_not_called()
480 self.assertFalse(self._ran_start_command)
481
482 def testConfModified(self):
483 """When the conf file is modified we restart chrome."""
484
485 # We intentionally add '\n' to MODIFIED_CONF_FILE to simulate echo adding a
486 # newline when invoked in the shell.
487 self.rc.AddCmdResult(
488 partial_mock.In(deploy_chrome.ENABLE_LACROS_VIA_CONF_COMMAND),
489 stdout=deploy_chrome.MODIFIED_CONF_FILE + '\n')
490
491 self.deploy.Perform()
492 self.deploy._KillAshChromeIfNeeded.assert_called()
493 self.assertTrue(self._ran_start_command)