blob: 8d2c0af7e849d306dca77e231946a29b817f5cd0 [file] [log] [blame]
David Pursell9476bf42015-03-30 13:34:27 -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 deploy module."""
6
7from __future__ import print_function
8
9import json
10import os
11
12from chromite.cli import deploy
13from chromite.lib import cros_build_lib
14from chromite.lib import cros_test_lib
15try:
16 import portage
17except ImportError:
18 if cros_build_lib.IsInsideChroot():
19 raise
20
21
22# pylint: disable=protected-access
23
24
25class ChromiumOSDeviceHandlerFake(object):
26 """Fake for chromite.lib.remote_access.ChomiumOSDeviceHandler."""
27
28 class RemoteAccessFake(object):
29 """Fake for chromite.lib.remote_access.RemoteAccess."""
30
31 def __init__(self):
32 self.remote_sh_output = None
33
34 def RemoteSh(self, *_args, **_kwargs):
35 return cros_build_lib.CommandResult(output=self.remote_sh_output)
36
37 def __init__(self):
38 self.agent = self.RemoteAccessFake()
39
40
41class DbApiFake(object):
42 """Fake for Portage dbapi."""
43
44 def __init__(self, pkgs):
45 self.pkg_db = {}
46 for cpv, slot, rdeps_raw, build_time in pkgs:
47 self.pkg_db[cpv] = {
48 'SLOT': slot, 'RDEPEND': rdeps_raw, 'BUILD_TIME': build_time}
49
50 def cpv_all(self):
51 return self.pkg_db.keys()
52
53 def aux_get(self, cpv, keys):
54 pkg_info = self.pkg_db[cpv]
55 return [pkg_info[key] for key in keys]
56
57
58class PortageTreeFake(object):
59 """Fake for Portage tree."""
60
61 def __init__(self, dbapi):
62 self.dbapi = dbapi
63
64
65class TestInstallPackageScanner(cros_test_lib.MockTestCase):
66 """Test the update package scanner."""
67 _BOARD = 'foo_board'
68 _BUILD_ROOT = '/build/%s' % _BOARD
69 _VARTREE = [
70 ('foo/app1-1.2.3-r4', '0', 'foo/app2 !foo/app3', '1413309336'),
71 ('foo/app2-4.5.6-r7', '0', '', '1413309336'),
72 ('foo/app4-2.0.0-r1', '0', 'foo/app1 foo/app5', '1413309336'),
73 ('foo/app5-3.0.7-r3', '0', '', '1413309336'),
74 ]
75
76 def setUp(self):
77 """Patch imported modules."""
78 self.PatchObject(cros_build_lib, 'GetChoice', return_value=0)
79 self.device = ChromiumOSDeviceHandlerFake()
80 self.scanner = deploy._InstallPackageScanner(self._BUILD_ROOT)
81
82 def SetupVartree(self, vartree_pkgs):
83 self.device.agent.remote_sh_output = json.dumps(vartree_pkgs)
84
85 def SetupBintree(self, bintree_pkgs):
86 bintree = PortageTreeFake(DbApiFake(bintree_pkgs))
87 build_root = os.path.join(self._BUILD_ROOT, '')
88 portage_db = {build_root: {'bintree': bintree}}
89 self.PatchObject(portage, 'create_trees', return_value=portage_db)
90
91 def ValidatePkgs(self, actual, expected, constraints=None):
92 # Containing exactly the same packages.
93 self.assertEquals(sorted(expected), sorted(actual))
94 # Packages appear in the right order.
95 if constraints is not None:
96 for needs, needed in constraints:
97 self.assertGreater(actual.index(needs), actual.index(needed))
98
99 def testRunUpdatedVersion(self):
100 self.SetupVartree(self._VARTREE)
101 app1 = 'foo/app1-1.2.5-r4'
102 self.SetupBintree([
103 (app1, '0', 'foo/app2 !foo/app3', '1413309336'),
104 ('foo/app2-4.5.6-r7', '0', '', '1413309336'),
105 ])
106 installs, listed, num_updates = self.scanner.Run(
107 self.device, '/', ['app1'], True, True, True)
108 self.ValidatePkgs(installs, [app1])
109 self.ValidatePkgs(listed, [app1])
110 self.assertEquals(num_updates, 1)
111
112 def testRunUpdatedBuildTime(self):
113 self.SetupVartree(self._VARTREE)
114 app1 = 'foo/app1-1.2.3-r4'
115 self.SetupBintree([
116 (app1, '0', 'foo/app2 !foo/app3', '1413309350'),
117 ('foo/app2-4.5.6-r7', '0', '', '1413309336'),
118 ])
119 installs, listed, num_updates = self.scanner.Run(
120 self.device, '/', ['app1'], True, True, True)
121 self.ValidatePkgs(installs, [app1])
122 self.ValidatePkgs(listed, [app1])
123 self.assertEquals(num_updates, 1)
124
125 def testRunExistingDepUpdated(self):
126 self.SetupVartree(self._VARTREE)
127 app1 = 'foo/app1-1.2.5-r2'
128 app2 = 'foo/app2-4.5.8-r3'
129 self.SetupBintree([
130 (app1, '0', 'foo/app2 !foo/app3', '1413309350'),
131 (app2, '0', '', '1413309350'),
132 ])
133 installs, listed, num_updates = self.scanner.Run(
134 self.device, '/', ['app1'], True, True, True)
135 self.ValidatePkgs(installs, [app1, app2], constraints=[(app1, app2)])
136 self.ValidatePkgs(listed, [app1])
137 self.assertEquals(num_updates, 2)
138
139 def testRunMissingDepUpdated(self):
140 self.SetupVartree(self._VARTREE)
141 app1 = 'foo/app1-1.2.5-r2'
142 app6 = 'foo/app6-1.0.0-r1'
143 self.SetupBintree([
144 (app1, '0', 'foo/app2 !foo/app3 foo/app6', '1413309350'),
145 ('foo/app2-4.5.6-r7', '0', '', '1413309336'),
146 (app6, '0', '', '1413309350'),
147 ])
148 installs, listed, num_updates = self.scanner.Run(
149 self.device, '/', ['app1'], True, True, True)
150 self.ValidatePkgs(installs, [app1, app6], constraints=[(app1, app6)])
151 self.ValidatePkgs(listed, [app1])
152 self.assertEquals(num_updates, 1)
153
154 def testRunExistingRevDepUpdated(self):
155 self.SetupVartree(self._VARTREE)
156 app1 = 'foo/app1-1.2.5-r2'
157 app4 = 'foo/app4-2.0.1-r3'
158 self.SetupBintree([
159 (app1, '0', 'foo/app2 !foo/app3', '1413309350'),
160 (app4, '0', 'foo/app1 foo/app5', '1413309350'),
161 ('foo/app5-3.0.7-r3', '0', '', '1413309336'),
162 ])
163 installs, listed, num_updates = self.scanner.Run(
164 self.device, '/', ['app1'], True, True, True)
165 self.ValidatePkgs(installs, [app1, app4], constraints=[(app4, app1)])
166 self.ValidatePkgs(listed, [app1])
167 self.assertEquals(num_updates, 2)
168
169 def testRunMissingRevDepNotUpdated(self):
170 self.SetupVartree(self._VARTREE)
171 app1 = 'foo/app1-1.2.5-r2'
172 app6 = 'foo/app6-1.0.0-r1'
173 self.SetupBintree([
174 (app1, '0', 'foo/app2 !foo/app3', '1413309350'),
175 (app6, '0', 'foo/app1', '1413309350'),
176 ])
177 installs, listed, num_updates = self.scanner.Run(
178 self.device, '/', ['app1'], True, True, True)
179 self.ValidatePkgs(installs, [app1])
180 self.ValidatePkgs(listed, [app1])
181 self.assertEquals(num_updates, 1)
182
183 def testRunTransitiveDepsUpdated(self):
184 self.SetupVartree(self._VARTREE)
185 app1 = 'foo/app1-1.2.5-r2'
186 app2 = 'foo/app2-4.5.8-r3'
187 app4 = 'foo/app4-2.0.0-r1'
188 app5 = 'foo/app5-3.0.8-r2'
189 self.SetupBintree([
190 (app1, '0', 'foo/app2 !foo/app3', '1413309350'),
191 (app2, '0', '', '1413309350'),
192 (app4, '0', 'foo/app1 foo/app5', '1413309350'),
193 (app5, '0', '', '1413309350'),
194 ])
195 installs, listed, num_updates = self.scanner.Run(
196 self.device, '/', ['app1'], True, True, True)
197 self.ValidatePkgs(installs, [app1, app2, app4, app5],
198 constraints=[(app1, app2), (app4, app1), (app4, app5)])
199 self.ValidatePkgs(listed, [app1])
200 self.assertEquals(num_updates, 4)
201
202 def testRunDisjunctiveDepsExistingUpdated(self):
203 self.SetupVartree(self._VARTREE)
204 app1 = 'foo/app1-1.2.5-r2'
205 self.SetupBintree([
206 (app1, '0', '|| ( foo/app6 foo/app2 ) !foo/app3', '1413309350'),
207 ('foo/app2-4.5.6-r7', '0', '', '1413309336'),
208 ])
209 installs, listed, num_updates = self.scanner.Run(
210 self.device, '/', ['app1'], True, True, True)
211 self.ValidatePkgs(installs, [app1])
212 self.ValidatePkgs(listed, [app1])
213 self.assertEquals(num_updates, 1)
214
215 def testRunDisjunctiveDepsDefaultUpdated(self):
216 self.SetupVartree(self._VARTREE)
217 app1 = 'foo/app1-1.2.5-r2'
218 app7 = 'foo/app7-1.0.0-r1'
219 self.SetupBintree([
220 (app1, '0', '|| ( foo/app6 foo/app7 ) !foo/app3', '1413309350'),
221 (app7, '0', '', '1413309350'),
222 ])
223 installs, listed, num_updates = self.scanner.Run(
224 self.device, '/', ['app1'], True, True, True)
225 self.ValidatePkgs(installs, [app1, app7], constraints=[(app1, app7)])
226 self.ValidatePkgs(listed, [app1])
227 self.assertEquals(num_updates, 1)