blob: 2ca8377e4dc3d5a760837f4d807408095b0aed0d [file] [log] [blame]
Evan Hernandezd437b4e2019-03-25 13:48:30 -06001# Copyright 2019 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"""Unittests for Binhost operations."""
6
Michael Mortensenfc823882019-08-27 14:38:07 -06007import os
Mike Frysinger166fea02021-02-12 05:30:33 -05008from unittest import mock
Mike Frysingeref94e4c2020-02-10 23:59:54 -05009
Alex Klein231d2da2019-07-22 16:44:45 -060010from chromite.api import api_config
Evan Hernandezd437b4e2019-03-25 13:48:30 -060011from chromite.api.controller import binhost
12from chromite.api.gen.chromite.api import binhost_pb2
LaMont Jonesc64ae212019-04-15 15:41:28 -060013from chromite.lib import cros_build_lib
Evan Hernandezd437b4e2019-03-25 13:48:30 -060014from chromite.lib import cros_test_lib
Michael Mortensenfc823882019-08-27 14:38:07 -060015from chromite.lib import osutils
Evan Hernandezd437b4e2019-03-25 13:48:30 -060016from chromite.service import binhost as binhost_service
17
Alex Klein231d2da2019-07-22 16:44:45 -060018
Michael Mortensena0af77b2019-11-13 11:15:15 -070019class GetBinhostsTest(cros_test_lib.MockTestCase, api_config.ApiConfigMixin):
20 """Unittests for GetBinhosts."""
21
22 def setUp(self):
23 self.response = binhost_pb2.BinhostGetResponse()
24
25 def testValidateOnly(self):
26 """Sanity check that a validate only call does not execute any logic."""
27 patch = self.PatchObject(binhost_service, 'GetBinhosts')
28
Michael Mortensen42251f92019-11-14 11:01:43 -070029 request = binhost_pb2.BinhostGetRequest()
Michael Mortensena0af77b2019-11-13 11:15:15 -070030 request.build_target.name = 'target'
31 binhost.GetBinhosts(request, self.response, self.validate_only_config)
32 patch.assert_not_called()
33
34 def testMockCall(self):
35 """Test that a mock call does not execute logic, returns mocked value."""
36 patch = self.PatchObject(binhost_service, 'GetBinhosts')
37
38 input_proto = binhost_pb2.BinhostGetRequest()
39 input_proto.build_target.name = 'target'
40
41 binhost.GetBinhosts(input_proto, self.response, self.mock_call_config)
42
43 self.assertEqual(len(self.response.binhosts), 1)
44 self.assertEqual(self.response.binhosts[0].package_index, 'Packages')
45 patch.assert_not_called()
46
47 def testGetBinhosts(self):
48 """GetBinhosts calls service with correct args."""
49 binhost_list = [
50 'gs://cr-prebuilt/board/amd64-generic/paladin-R66-17.0.0-rc2/packages/',
51 'gs://cr-prebuilt/board/eve/paladin-R66-17.0.0-rc2/packages/']
52 get_binhost = self.PatchObject(binhost_service, 'GetBinhosts',
53 return_value=binhost_list)
54
55 input_proto = binhost_pb2.BinhostGetRequest()
56 input_proto.build_target.name = 'target'
57
58 binhost.GetBinhosts(input_proto, self.response, self.api_config)
59
60 self.assertEqual(len(self.response.binhosts), 2)
61 self.assertEqual(self.response.binhosts[0].package_index, 'Packages')
62 get_binhost.assert_called_once_with(mock.ANY)
63
64
Michael Mortensen42251f92019-11-14 11:01:43 -070065class GetPrivatePrebuiltAclArgsTest(cros_test_lib.MockTestCase,
66 api_config.ApiConfigMixin):
67 """Unittests for GetPrivatePrebuiltAclArgs."""
68
69 def setUp(self):
70 self.response = binhost_pb2.AclArgsResponse()
71
72 def testValidateOnly(self):
73 """Sanity check that a validate only call does not execute any logic."""
74 patch = self.PatchObject(binhost_service, 'GetPrebuiltAclArgs')
75
76 request = binhost_pb2.AclArgsRequest()
77 request.build_target.name = 'target'
78 binhost.GetPrivatePrebuiltAclArgs(request, self.response,
79 self.validate_only_config)
80 patch.assert_not_called()
81
82 def testMockCall(self):
83 """Test that a mock call does not execute logic, returns mocked value."""
84 patch = self.PatchObject(binhost_service, 'GetPrebuiltAclArgs')
85
86 input_proto = binhost_pb2.AclArgsRequest()
87 input_proto.build_target.name = 'target'
88
89 binhost.GetPrivatePrebuiltAclArgs(input_proto, self.response,
90 self.mock_call_config)
91
92 self.assertEqual(len(self.response.args), 1)
93 self.assertEqual(self.response.args[0].arg, '-g')
94 self.assertEqual(self.response.args[0].value, 'group1:READ')
95 patch.assert_not_called()
96
97 def testGetPrivatePrebuiltAclArgs(self):
98 """GetPrivatePrebuildAclsArgs calls service with correct args."""
99 argvalue_list = [['-g', 'group1:READ']]
100 get_binhost = self.PatchObject(binhost_service, 'GetPrebuiltAclArgs',
101 return_value=argvalue_list)
102
103 input_proto = binhost_pb2.AclArgsRequest()
104 input_proto.build_target.name = 'target'
105
106 binhost.GetPrivatePrebuiltAclArgs(input_proto, self.response,
107 self.api_config)
108
109 self.assertEqual(len(self.response.args), 1)
110 self.assertEqual(self.response.args[0].arg, '-g')
111 self.assertEqual(self.response.args[0].value, 'group1:READ')
112 get_binhost.assert_called_once_with(mock.ANY)
113
114
Alex Klein231d2da2019-07-22 16:44:45 -0600115class PrepareBinhostUploadsTest(cros_test_lib.MockTestCase,
116 api_config.ApiConfigMixin):
Evan Hernandezd437b4e2019-03-25 13:48:30 -0600117 """Unittests for PrepareBinhostUploads."""
118
119 def setUp(self):
120 self.PatchObject(binhost_service, 'GetPrebuiltsRoot',
121 return_value='/build/target/packages')
122 self.PatchObject(binhost_service, 'GetPrebuiltsFiles',
123 return_value=['foo.tbz2', 'bar.tbz2'])
124 self.PatchObject(binhost_service, 'UpdatePackageIndex',
125 return_value='/build/target/packages/Packages')
126
Alex Klein231d2da2019-07-22 16:44:45 -0600127 self.response = binhost_pb2.PrepareBinhostUploadsResponse()
128
129 def testValidateOnly(self):
130 """Sanity check that a validate only call does not execute any logic."""
131 patch = self.PatchObject(binhost_service, 'GetPrebuiltsRoot')
132
133 request = binhost_pb2.PrepareBinhostUploadsRequest()
134 request.build_target.name = 'target'
135 request.uri = 'gs://chromeos-prebuilt/target'
136 rc = binhost.PrepareBinhostUploads(request, self.response,
137 self.validate_only_config)
138 patch.assert_not_called()
139 self.assertEqual(rc, 0)
140
Michael Mortensen42251f92019-11-14 11:01:43 -0700141 def testMockCall(self):
142 """Test that a mock call does not execute logic, returns mocked value."""
143 patch = self.PatchObject(binhost_service, 'GetPrebuiltsRoot')
144
145 request = binhost_pb2.PrepareBinhostUploadsRequest()
146 request.build_target.name = 'target'
147 request.uri = 'gs://chromeos-prebuilt/target'
148 rc = binhost.PrepareBinhostUploads(request, self.response,
149 self.mock_call_config)
150 self.assertEqual(self.response.uploads_dir, '/upload/directory')
151 self.assertEqual(self.response.upload_targets[0].path, 'upload_target')
152 patch.assert_not_called()
153 self.assertEqual(rc, 0)
154
Evan Hernandezd437b4e2019-03-25 13:48:30 -0600155 def testPrepareBinhostUploads(self):
156 """PrepareBinhostUploads returns Packages and tar files."""
157 input_proto = binhost_pb2.PrepareBinhostUploadsRequest()
158 input_proto.build_target.name = 'target'
159 input_proto.uri = 'gs://chromeos-prebuilt/target'
Alex Klein231d2da2019-07-22 16:44:45 -0600160 binhost.PrepareBinhostUploads(input_proto, self.response, self.api_config)
161 self.assertEqual(self.response.uploads_dir, '/build/target/packages')
Mike Frysinger678735c2019-09-28 18:23:28 -0400162 self.assertCountEqual(
Alex Klein231d2da2019-07-22 16:44:45 -0600163 [ut.path for ut in self.response.upload_targets],
Evan Hernandezd437b4e2019-03-25 13:48:30 -0600164 ['Packages', 'foo.tbz2', 'bar.tbz2'])
165
166 def testPrepareBinhostUploadsNonGsUri(self):
167 """PrepareBinhostUploads dies when URI does not point to GS."""
168 input_proto = binhost_pb2.PrepareBinhostUploadsRequest()
169 input_proto.build_target.name = 'target'
170 input_proto.uri = 'https://foo.bar'
Evan Hernandezd437b4e2019-03-25 13:48:30 -0600171 with self.assertRaises(ValueError):
Alex Klein231d2da2019-07-22 16:44:45 -0600172 binhost.PrepareBinhostUploads(input_proto, self.response, self.api_config)
Evan Hernandezd437b4e2019-03-25 13:48:30 -0600173
174
Alex Klein231d2da2019-07-22 16:44:45 -0600175class SetBinhostTest(cros_test_lib.MockTestCase, api_config.ApiConfigMixin):
Evan Hernandezd437b4e2019-03-25 13:48:30 -0600176 """Unittests for SetBinhost."""
177
Alex Klein231d2da2019-07-22 16:44:45 -0600178 def setUp(self):
179 self.response = binhost_pb2.SetBinhostResponse()
180
181 def testValidateOnly(self):
182 """Sanity check that a validate only call does not execute any logic."""
Michael Mortensen42251f92019-11-14 11:01:43 -0700183 patch = self.PatchObject(binhost_service, 'SetBinhost')
Alex Klein231d2da2019-07-22 16:44:45 -0600184
Michael Mortensen42251f92019-11-14 11:01:43 -0700185 request = binhost_pb2.SetBinhostRequest()
Alex Klein231d2da2019-07-22 16:44:45 -0600186 request.build_target.name = 'target'
Michael Mortensen42251f92019-11-14 11:01:43 -0700187 request.key = binhost_pb2.POSTSUBMIT_BINHOST
Alex Klein231d2da2019-07-22 16:44:45 -0600188 request.uri = 'gs://chromeos-prebuilt/target'
Michael Mortensen42251f92019-11-14 11:01:43 -0700189 binhost.SetBinhost(request, self.response, self.validate_only_config)
Alex Klein231d2da2019-07-22 16:44:45 -0600190 patch.assert_not_called()
191
Michael Mortensen42251f92019-11-14 11:01:43 -0700192 def testMockCall(self):
193 """Test that a mock call does not execute logic, returns mocked value."""
194 patch = self.PatchObject(binhost_service, 'SetBinhost')
195
196 request = binhost_pb2.SetBinhostRequest()
197 request.build_target.name = 'target'
198 request.key = binhost_pb2.POSTSUBMIT_BINHOST
199 request.uri = 'gs://chromeos-prebuilt/target'
200 binhost.SetBinhost(request, self.response, self.mock_call_config)
201 patch.assert_not_called()
202 self.assertEqual(self.response.output_file, '/path/to/BINHOST.conf')
203
Evan Hernandezd437b4e2019-03-25 13:48:30 -0600204 def testSetBinhost(self):
205 """SetBinhost calls service with correct args."""
206 set_binhost = self.PatchObject(binhost_service, 'SetBinhost',
207 return_value='/path/to/BINHOST.conf')
208
209 input_proto = binhost_pb2.SetBinhostRequest()
210 input_proto.build_target.name = 'target'
211 input_proto.private = True
212 input_proto.key = binhost_pb2.POSTSUBMIT_BINHOST
213 input_proto.uri = 'gs://chromeos-prebuilt/target'
214
Alex Klein231d2da2019-07-22 16:44:45 -0600215 binhost.SetBinhost(input_proto, self.response, self.api_config)
Evan Hernandezd437b4e2019-03-25 13:48:30 -0600216
Alex Klein231d2da2019-07-22 16:44:45 -0600217 self.assertEqual(self.response.output_file, '/path/to/BINHOST.conf')
LaMont Jonesc64ae212019-04-15 15:41:28 -0600218 set_binhost.assert_called_once_with(
Alex Kleinc010de02019-10-11 15:44:04 -0600219 'target',
220 'POSTSUBMIT_BINHOST',
221 'gs://chromeos-prebuilt/target',
222 private=True)
LaMont Jonesc64ae212019-04-15 15:41:28 -0600223
Alex Klein231d2da2019-07-22 16:44:45 -0600224
225class RegenBuildCacheTest(cros_test_lib.MockTestCase,
226 api_config.ApiConfigMixin):
LaMont Jonesc64ae212019-04-15 15:41:28 -0600227 """Unittests for RegenBuildCache."""
228
Alex Klein231d2da2019-07-22 16:44:45 -0600229 def setUp(self):
230 self.response = binhost_pb2.RegenBuildCacheResponse()
231
232 def testValidateOnly(self):
233 """Sanity check that a validate only call does not execute any logic."""
234 patch = self.PatchObject(binhost_service, 'RegenBuildCache')
235
236 request = binhost_pb2.RegenBuildCacheRequest()
237 request.overlay_type = binhost_pb2.OVERLAYTYPE_BOTH
238 binhost.RegenBuildCache(request, self.response, self.validate_only_config)
239 patch.assert_not_called()
240
Michael Mortensen42251f92019-11-14 11:01:43 -0700241 def testMockCall(self):
242 """Test that a mock call does not execute logic, returns mocked value."""
243 patch = self.PatchObject(binhost_service, 'RegenBuildCache')
244
245 request = binhost_pb2.RegenBuildCacheRequest()
246 request.overlay_type = binhost_pb2.OVERLAYTYPE_BOTH
247 binhost.RegenBuildCache(request, self.response, self.mock_call_config)
248 patch.assert_not_called()
249 self.assertEqual(len(self.response.modified_overlays), 1)
250 self.assertEqual(self.response.modified_overlays[0].path,
251 '/path/to/BuildCache')
252
253
LaMont Jonesc64ae212019-04-15 15:41:28 -0600254 def testRegenBuildCache(self):
255 """RegenBuildCache calls service with the correct args."""
256 regen_cache = self.PatchObject(binhost_service, 'RegenBuildCache')
257
258 input_proto = binhost_pb2.RegenBuildCacheRequest()
259 input_proto.overlay_type = binhost_pb2.OVERLAYTYPE_BOTH
LaMont Jonesc64ae212019-04-15 15:41:28 -0600260
Alex Klein231d2da2019-07-22 16:44:45 -0600261 binhost.RegenBuildCache(input_proto, self.response, self.api_config)
Alex Klein82c85d42019-08-14 15:47:51 -0600262 regen_cache.assert_called_once_with(mock.ANY, 'both')
LaMont Jonesc64ae212019-04-15 15:41:28 -0600263
264 def testRequiresOverlayType(self):
265 """RegenBuildCache dies if overlay_type not specified."""
266 regen_cache = self.PatchObject(binhost_service, 'RegenBuildCache')
LaMont Jonesc64ae212019-04-15 15:41:28 -0600267
268 input_proto = binhost_pb2.RegenBuildCacheRequest()
269 input_proto.overlay_type = binhost_pb2.OVERLAYTYPE_UNSPECIFIED
LaMont Jonesc64ae212019-04-15 15:41:28 -0600270
Alex Klein231d2da2019-07-22 16:44:45 -0600271 with self.assertRaises(cros_build_lib.DieSystemExit):
272 binhost.RegenBuildCache(input_proto, self.response, self.api_config)
LaMont Jonesc64ae212019-04-15 15:41:28 -0600273 regen_cache.assert_not_called()
Michael Mortensenfc823882019-08-27 14:38:07 -0600274
275
276class PrepareDevInstallerBinhostUploadsTest(cros_test_lib.MockTempDirTestCase,
277 api_config.ApiConfigMixin):
278 """Tests for the UploadDevInstallerPrebuilts stage."""
279 def setUp(self):
280 # target packages dir
281 self.chroot_path = os.path.join(self.tempdir, 'chroot')
282 self.sysroot_path = '/build/target'
283 self.chroot_path = os.path.join(self.tempdir, 'chroot')
284 full_sysroot_path = os.path.join(self.chroot_path,
285 self.sysroot_path.lstrip(os.sep))
286 self.full_sysroot_package_path = os.path.join(full_sysroot_path,
287 'packages')
288 osutils.SafeMakedirs(self.full_sysroot_package_path)
289 self.uploads_dir = os.path.join(self.tempdir, 'uploads_dir')
290 osutils.SafeMakedirs(self.uploads_dir)
291 # Create packages/Packages file
292 packages_file = os.path.join(self.full_sysroot_package_path, 'Packages')
293 packages_content = """\
294USE: test
295
296CPV: app-arch/brotli-1.0.6
297
298CPV: app-arch/zip-3.0-r3
299
300CPV: chromeos-base/shill-0.0.1-r1
301
302CPV: chromeos-base/test-0.0.1-r1
303
304CPV: virtual/chromium-os-printing-1-r4
305
306CPV: virtual/python-enum34-1
307
308"""
309 osutils.WriteFile(packages_file, packages_content)
310
311
312 # Create package.installable file
313 self.dev_install_packages = ['app-arch/zip-3.0-r3',
314 'virtual/chromium-os-printing-1-r4',
315 'virtual/python-enum34-1']
316 package_installable_dir = os.path.join(full_sysroot_path,
317 'build/dev-install')
318 osutils.SafeMakedirs(package_installable_dir)
319 package_installable_filename = os.path.join(package_installable_dir,
320 'package.installable')
321
322 # Create path to the dev_install_packages
323 packages_dir = os.path.join(full_sysroot_path, 'packages')
324 osutils.SafeMakedirs(packages_dir)
325 for package in self.dev_install_packages:
326 # Since a package has a category, such as app-arch/zip-3.0-r3, we need
327 # to create the packages_dir / category dir as needed.
328 category = package.split(os.sep)[0]
329 osutils.SafeMakedirs(os.path.join(packages_dir, category))
330 package_tbz2_file = os.path.join(packages_dir, package) + '.tbz2'
331 osutils.Touch(package_tbz2_file)
332 package_installable_file = open(package_installable_filename, 'w')
333 for package in self.dev_install_packages:
334 package_installable_file.write(package + '\n')
335 package_installable_file.close()
336 self.response = binhost_pb2.PrepareDevInstallBinhostUploadsResponse()
337
Michael Mortensen42251f92019-11-14 11:01:43 -0700338 def testValidateOnly(self):
339 """Sanity check that a validate only call does not execute any logic."""
340 patch = self.PatchObject(binhost_service,
341 'ReadDevInstallFilesToCreatePackageIndex')
342
343 input_proto = binhost_pb2.PrepareDevInstallBinhostUploadsRequest()
344 input_proto.uri = 'gs://chromeos-prebuilt/target'
345 input_proto.chroot.path = self.chroot_path
346 input_proto.sysroot.path = self.sysroot_path
347 input_proto.uploads_dir = self.uploads_dir
348 binhost.PrepareDevInstallBinhostUploads(input_proto, self.response,
349 self.validate_only_config)
350 patch.assert_not_called()
351
352 def testMockCall(self):
353 """Test that a mock call does not execute logic, returns mocked value."""
354 patch = self.PatchObject(binhost_service,
355 'ReadDevInstallFilesToCreatePackageIndex')
356
357 input_proto = binhost_pb2.PrepareDevInstallBinhostUploadsRequest()
358 input_proto.uri = 'gs://chromeos-prebuilt/target'
359 input_proto.chroot.path = self.chroot_path
360 input_proto.sysroot.path = self.sysroot_path
361 input_proto.uploads_dir = self.uploads_dir
362 binhost.PrepareDevInstallBinhostUploads(input_proto, self.response,
363 self.mock_call_config)
364 self.assertEqual(len(self.response.upload_targets), 3)
365 self.assertEqual(self.response.upload_targets[2].path, 'Packages')
366 patch.assert_not_called()
367
Michael Mortensenfc823882019-08-27 14:38:07 -0600368 def testDevInstallerUpload(self):
369 """Basic sanity test testing uploads of dev installer prebuilts."""
370 # self.RunStage()
371 input_proto = binhost_pb2.PrepareDevInstallBinhostUploadsRequest()
372 input_proto.uri = 'gs://chromeos-prebuilt/target'
373 input_proto.chroot.path = self.chroot_path
374 input_proto.sysroot.path = self.sysroot_path
375 input_proto.uploads_dir = self.uploads_dir
376 # Call method under test
377 binhost.PrepareDevInstallBinhostUploads(input_proto, self.response,
378 self.api_config)
379 # Verify results
380 expected_upload_targets = ['app-arch/zip-3.0-r3.tbz2',
381 'virtual/chromium-os-printing-1-r4.tbz2',
382 'virtual/python-enum34-1.tbz2',
383 'Packages']
Mike Frysinger678735c2019-09-28 18:23:28 -0400384 self.assertCountEqual(
Michael Mortensenfc823882019-08-27 14:38:07 -0600385 [ut.path for ut in self.response.upload_targets],
386 expected_upload_targets)
387 # All of the upload_targets should also be in the uploads_directory
388 for target in self.response.upload_targets:
389 self.assertExists(os.path.join(input_proto.uploads_dir, target.path))
390
391 def testPrepareBinhostUploadsNonGsUri(self):
392 """PrepareBinhostUploads dies when URI does not point to GS."""
393 input_proto = binhost_pb2.PrepareDevInstallBinhostUploadsRequest()
394 input_proto.chroot.path = self.chroot_path
395 input_proto.sysroot.path = self.sysroot_path
396 input_proto.uploads_dir = self.uploads_dir
397 input_proto.uri = 'https://foo.bar'
398 with self.assertRaises(ValueError):
399 binhost.PrepareDevInstallBinhostUploads(input_proto, self.response,
400 self.api_config)