blob: dce8ca4d414a394bd6f7681abb13801844838fd0 [file] [log] [blame]
Mike Frysingerf1ba7ad2022-09-12 05:42:57 -04001# Copyright 2015 The ChromiumOS Authors
David Pursell9476bf42015-03-30 13:34:27 -07002# 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 deploy module."""
6
David Pursell9476bf42015-03-30 13:34:27 -07007import json
Ralph Nathane01ccf12015-04-16 10:40:32 -07008import multiprocessing
David Pursell9476bf42015-03-30 13:34:27 -07009import os
Mike Frysinger050fa5a2019-12-01 16:16:29 -050010import sys
Mike Frysinger166fea02021-02-12 05:30:33 -050011from unittest import mock
David Pursell9476bf42015-03-30 13:34:27 -070012
Ralph Nathane01ccf12015-04-16 10:40:32 -070013from chromite.cli import command
David Pursell9476bf42015-03-30 13:34:27 -070014from chromite.cli import deploy
Mike Frysinger06a51c82021-04-06 11:39:17 -040015from chromite.lib import build_target_lib
David Pursell9476bf42015-03-30 13:34:27 -070016from chromite.lib import cros_build_lib
17from chromite.lib import cros_test_lib
Brian Norris2eee8892021-04-06 16:23:23 -070018from chromite.lib import osutils
Ralph Nathane01ccf12015-04-16 10:40:32 -070019from chromite.lib import remote_access
Brian Norris2eee8892021-04-06 16:23:23 -070020from chromite.lib import sysroot_lib
Sloan Johnsona85640f2021-10-01 22:32:40 +000021from chromite.lib import unittest_lib
Alex Klein18a60af2020-06-11 12:08:47 -060022from chromite.lib.parser import package_info
Mike Frysinger40ffb532021-02-12 07:36:08 -050023
Greg Edelstona4c9b3b2020-01-07 17:51:13 -070024
Chris McDonald186b9ee2020-04-16 05:56:49 -060025pytestmark = [cros_test_lib.pytestmark_inside_only]
Greg Edelstona4c9b3b2020-01-07 17:51:13 -070026
27
28if cros_build_lib.IsInsideChroot():
Alex Klein1699fab2022-09-08 08:46:06 -060029 import portage # pylint: disable=import-error
David Pursell9476bf42015-03-30 13:34:27 -070030
31
32# pylint: disable=protected-access
33
34
Ralph Nathane01ccf12015-04-16 10:40:32 -070035class ChromiumOSDeviceFake(object):
Alex Klein1699fab2022-09-08 08:46:06 -060036 """Fake for device."""
Ralph Nathane01ccf12015-04-16 10:40:32 -070037
Alex Klein1699fab2022-09-08 08:46:06 -060038 def __init__(self):
39 self.board = "board"
40 self.hostname = None
41 self.username = None
42 self.port = None
43 self.lsb_release = None
44 self.cmds = []
45 self.work_dir = "/testdir/"
46 self.selinux_available = False
Ralph Nathane01ccf12015-04-16 10:40:32 -070047
Alex Klein1699fab2022-09-08 08:46:06 -060048 def MountRootfsReadWrite(self):
49 return True
Ralph Nathane01ccf12015-04-16 10:40:32 -070050
Alex Klein1699fab2022-09-08 08:46:06 -060051 def IsSELinuxAvailable(self):
52 return self.selinux_available
Ben Pastene5f03b052019-08-12 18:03:24 -070053
Alex Klein1699fab2022-09-08 08:46:06 -060054 def IsSELinuxEnforced(self):
55 return True
Ben Pastene5f03b052019-08-12 18:03:24 -070056
Alex Klein1699fab2022-09-08 08:46:06 -060057 def run(self, cmd, **_kwargs):
58 self.cmds.append(cmd)
Andrewc7e1c6b2020-02-27 16:03:53 -080059
Alex Klein1699fab2022-09-08 08:46:06 -060060 def CopyToDevice(self, _src, _dest, _mode="rsync", **_kwargs):
61 return True
Andrewc7e1c6b2020-02-27 16:03:53 -080062
Ralph Nathane01ccf12015-04-16 10:40:32 -070063
David Pursell9476bf42015-03-30 13:34:27 -070064class ChromiumOSDeviceHandlerFake(object):
Alex Klein1699fab2022-09-08 08:46:06 -060065 """Fake for chromite.lib.remote_access.ChomiumOSDeviceHandler."""
David Pursell9476bf42015-03-30 13:34:27 -070066
Alex Klein1699fab2022-09-08 08:46:06 -060067 class RemoteAccessFake(object):
68 """Fake for chromite.lib.remote_access.RemoteAccess."""
David Pursell9476bf42015-03-30 13:34:27 -070069
Alex Klein1699fab2022-09-08 08:46:06 -060070 def __init__(self):
71 self.remote_sh_output = None
David Pursell9476bf42015-03-30 13:34:27 -070072
Alex Klein1699fab2022-09-08 08:46:06 -060073 def RemoteSh(self, *_args, **_kwargs):
74 return cros_build_lib.CompletedProcess(stdout=self.remote_sh_output)
David Pursell9476bf42015-03-30 13:34:27 -070075
Alex Klein1699fab2022-09-08 08:46:06 -060076 def __init__(self, *_args, **_kwargs):
77 self._agent = self.RemoteAccessFake()
78 self.device = ChromiumOSDeviceFake()
David Pursell67a82762015-04-30 17:26:59 -070079
Alex Klein1699fab2022-09-08 08:46:06 -060080 # TODO(dpursell): Mock remote access object in cros_test_lib (brbug.com/986).
Mike Frysingerc0780a62022-08-29 04:41:56 -040081 @property
82 def agent(self):
Alex Klein1699fab2022-09-08 08:46:06 -060083 return self._agent
David Pursell9476bf42015-03-30 13:34:27 -070084
Alex Klein1699fab2022-09-08 08:46:06 -060085 def __exit__(self, _type, _value, _traceback):
86 pass
Ralph Nathane01ccf12015-04-16 10:40:32 -070087
Alex Klein1699fab2022-09-08 08:46:06 -060088 def __enter__(self):
89 return self.device
Ralph Nathane01ccf12015-04-16 10:40:32 -070090
91
92class BrilloDeployOperationFake(deploy.BrilloDeployOperation):
Alex Klein1699fab2022-09-08 08:46:06 -060093 """Fake for deploy.BrilloDeployOperation."""
Ralph Nathane01ccf12015-04-16 10:40:32 -070094
Alex Klein1699fab2022-09-08 08:46:06 -060095 def __init__(self, emerge, queue):
96 super().__init__(emerge)
97 self._queue = queue
98
99 def ParseOutput(self, output=None):
100 super().ParseOutput(output)
101 self._queue.put("advance")
Ralph Nathane01ccf12015-04-16 10:40:32 -0700102
David Pursell9476bf42015-03-30 13:34:27 -0700103
104class DbApiFake(object):
Alex Klein1699fab2022-09-08 08:46:06 -0600105 """Fake for Portage dbapi."""
David Pursell9476bf42015-03-30 13:34:27 -0700106
Alex Klein1699fab2022-09-08 08:46:06 -0600107 def __init__(self, pkgs):
108 self.pkg_db = {}
109 for cpv, slot, rdeps_raw, build_time in pkgs:
110 self.pkg_db[cpv] = {
111 "SLOT": slot,
112 "RDEPEND": rdeps_raw,
113 "BUILD_TIME": build_time,
114 }
David Pursell9476bf42015-03-30 13:34:27 -0700115
Alex Klein1699fab2022-09-08 08:46:06 -0600116 def cpv_all(self):
117 return list(self.pkg_db)
David Pursell9476bf42015-03-30 13:34:27 -0700118
Alex Klein1699fab2022-09-08 08:46:06 -0600119 def aux_get(self, cpv, keys):
120 pkg_info = self.pkg_db[cpv]
121 return [pkg_info[key] for key in keys]
David Pursell9476bf42015-03-30 13:34:27 -0700122
123
Ralph Nathane01ccf12015-04-16 10:40:32 -0700124class PackageScannerFake(object):
Alex Klein1699fab2022-09-08 08:46:06 -0600125 """Fake for PackageScanner."""
Ralph Nathane01ccf12015-04-16 10:40:32 -0700126
Alex Klein1699fab2022-09-08 08:46:06 -0600127 def __init__(self, packages, pkgs_attrs, packages_cpvs=None):
128 self.pkgs = packages
129 self.cpvs = packages_cpvs or packages
130 self.listed = []
131 self.num_updates = 0
132 self.pkgs_attrs = pkgs_attrs
Ralph Nathane01ccf12015-04-16 10:40:32 -0700133
Alex Klein1699fab2022-09-08 08:46:06 -0600134 def Run(self, _device, _root, _packages, _update, _deep, _deep_rev):
135 return self.cpvs, self.listed, self.num_updates, self.pkgs_attrs
Ralph Nathane01ccf12015-04-16 10:40:32 -0700136
137
David Pursell9476bf42015-03-30 13:34:27 -0700138class PortageTreeFake(object):
Alex Klein1699fab2022-09-08 08:46:06 -0600139 """Fake for Portage tree."""
David Pursell9476bf42015-03-30 13:34:27 -0700140
Alex Klein1699fab2022-09-08 08:46:06 -0600141 def __init__(self, dbapi):
142 self.dbapi = dbapi
David Pursell9476bf42015-03-30 13:34:27 -0700143
144
Ralph Nathane01ccf12015-04-16 10:40:32 -0700145class TestInstallPackageScanner(cros_test_lib.MockOutputTestCase):
Alex Klein1699fab2022-09-08 08:46:06 -0600146 """Test the update package scanner."""
David Pursell9476bf42015-03-30 13:34:27 -0700147
Alex Klein1699fab2022-09-08 08:46:06 -0600148 _BOARD = "foo_board"
149 _BUILD_ROOT = "/build/%s" % _BOARD
150 _VARTREE = [
151 ("foo/app1-1.2.3-r4", "0", "foo/app2 !foo/app3", "1413309336"),
152 ("foo/app2-4.5.6-r7", "0", "", "1413309336"),
153 ("foo/app4-2.0.0-r1", "0", "foo/app1 foo/app5", "1413309336"),
154 ("foo/app5-3.0.7-r3", "0", "", "1413309336"),
155 ]
David Pursell9476bf42015-03-30 13:34:27 -0700156
Alex Klein1699fab2022-09-08 08:46:06 -0600157 def setUp(self):
158 """Patch imported modules."""
159 self.PatchObject(cros_build_lib, "GetChoice", return_value=0)
160 self.device = ChromiumOSDeviceHandlerFake()
161 self.scanner = deploy._InstallPackageScanner(self._BUILD_ROOT)
162 self.PatchObject(deploy, "_GetDLCInfo", return_value=(None, None))
David Pursell9476bf42015-03-30 13:34:27 -0700163
Alex Klein1699fab2022-09-08 08:46:06 -0600164 def SetupVartree(self, vartree_pkgs):
Mike Frysingerc0780a62022-08-29 04:41:56 -0400165 self.device.agent.remote_sh_output = json.dumps(vartree_pkgs)
David Pursell9476bf42015-03-30 13:34:27 -0700166
Alex Klein1699fab2022-09-08 08:46:06 -0600167 def SetupBintree(self, bintree_pkgs):
168 bintree = PortageTreeFake(DbApiFake(bintree_pkgs))
169 build_root = os.path.join(self._BUILD_ROOT, "")
170 portage_db = {build_root: {"bintree": bintree}}
171 self.PatchObject(portage, "create_trees", return_value=portage_db)
David Pursell9476bf42015-03-30 13:34:27 -0700172
Alex Klein1699fab2022-09-08 08:46:06 -0600173 def ValidatePkgs(self, actual, expected, constraints=None):
174 # Containing exactly the same packages.
175 self.assertEqual(sorted(expected), sorted(actual))
176 # Packages appear in the right order.
177 if constraints is not None:
178 for needs, needed in constraints:
179 self.assertGreater(actual.index(needs), actual.index(needed))
David Pursell9476bf42015-03-30 13:34:27 -0700180
Alex Klein1699fab2022-09-08 08:46:06 -0600181 def testRunUpdatedVersion(self):
182 self.SetupVartree(self._VARTREE)
183 app1 = "foo/app1-1.2.5-r4"
184 self.SetupBintree(
185 [
186 (app1, "0", "foo/app2 !foo/app3", "1413309336"),
187 ("foo/app2-4.5.6-r7", "0", "", "1413309336"),
188 ]
189 )
190 installs, listed, num_updates, _ = self.scanner.Run(
191 self.device, "/", ["app1"], True, True, True
192 )
193 self.ValidatePkgs(installs, [app1])
194 self.ValidatePkgs(listed, [app1])
195 self.assertEqual(num_updates, 1)
David Pursell9476bf42015-03-30 13:34:27 -0700196
Alex Klein1699fab2022-09-08 08:46:06 -0600197 def testRunUpdatedBuildTime(self):
198 self.SetupVartree(self._VARTREE)
199 app1 = "foo/app1-1.2.3-r4"
200 self.SetupBintree(
201 [
202 (app1, "0", "foo/app2 !foo/app3", "1413309350"),
203 ("foo/app2-4.5.6-r7", "0", "", "1413309336"),
204 ]
205 )
206 installs, listed, num_updates, _ = self.scanner.Run(
207 self.device, "/", ["app1"], True, True, True
208 )
209 self.ValidatePkgs(installs, [app1])
210 self.ValidatePkgs(listed, [app1])
211 self.assertEqual(num_updates, 1)
David Pursell9476bf42015-03-30 13:34:27 -0700212
Alex Klein1699fab2022-09-08 08:46:06 -0600213 def testRunExistingDepUpdated(self):
214 self.SetupVartree(self._VARTREE)
215 app1 = "foo/app1-1.2.5-r2"
216 app2 = "foo/app2-4.5.8-r3"
217 self.SetupBintree(
218 [
219 (app1, "0", "foo/app2 !foo/app3", "1413309350"),
220 (app2, "0", "", "1413309350"),
221 ]
222 )
223 installs, listed, num_updates, _ = self.scanner.Run(
224 self.device, "/", ["app1"], True, True, True
225 )
226 self.ValidatePkgs(installs, [app1, app2], constraints=[(app1, app2)])
227 self.ValidatePkgs(listed, [app1])
228 self.assertEqual(num_updates, 2)
David Pursell9476bf42015-03-30 13:34:27 -0700229
Alex Klein1699fab2022-09-08 08:46:06 -0600230 def testRunMissingDepUpdated(self):
231 self.SetupVartree(self._VARTREE)
232 app1 = "foo/app1-1.2.5-r2"
233 app6 = "foo/app6-1.0.0-r1"
234 self.SetupBintree(
235 [
236 (app1, "0", "foo/app2 !foo/app3 foo/app6", "1413309350"),
237 ("foo/app2-4.5.6-r7", "0", "", "1413309336"),
238 (app6, "0", "", "1413309350"),
239 ]
240 )
241 installs, listed, num_updates, _ = self.scanner.Run(
242 self.device, "/", ["app1"], True, True, True
243 )
244 self.ValidatePkgs(installs, [app1, app6], constraints=[(app1, app6)])
245 self.ValidatePkgs(listed, [app1])
246 self.assertEqual(num_updates, 1)
David Pursell9476bf42015-03-30 13:34:27 -0700247
Alex Klein1699fab2022-09-08 08:46:06 -0600248 def testRunExistingRevDepUpdated(self):
249 self.SetupVartree(self._VARTREE)
250 app1 = "foo/app1-1.2.5-r2"
251 app4 = "foo/app4-2.0.1-r3"
252 self.SetupBintree(
253 [
254 (app1, "0", "foo/app2 !foo/app3", "1413309350"),
255 (app4, "0", "foo/app1 foo/app5", "1413309350"),
256 ("foo/app5-3.0.7-r3", "0", "", "1413309336"),
257 ]
258 )
259 installs, listed, num_updates, _ = self.scanner.Run(
260 self.device, "/", ["app1"], True, True, True
261 )
262 self.ValidatePkgs(installs, [app1, app4], constraints=[(app4, app1)])
263 self.ValidatePkgs(listed, [app1])
264 self.assertEqual(num_updates, 2)
David Pursell9476bf42015-03-30 13:34:27 -0700265
Alex Klein1699fab2022-09-08 08:46:06 -0600266 def testRunMissingRevDepNotUpdated(self):
267 self.SetupVartree(self._VARTREE)
268 app1 = "foo/app1-1.2.5-r2"
269 app6 = "foo/app6-1.0.0-r1"
270 self.SetupBintree(
271 [
272 (app1, "0", "foo/app2 !foo/app3", "1413309350"),
273 (app6, "0", "foo/app1", "1413309350"),
274 ]
275 )
276 installs, listed, num_updates, _ = self.scanner.Run(
277 self.device, "/", ["app1"], True, True, True
278 )
279 self.ValidatePkgs(installs, [app1])
280 self.ValidatePkgs(listed, [app1])
281 self.assertEqual(num_updates, 1)
David Pursell9476bf42015-03-30 13:34:27 -0700282
Alex Klein1699fab2022-09-08 08:46:06 -0600283 def testRunTransitiveDepsUpdated(self):
284 self.SetupVartree(self._VARTREE)
285 app1 = "foo/app1-1.2.5-r2"
286 app2 = "foo/app2-4.5.8-r3"
287 app4 = "foo/app4-2.0.0-r1"
288 app5 = "foo/app5-3.0.8-r2"
289 self.SetupBintree(
290 [
291 (app1, "0", "foo/app2 !foo/app3", "1413309350"),
292 (app2, "0", "", "1413309350"),
293 (app4, "0", "foo/app1 foo/app5", "1413309350"),
294 (app5, "0", "", "1413309350"),
295 ]
296 )
297 installs, listed, num_updates, _ = self.scanner.Run(
298 self.device, "/", ["app1"], True, True, True
299 )
300 self.ValidatePkgs(
301 installs,
302 [app1, app2, app4, app5],
303 constraints=[(app1, app2), (app4, app1), (app4, app5)],
304 )
305 self.ValidatePkgs(listed, [app1])
306 self.assertEqual(num_updates, 4)
David Pursell9476bf42015-03-30 13:34:27 -0700307
Alex Klein1699fab2022-09-08 08:46:06 -0600308 def testRunDisjunctiveDepsExistingUpdated(self):
309 self.SetupVartree(self._VARTREE)
310 app1 = "foo/app1-1.2.5-r2"
311 self.SetupBintree(
312 [
313 (app1, "0", "|| ( foo/app6 foo/app2 ) !foo/app3", "1413309350"),
314 ("foo/app2-4.5.6-r7", "0", "", "1413309336"),
315 ]
316 )
317 installs, listed, num_updates, _ = self.scanner.Run(
318 self.device, "/", ["app1"], True, True, True
319 )
320 self.ValidatePkgs(installs, [app1])
321 self.ValidatePkgs(listed, [app1])
322 self.assertEqual(num_updates, 1)
323
324 def testRunDisjunctiveDepsDefaultUpdated(self):
325 self.SetupVartree(self._VARTREE)
326 app1 = "foo/app1-1.2.5-r2"
327 app7 = "foo/app7-1.0.0-r1"
328 self.SetupBintree(
329 [
330 (app1, "0", "|| ( foo/app6 foo/app7 ) !foo/app3", "1413309350"),
331 (app7, "0", "", "1413309350"),
332 ]
333 )
334 installs, listed, num_updates, _ = self.scanner.Run(
335 self.device, "/", ["app1"], True, True, True
336 )
337 self.ValidatePkgs(installs, [app1, app7], constraints=[(app1, app7)])
338 self.ValidatePkgs(listed, [app1])
339 self.assertEqual(num_updates, 1)
Ralph Nathane01ccf12015-04-16 10:40:32 -0700340
341
Alex Klein1699fab2022-09-08 08:46:06 -0600342class TestDeploy(
343 cros_test_lib.ProgressBarTestCase, cros_test_lib.MockTempDirTestCase
344):
345 """Test deploy.Deploy."""
Ralph Nathane01ccf12015-04-16 10:40:32 -0700346
Alex Klein1699fab2022-09-08 08:46:06 -0600347 @staticmethod
348 def FakeGetPackagesByCPV(cpvs, _strip, _sysroot):
349 return ["/path/to/%s.tbz2" % cpv.pv for cpv in cpvs]
Gilad Arnold0e1b1da2015-06-10 06:41:05 -0700350
Alex Klein1699fab2022-09-08 08:46:06 -0600351 def setUp(self):
352 # Fake being root to avoid running filesystem commands with sudo_run.
353 self.PatchObject(osutils, "IsRootUser", return_value=True)
354 self._sysroot = os.path.join(self.tempdir, "sysroot")
355 osutils.SafeMakedirs(self._sysroot)
356 self.device = ChromiumOSDeviceHandlerFake()
357 self.PatchObject(
358 remote_access, "ChromiumOSDeviceHandler", return_value=self.device
359 )
360 self.PatchObject(cros_build_lib, "GetBoard", return_value=None)
361 self.PatchObject(
362 build_target_lib,
363 "get_default_sysroot_path",
364 return_value=self._sysroot,
365 )
366 self.package_scanner = self.PatchObject(
367 deploy, "_InstallPackageScanner"
368 )
369 self.get_packages_paths = self.PatchObject(
370 deploy, "_GetPackagesByCPV", side_effect=self.FakeGetPackagesByCPV
371 )
372 self.emerge = self.PatchObject(deploy, "_Emerge", return_value=None)
373 self.unmerge = self.PatchObject(deploy, "_Unmerge", return_value=None)
374 self.PatchObject(deploy, "_GetDLCInfo", return_value=(None, None))
375 # Avoid running the portageq command.
376 sysroot_lib.Sysroot(self._sysroot).WriteConfig(
377 'ARCH="amd64"\nPORTDIR_OVERLAY="%s"' % "/nothing/here"
378 )
379 # make.conf needs to exist to correctly read back config.
380 unittest_lib.create_stub_make_conf(self._sysroot)
Brian Norris2eee8892021-04-06 16:23:23 -0700381
Alex Klein1699fab2022-09-08 08:46:06 -0600382 def testDeployEmerge(self):
383 """Test that deploy._Emerge is called for each package."""
Ralph Nathane01ccf12015-04-16 10:40:32 -0700384
Alex Klein1699fab2022-09-08 08:46:06 -0600385 _BINPKG = "/path/to/bar-1.2.5.tbz2"
Gilad Arnold0e1b1da2015-06-10 06:41:05 -0700386
Alex Klein1699fab2022-09-08 08:46:06 -0600387 def FakeIsFile(fname):
388 return fname == _BINPKG
Gilad Arnold0e1b1da2015-06-10 06:41:05 -0700389
Alex Klein1699fab2022-09-08 08:46:06 -0600390 packages = ["some/foo-1.2.3", _BINPKG, "some/foobar-2.0"]
391 cpvs = ["some/foo-1.2.3", "to/bar-1.2.5", "some/foobar-2.0"]
392 self.package_scanner.return_value = PackageScannerFake(
393 packages,
394 {"some/foo-1.2.3": {}, _BINPKG: {}, "some/foobar-2.0": {}},
395 cpvs,
396 )
397 self.PatchObject(os.path, "isfile", side_effect=FakeIsFile)
Ralph Nathane01ccf12015-04-16 10:40:32 -0700398
Alex Klein1699fab2022-09-08 08:46:06 -0600399 deploy.Deploy(None, ["package"], force=True, clean_binpkg=False)
Ralph Nathane01ccf12015-04-16 10:40:32 -0700400
Alex Klein1699fab2022-09-08 08:46:06 -0600401 # Check that package names were correctly resolved into binary packages.
402 self.get_packages_paths.assert_called_once_with(
403 [package_info.SplitCPV(p) for p in cpvs], True, self._sysroot
404 )
405 # Check that deploy._Emerge is called the right number of times.
406 self.emerge.assert_called_once_with(
407 mock.ANY,
408 [
409 "/path/to/foo-1.2.3.tbz2",
410 "/path/to/bar-1.2.5.tbz2",
411 "/path/to/foobar-2.0.tbz2",
412 ],
413 "/",
414 extra_args=None,
415 )
416 self.assertEqual(self.unmerge.call_count, 0)
Qijiang Fan8a945032019-04-25 20:53:29 +0900417
Alex Klein1699fab2022-09-08 08:46:06 -0600418 def testDeployEmergeDLC(self):
419 """Test that deploy._Emerge installs images for DLC packages."""
420 packages = ["some/foodlc-1.0", "some/bardlc-2.0"]
421 cpvs = ["some/foodlc-1.0", "some/bardlc-2.0"]
422 self.package_scanner.return_value = PackageScannerFake(
423 packages, {"some/foodlc-1.0": {}, "some/bardlc-2.0": {}}, cpvs
424 )
425 self.PatchObject(
426 deploy, "_GetDLCInfo", return_value=("foo_id", "foo_package")
427 )
Xiaochu Liu2726e7c2019-07-18 10:28:10 -0700428
Alex Klein1699fab2022-09-08 08:46:06 -0600429 deploy.Deploy(None, ["package"], force=True, clean_binpkg=False)
430 # Check that dlcservice is restarted (DLC modules are deployed).
431 self.assertTrue(["restart", "dlcservice"] in self.device.device.cmds)
Xiaochu Liu2726e7c2019-07-18 10:28:10 -0700432
Alex Klein1699fab2022-09-08 08:46:06 -0600433 def testDeployEmergeSELinux(self):
434 """Test deploy progress when the device has SELinux"""
Qijiang Fan8a945032019-04-25 20:53:29 +0900435
Alex Klein1699fab2022-09-08 08:46:06 -0600436 _BINPKG = "/path/to/bar-1.2.5.tbz2"
Qijiang Fan8a945032019-04-25 20:53:29 +0900437
Alex Klein1699fab2022-09-08 08:46:06 -0600438 def FakeIsFile(fname):
439 return fname == _BINPKG
Qijiang Fan8a945032019-04-25 20:53:29 +0900440
Alex Klein1699fab2022-09-08 08:46:06 -0600441 def GetRestoreconCommand(pkgfile):
442 remote_path = os.path.join("/testdir/packages/to/", pkgfile)
443 return [
444 [
445 "cd",
446 "/",
447 "&&",
448 "tar",
449 "tf",
450 remote_path,
451 "|",
452 "restorecon",
453 "-i",
454 "-f",
455 "-",
456 ]
457 ]
Qijiang Fan8a945032019-04-25 20:53:29 +0900458
Alex Klein1699fab2022-09-08 08:46:06 -0600459 self.device.device.selinux_available = True
460 packages = ["some/foo-1.2.3", _BINPKG, "some/foobar-2.0"]
461 cpvs = ["some/foo-1.2.3", "to/bar-1.2.5", "some/foobar-2.0"]
462 self.package_scanner.return_value = PackageScannerFake(
463 packages,
464 {"some/foo-1.2.3": {}, _BINPKG: {}, "some/foobar-2.0": {}},
465 cpvs,
466 )
467 self.PatchObject(os.path, "isfile", side_effect=FakeIsFile)
Qijiang Fan8a945032019-04-25 20:53:29 +0900468
Alex Klein1699fab2022-09-08 08:46:06 -0600469 deploy.Deploy(None, ["package"], force=True, clean_binpkg=False)
Qijiang Fan8a945032019-04-25 20:53:29 +0900470
Alex Klein1699fab2022-09-08 08:46:06 -0600471 # Check that package names were correctly resolved into binary packages.
472 self.get_packages_paths.assert_called_once_with(
473 [package_info.SplitCPV(p) for p in cpvs], True, self._sysroot
474 )
475 # Check that deploy._Emerge is called the right number of times.
476 self.assertEqual(self.emerge.call_count, 1)
477 self.assertEqual(self.unmerge.call_count, 0)
Ralph Nathane01ccf12015-04-16 10:40:32 -0700478
Alex Klein1699fab2022-09-08 08:46:06 -0600479 self.assertEqual(
480 self.device.device.cmds,
481 [["setenforce", "0"]]
482 + GetRestoreconCommand("foo-1.2.3.tbz2")
483 + GetRestoreconCommand("bar-1.2.5.tbz2")
484 + GetRestoreconCommand("foobar-2.0.tbz2")
485 + [["setenforce", "1"]],
486 )
Ralph Nathane01ccf12015-04-16 10:40:32 -0700487
Alex Klein1699fab2022-09-08 08:46:06 -0600488 def testDeployUnmerge(self):
489 """Test that deploy._Unmerge is called for each package."""
490 packages = ["foo", "bar", "foobar", "foodlc"]
491 self.package_scanner.return_value = PackageScannerFake(
492 packages,
493 {
494 "foo": {},
495 "bar": {},
496 "foobar": {},
497 "foodlc": {
498 deploy._DLC_ID: "foodlc",
499 deploy._DLC_PACKAGE: "foopackage",
500 },
501 },
502 )
Ralph Nathane01ccf12015-04-16 10:40:32 -0700503
Alex Klein1699fab2022-09-08 08:46:06 -0600504 deploy.Deploy(
505 None, ["package"], force=True, clean_binpkg=False, emerge=False
506 )
Ralph Nathane01ccf12015-04-16 10:40:32 -0700507
Alex Klein1699fab2022-09-08 08:46:06 -0600508 # Check that deploy._Unmerge is called the right number of times.
509 self.assertEqual(self.emerge.call_count, 0)
510 self.unmerge.assert_called_once_with(mock.ANY, packages, "/")
Xiaochu Liu2726e7c2019-07-18 10:28:10 -0700511
Alex Klein1699fab2022-09-08 08:46:06 -0600512 self.assertEqual(
513 self.device.device.cmds,
514 [
515 ["dlcservice_util", "--uninstall", "--id=foodlc"],
516 ["restart", "dlcservice"],
517 ],
518 )
Ralph Nathane01ccf12015-04-16 10:40:32 -0700519
Alex Klein1699fab2022-09-08 08:46:06 -0600520 def testDeployMergeWithProgressBar(self):
521 """Test that BrilloDeployOperation.Run() is called for merge."""
522 packages = ["foo", "bar", "foobar"]
523 self.package_scanner.return_value = PackageScannerFake(
524 packages, {"foo": {}, "bar": {}, "foobar": {}}
525 )
Ralph Nathane01ccf12015-04-16 10:40:32 -0700526
Alex Klein1699fab2022-09-08 08:46:06 -0600527 run = self.PatchObject(
528 deploy.BrilloDeployOperation, "Run", return_value=None
529 )
Ralph Nathane01ccf12015-04-16 10:40:32 -0700530
Alex Klein1699fab2022-09-08 08:46:06 -0600531 self.PatchObject(command, "UseProgressBar", return_value=True)
532 deploy.Deploy(None, ["package"], force=True, clean_binpkg=False)
Ralph Nathane01ccf12015-04-16 10:40:32 -0700533
Alex Klein1699fab2022-09-08 08:46:06 -0600534 # Check that BrilloDeployOperation.Run was called.
535 self.assertTrue(run.called)
Ralph Nathane01ccf12015-04-16 10:40:32 -0700536
Alex Klein1699fab2022-09-08 08:46:06 -0600537 def testDeployUnmergeWithProgressBar(self):
538 """Test that BrilloDeployOperation.Run() is called for unmerge."""
539 packages = ["foo", "bar", "foobar"]
540 self.package_scanner.return_value = PackageScannerFake(
541 packages, {"foo": {}, "bar": {}, "foobar": {}}
542 )
Ralph Nathane01ccf12015-04-16 10:40:32 -0700543
Alex Klein1699fab2022-09-08 08:46:06 -0600544 run = self.PatchObject(
545 deploy.BrilloDeployOperation, "Run", return_value=None
546 )
Ralph Nathane01ccf12015-04-16 10:40:32 -0700547
Alex Klein1699fab2022-09-08 08:46:06 -0600548 self.PatchObject(command, "UseProgressBar", return_value=True)
549 deploy.Deploy(
550 None, ["package"], force=True, clean_binpkg=False, emerge=False
551 )
Ralph Nathane01ccf12015-04-16 10:40:32 -0700552
Alex Klein1699fab2022-09-08 08:46:06 -0600553 # Check that BrilloDeployOperation.Run was called.
554 self.assertTrue(run.called)
Ralph Nathane01ccf12015-04-16 10:40:32 -0700555
Alex Klein1699fab2022-09-08 08:46:06 -0600556 def testBrilloDeployMergeOperation(self):
557 """Test that BrilloDeployOperation works for merge."""
Ralph Nathane01ccf12015-04-16 10:40:32 -0700558
Alex Klein1699fab2022-09-08 08:46:06 -0600559 def func(queue):
560 for event in op.MERGE_EVENTS:
561 queue.get()
562 print(event)
563 sys.stdout.flush()
Ralph Nathane01ccf12015-04-16 10:40:32 -0700564
Alex Klein1699fab2022-09-08 08:46:06 -0600565 queue = multiprocessing.Queue()
566 # Emerge one package.
567 op = BrilloDeployOperationFake(True, queue)
Ralph Nathane01ccf12015-04-16 10:40:32 -0700568
Alex Klein1699fab2022-09-08 08:46:06 -0600569 with self.OutputCapturer():
570 op.Run(func, queue)
Ralph Nathane01ccf12015-04-16 10:40:32 -0700571
Alex Klein1699fab2022-09-08 08:46:06 -0600572 # Check that the progress bar prints correctly.
573 self.AssertProgressBarAllEvents(len(op.MERGE_EVENTS))
Ralph Nathane01ccf12015-04-16 10:40:32 -0700574
Alex Klein1699fab2022-09-08 08:46:06 -0600575 def testBrilloDeployUnmergeOperation(self):
576 """Test that BrilloDeployOperation works for unmerge."""
Ralph Nathane01ccf12015-04-16 10:40:32 -0700577
Alex Klein1699fab2022-09-08 08:46:06 -0600578 def func(queue):
579 for event in op.UNMERGE_EVENTS:
580 queue.get()
581 print(event)
582 sys.stdout.flush()
583
584 queue = multiprocessing.Queue()
585 # Unmerge one package.
586 op = BrilloDeployOperationFake(False, queue)
587
588 with self.OutputCapturer():
589 op.Run(func, queue)
590
591 # Check that the progress bar prints correctly.
592 self.AssertProgressBarAllEvents(len(op.UNMERGE_EVENTS))