blob: e494c649cabf54487789e8ce28a5f97ecf736be1 [file] [log] [blame]
Evan Hernandezd437b4e2019-03-25 13:48:30 -06001# -*- coding: utf-8 -*-
2# Copyright 2019 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
6"""Unittests for Binhost operations."""
7
8from __future__ import print_function
9
Michael Mortensenfc823882019-08-27 14:38:07 -060010import os
Alex Klein82c85d42019-08-14 15:47:51 -060011import mock
12
Alex Klein231d2da2019-07-22 16:44:45 -060013from chromite.api import api_config
Evan Hernandezd437b4e2019-03-25 13:48:30 -060014from chromite.api.controller import binhost
15from chromite.api.gen.chromite.api import binhost_pb2
LaMont Jonesc64ae212019-04-15 15:41:28 -060016from chromite.lib import cros_build_lib
Evan Hernandezd437b4e2019-03-25 13:48:30 -060017from chromite.lib import cros_test_lib
Michael Mortensenfc823882019-08-27 14:38:07 -060018from chromite.lib import osutils
Evan Hernandezd437b4e2019-03-25 13:48:30 -060019from chromite.service import binhost as binhost_service
20
Alex Klein231d2da2019-07-22 16:44:45 -060021
Michael Mortensena0af77b2019-11-13 11:15:15 -070022class GetBinhostsTest(cros_test_lib.MockTestCase, api_config.ApiConfigMixin):
23 """Unittests for GetBinhosts."""
24
25 def setUp(self):
26 self.response = binhost_pb2.BinhostGetResponse()
27
28 def testValidateOnly(self):
29 """Sanity check that a validate only call does not execute any logic."""
30 patch = self.PatchObject(binhost_service, 'GetBinhosts')
31
Michael Mortensen42251f92019-11-14 11:01:43 -070032 request = binhost_pb2.BinhostGetRequest()
Michael Mortensena0af77b2019-11-13 11:15:15 -070033 request.build_target.name = 'target'
34 binhost.GetBinhosts(request, self.response, self.validate_only_config)
35 patch.assert_not_called()
36
37 def testMockCall(self):
38 """Test that a mock call does not execute logic, returns mocked value."""
39 patch = self.PatchObject(binhost_service, 'GetBinhosts')
40
41 input_proto = binhost_pb2.BinhostGetRequest()
42 input_proto.build_target.name = 'target'
43
44 binhost.GetBinhosts(input_proto, self.response, self.mock_call_config)
45
46 self.assertEqual(len(self.response.binhosts), 1)
47 self.assertEqual(self.response.binhosts[0].package_index, 'Packages')
48 patch.assert_not_called()
49
50 def testGetBinhosts(self):
51 """GetBinhosts calls service with correct args."""
52 binhost_list = [
53 'gs://cr-prebuilt/board/amd64-generic/paladin-R66-17.0.0-rc2/packages/',
54 'gs://cr-prebuilt/board/eve/paladin-R66-17.0.0-rc2/packages/']
55 get_binhost = self.PatchObject(binhost_service, 'GetBinhosts',
56 return_value=binhost_list)
57
58 input_proto = binhost_pb2.BinhostGetRequest()
59 input_proto.build_target.name = 'target'
60
61 binhost.GetBinhosts(input_proto, self.response, self.api_config)
62
63 self.assertEqual(len(self.response.binhosts), 2)
64 self.assertEqual(self.response.binhosts[0].package_index, 'Packages')
65 get_binhost.assert_called_once_with(mock.ANY)
66
67
Michael Mortensen42251f92019-11-14 11:01:43 -070068class GetPrivatePrebuiltAclArgsTest(cros_test_lib.MockTestCase,
69 api_config.ApiConfigMixin):
70 """Unittests for GetPrivatePrebuiltAclArgs."""
71
72 def setUp(self):
73 self.response = binhost_pb2.AclArgsResponse()
74
75 def testValidateOnly(self):
76 """Sanity check that a validate only call does not execute any logic."""
77 patch = self.PatchObject(binhost_service, 'GetPrebuiltAclArgs')
78
79 request = binhost_pb2.AclArgsRequest()
80 request.build_target.name = 'target'
81 binhost.GetPrivatePrebuiltAclArgs(request, self.response,
82 self.validate_only_config)
83 patch.assert_not_called()
84
85 def testMockCall(self):
86 """Test that a mock call does not execute logic, returns mocked value."""
87 patch = self.PatchObject(binhost_service, 'GetPrebuiltAclArgs')
88
89 input_proto = binhost_pb2.AclArgsRequest()
90 input_proto.build_target.name = 'target'
91
92 binhost.GetPrivatePrebuiltAclArgs(input_proto, self.response,
93 self.mock_call_config)
94
95 self.assertEqual(len(self.response.args), 1)
96 self.assertEqual(self.response.args[0].arg, '-g')
97 self.assertEqual(self.response.args[0].value, 'group1:READ')
98 patch.assert_not_called()
99
100 def testGetPrivatePrebuiltAclArgs(self):
101 """GetPrivatePrebuildAclsArgs calls service with correct args."""
102 argvalue_list = [['-g', 'group1:READ']]
103 get_binhost = self.PatchObject(binhost_service, 'GetPrebuiltAclArgs',
104 return_value=argvalue_list)
105
106 input_proto = binhost_pb2.AclArgsRequest()
107 input_proto.build_target.name = 'target'
108
109 binhost.GetPrivatePrebuiltAclArgs(input_proto, self.response,
110 self.api_config)
111
112 self.assertEqual(len(self.response.args), 1)
113 self.assertEqual(self.response.args[0].arg, '-g')
114 self.assertEqual(self.response.args[0].value, 'group1:READ')
115 get_binhost.assert_called_once_with(mock.ANY)
116
117
Alex Klein231d2da2019-07-22 16:44:45 -0600118class PrepareBinhostUploadsTest(cros_test_lib.MockTestCase,
119 api_config.ApiConfigMixin):
Evan Hernandezd437b4e2019-03-25 13:48:30 -0600120 """Unittests for PrepareBinhostUploads."""
121
122 def setUp(self):
123 self.PatchObject(binhost_service, 'GetPrebuiltsRoot',
124 return_value='/build/target/packages')
125 self.PatchObject(binhost_service, 'GetPrebuiltsFiles',
126 return_value=['foo.tbz2', 'bar.tbz2'])
127 self.PatchObject(binhost_service, 'UpdatePackageIndex',
128 return_value='/build/target/packages/Packages')
129
Alex Klein231d2da2019-07-22 16:44:45 -0600130 self.response = binhost_pb2.PrepareBinhostUploadsResponse()
131
132 def testValidateOnly(self):
133 """Sanity check that a validate only call does not execute any logic."""
134 patch = self.PatchObject(binhost_service, 'GetPrebuiltsRoot')
135
136 request = binhost_pb2.PrepareBinhostUploadsRequest()
137 request.build_target.name = 'target'
138 request.uri = 'gs://chromeos-prebuilt/target'
139 rc = binhost.PrepareBinhostUploads(request, self.response,
140 self.validate_only_config)
141 patch.assert_not_called()
142 self.assertEqual(rc, 0)
143
Michael Mortensen42251f92019-11-14 11:01:43 -0700144 def testMockCall(self):
145 """Test that a mock call does not execute logic, returns mocked value."""
146 patch = self.PatchObject(binhost_service, 'GetPrebuiltsRoot')
147
148 request = binhost_pb2.PrepareBinhostUploadsRequest()
149 request.build_target.name = 'target'
150 request.uri = 'gs://chromeos-prebuilt/target'
151 rc = binhost.PrepareBinhostUploads(request, self.response,
152 self.mock_call_config)
153 self.assertEqual(self.response.uploads_dir, '/upload/directory')
154 self.assertEqual(self.response.upload_targets[0].path, 'upload_target')
155 patch.assert_not_called()
156 self.assertEqual(rc, 0)
157
Evan Hernandezd437b4e2019-03-25 13:48:30 -0600158 def testPrepareBinhostUploads(self):
159 """PrepareBinhostUploads returns Packages and tar files."""
160 input_proto = binhost_pb2.PrepareBinhostUploadsRequest()
161 input_proto.build_target.name = 'target'
162 input_proto.uri = 'gs://chromeos-prebuilt/target'
Alex Klein231d2da2019-07-22 16:44:45 -0600163 binhost.PrepareBinhostUploads(input_proto, self.response, self.api_config)
164 self.assertEqual(self.response.uploads_dir, '/build/target/packages')
Mike Frysinger678735c2019-09-28 18:23:28 -0400165 self.assertCountEqual(
Alex Klein231d2da2019-07-22 16:44:45 -0600166 [ut.path for ut in self.response.upload_targets],
Evan Hernandezd437b4e2019-03-25 13:48:30 -0600167 ['Packages', 'foo.tbz2', 'bar.tbz2'])
168
169 def testPrepareBinhostUploadsNonGsUri(self):
170 """PrepareBinhostUploads dies when URI does not point to GS."""
171 input_proto = binhost_pb2.PrepareBinhostUploadsRequest()
172 input_proto.build_target.name = 'target'
173 input_proto.uri = 'https://foo.bar'
Evan Hernandezd437b4e2019-03-25 13:48:30 -0600174 with self.assertRaises(ValueError):
Alex Klein231d2da2019-07-22 16:44:45 -0600175 binhost.PrepareBinhostUploads(input_proto, self.response, self.api_config)
Evan Hernandezd437b4e2019-03-25 13:48:30 -0600176
177
Alex Klein231d2da2019-07-22 16:44:45 -0600178class SetBinhostTest(cros_test_lib.MockTestCase, api_config.ApiConfigMixin):
Evan Hernandezd437b4e2019-03-25 13:48:30 -0600179 """Unittests for SetBinhost."""
180
Alex Klein231d2da2019-07-22 16:44:45 -0600181 def setUp(self):
182 self.response = binhost_pb2.SetBinhostResponse()
183
184 def testValidateOnly(self):
185 """Sanity check that a validate only call does not execute any logic."""
Michael Mortensen42251f92019-11-14 11:01:43 -0700186 patch = self.PatchObject(binhost_service, 'SetBinhost')
Alex Klein231d2da2019-07-22 16:44:45 -0600187
Michael Mortensen42251f92019-11-14 11:01:43 -0700188 request = binhost_pb2.SetBinhostRequest()
Alex Klein231d2da2019-07-22 16:44:45 -0600189 request.build_target.name = 'target'
Michael Mortensen42251f92019-11-14 11:01:43 -0700190 request.key = binhost_pb2.POSTSUBMIT_BINHOST
Alex Klein231d2da2019-07-22 16:44:45 -0600191 request.uri = 'gs://chromeos-prebuilt/target'
Michael Mortensen42251f92019-11-14 11:01:43 -0700192 binhost.SetBinhost(request, self.response, self.validate_only_config)
Alex Klein231d2da2019-07-22 16:44:45 -0600193 patch.assert_not_called()
194
Michael Mortensen42251f92019-11-14 11:01:43 -0700195 def testMockCall(self):
196 """Test that a mock call does not execute logic, returns mocked value."""
197 patch = self.PatchObject(binhost_service, 'SetBinhost')
198
199 request = binhost_pb2.SetBinhostRequest()
200 request.build_target.name = 'target'
201 request.key = binhost_pb2.POSTSUBMIT_BINHOST
202 request.uri = 'gs://chromeos-prebuilt/target'
203 binhost.SetBinhost(request, self.response, self.mock_call_config)
204 patch.assert_not_called()
205 self.assertEqual(self.response.output_file, '/path/to/BINHOST.conf')
206
Evan Hernandezd437b4e2019-03-25 13:48:30 -0600207 def testSetBinhost(self):
208 """SetBinhost calls service with correct args."""
209 set_binhost = self.PatchObject(binhost_service, 'SetBinhost',
210 return_value='/path/to/BINHOST.conf')
211
212 input_proto = binhost_pb2.SetBinhostRequest()
213 input_proto.build_target.name = 'target'
214 input_proto.private = True
215 input_proto.key = binhost_pb2.POSTSUBMIT_BINHOST
216 input_proto.uri = 'gs://chromeos-prebuilt/target'
217
Alex Klein231d2da2019-07-22 16:44:45 -0600218 binhost.SetBinhost(input_proto, self.response, self.api_config)
Evan Hernandezd437b4e2019-03-25 13:48:30 -0600219
Alex Klein231d2da2019-07-22 16:44:45 -0600220 self.assertEqual(self.response.output_file, '/path/to/BINHOST.conf')
LaMont Jonesc64ae212019-04-15 15:41:28 -0600221 set_binhost.assert_called_once_with(
Alex Kleinc010de02019-10-11 15:44:04 -0600222 'target',
223 'POSTSUBMIT_BINHOST',
224 'gs://chromeos-prebuilt/target',
225 private=True)
LaMont Jonesc64ae212019-04-15 15:41:28 -0600226
Alex Klein231d2da2019-07-22 16:44:45 -0600227
228class RegenBuildCacheTest(cros_test_lib.MockTestCase,
229 api_config.ApiConfigMixin):
LaMont Jonesc64ae212019-04-15 15:41:28 -0600230 """Unittests for RegenBuildCache."""
231
Alex Klein231d2da2019-07-22 16:44:45 -0600232 def setUp(self):
233 self.response = binhost_pb2.RegenBuildCacheResponse()
234
235 def testValidateOnly(self):
236 """Sanity check that a validate only call does not execute any logic."""
237 patch = self.PatchObject(binhost_service, 'RegenBuildCache')
238
239 request = binhost_pb2.RegenBuildCacheRequest()
240 request.overlay_type = binhost_pb2.OVERLAYTYPE_BOTH
241 binhost.RegenBuildCache(request, self.response, self.validate_only_config)
242 patch.assert_not_called()
243
Michael Mortensen42251f92019-11-14 11:01:43 -0700244 def testMockCall(self):
245 """Test that a mock call does not execute logic, returns mocked value."""
246 patch = self.PatchObject(binhost_service, 'RegenBuildCache')
247
248 request = binhost_pb2.RegenBuildCacheRequest()
249 request.overlay_type = binhost_pb2.OVERLAYTYPE_BOTH
250 binhost.RegenBuildCache(request, self.response, self.mock_call_config)
251 patch.assert_not_called()
252 self.assertEqual(len(self.response.modified_overlays), 1)
253 self.assertEqual(self.response.modified_overlays[0].path,
254 '/path/to/BuildCache')
255
256
LaMont Jonesc64ae212019-04-15 15:41:28 -0600257 def testRegenBuildCache(self):
258 """RegenBuildCache calls service with the correct args."""
259 regen_cache = self.PatchObject(binhost_service, 'RegenBuildCache')
260
261 input_proto = binhost_pb2.RegenBuildCacheRequest()
262 input_proto.overlay_type = binhost_pb2.OVERLAYTYPE_BOTH
LaMont Jonesc64ae212019-04-15 15:41:28 -0600263
Alex Klein231d2da2019-07-22 16:44:45 -0600264 binhost.RegenBuildCache(input_proto, self.response, self.api_config)
Alex Klein82c85d42019-08-14 15:47:51 -0600265 regen_cache.assert_called_once_with(mock.ANY, 'both')
LaMont Jonesc64ae212019-04-15 15:41:28 -0600266
267 def testRequiresOverlayType(self):
268 """RegenBuildCache dies if overlay_type not specified."""
269 regen_cache = self.PatchObject(binhost_service, 'RegenBuildCache')
LaMont Jonesc64ae212019-04-15 15:41:28 -0600270
271 input_proto = binhost_pb2.RegenBuildCacheRequest()
272 input_proto.overlay_type = binhost_pb2.OVERLAYTYPE_UNSPECIFIED
LaMont Jonesc64ae212019-04-15 15:41:28 -0600273
Alex Klein231d2da2019-07-22 16:44:45 -0600274 with self.assertRaises(cros_build_lib.DieSystemExit):
275 binhost.RegenBuildCache(input_proto, self.response, self.api_config)
LaMont Jonesc64ae212019-04-15 15:41:28 -0600276 regen_cache.assert_not_called()
Michael Mortensenfc823882019-08-27 14:38:07 -0600277
278
279class PrepareDevInstallerBinhostUploadsTest(cros_test_lib.MockTempDirTestCase,
280 api_config.ApiConfigMixin):
281 """Tests for the UploadDevInstallerPrebuilts stage."""
282 def setUp(self):
283 # target packages dir
284 self.chroot_path = os.path.join(self.tempdir, 'chroot')
285 self.sysroot_path = '/build/target'
286 self.chroot_path = os.path.join(self.tempdir, 'chroot')
287 full_sysroot_path = os.path.join(self.chroot_path,
288 self.sysroot_path.lstrip(os.sep))
289 self.full_sysroot_package_path = os.path.join(full_sysroot_path,
290 'packages')
291 osutils.SafeMakedirs(self.full_sysroot_package_path)
292 self.uploads_dir = os.path.join(self.tempdir, 'uploads_dir')
293 osutils.SafeMakedirs(self.uploads_dir)
294 # Create packages/Packages file
295 packages_file = os.path.join(self.full_sysroot_package_path, 'Packages')
296 packages_content = """\
297USE: test
298
299CPV: app-arch/brotli-1.0.6
300
301CPV: app-arch/zip-3.0-r3
302
303CPV: chromeos-base/shill-0.0.1-r1
304
305CPV: chromeos-base/test-0.0.1-r1
306
307CPV: virtual/chromium-os-printing-1-r4
308
309CPV: virtual/python-enum34-1
310
311"""
312 osutils.WriteFile(packages_file, packages_content)
313
314
315 # Create package.installable file
316 self.dev_install_packages = ['app-arch/zip-3.0-r3',
317 'virtual/chromium-os-printing-1-r4',
318 'virtual/python-enum34-1']
319 package_installable_dir = os.path.join(full_sysroot_path,
320 'build/dev-install')
321 osutils.SafeMakedirs(package_installable_dir)
322 package_installable_filename = os.path.join(package_installable_dir,
323 'package.installable')
324
325 # Create path to the dev_install_packages
326 packages_dir = os.path.join(full_sysroot_path, 'packages')
327 osutils.SafeMakedirs(packages_dir)
328 for package in self.dev_install_packages:
329 # Since a package has a category, such as app-arch/zip-3.0-r3, we need
330 # to create the packages_dir / category dir as needed.
331 category = package.split(os.sep)[0]
332 osutils.SafeMakedirs(os.path.join(packages_dir, category))
333 package_tbz2_file = os.path.join(packages_dir, package) + '.tbz2'
334 osutils.Touch(package_tbz2_file)
335 package_installable_file = open(package_installable_filename, 'w')
336 for package in self.dev_install_packages:
337 package_installable_file.write(package + '\n')
338 package_installable_file.close()
339 self.response = binhost_pb2.PrepareDevInstallBinhostUploadsResponse()
340
Michael Mortensen42251f92019-11-14 11:01:43 -0700341 def testValidateOnly(self):
342 """Sanity check that a validate only call does not execute any logic."""
343 patch = self.PatchObject(binhost_service,
344 'ReadDevInstallFilesToCreatePackageIndex')
345
346 input_proto = binhost_pb2.PrepareDevInstallBinhostUploadsRequest()
347 input_proto.uri = 'gs://chromeos-prebuilt/target'
348 input_proto.chroot.path = self.chroot_path
349 input_proto.sysroot.path = self.sysroot_path
350 input_proto.uploads_dir = self.uploads_dir
351 binhost.PrepareDevInstallBinhostUploads(input_proto, self.response,
352 self.validate_only_config)
353 patch.assert_not_called()
354
355 def testMockCall(self):
356 """Test that a mock call does not execute logic, returns mocked value."""
357 patch = self.PatchObject(binhost_service,
358 'ReadDevInstallFilesToCreatePackageIndex')
359
360 input_proto = binhost_pb2.PrepareDevInstallBinhostUploadsRequest()
361 input_proto.uri = 'gs://chromeos-prebuilt/target'
362 input_proto.chroot.path = self.chroot_path
363 input_proto.sysroot.path = self.sysroot_path
364 input_proto.uploads_dir = self.uploads_dir
365 binhost.PrepareDevInstallBinhostUploads(input_proto, self.response,
366 self.mock_call_config)
367 self.assertEqual(len(self.response.upload_targets), 3)
368 self.assertEqual(self.response.upload_targets[2].path, 'Packages')
369 patch.assert_not_called()
370
Michael Mortensenfc823882019-08-27 14:38:07 -0600371 def testDevInstallerUpload(self):
372 """Basic sanity test testing uploads of dev installer prebuilts."""
373 # self.RunStage()
374 input_proto = binhost_pb2.PrepareDevInstallBinhostUploadsRequest()
375 input_proto.uri = 'gs://chromeos-prebuilt/target'
376 input_proto.chroot.path = self.chroot_path
377 input_proto.sysroot.path = self.sysroot_path
378 input_proto.uploads_dir = self.uploads_dir
379 # Call method under test
380 binhost.PrepareDevInstallBinhostUploads(input_proto, self.response,
381 self.api_config)
382 # Verify results
383 expected_upload_targets = ['app-arch/zip-3.0-r3.tbz2',
384 'virtual/chromium-os-printing-1-r4.tbz2',
385 'virtual/python-enum34-1.tbz2',
386 'Packages']
Mike Frysinger678735c2019-09-28 18:23:28 -0400387 self.assertCountEqual(
Michael Mortensenfc823882019-08-27 14:38:07 -0600388 [ut.path for ut in self.response.upload_targets],
389 expected_upload_targets)
390 # All of the upload_targets should also be in the uploads_directory
391 for target in self.response.upload_targets:
392 self.assertExists(os.path.join(input_proto.uploads_dir, target.path))
393
394 def testPrepareBinhostUploadsNonGsUri(self):
395 """PrepareBinhostUploads dies when URI does not point to GS."""
396 input_proto = binhost_pb2.PrepareDevInstallBinhostUploadsRequest()
397 input_proto.chroot.path = self.chroot_path
398 input_proto.sysroot.path = self.sysroot_path
399 input_proto.uploads_dir = self.uploads_dir
400 input_proto.uri = 'https://foo.bar'
401 with self.assertRaises(ValueError):
402 binhost.PrepareDevInstallBinhostUploads(input_proto, self.response,
403 self.api_config)