blob: 956e1dfb4e74c4fc6771a9179229e4154c7b0208 [file] [log] [blame]
Mike Frysingerf1ba7ad2022-09-12 05:42:57 -04001# Copyright 2019 The ChromiumOS Authors
Alex Klein19c4cc42019-02-27 14:47:57 -07002# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""SDK tests."""
6
Navil Pereze73734a2023-08-11 13:07:41 +00007import datetime
Greg Edelston9dcdc8a2023-01-11 17:07:10 -07008import os
Brian Norris41f247b2023-06-30 11:09:40 -07009from pathlib import Path
Navil Pereze73734a2023-08-11 13:07:41 +000010from typing import List, Optional, Union
Mike Frysinger166fea02021-02-12 05:30:33 -050011from unittest import mock
12
Alex Klein231d2da2019-07-22 16:44:45 -060013from chromite.api import api_config
Navil Pereze73734a2023-08-11 13:07:41 +000014from chromite.api import controller
15from chromite.api.controller import controller_util
Alex Klein19c4cc42019-02-27 14:47:57 -070016from chromite.api.controller import sdk as sdk_controller
Alex Klein7107bdd2019-03-14 17:14:31 -060017from chromite.api.gen.chromite.api import sdk_pb2
Greg Edelston9dcdc8a2023-01-11 17:07:10 -070018from chromite.api.gen.chromiumos import common_pb2
Brian Norris41f247b2023-06-30 11:09:40 -070019from chromite.lib import chroot_lib
Greg Edelston9dcdc8a2023-01-11 17:07:10 -070020from chromite.lib import constants
Alex Klein19c4cc42019-02-27 14:47:57 -070021from chromite.lib import cros_build_lib
Alex Klein231d2da2019-07-22 16:44:45 -060022from chromite.lib import cros_test_lib
Navil Pereze73734a2023-08-11 13:07:41 +000023from chromite.lib import osutils
24from chromite.lib import sysroot_lib
25from chromite.lib.parser import package_info
Alex Klein19c4cc42019-02-27 14:47:57 -070026from chromite.service import sdk as sdk_service
27
28
Alex Klein231d2da2019-07-22 16:44:45 -060029class SdkCreateTest(cros_test_lib.MockTestCase, api_config.ApiConfigMixin):
Alex Klein1699fab2022-09-08 08:46:06 -060030 """Create tests."""
Alex Klein19c4cc42019-02-27 14:47:57 -070031
Alex Klein1699fab2022-09-08 08:46:06 -060032 def setUp(self):
33 """Setup method."""
34 # We need to run the command outside the chroot.
35 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=False)
36 self.response = sdk_pb2.CreateResponse()
Alex Klein19c4cc42019-02-27 14:47:57 -070037
Alex Klein1699fab2022-09-08 08:46:06 -060038 def _GetRequest(
39 self,
40 no_replace=False,
Chris McDonald5dcdb892020-02-07 15:10:46 -070041 bootstrap=False,
Alex Klein1699fab2022-09-08 08:46:06 -060042 cache_path=None,
43 chroot_path=None,
44 sdk_version=None,
45 skip_chroot_upgrade=False,
George Burgess IV6e04d602023-08-16 15:08:32 -060046 ccache_disable=False,
Alex Klein1699fab2022-09-08 08:46:06 -060047 ):
48 """Helper to build a create request message."""
49 request = sdk_pb2.CreateRequest()
50 request.flags.no_replace = no_replace
51 request.flags.bootstrap = bootstrap
Alex Klein231d2da2019-07-22 16:44:45 -060052
Alex Klein1699fab2022-09-08 08:46:06 -060053 if cache_path:
54 request.chroot.cache_dir = cache_path
55 if chroot_path:
56 request.chroot.path = chroot_path
57 if sdk_version:
58 request.sdk_version = sdk_version
59 if skip_chroot_upgrade:
60 request.skip_chroot_upgrade = skip_chroot_upgrade
George Burgess IV6e04d602023-08-16 15:08:32 -060061 if ccache_disable:
62 request.ccache_disable = ccache_disable
Alex Klein19c4cc42019-02-27 14:47:57 -070063
Alex Klein1699fab2022-09-08 08:46:06 -060064 return request
65
66 def testValidateOnly(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -070067 """Verify a validate-only call does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -060068 patch = self.PatchObject(sdk_service, "Create")
69
70 sdk_controller.Create(
71 self._GetRequest(), self.response, self.validate_only_config
72 )
73 patch.assert_not_called()
74
75 def testMockCall(self):
76 """Sanity check that a mock call does not execute any logic."""
77 patch = self.PatchObject(sdk_service, "Create")
78
79 rc = sdk_controller.Create(
80 self._GetRequest(), self.response, self.mock_call_config
81 )
82 patch.assert_not_called()
83 self.assertFalse(rc)
84 self.assertTrue(self.response.version.version)
85
86 def testSuccess(self):
87 """Test the successful call output handling."""
88 self.PatchObject(sdk_service, "Create", return_value=1)
89
90 request = self._GetRequest()
91
92 sdk_controller.Create(request, self.response, self.api_config)
93
94 self.assertEqual(1, self.response.version.version)
95
96 def testFalseArguments(self):
97 """Test False argument handling."""
98 # Create the patches.
99 self.PatchObject(sdk_service, "Create", return_value=1)
100 args_patch = self.PatchObject(sdk_service, "CreateArguments")
101
102 # Flag translation tests.
103 # Test all false values in the message.
104 request = self._GetRequest(
Brian Norris35a7ed02023-02-23 12:50:14 -0800105 no_replace=False,
106 bootstrap=False,
Alex Klein1699fab2022-09-08 08:46:06 -0600107 )
108 sdk_controller.Create(request, self.response, self.api_config)
109 args_patch.assert_called_with(
110 replace=True,
111 bootstrap=False,
Brian Norris67374d82023-05-01 12:31:12 -0700112 chroot=mock.ANY,
Alex Klein1699fab2022-09-08 08:46:06 -0600113 sdk_version=mock.ANY,
114 skip_chroot_upgrade=mock.ANY,
George Burgess IV6e04d602023-08-16 15:08:32 -0600115 ccache_disable=mock.ANY,
Alex Klein1699fab2022-09-08 08:46:06 -0600116 )
117
118 def testTrueArguments(self):
119 """Test True arguments handling."""
120 # Create the patches.
121 self.PatchObject(sdk_service, "Create", return_value=1)
122 args_patch = self.PatchObject(sdk_service, "CreateArguments")
123
124 # Test all True values in the message.
125 request = self._GetRequest(
126 no_replace=True,
127 bootstrap=True,
Alex Klein1699fab2022-09-08 08:46:06 -0600128 sdk_version="foo",
129 skip_chroot_upgrade=True,
George Burgess IV6e04d602023-08-16 15:08:32 -0600130 ccache_disable=True,
Alex Klein1699fab2022-09-08 08:46:06 -0600131 )
132 sdk_controller.Create(request, self.response, self.api_config)
133 args_patch.assert_called_with(
134 replace=False,
135 bootstrap=True,
Brian Norris67374d82023-05-01 12:31:12 -0700136 chroot=mock.ANY,
Alex Klein1699fab2022-09-08 08:46:06 -0600137 sdk_version="foo",
138 skip_chroot_upgrade=True,
George Burgess IV6e04d602023-08-16 15:08:32 -0600139 ccache_disable=True,
Alex Klein1699fab2022-09-08 08:46:06 -0600140 )
Mike Frysingercb8992a2020-02-11 05:13:13 +0000141
Alex Kleinaa5c4172019-02-27 17:12:20 -0700142
George Engelbrecht86cfae62023-04-05 10:57:41 -0600143class SdkCleanTest(cros_test_lib.MockTestCase, api_config.ApiConfigMixin):
144 """Clean tests."""
145
146 def setUp(self):
147 """Setup method."""
148 # We need to run the command outside the chroot.
149 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=False)
150 self.response = sdk_pb2.CleanResponse()
151
152 def _GetRequest(self, chroot_path=None, incrementals=False):
153 """Helper to build a clean request message."""
154 request = sdk_pb2.CleanRequest()
155 if chroot_path:
156 request.chroot.path = chroot_path
157
158 request.incrementals = incrementals
159
160 return request
161
162 def testMockCall(self):
163 """Sanity check that a mock call does not execute any logic."""
164 patch = self.PatchObject(sdk_service, "Clean")
165
166 rc = sdk_controller.Clean(
167 self._GetRequest(), self.response, self.mock_call_config
168 )
169 patch.assert_not_called()
170 self.assertFalse(rc)
171
172 def testSuccess(self):
173 """Test the successful call by verifying service invocation."""
174 patch = self.PatchObject(sdk_service, "Clean", return_value=0)
175
176 request = self._GetRequest(incrementals=True)
177
178 sdk_controller.Clean(request, self.response, self.api_config)
179 patch.assert_called_once_with(
180 mock.ANY,
181 safe=False,
182 images=False,
183 sysroots=False,
184 tmp=False,
185 cache=False,
186 logs=False,
187 workdirs=False,
188 incrementals=True,
189 )
190
191 def testDefaults(self):
192 """Test the successful call by verifying service invocation."""
193 patch = self.PatchObject(sdk_service, "Clean", return_value=0)
194
195 request = self._GetRequest()
196
197 sdk_controller.Clean(request, self.response, self.api_config)
198 patch.assert_called_once_with(mock.ANY, safe=True, sysroots=True)
199
200
Michael Mortensene87d8a62020-07-06 11:44:35 -0600201class SdkDeleteTest(cros_test_lib.MockTestCase, api_config.ApiConfigMixin):
George Engelbrecht86cfae62023-04-05 10:57:41 -0600202 """Delete tests."""
Michael Mortensene87d8a62020-07-06 11:44:35 -0600203
Alex Klein1699fab2022-09-08 08:46:06 -0600204 def setUp(self):
205 """Setup method."""
206 # We need to run the command outside the chroot.
207 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=False)
208 self.response = sdk_pb2.DeleteResponse()
Michael Mortensene87d8a62020-07-06 11:44:35 -0600209
Alex Klein1699fab2022-09-08 08:46:06 -0600210 def _GetRequest(self, chroot_path=None):
211 """Helper to build a delete request message."""
212 request = sdk_pb2.DeleteRequest()
213 if chroot_path:
214 request.chroot.path = chroot_path
Michael Mortensene87d8a62020-07-06 11:44:35 -0600215
Alex Klein1699fab2022-09-08 08:46:06 -0600216 return request
Michael Mortensene87d8a62020-07-06 11:44:35 -0600217
Alex Klein1699fab2022-09-08 08:46:06 -0600218 def testValidateOnly(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700219 """Verify a validate-only call does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -0600220 patch = self.PatchObject(sdk_service, "Delete")
Michael Mortensene87d8a62020-07-06 11:44:35 -0600221
Alex Klein1699fab2022-09-08 08:46:06 -0600222 sdk_controller.Delete(
223 self._GetRequest(), self.response, self.validate_only_config
224 )
225 patch.assert_not_called()
Michael Mortensene87d8a62020-07-06 11:44:35 -0600226
Alex Klein1699fab2022-09-08 08:46:06 -0600227 def testMockCall(self):
228 """Sanity check that a mock call does not execute any logic."""
229 patch = self.PatchObject(sdk_service, "Delete")
Michael Mortensene87d8a62020-07-06 11:44:35 -0600230
Alex Klein1699fab2022-09-08 08:46:06 -0600231 rc = sdk_controller.Delete(
232 self._GetRequest(), self.response, self.mock_call_config
233 )
234 patch.assert_not_called()
235 self.assertFalse(rc)
Michael Mortensene87d8a62020-07-06 11:44:35 -0600236
Alex Klein1699fab2022-09-08 08:46:06 -0600237 def testSuccess(self):
238 """Test the successful call by verifying service invocation."""
239 patch = self.PatchObject(sdk_service, "Delete", return_value=1)
Michael Mortensene87d8a62020-07-06 11:44:35 -0600240
Alex Klein1699fab2022-09-08 08:46:06 -0600241 request = self._GetRequest()
Michael Mortensene87d8a62020-07-06 11:44:35 -0600242
Alex Klein1699fab2022-09-08 08:46:06 -0600243 sdk_controller.Delete(request, self.response, self.api_config)
244 # Verify that by default sdk_service.Delete is called with force=True.
245 patch.assert_called_once_with(mock.ANY, force=True)
Michael Mortensene87d8a62020-07-06 11:44:35 -0600246
247
Brian Norrisf624bf42023-03-02 12:57:49 -0800248class SdkUnmountTest(cros_test_lib.MockTestCase, api_config.ApiConfigMixin):
249 """SDK Unmount tests."""
250
251 def testNoop(self):
252 """Unmount is a deprecated noop."""
253 request = sdk_pb2.UnmountRequest()
254 response = sdk_pb2.UnmountResponse()
255 rc = sdk_controller.Unmount(request, response, self.api_config)
256 self.assertFalse(rc)
257
258
Michael Mortensen52a98ac2020-07-28 16:00:18 -0600259class SdkUnmountPathTest(cros_test_lib.MockTestCase, api_config.ApiConfigMixin):
Alex Klein1699fab2022-09-08 08:46:06 -0600260 """Update tests."""
Michael Mortensen52a98ac2020-07-28 16:00:18 -0600261
Alex Klein1699fab2022-09-08 08:46:06 -0600262 def setUp(self):
263 """Setup method."""
264 self.response = sdk_pb2.UnmountPathResponse()
Michael Mortensen52a98ac2020-07-28 16:00:18 -0600265
Alex Klein1699fab2022-09-08 08:46:06 -0600266 def _UnmountPathRequest(self, path=None):
267 """Helper to build a delete request message."""
268 request = sdk_pb2.UnmountPathRequest()
269 if path:
270 request.path.path = path
271 return request
Michael Mortensen52a98ac2020-07-28 16:00:18 -0600272
Alex Klein1699fab2022-09-08 08:46:06 -0600273 def testValidateOnly(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700274 """Verify a validate-only call does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -0600275 patch = self.PatchObject(sdk_service, "UnmountPath")
Michael Mortensen52a98ac2020-07-28 16:00:18 -0600276
Alex Klein1699fab2022-09-08 08:46:06 -0600277 sdk_controller.UnmountPath(
278 self._UnmountPathRequest("/test/path"),
279 self.response,
280 self.validate_only_config,
281 )
282 patch.assert_not_called()
Michael Mortensen52a98ac2020-07-28 16:00:18 -0600283
Alex Klein1699fab2022-09-08 08:46:06 -0600284 def testMockCall(self):
285 """Sanity check that a mock call does not execute any logic."""
286 patch = self.PatchObject(sdk_service, "UnmountPath")
Michael Mortensen52a98ac2020-07-28 16:00:18 -0600287
Alex Klein1699fab2022-09-08 08:46:06 -0600288 rc = sdk_controller.UnmountPath(
289 self._UnmountPathRequest(), self.response, self.mock_call_config
290 )
291 patch.assert_not_called()
292 self.assertFalse(rc)
Michael Mortensen52a98ac2020-07-28 16:00:18 -0600293
Alex Klein1699fab2022-09-08 08:46:06 -0600294 def testSuccess(self):
295 """Test the successful call by verifying service invocation."""
296 patch = self.PatchObject(sdk_service, "UnmountPath", return_value=1)
Michael Mortensen52a98ac2020-07-28 16:00:18 -0600297
Alex Klein1699fab2022-09-08 08:46:06 -0600298 request = self._UnmountPathRequest("/test/path")
299 sdk_controller.UnmountPath(request, self.response, self.api_config)
300 patch.assert_called_once_with("/test/path")
Michael Mortensen52a98ac2020-07-28 16:00:18 -0600301
302
Navil Pereze73734a2023-08-11 13:07:41 +0000303class SdkUpdateTest(
304 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin
305):
Alex Klein1699fab2022-09-08 08:46:06 -0600306 """Update tests."""
Alex Kleinaa5c4172019-02-27 17:12:20 -0700307
Alex Klein1699fab2022-09-08 08:46:06 -0600308 def setUp(self):
309 """Setup method."""
310 # We need to run the command inside the chroot.
311 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=True)
Alex Kleinaa5c4172019-02-27 17:12:20 -0700312
Navil Pereze73734a2023-08-11 13:07:41 +0000313 self.portage_dir = os.path.join(self.tempdir, "portage_logdir")
314 self.PatchObject(
315 sysroot_lib.Sysroot, "portage_logdir", new=self.portage_dir
316 )
317 osutils.SafeMakedirs(self.portage_dir)
318
Alex Klein1699fab2022-09-08 08:46:06 -0600319 self.response = sdk_pb2.UpdateResponse()
Alex Klein231d2da2019-07-22 16:44:45 -0600320
Alex Klein1699fab2022-09-08 08:46:06 -0600321 def _GetRequest(self, build_source=False, targets=None):
322 """Helper to simplify building a request instance."""
323 request = sdk_pb2.UpdateRequest()
324 request.flags.build_source = build_source
Alex Kleinaa5c4172019-02-27 17:12:20 -0700325
Alex Klein1699fab2022-09-08 08:46:06 -0600326 for target in targets or []:
327 added = request.toolchain_targets.add()
328 added.name = target
Alex Kleinaa5c4172019-02-27 17:12:20 -0700329
Alex Klein1699fab2022-09-08 08:46:06 -0600330 return request
Alex Kleinaa5c4172019-02-27 17:12:20 -0700331
Navil Pereze73734a2023-08-11 13:07:41 +0000332 def _CreatePortageLogFile(
333 self,
334 log_path: Union[str, os.PathLike],
335 pkg_info: package_info.PackageInfo,
336 timestamp: datetime.datetime,
337 ) -> str:
338 """Creates a log file to test for individual packages built by Portage.
339
340 Args:
341 log_path: The PORTAGE_LOGDIR path.
342 pkg_info: name components for log file.
343 timestamp: Timestamp used to name the file.
344 """
345 path = os.path.join(
346 log_path,
347 f"{pkg_info.category}:{pkg_info.pvr}:"
348 f'{timestamp.strftime("%Y%m%d-%H%M%S")}.log',
349 )
350 osutils.WriteFile(
351 path,
352 f"Test log file for package {pkg_info.category}/"
353 f"{pkg_info.package} written to {path}",
354 )
355 return path
356
Alex Klein1699fab2022-09-08 08:46:06 -0600357 def testValidateOnly(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700358 """Verify a validate-only call does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -0600359 patch = self.PatchObject(sdk_service, "Update")
Alex Klein231d2da2019-07-22 16:44:45 -0600360
Alex Klein1699fab2022-09-08 08:46:06 -0600361 sdk_controller.Update(
362 self._GetRequest(), self.response, self.validate_only_config
363 )
364 patch.assert_not_called()
Alex Kleinaa5c4172019-02-27 17:12:20 -0700365
Alex Klein1699fab2022-09-08 08:46:06 -0600366 def testMockCall(self):
367 """Sanity check that a mock call does not execute any logic."""
368 patch = self.PatchObject(sdk_service, "Update")
Alex Klein076841b2019-08-29 15:19:39 -0600369
Alex Klein1699fab2022-09-08 08:46:06 -0600370 rc = sdk_controller.Create(
371 self._GetRequest(), self.response, self.mock_call_config
372 )
373 patch.assert_not_called()
374 self.assertFalse(rc)
375 self.assertTrue(self.response.version.version)
Alex Klein076841b2019-08-29 15:19:39 -0600376
Alex Klein1699fab2022-09-08 08:46:06 -0600377 def testSuccess(self):
378 """Successful call output handling test."""
379 expected_version = 1
Navil Pereze73734a2023-08-11 13:07:41 +0000380 expected_return = sdk_service.UpdateResult(
381 return_code=0, version=expected_version
382 )
383 self.PatchObject(sdk_service, "Update", return_value=expected_return)
Alex Klein1699fab2022-09-08 08:46:06 -0600384 request = self._GetRequest()
Alex Kleinaa5c4172019-02-27 17:12:20 -0700385
Alex Klein1699fab2022-09-08 08:46:06 -0600386 sdk_controller.Update(request, self.response, self.api_config)
Alex Kleinaa5c4172019-02-27 17:12:20 -0700387
Alex Klein1699fab2022-09-08 08:46:06 -0600388 self.assertEqual(expected_version, self.response.version.version)
Alex Kleinaa5c4172019-02-27 17:12:20 -0700389
Navil Pereze73734a2023-08-11 13:07:41 +0000390 def testNonPackageFailure(self):
391 """Test output handling when the call fails."""
392 expected_return = sdk_service.UpdateResult(return_code=1)
393 self.PatchObject(sdk_service, "Update", return_value=expected_return)
394
395 rc = sdk_controller.Update(
396 self._GetRequest(), self.response, self.api_config
397 )
398 self.assertEqual(controller.RETURN_CODE_COMPLETED_UNSUCCESSFULLY, rc)
399
400 def testPackageFailure(self):
401 """Test output handling when the call fails with a package failure."""
402 pkgs = ["cat/pkg-1.0-r1", "foo/bar-2.0-r1"]
403 cpvrs = [package_info.parse(pkg) for pkg in pkgs]
404 new_logs = {}
405 for i, pkg in enumerate(pkgs):
406 self._CreatePortageLogFile(
407 self.portage_dir,
408 cpvrs[i],
409 datetime.datetime(2021, 6, 9, 13, 37, 0),
410 )
411 new_logs[pkg] = self._CreatePortageLogFile(
412 self.portage_dir,
413 cpvrs[i],
414 datetime.datetime(2021, 6, 9, 16, 20, 0),
415 )
416
417 expected_return = sdk_service.UpdateResult(
418 return_code=1,
419 failed_pkgs=cpvrs,
420 )
421 self.PatchObject(sdk_service, "Update", return_value=expected_return)
422
423 rc = sdk_controller.Update(
424 self._GetRequest(), self.response, self.api_config
425 )
426 self.assertEqual(
427 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
428 )
429 self.assertTrue(self.response.failed_package_data)
430
431 expected_failed_pkgs = [("cat", "pkg"), ("foo", "bar")]
432 failed_pkgs = []
433 for data in self.response.failed_package_data:
434 failed_pkgs.append((data.name.category, data.name.package_name))
435 package = controller_util.deserialize_package_info(data.name)
436 self.assertEqual(data.log_path.path, new_logs[package.cpvr])
437 self.assertCountEqual(expected_failed_pkgs, failed_pkgs)
438
Alex Klein1699fab2022-09-08 08:46:06 -0600439 def testArgumentHandling(self):
440 """Test the proto argument handling."""
Navil Pereze73734a2023-08-11 13:07:41 +0000441 expected_return = sdk_service.UpdateResult(return_code=0, version=1)
Alex Klein1699fab2022-09-08 08:46:06 -0600442 args = sdk_service.UpdateArguments()
Navil Pereze73734a2023-08-11 13:07:41 +0000443 self.PatchObject(sdk_service, "Update", return_value=expected_return)
Alex Klein1699fab2022-09-08 08:46:06 -0600444 args_patch = self.PatchObject(
445 sdk_service, "UpdateArguments", return_value=args
446 )
Alex Kleinaa5c4172019-02-27 17:12:20 -0700447
Alex Klein1699fab2022-09-08 08:46:06 -0600448 # No boards and flags False.
449 request = self._GetRequest(build_source=False)
450 sdk_controller.Update(request, self.response, self.api_config)
451 args_patch.assert_called_with(
452 build_source=False, toolchain_targets=[], toolchain_changed=False
453 )
Alex Kleinaa5c4172019-02-27 17:12:20 -0700454
Alex Klein1699fab2022-09-08 08:46:06 -0600455 # Multiple boards and flags True.
456 targets = ["board1", "board2"]
457 request = self._GetRequest(build_source=True, targets=targets)
458 sdk_controller.Update(request, self.response, self.api_config)
459 args_patch.assert_called_with(
460 build_source=True,
461 toolchain_targets=targets,
462 toolchain_changed=False,
463 )
Greg Edelston9dcdc8a2023-01-11 17:07:10 -0700464
465
Greg Edelston01ae5942023-01-30 16:26:54 -0700466class CreateManifestFromSdkTest(
467 cros_test_lib.MockTestCase, api_config.ApiConfigMixin
468):
469 """Test the SdkService/CreateManifestFromSdk endpoint."""
470
Brian Norris41f247b2023-06-30 11:09:40 -0700471 _sdk_path = "/build/my_sdk"
Greg Edelston01ae5942023-01-30 16:26:54 -0700472 _dest_dir = "/build"
473 _manifest_path = "/build/my_sdk.Manifest"
474
475 def _NewRequest(self, inside: bool) -> sdk_pb2.CreateManifestFromSdkRequest:
476 return sdk_pb2.CreateManifestFromSdkRequest(
Brian Norris41f247b2023-06-30 11:09:40 -0700477 chroot=common_pb2.Chroot(
478 path=self.chroot.path, out_path=str(self.chroot.out_path)
479 ),
Greg Edelston01ae5942023-01-30 16:26:54 -0700480 sdk_path=common_pb2.Path(
Brian Norris41f247b2023-06-30 11:09:40 -0700481 path=self._sdk_path,
Greg Edelston01ae5942023-01-30 16:26:54 -0700482 location=common_pb2.Path.Location.INSIDE
483 if inside
484 else common_pb2.Path.Location.OUTSIDE,
485 ),
486 dest_dir=common_pb2.Path(
487 path=self._dest_dir,
488 location=common_pb2.Path.Location.OUTSIDE,
489 ),
490 )
491
492 def _NewResponse(self) -> sdk_pb2.CreateManifestFromSdkResponse:
493 return sdk_pb2.CreateManifestFromSdkResponse()
494
Brian Norris41f247b2023-06-30 11:09:40 -0700495 def setUp(self):
496 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=False)
497
498 self.chroot = chroot_lib.Chroot(
499 path=Path("/path/to/chroot"),
500 out_path=Path("/path/to/out"),
501 )
502
Greg Edelston01ae5942023-01-30 16:26:54 -0700503 def testValidateOnly(self):
504 """Check that a validate only call does not execute any logic."""
505 impl_patch = self.PatchObject(sdk_service, "CreateManifestFromSdk")
Greg Edelstone265a172023-06-26 17:20:05 -0600506 sdk_controller.CreateManifestFromSdk(
Greg Edelston01ae5942023-01-30 16:26:54 -0700507 self._NewRequest(False),
508 self._NewResponse(),
509 self.validate_only_config,
510 )
511 impl_patch.assert_not_called()
512
513 def testOutside(self):
514 """Check that a call with an outside path succeeds."""
515 impl_patch = self.PatchObject(
516 sdk_service,
517 "CreateManifestFromSdk",
Brian Norris41f247b2023-06-30 11:09:40 -0700518 return_value=Path(self._manifest_path),
Greg Edelston01ae5942023-01-30 16:26:54 -0700519 )
520 request = self._NewRequest(inside=False)
521 response = self._NewResponse()
522 sdk_controller.CreateManifestFromSdk(
523 request,
524 response,
525 self.api_config,
526 )
527 impl_patch.assert_called_with(
Brian Norris41f247b2023-06-30 11:09:40 -0700528 Path(self._sdk_path),
529 Path(self._dest_dir),
Greg Edelston01ae5942023-01-30 16:26:54 -0700530 )
531 self.assertEqual(
532 response.manifest_path.location, common_pb2.Path.Location.OUTSIDE
533 )
534 self.assertEqual(response.manifest_path.path, self._manifest_path)
535
536 def testInside(self):
537 """Check that an inside path parses correctly and the call succeeds."""
538 impl_patch = self.PatchObject(
539 sdk_service,
540 "CreateManifestFromSdk",
Brian Norris41f247b2023-06-30 11:09:40 -0700541 return_value=Path(self._manifest_path),
Greg Edelston01ae5942023-01-30 16:26:54 -0700542 )
543 request = self._NewRequest(inside=True)
544 response = self._NewResponse()
545 sdk_controller.CreateManifestFromSdk(
546 request,
547 response,
548 self.api_config,
549 )
550 impl_patch.assert_called_with(
Brian Norris41f247b2023-06-30 11:09:40 -0700551 Path(self.chroot.full_path(self._sdk_path)),
552 Path(self._dest_dir),
Greg Edelston01ae5942023-01-30 16:26:54 -0700553 )
554 self.assertEqual(
555 response.manifest_path.location, common_pb2.Path.Location.OUTSIDE
556 )
557 self.assertEqual(response.manifest_path.path, self._manifest_path)
558
559
Greg Edelston9dcdc8a2023-01-11 17:07:10 -0700560class BuildSdkToolchainTest(
561 cros_test_lib.MockTestCase, api_config.ApiConfigMixin
562):
563 """Test the SdkService/BuildSdkToolchain endpoint."""
564
565 def setUp(self):
566 """Set up the test case."""
567 self._chroot_path = "/path/to/chroot"
Greg Edelstone265a172023-06-26 17:20:05 -0600568 self._result_dir = "/out/toolchain-pkgs/"
Greg Edelston9dcdc8a2023-01-11 17:07:10 -0700569 self._response = sdk_pb2.BuildSdkToolchainResponse()
570 self._generated_filenames = (
571 "armv7a-cros-linux-gnueabihf.tar.xz",
572 "x86_64-cros-linux-gnu.tar.xz",
573 )
574 self._paths_for_generated_files = [
575 common_pb2.Path(
576 path=os.path.join(constants.SDK_TOOLCHAINS_OUTPUT, fname),
577 location=common_pb2.Path.Location.INSIDE,
578 )
579 for fname in self._generated_filenames
580 ]
581
582 def _NewRequest(
583 self,
584 chroot_path: Optional[str] = None,
585 use_flags: Optional[List[str]] = None,
586 ) -> sdk_pb2.BuildSdkToolchainRequest:
587 """Return a new BuildSdkToolchainRequest message."""
Greg Edelstone265a172023-06-26 17:20:05 -0600588 request = sdk_pb2.BuildSdkToolchainRequest(
589 result_path=common_pb2.ResultPath(
590 path=common_pb2.Path(
591 path=self._result_dir,
592 location=common_pb2.Path.Location.OUTSIDE,
593 )
594 )
595 )
Greg Edelston9dcdc8a2023-01-11 17:07:10 -0700596 if chroot_path:
597 request.chroot.path = chroot_path
598 if use_flags:
599 request.use_flags.extend(
600 common_pb2.UseFlag(flag=flag) for flag in use_flags
601 )
602 return request
603
604 def _NewResponse(
605 self, generated_filenames: Optional[List[str]] = None
606 ) -> sdk_pb2.BuildSdkToolchainResponse:
607 """Return a new BuildSdkToolchainResponse message."""
608 response = sdk_pb2.BuildSdkToolchainResponse()
609 if generated_filenames:
610 response.generated_files.extend(
611 common_pb2.Path(
Greg Edelstone265a172023-06-26 17:20:05 -0600612 path=os.path.join(self._result_dir, fname),
613 location=common_pb2.Path.Location.OUTSIDE,
Greg Edelston9dcdc8a2023-01-11 17:07:10 -0700614 )
615 for fname in generated_filenames
616 )
617 return response
618
619 def testValidateOnly(self):
620 """Check that a validate only call does not execute any logic."""
621 impl_patch = self.PatchObject(sdk_service, "BuildSdkToolchain")
622 sdk_controller.BuildSdkToolchain(
623 self._NewRequest(), self._NewResponse(), self.validate_only_config
624 )
625 impl_patch.assert_not_called()
626
627 def testSuccess(self):
628 """Check that a normal call defers to the SDK service as expected."""
629 impl_patch = self.PatchObject(sdk_service, "BuildSdkToolchain")
630 request = self._NewRequest(use_flags=[])
631 response = self._NewResponse()
632 sdk_controller.BuildSdkToolchain(
633 request,
634 response,
635 self.api_config,
636 )
637 # Can't use assert_called_with, since the chroot objects are equal but
638 # not identical.
639 impl_patch.assert_called_once()
Greg Edelston9dcdc8a2023-01-11 17:07:10 -0700640 self.assertEqual(impl_patch.call_args.kwargs["extra_env"], {})
641
642 def testSuccessWithUseFlags(self):
643 """Check that a call with USE flags works as expected."""
644 impl_patch = self.PatchObject(sdk_service, "BuildSdkToolchain")
645 request = self._NewRequest(use_flags=["llvm-next", "another-flag"])
646 response = self._NewResponse()
647 sdk_controller.BuildSdkToolchain(
648 request,
649 response,
650 self.api_config,
651 )
652 # Can't use assert_called_with, since the chroot objects are equal but
653 # not identical.
654 impl_patch.assert_called_once()
655 self.assertEqual(
Greg Edelston9dcdc8a2023-01-11 17:07:10 -0700656 impl_patch.call_args.kwargs["extra_env"],
657 {"USE": "llvm-next another-flag"},
658 )
Greg Edelston6733dc52023-02-15 15:20:07 -0700659
660
Greg Edelstond401e5a2023-04-28 15:29:11 -0600661class uprev_test(cros_test_lib.MockTestCase, api_config.ApiConfigMixin):
Greg Edelston6733dc52023-02-15 15:20:07 -0700662 """Test case for SdkService/Uprev() endpoint."""
663
Greg Edelston6733dc52023-02-15 15:20:07 -0700664 _binhost_gs_bucket = "gs://chromiumos-prebuilts/"
Greg Edelston40aea812023-03-27 16:34:35 -0600665 _latest_uprev_target_version = "2023.02.19.112358"
Greg Edelston6733dc52023-02-15 15:20:07 -0700666
667 def setUp(self):
668 """Set up the test case."""
Greg Edelston6733dc52023-02-15 15:20:07 -0700669 self.PatchObject(
670 sdk_service,
Greg Edelstond401e5a2023-04-28 15:29:11 -0600671 "get_latest_uprev_target_version",
Greg Edelston40aea812023-03-27 16:34:35 -0600672 return_value=self._latest_uprev_target_version,
Greg Edelston6733dc52023-02-15 15:20:07 -0700673 )
674 self._uprev_patch = self.PatchObject(
675 sdk_service,
Greg Edelstond401e5a2023-04-28 15:29:11 -0600676 "uprev_sdk_and_prebuilts",
Greg Edelston6733dc52023-02-15 15:20:07 -0700677 )
678
Greg Edelston0382ca42023-05-04 14:00:15 -0600679 def NewRequest(
680 self, version: str = "", toolchain_tarball_template: str = ""
681 ):
Greg Edelston6733dc52023-02-15 15:20:07 -0700682 """Return a new UprevRequest with standard inputs."""
683 return sdk_pb2.UprevRequest(
Greg Edelston6733dc52023-02-15 15:20:07 -0700684 binhost_gs_bucket=self._binhost_gs_bucket,
685 version=version,
Greg Edelston0382ca42023-05-04 14:00:15 -0600686 toolchain_tarball_template=toolchain_tarball_template,
Greg Edelston6733dc52023-02-15 15:20:07 -0700687 )
688
689 @staticmethod
690 def NewResponse() -> sdk_pb2.UprevResponse:
691 """Return a new empty UprevResponse."""
692 return sdk_pb2.UprevResponse()
693
694 def testWithVersion(self):
695 """Test the endpoint with `version` specified.
696
697 In this case, we expect that sdk_controller.Uprev is called with the
698 version specified in the UprevRequest.
699 """
700 specified_version = "1970.01.01.000000"
Greg Edelston0382ca42023-05-04 14:00:15 -0600701 toolchain_tarball_template = "path/to/%(version)s/toolchain"
702 request = self.NewRequest(
703 version=specified_version,
704 toolchain_tarball_template=toolchain_tarball_template,
705 )
Greg Edelston6733dc52023-02-15 15:20:07 -0700706 response = self.NewResponse()
707 sdk_controller.Uprev(request, response, self.api_config)
708 self._uprev_patch.assert_called_with(
Greg Edelston6733dc52023-02-15 15:20:07 -0700709 binhost_gs_bucket=self._binhost_gs_bucket,
Greg Edelston8bf6d4c2023-06-30 17:14:39 -0600710 sdk_version=specified_version,
Greg Edelston0382ca42023-05-04 14:00:15 -0600711 toolchain_tarball_template=toolchain_tarball_template,
Greg Edelston6733dc52023-02-15 15:20:07 -0700712 )
713
714 def testWithoutVersion(self):
715 """Test the endpoint with `version` not specified.
716
717 In this case, we expect that sdk_controller.Uprev is called with the
Greg Edelston40aea812023-03-27 16:34:35 -0600718 latest uprev target version, based on the remote file in gs://. This is
719 fetched via sdk_controller.GetLatestUprevTargetVersionVersion
720 (mocked here in setUp()).
Greg Edelston6733dc52023-02-15 15:20:07 -0700721 """
Greg Edelston0382ca42023-05-04 14:00:15 -0600722 toolchain_tarball_template = "path/to/%(version)s/toolchain"
723 request = self.NewRequest(
724 toolchain_tarball_template=toolchain_tarball_template
725 )
Greg Edelston6733dc52023-02-15 15:20:07 -0700726 response = self.NewResponse()
727 sdk_controller.Uprev(request, response, self.api_config)
728 self._uprev_patch.assert_called_with(
Greg Edelston6733dc52023-02-15 15:20:07 -0700729 binhost_gs_bucket=self._binhost_gs_bucket,
Greg Edelston8bf6d4c2023-06-30 17:14:39 -0600730 sdk_version=self._latest_uprev_target_version,
Greg Edelston0382ca42023-05-04 14:00:15 -0600731 toolchain_tarball_template=toolchain_tarball_template,
Greg Edelston6733dc52023-02-15 15:20:07 -0700732 )
Greg Edelston0382ca42023-05-04 14:00:15 -0600733
734 def testWithoutToolchainTarballTemplate(self):
735 """Test the endpoint with `toolchain_tarball_template` not specified."""
736 request = self.NewRequest(version="1234")
737 response = self.NewResponse()
738 with self.assertRaises(cros_build_lib.DieSystemExit):
739 sdk_controller.Uprev(request, response, self.api_config)