blob: 2ce8f8920216f0f94542e30e12e4356edf6b702a [file] [log] [blame]
Mike Frysingerf1ba7ad2022-09-12 05:42:57 -04001# Copyright 2019 The ChromiumOS Authors
Alex Kleinda35fcf2019-03-07 16:01:15 -07002# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Sysroot controller tests."""
6
Michael Mortensen798ee192020-01-17 13:04:43 -07007import datetime
Alex Kleinda35fcf2019-03-07 16:01:15 -07008import os
Lizzy Preslandfc1db002022-05-06 18:19:49 +00009from typing import Union
Alex Kleinda35fcf2019-03-07 16:01:15 -070010
Alex Klein231d2da2019-07-22 16:44:45 -060011from chromite.api import api_config
Alex Klein8cb365a2019-05-15 16:24:53 -060012from chromite.api import controller
Alex Kleinca572ee2020-09-03 10:47:14 -060013from chromite.api.controller import controller_util
Alex Kleinda35fcf2019-03-07 16:01:15 -070014from chromite.api.controller import sysroot as sysroot_controller
15from chromite.api.gen.chromite.api import sysroot_pb2
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -070016from chromite.api.gen.chromiumos import common_pb2
Alex Kleinda35fcf2019-03-07 16:01:15 -070017from chromite.lib import cros_build_lib
18from chromite.lib import cros_test_lib
19from chromite.lib import osutils
Alex Kleinda35fcf2019-03-07 16:01:15 -070020from chromite.lib import sysroot_lib
Alex Klein18a60af2020-06-11 12:08:47 -060021from chromite.lib.parser import package_info
Alex Kleinda35fcf2019-03-07 16:01:15 -070022from chromite.service import sysroot as sysroot_service
23
24
Alex Klein231d2da2019-07-22 16:44:45 -060025class CreateTest(cros_test_lib.MockTestCase, api_config.ApiConfigMixin):
Alex Klein1699fab2022-09-08 08:46:06 -060026 """Create function tests."""
Alex Kleinda35fcf2019-03-07 16:01:15 -070027
Alex Klein1699fab2022-09-08 08:46:06 -060028 def _InputProto(
29 self,
30 build_target=None,
31 profile=None,
32 replace=False,
33 current=False,
Yoshiki Iguchi2f7f0222023-05-17 19:30:09 +090034 use_cq_prebuilts=False,
Alex Klein1699fab2022-09-08 08:46:06 -060035 package_indexes=None,
36 ):
37 """Helper to build and input proto instance."""
38 proto = sysroot_pb2.SysrootCreateRequest()
39 if build_target:
40 proto.build_target.name = build_target
41 if profile:
42 proto.profile.name = profile
43 if replace:
44 proto.flags.replace = replace
45 if current:
46 proto.flags.chroot_current = current
Yoshiki Iguchi2f7f0222023-05-17 19:30:09 +090047 if use_cq_prebuilts:
48 proto.flags.use_cq_prebuilts = use_cq_prebuilts
Alex Klein1699fab2022-09-08 08:46:06 -060049 if package_indexes:
50 proto.package_indexes.extend(package_indexes)
Alex Kleinda35fcf2019-03-07 16:01:15 -070051
Alex Klein1699fab2022-09-08 08:46:06 -060052 return proto
Alex Kleinda35fcf2019-03-07 16:01:15 -070053
Alex Klein1699fab2022-09-08 08:46:06 -060054 def _OutputProto(self):
55 """Helper to build output proto instance."""
56 return sysroot_pb2.SysrootCreateResponse()
Alex Kleinda35fcf2019-03-07 16:01:15 -070057
Alex Klein1699fab2022-09-08 08:46:06 -060058 def testValidateOnly(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -070059 """Verify a validate-only call does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -060060 patch = self.PatchObject(sysroot_service, "Create")
Alex Klein231d2da2019-07-22 16:44:45 -060061
Alex Klein1699fab2022-09-08 08:46:06 -060062 board = "board"
63 profile = None
64 force = False
65 upgrade_chroot = True
66 in_proto = self._InputProto(
67 build_target=board,
68 profile=profile,
69 replace=force,
70 current=not upgrade_chroot,
71 )
72 sysroot_controller.Create(
73 in_proto, self._OutputProto(), self.validate_only_config
74 )
75 patch.assert_not_called()
Alex Klein231d2da2019-07-22 16:44:45 -060076
Alex Klein1699fab2022-09-08 08:46:06 -060077 def testMockCall(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -070078 """Verify a mock call does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -060079 patch = self.PatchObject(sysroot_service, "Create")
80 request = self._InputProto()
81 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -060082
Alex Klein1699fab2022-09-08 08:46:06 -060083 rc = sysroot_controller.Create(request, response, self.mock_call_config)
Alex Klein076841b2019-08-29 15:19:39 -060084
Alex Klein1699fab2022-09-08 08:46:06 -060085 patch.assert_not_called()
86 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
Alex Klein076841b2019-08-29 15:19:39 -060087
Alex Klein1699fab2022-09-08 08:46:06 -060088 def testMockError(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -070089 """Verify a mock error does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -060090 patch = self.PatchObject(sysroot_service, "Create")
91 request = self._InputProto()
92 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -060093
Alex Klein1699fab2022-09-08 08:46:06 -060094 rc = sysroot_controller.Create(
95 request, response, self.mock_error_config
96 )
Alex Klein076841b2019-08-29 15:19:39 -060097
Alex Klein1699fab2022-09-08 08:46:06 -060098 patch.assert_not_called()
99 self.assertEqual(controller.RETURN_CODE_UNRECOVERABLE, rc)
Alex Klein076841b2019-08-29 15:19:39 -0600100
Alex Klein1699fab2022-09-08 08:46:06 -0600101 def testArgumentValidation(self):
102 """Test the input argument validation."""
103 # Error when no name provided.
104 in_proto = self._InputProto()
105 out_proto = self._OutputProto()
106 with self.assertRaises(cros_build_lib.DieSystemExit):
107 sysroot_controller.Create(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700108
Alex Klein1699fab2022-09-08 08:46:06 -0600109 # Valid when board passed.
110 result = sysroot_lib.Sysroot("/sysroot/path")
111 patch = self.PatchObject(sysroot_service, "Create", return_value=result)
112 in_proto = self._InputProto("board")
113 out_proto = self._OutputProto()
114 sysroot_controller.Create(in_proto, out_proto, self.api_config)
115 patch.assert_called_once()
Alex Kleinda35fcf2019-03-07 16:01:15 -0700116
Alex Klein1699fab2022-09-08 08:46:06 -0600117 def testArgumentHandling(self):
118 """Test the arguments get processed and passed correctly."""
119 sysroot_path = "/sysroot/path"
Alex Kleinda35fcf2019-03-07 16:01:15 -0700120
Alex Klein1699fab2022-09-08 08:46:06 -0600121 sysroot = sysroot_lib.Sysroot(sysroot_path)
122 create_patch = self.PatchObject(
123 sysroot_service, "Create", return_value=sysroot
124 )
125 rc_patch = self.PatchObject(sysroot_service, "SetupBoardRunConfig")
Alex Kleinda35fcf2019-03-07 16:01:15 -0700126
Alex Klein1699fab2022-09-08 08:46:06 -0600127 # Default values.
128 board = "board"
129 profile = None
130 force = False
131 upgrade_chroot = True
Yoshiki Iguchi2f7f0222023-05-17 19:30:09 +0900132 use_cq_prebuilts = False
Alex Klein1699fab2022-09-08 08:46:06 -0600133 in_proto = self._InputProto(
134 build_target=board,
135 profile=profile,
136 replace=force,
137 current=not upgrade_chroot,
Yoshiki Iguchi2f7f0222023-05-17 19:30:09 +0900138 use_cq_prebuilts=use_cq_prebuilts,
Alex Klein1699fab2022-09-08 08:46:06 -0600139 )
140 out_proto = self._OutputProto()
141 sysroot_controller.Create(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700142
Alex Klein1699fab2022-09-08 08:46:06 -0600143 # Default value checks.
144 rc_patch.assert_called_with(
145 force=force,
146 upgrade_chroot=upgrade_chroot,
147 package_indexes=[],
Yoshiki Iguchi2f7f0222023-05-17 19:30:09 +0900148 use_cq_prebuilts=use_cq_prebuilts,
Alex Klein1699fab2022-09-08 08:46:06 -0600149 backtrack=sysroot_controller.DEFAULT_BACKTRACK,
150 )
151 self.assertEqual(board, out_proto.sysroot.build_target.name)
152 self.assertEqual(sysroot_path, out_proto.sysroot.path)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700153
Alex Klein1699fab2022-09-08 08:46:06 -0600154 # Not default values.
155 create_patch.reset_mock()
156 board = "board"
157 profile = "profile"
158 force = True
159 upgrade_chroot = False
Yoshiki Iguchi2f7f0222023-05-17 19:30:09 +0900160 use_cq_prebuilts = True
Alex Klein1699fab2022-09-08 08:46:06 -0600161 package_indexes = [
162 common_pb2.PackageIndexInfo(
163 snapshot_sha="SHA",
164 snapshot_number=5,
165 build_target=common_pb2.BuildTarget(name=board),
166 location="LOCATION",
167 profile=common_pb2.Profile(name=profile),
168 ),
169 common_pb2.PackageIndexInfo(
170 snapshot_sha="SHA2",
171 snapshot_number=4,
172 build_target=common_pb2.BuildTarget(name=board),
173 location="LOCATION2",
174 profile=common_pb2.Profile(name=profile),
175 ),
176 ]
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600177
Alex Klein1699fab2022-09-08 08:46:06 -0600178 in_proto = self._InputProto(
179 build_target=board,
180 profile=profile,
181 replace=force,
182 current=not upgrade_chroot,
Yoshiki Iguchi2f7f0222023-05-17 19:30:09 +0900183 use_cq_prebuilts=use_cq_prebuilts,
Alex Klein1699fab2022-09-08 08:46:06 -0600184 package_indexes=package_indexes,
185 )
186 out_proto = self._OutputProto()
187 sysroot_controller.Create(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700188
Alex Klein1699fab2022-09-08 08:46:06 -0600189 # Not default value checks.
190 rc_patch.assert_called_with(
191 force=force,
192 package_indexes=[
Alex Klein6d718d62023-01-18 15:55:51 -0700193 controller_util.deserialize_package_index_info(x)
Alex Klein1699fab2022-09-08 08:46:06 -0600194 for x in package_indexes
195 ],
196 upgrade_chroot=upgrade_chroot,
Yoshiki Iguchi2f7f0222023-05-17 19:30:09 +0900197 use_cq_prebuilts=use_cq_prebuilts,
Alex Klein1699fab2022-09-08 08:46:06 -0600198 backtrack=sysroot_controller.DEFAULT_BACKTRACK,
199 )
200 self.assertEqual(board, out_proto.sysroot.build_target.name)
201 self.assertEqual(sysroot_path, out_proto.sysroot.path)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700202
203
Jack Neus26b94672022-10-27 17:33:21 +0000204class GetArtifactsTest(cros_test_lib.MockTestCase, api_config.ApiConfigMixin):
205 """GetArtifacts function tests."""
206
Alex Kleinab87ceb2023-01-24 12:00:51 -0700207 # pylint: disable=line-too-long
Jack Neus26b94672022-10-27 17:33:21 +0000208 _artifact_funcs = {
209 common_pb2.ArtifactsByService.Sysroot.ArtifactType.SIMPLE_CHROME_SYSROOT: sysroot_service.CreateSimpleChromeSysroot,
210 common_pb2.ArtifactsByService.Sysroot.ArtifactType.CHROME_EBUILD_ENV: sysroot_service.CreateChromeEbuildEnv,
211 common_pb2.ArtifactsByService.Sysroot.ArtifactType.BREAKPAD_DEBUG_SYMBOLS: sysroot_service.BundleBreakpadSymbols,
212 common_pb2.ArtifactsByService.Sysroot.ArtifactType.DEBUG_SYMBOLS: sysroot_service.BundleDebugSymbols,
213 common_pb2.ArtifactsByService.Sysroot.ArtifactType.FUZZER_SYSROOT: sysroot_service.CreateFuzzerSysroot,
Ram Chandrasekar5ba36b22023-03-20 16:10:48 -0600214 common_pb2.ArtifactsByService.Sysroot.ArtifactType.SYSROOT_ARCHIVE: sysroot_service.ArchiveSysroot,
Jack Neus26b94672022-10-27 17:33:21 +0000215 }
216
Alex Kleinab87ceb2023-01-24 12:00:51 -0700217 # pylint: enable=line-too-long
218
Jack Neus26b94672022-10-27 17:33:21 +0000219 def setUp(self):
220 self._mocks = {}
221 for artifact, func in self._artifact_funcs.items():
222 self._mocks[artifact] = self.PatchObject(
223 sysroot_service, func.__name__
224 )
225
226 def _InputProto(
227 self,
228 artifact_types=_artifact_funcs.keys(),
229 ):
230 """Helper to build an input proto instance."""
231 return common_pb2.ArtifactsByService.Sysroot(
232 output_artifacts=[
233 common_pb2.ArtifactsByService.Sysroot.ArtifactInfo(
234 artifact_types=artifact_types
235 )
236 ]
237 )
238
239 def testNoArtifacts(self):
240 """Test GetArtifacts with no artifact types."""
241 in_proto = self._InputProto(artifact_types=[])
242 sysroot_controller.GetArtifacts(
243 in_proto, None, None, "build_target", ""
244 )
245
246 for _, patch in self._mocks.items():
247 patch.assert_not_called()
248
249 def testArtifactsSuccess(self):
250 """Test GetArtifacts with all artifact types."""
251 sysroot_controller.GetArtifacts(
252 self._InputProto(), None, None, "build_target", ""
253 )
254
255 for _, patch in self._mocks.items():
256 patch.assert_called_once()
257
258 def testArtifactsException(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700259 """Test with all artifact types when one type throws an exception."""
Jack Neus26b94672022-10-27 17:33:21 +0000260
261 self._mocks[
262 common_pb2.ArtifactsByService.Sysroot.ArtifactType.FUZZER_SYSROOT
263 ].side_effect = Exception("foo bar")
264 generated = sysroot_controller.GetArtifacts(
265 self._InputProto(), None, None, "build_target", ""
266 )
267
268 for _, patch in self._mocks.items():
269 patch.assert_called_once()
270
271 found_artifact = False
272 for data in generated:
273 artifact_type = (
274 common_pb2.ArtifactsByService.Sysroot.ArtifactType.Name(
275 data["type"]
276 )
277 )
278 if artifact_type == "FUZZER_SYSROOT":
279 found_artifact = True
280 self.assertTrue(data["failed"])
281 self.assertEqual(data["failure_reason"], "foo bar")
282 self.assertTrue(found_artifact)
283
284
Alex Klein1699fab2022-09-08 08:46:06 -0600285class GenerateArchiveTest(
286 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin
287):
288 """GenerateArchive function tests."""
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700289
Alex Klein1699fab2022-09-08 08:46:06 -0600290 def setUp(self):
291 self.chroot_path = "/path/to/chroot"
292 self.board = "board"
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700293
Alex Klein1699fab2022-09-08 08:46:06 -0600294 def _InputProto(self, build_target=None, chroot_path=None, pkg_list=None):
295 """Helper to build and input proto instance."""
296 # pkg_list will be a list of category/package strings such as
297 # ['virtual/target-fuzzers'].
298 if pkg_list:
299 package_list = []
300 for pkg in pkg_list:
301 pkg_string_parts = pkg.split("/")
302 package_info_msg = common_pb2.PackageInfo(
303 category=pkg_string_parts[0],
304 package_name=pkg_string_parts[1],
305 )
306 package_list.append(package_info_msg)
307 else:
308 package_list = []
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700309
Alex Klein1699fab2022-09-08 08:46:06 -0600310 return sysroot_pb2.SysrootGenerateArchiveRequest(
311 build_target={"name": build_target},
312 chroot={"path": chroot_path},
313 packages=package_list,
314 )
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700315
Alex Klein1699fab2022-09-08 08:46:06 -0600316 def _OutputProto(self):
317 """Helper to build output proto instance."""
318 return sysroot_pb2.SysrootGenerateArchiveResponse()
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700319
Alex Klein1699fab2022-09-08 08:46:06 -0600320 def testValidateOnly(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700321 """Verify a validate-only call does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -0600322 patch = self.PatchObject(sysroot_service, "GenerateArchive")
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700323
Alex Klein1699fab2022-09-08 08:46:06 -0600324 in_proto = self._InputProto(
325 build_target=self.board,
326 chroot_path=self.chroot_path,
327 pkg_list=["virtual/target-fuzzers"],
328 )
329 sysroot_controller.GenerateArchive(
330 in_proto, self._OutputProto(), self.validate_only_config
331 )
332 patch.assert_not_called()
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700333
Alex Klein1699fab2022-09-08 08:46:06 -0600334 def testMockCall(self):
335 """Sanity check that a mock call does not execute any logic."""
336 patch = self.PatchObject(sysroot_service, "GenerateArchive")
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700337
Alex Klein1699fab2022-09-08 08:46:06 -0600338 in_proto = self._InputProto(
339 build_target=self.board,
340 chroot_path=self.chroot_path,
341 pkg_list=["virtual/target-fuzzers"],
342 )
343 sysroot_controller.GenerateArchive(
344 in_proto, self._OutputProto(), self.mock_call_config
345 )
346 patch.assert_not_called()
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700347
Alex Klein1699fab2022-09-08 08:46:06 -0600348 def testArgumentValidation(self):
349 """Test the input argument validation."""
350 # Error when no build target provided.
351 in_proto = self._InputProto()
352 out_proto = self._OutputProto()
353 with self.assertRaises(cros_build_lib.DieSystemExit):
354 sysroot_controller.GenerateArchive(
355 in_proto, out_proto, self.api_config
356 )
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700357
Alex Klein1699fab2022-09-08 08:46:06 -0600358 # Error when packages is not specified.
359 in_proto = self._InputProto(
360 build_target="board", chroot_path=self.chroot_path
361 )
362 with self.assertRaises(cros_build_lib.DieSystemExit):
363 sysroot_controller.GenerateArchive(
364 in_proto, out_proto, self.api_config
365 )
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700366
Alex Klein1699fab2022-09-08 08:46:06 -0600367 # Valid when board, chroot path, and package are specified.
368 patch = self.PatchObject(
369 sysroot_service,
370 "GenerateArchive",
371 return_value="/path/to/sysroot/tar.bz",
372 )
373 in_proto = self._InputProto(
374 build_target="board",
375 chroot_path=self.chroot_path,
376 pkg_list=["virtual/target-fuzzers"],
377 )
378 out_proto = self._OutputProto()
379 sysroot_controller.GenerateArchive(in_proto, out_proto, self.api_config)
380 patch.assert_called_once()
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700381
382
Alex Klein1699fab2022-09-08 08:46:06 -0600383class InstallToolchainTest(
384 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin
385):
386 """Install toolchain function tests."""
Alex Kleinda35fcf2019-03-07 16:01:15 -0700387
Alex Klein1699fab2022-09-08 08:46:06 -0600388 def setUp(self):
389 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=True)
390 # Avoid running the portageq command.
391 self.PatchObject(sysroot_controller, "_LogBinhost")
392 self.board = "board"
393 self.sysroot = os.path.join(self.tempdir, "board")
394 self.invalid_sysroot = os.path.join(self.tempdir, "invalid", "sysroot")
395 osutils.SafeMakedirs(self.sysroot)
396 # Set up portage log directory.
397 self.target_sysroot = sysroot_lib.Sysroot(self.sysroot)
398 self.portage_dir = os.path.join(self.tempdir, "portage_logdir")
399 self.PatchObject(
400 sysroot_lib.Sysroot, "portage_logdir", new=self.portage_dir
401 )
402 osutils.SafeMakedirs(self.portage_dir)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700403
Alex Klein1699fab2022-09-08 08:46:06 -0600404 def _InputProto(
405 self, build_target=None, sysroot_path=None, compile_source=False
406 ):
407 """Helper to build an input proto instance."""
408 proto = sysroot_pb2.InstallToolchainRequest()
409 if build_target:
410 proto.sysroot.build_target.name = build_target
411 if sysroot_path:
412 proto.sysroot.path = sysroot_path
413 if compile_source:
414 proto.flags.compile_source = compile_source
Alex Kleinda35fcf2019-03-07 16:01:15 -0700415
Alex Klein1699fab2022-09-08 08:46:06 -0600416 return proto
Alex Kleinda35fcf2019-03-07 16:01:15 -0700417
Alex Klein1699fab2022-09-08 08:46:06 -0600418 def _OutputProto(self):
419 """Helper to build output proto instance."""
420 return sysroot_pb2.InstallToolchainResponse()
Alex Kleinda35fcf2019-03-07 16:01:15 -0700421
Alex Klein1699fab2022-09-08 08:46:06 -0600422 def _CreatePortageLogFile(
423 self,
424 log_path: Union[str, os.PathLike],
425 pkg_info: package_info.PackageInfo,
426 timestamp: datetime.datetime,
427 ):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700428 """Creates a log file to test for individual packages built by Portage.
Lizzy Presland7e23a612021-11-09 21:49:42 +0000429
Alex Klein1699fab2022-09-08 08:46:06 -0600430 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600431 log_path: The PORTAGE_LOGDIR path.
432 pkg_info: Package name used to name the log file.
433 timestamp: Timestamp used to name the file.
Alex Klein1699fab2022-09-08 08:46:06 -0600434 """
435 path = os.path.join(
436 log_path,
437 f"{pkg_info.category}:{pkg_info.pvr}:"
438 f'{timestamp.strftime("%Y%m%d-%H%M%S")}.log',
439 )
440 osutils.WriteFile(
441 path,
442 f"Test log file for package {pkg_info.category}/"
443 f"{pkg_info.package} written to {path}",
444 )
445 return path
Lizzy Presland7e23a612021-11-09 21:49:42 +0000446
Alex Klein1699fab2022-09-08 08:46:06 -0600447 def testValidateOnly(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700448 """Verify a validate-only call does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -0600449 patch = self.PatchObject(sysroot_service, "InstallToolchain")
Alex Klein231d2da2019-07-22 16:44:45 -0600450
Alex Klein1699fab2022-09-08 08:46:06 -0600451 in_proto = self._InputProto(
452 build_target=self.board, sysroot_path=self.sysroot
453 )
454 sysroot_controller.InstallToolchain(
455 in_proto, self._OutputProto(), self.validate_only_config
456 )
457 patch.assert_not_called()
Alex Klein231d2da2019-07-22 16:44:45 -0600458
Alex Klein1699fab2022-09-08 08:46:06 -0600459 def testMockCall(self):
460 """Sanity check that a mock call does not execute any logic."""
461 patch = self.PatchObject(sysroot_service, "InstallToolchain")
462 request = self._InputProto()
463 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -0600464
Alex Klein1699fab2022-09-08 08:46:06 -0600465 rc = sysroot_controller.InstallToolchain(
466 request, response, self.mock_call_config
467 )
Alex Klein076841b2019-08-29 15:19:39 -0600468
Alex Klein1699fab2022-09-08 08:46:06 -0600469 patch.assert_not_called()
470 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
Alex Klein076841b2019-08-29 15:19:39 -0600471
Alex Klein1699fab2022-09-08 08:46:06 -0600472 def testMockError(self):
473 """Sanity check that a mock error does not execute any logic."""
474 patch = self.PatchObject(sysroot_service, "InstallToolchain")
475 request = self._InputProto()
476 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -0600477
Alex Klein1699fab2022-09-08 08:46:06 -0600478 rc = sysroot_controller.InstallToolchain(
479 request, response, self.mock_error_config
480 )
Alex Klein076841b2019-08-29 15:19:39 -0600481
Alex Klein1699fab2022-09-08 08:46:06 -0600482 patch.assert_not_called()
483 self.assertEqual(
484 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
485 )
486 self.assertTrue(response.failed_package_data)
Alex Klein076841b2019-08-29 15:19:39 -0600487
Alex Klein1699fab2022-09-08 08:46:06 -0600488 def testArgumentValidation(self):
489 """Test the argument validation."""
490 # Test errors on missing inputs.
491 out_proto = self._OutputProto()
492 # Both missing.
493 in_proto = self._InputProto()
494 with self.assertRaises(cros_build_lib.DieSystemExit):
495 sysroot_controller.InstallToolchain(
496 in_proto, out_proto, self.api_config
497 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700498
Alex Klein1699fab2022-09-08 08:46:06 -0600499 # Sysroot path missing.
500 in_proto = self._InputProto(build_target=self.board)
501 with self.assertRaises(cros_build_lib.DieSystemExit):
502 sysroot_controller.InstallToolchain(
503 in_proto, out_proto, self.api_config
504 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700505
Alex Klein1699fab2022-09-08 08:46:06 -0600506 # Build target name missing.
507 in_proto = self._InputProto(sysroot_path=self.sysroot)
508 with self.assertRaises(cros_build_lib.DieSystemExit):
509 sysroot_controller.InstallToolchain(
510 in_proto, out_proto, self.api_config
511 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700512
Alex Klein1699fab2022-09-08 08:46:06 -0600513 # Both provided, but invalid sysroot path.
514 in_proto = self._InputProto(
515 build_target=self.board, sysroot_path=self.invalid_sysroot
516 )
517 with self.assertRaises(cros_build_lib.DieSystemExit):
518 sysroot_controller.InstallToolchain(
519 in_proto, out_proto, self.api_config
520 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700521
Alex Klein1699fab2022-09-08 08:46:06 -0600522 def testSuccessOutputHandling(self):
523 """Test the output is processed and recorded correctly."""
524 self.PatchObject(sysroot_service, "InstallToolchain")
525 out_proto = self._OutputProto()
526 in_proto = self._InputProto(
527 build_target=self.board, sysroot_path=self.sysroot
528 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700529
Alex Klein1699fab2022-09-08 08:46:06 -0600530 rc = sysroot_controller.InstallToolchain(
531 in_proto, out_proto, self.api_config
532 )
533 self.assertFalse(rc)
534 self.assertFalse(out_proto.failed_package_data)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700535
Alex Klein1699fab2022-09-08 08:46:06 -0600536 def testErrorOutputHandling(self):
537 """Test the error output is processed and recorded correctly."""
538 out_proto = self._OutputProto()
539 in_proto = self._InputProto(
540 build_target=self.board, sysroot_path=self.sysroot
541 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700542
Alex Klein1699fab2022-09-08 08:46:06 -0600543 err_pkgs = ["cat/pkg-1.0-r1", "cat2/pkg2-1.0-r1"]
544 err_cpvs = [package_info.parse(pkg) for pkg in err_pkgs]
545 expected = [("cat", "pkg"), ("cat2", "pkg2")]
Lizzy Presland7e23a612021-11-09 21:49:42 +0000546
Alex Klein1699fab2022-09-08 08:46:06 -0600547 new_logs = {}
548 for i, pkg in enumerate(err_pkgs):
549 self._CreatePortageLogFile(
550 self.portage_dir,
551 err_cpvs[i],
552 datetime.datetime(2021, 6, 9, 13, 37, 0),
553 )
554 new_logs[pkg] = self._CreatePortageLogFile(
555 self.portage_dir,
556 err_cpvs[i],
557 datetime.datetime(2021, 6, 9, 16, 20, 0),
558 )
Lizzy Presland7e23a612021-11-09 21:49:42 +0000559
Alex Klein1699fab2022-09-08 08:46:06 -0600560 err = sysroot_lib.ToolchainInstallError(
561 "Error", cros_build_lib.CompletedProcess(), tc_info=err_cpvs
562 )
563 self.PatchObject(sysroot_service, "InstallToolchain", side_effect=err)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700564
Alex Klein1699fab2022-09-08 08:46:06 -0600565 rc = sysroot_controller.InstallToolchain(
566 in_proto, out_proto, self.api_config
567 )
568 self.assertEqual(
569 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
570 )
571 self.assertTrue(out_proto.failed_package_data)
572 # This needs to return 2 to indicate the available error response.
573 self.assertEqual(
574 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
575 )
576 for data in out_proto.failed_package_data:
577 package = controller_util.deserialize_package_info(data.name)
578 cat_pkg = (data.name.category, data.name.package_name)
579 self.assertIn(cat_pkg, expected)
580 self.assertEqual(data.log_path.path, new_logs[package.cpvr])
Lizzy Presland7e23a612021-11-09 21:49:42 +0000581
Alex Kleind4e1e422019-03-18 16:00:41 -0600582
Alex Klein1699fab2022-09-08 08:46:06 -0600583class InstallPackagesTest(
584 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin
585):
586 """InstallPackages tests."""
Alex Kleind4e1e422019-03-18 16:00:41 -0600587
Alex Klein1699fab2022-09-08 08:46:06 -0600588 def setUp(self):
589 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=True)
590 # Avoid running the portageq command.
591 self.PatchObject(sysroot_controller, "_LogBinhost")
592 self.build_target = "board"
593 self.sysroot = os.path.join(self.tempdir, "build", "board")
594 osutils.SafeMakedirs(self.sysroot)
595 # Set up portage log directory.
596 self.target_sysroot = sysroot_lib.Sysroot(self.sysroot)
597 self.portage_dir = os.path.join(self.tempdir, "portage_logdir")
598 self.PatchObject(
599 sysroot_lib.Sysroot, "portage_logdir", new=self.portage_dir
600 )
601 osutils.SafeMakedirs(self.portage_dir)
602 # Set up goma directories.
603 self.goma_dir = os.path.join(self.tempdir, "goma_dir")
604 osutils.SafeMakedirs(self.goma_dir)
605 self.goma_out_dir = os.path.join(self.tempdir, "goma_out_dir")
606 osutils.SafeMakedirs(self.goma_out_dir)
607 os.environ["GLOG_log_dir"] = self.goma_dir
Alex Kleind4e1e422019-03-18 16:00:41 -0600608
Alex Klein1699fab2022-09-08 08:46:06 -0600609 def _InputProto(
610 self,
611 build_target=None,
612 sysroot_path=None,
613 build_source=False,
Yoshiki Iguchi2f7f0222023-05-17 19:30:09 +0900614 use_cq_prebuilts=False,
Alex Klein1699fab2022-09-08 08:46:06 -0600615 goma_dir=None,
616 goma_log_dir=None,
617 goma_stats_file=None,
618 goma_counterz_file=None,
619 package_indexes=None,
620 packages=None,
621 ):
622 """Helper to build an input proto instance."""
623 instance = sysroot_pb2.InstallPackagesRequest()
Alex Kleind4e1e422019-03-18 16:00:41 -0600624
Alex Klein1699fab2022-09-08 08:46:06 -0600625 if build_target:
626 instance.sysroot.build_target.name = build_target
627 if sysroot_path:
628 instance.sysroot.path = sysroot_path
629 if build_source:
630 instance.flags.build_source = build_source
Yoshiki Iguchi2f7f0222023-05-17 19:30:09 +0900631 if use_cq_prebuilts:
632 instance.flags.use_cq_prebuilts = use_cq_prebuilts
Alex Klein1699fab2022-09-08 08:46:06 -0600633 if goma_dir:
634 instance.goma_config.goma_dir = goma_dir
635 if goma_log_dir:
636 instance.goma_config.log_dir.dir = goma_log_dir
637 if goma_stats_file:
638 instance.goma_config.stats_file = goma_stats_file
639 if goma_counterz_file:
640 instance.goma_config.counterz_file = goma_counterz_file
641 if package_indexes:
642 instance.package_indexes.extend(package_indexes)
643 if packages:
644 for pkg in packages:
645 pkg_info = package_info.parse(pkg)
646 pkg_info_msg = instance.packages.add()
647 controller_util.serialize_package_info(pkg_info, pkg_info_msg)
648 return instance
Alex Kleind4e1e422019-03-18 16:00:41 -0600649
Alex Klein1699fab2022-09-08 08:46:06 -0600650 def _OutputProto(self):
651 """Helper to build an empty output proto instance."""
652 return sysroot_pb2.InstallPackagesResponse()
Alex Kleind4e1e422019-03-18 16:00:41 -0600653
Alex Klein1699fab2022-09-08 08:46:06 -0600654 def _CreateGomaLogFile(
655 self,
656 goma_log_dir: Union[str, os.PathLike],
657 name: str,
658 timestamp: datetime.datetime,
659 ):
660 """Creates a log file for testing.
Michael Mortensen798ee192020-01-17 13:04:43 -0700661
Alex Klein1699fab2022-09-08 08:46:06 -0600662 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600663 goma_log_dir: Directory where the file will be created.
664 name: Log file 'base' name that is combined with the timestamp.
665 timestamp: Timestamp that is written to the file.
Alex Klein1699fab2022-09-08 08:46:06 -0600666 """
667 path = os.path.join(
668 goma_log_dir,
669 "%s.host.log.INFO.%s"
670 % (name, timestamp.strftime("%Y%m%d-%H%M%S.%f")),
671 )
672 osutils.WriteFile(
673 path,
674 timestamp.strftime("Goma log file created at: %Y/%m/%d %H:%M:%S"),
675 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700676
Alex Klein1699fab2022-09-08 08:46:06 -0600677 def _CreatePortageLogFile(
678 self,
679 log_path: Union[str, os.PathLike],
680 pkg_info: package_info.PackageInfo,
681 timestamp: datetime.datetime,
682 ):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700683 """Creates a log file to test for individual packages built by Portage.
Lizzy Presland7e23a612021-11-09 21:49:42 +0000684
Alex Klein1699fab2022-09-08 08:46:06 -0600685 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600686 log_path: The PORTAGE_LOGDIR path.
687 pkg_info: Package name used to name the log file.
688 timestamp: Timestamp used to name the file.
Alex Klein1699fab2022-09-08 08:46:06 -0600689 """
690 path = os.path.join(
691 log_path,
692 f"{pkg_info.category}:{pkg_info.pvr}:"
693 f'{timestamp.strftime("%Y%m%d-%H%M%S")}.log',
694 )
695 osutils.WriteFile(
696 path,
697 f"Test log file for package {pkg_info.category}/"
698 f"{pkg_info.package} written to {path}",
699 )
700 return path
Lizzy Presland7e23a612021-11-09 21:49:42 +0000701
Alex Klein1699fab2022-09-08 08:46:06 -0600702 def testValidateOnly(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700703 """Verify a validate-only call does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -0600704 patch = self.PatchObject(sysroot_service, "BuildPackages")
Alex Klein231d2da2019-07-22 16:44:45 -0600705
Alex Klein1699fab2022-09-08 08:46:06 -0600706 in_proto = self._InputProto(
707 build_target=self.build_target, sysroot_path=self.sysroot
708 )
709 sysroot_controller.InstallPackages(
710 in_proto, self._OutputProto(), self.validate_only_config
711 )
712 patch.assert_not_called()
Alex Klein231d2da2019-07-22 16:44:45 -0600713
Alex Klein1699fab2022-09-08 08:46:06 -0600714 def testMockCall(self):
715 """Sanity check that a mock call does not execute any logic."""
716 patch = self.PatchObject(sysroot_service, "BuildPackages")
717 request = self._InputProto()
718 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -0600719
Alex Klein1699fab2022-09-08 08:46:06 -0600720 rc = sysroot_controller.InstallPackages(
721 request, response, self.mock_call_config
722 )
Alex Klein076841b2019-08-29 15:19:39 -0600723
Alex Klein1699fab2022-09-08 08:46:06 -0600724 patch.assert_not_called()
725 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
Alex Klein076841b2019-08-29 15:19:39 -0600726
Alex Klein1699fab2022-09-08 08:46:06 -0600727 def testMockError(self):
728 """Sanity check that a mock error does not execute any logic."""
729 patch = self.PatchObject(sysroot_service, "BuildPackages")
730 request = self._InputProto()
731 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -0600732
Alex Klein1699fab2022-09-08 08:46:06 -0600733 rc = sysroot_controller.InstallPackages(
734 request, response, self.mock_error_config
735 )
Alex Klein076841b2019-08-29 15:19:39 -0600736
Alex Klein1699fab2022-09-08 08:46:06 -0600737 patch.assert_not_called()
738 self.assertEqual(
739 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
740 )
741 self.assertTrue(response.failed_package_data)
Alex Klein076841b2019-08-29 15:19:39 -0600742
Alex Klein1699fab2022-09-08 08:46:06 -0600743 def testArgumentValidationAllMissing(self):
744 """Test missing all arguments."""
745 out_proto = self._OutputProto()
746 in_proto = self._InputProto()
747 with self.assertRaises(cros_build_lib.DieSystemExit):
748 sysroot_controller.InstallPackages(
749 in_proto, out_proto, self.api_config
750 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600751
Alex Klein1699fab2022-09-08 08:46:06 -0600752 def testArgumentValidationNoSysroot(self):
753 """Test missing sysroot path."""
754 out_proto = self._OutputProto()
755 in_proto = self._InputProto(build_target=self.build_target)
756 with self.assertRaises(cros_build_lib.DieSystemExit):
757 sysroot_controller.InstallPackages(
758 in_proto, out_proto, self.api_config
759 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600760
Alex Klein1699fab2022-09-08 08:46:06 -0600761 def testArgumentValidationNoBuildTarget(self):
762 """Test missing build target name."""
763 out_proto = self._OutputProto()
764 in_proto = self._InputProto(sysroot_path=self.sysroot)
765 with self.assertRaises(cros_build_lib.DieSystemExit):
766 sysroot_controller.InstallPackages(
767 in_proto, out_proto, self.api_config
768 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600769
Alex Klein1699fab2022-09-08 08:46:06 -0600770 def testArgumentValidationInvalidSysroot(self):
771 """Test sysroot that hasn't had the toolchain installed."""
772 out_proto = self._OutputProto()
773 in_proto = self._InputProto(
774 build_target=self.build_target, sysroot_path=self.sysroot
775 )
776 self.PatchObject(
777 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=False
778 )
779 with self.assertRaises(cros_build_lib.DieSystemExit):
780 sysroot_controller.InstallPackages(
781 in_proto, out_proto, self.api_config
782 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600783
Alex Klein1699fab2022-09-08 08:46:06 -0600784 def testArgumentValidationInvalidPackage(self):
785 out_proto = self._OutputProto()
786 in_proto = self._InputProto(
787 build_target=self.build_target,
788 sysroot_path=self.sysroot,
789 packages=["package-1.0.0-r2"],
790 )
791 with self.assertRaises(cros_build_lib.DieSystemExit):
792 sysroot_controller.InstallPackages(
793 in_proto, out_proto, self.api_config
794 )
Alex Kleinca572ee2020-09-03 10:47:14 -0600795
Alex Klein1699fab2022-09-08 08:46:06 -0600796 def testSuccessOutputHandling(self):
797 """Test successful call output handling."""
798 # Prevent argument validation error.
799 self.PatchObject(
800 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
801 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600802
Alex Klein1699fab2022-09-08 08:46:06 -0600803 in_proto = self._InputProto(
804 build_target=self.build_target, sysroot_path=self.sysroot
805 )
806 out_proto = self._OutputProto()
807 self.PatchObject(sysroot_service, "BuildPackages")
Alex Kleind4e1e422019-03-18 16:00:41 -0600808
Alex Klein1699fab2022-09-08 08:46:06 -0600809 rc = sysroot_controller.InstallPackages(
810 in_proto, out_proto, self.api_config
811 )
812 self.assertFalse(rc)
813 self.assertFalse(out_proto.failed_package_data)
Alex Kleind4e1e422019-03-18 16:00:41 -0600814
Alex Klein1699fab2022-09-08 08:46:06 -0600815 def testSuccessPackageIndexes(self):
816 """Test successful call with package_indexes."""
817 # Prevent argument validation error.
818 self.PatchObject(
819 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
820 )
821 package_indexes = [
822 common_pb2.PackageIndexInfo(
823 snapshot_sha="SHA",
824 snapshot_number=5,
825 build_target=common_pb2.BuildTarget(name="board"),
826 location="LOCATION",
827 profile=common_pb2.Profile(name="profile"),
828 ),
829 common_pb2.PackageIndexInfo(
830 snapshot_sha="SHA2",
831 snapshot_number=4,
832 build_target=common_pb2.BuildTarget(name="board"),
833 location="LOCATION2",
834 profile=common_pb2.Profile(name="profile"),
835 ),
836 ]
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600837
Alex Klein1699fab2022-09-08 08:46:06 -0600838 in_proto = self._InputProto(
839 build_target=self.build_target,
840 sysroot_path=self.sysroot,
841 package_indexes=package_indexes,
842 )
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600843
Alex Klein1699fab2022-09-08 08:46:06 -0600844 out_proto = self._OutputProto()
845 rc_patch = self.PatchObject(sysroot_service, "BuildPackagesRunConfig")
846 self.PatchObject(sysroot_service, "BuildPackages")
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600847
Alex Klein1699fab2022-09-08 08:46:06 -0600848 rc = sysroot_controller.InstallPackages(
849 in_proto, out_proto, self.api_config
850 )
851 self.assertFalse(rc)
852 rc_patch.assert_called_with(
853 use_any_chrome=False,
854 usepkg=True,
855 install_debug_symbols=True,
856 packages=[],
857 package_indexes=[
Alex Klein6d718d62023-01-18 15:55:51 -0700858 controller_util.deserialize_package_index_info(x)
Alex Klein1699fab2022-09-08 08:46:06 -0600859 for x in package_indexes
860 ],
861 use_flags=[],
862 use_goma=False,
863 use_remoteexec=False,
864 incremental_build=False,
865 dryrun=False,
866 backtrack=sysroot_controller.DEFAULT_BACKTRACK,
Alex Klein8393dc22023-03-30 10:54:27 -0600867 workon=False,
Alex Klein1699fab2022-09-08 08:46:06 -0600868 )
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600869
Alex Klein1699fab2022-09-08 08:46:06 -0600870 def testSuccessWithGomaLogs(self):
871 """Test successful call with goma."""
872 self._CreateGomaLogFile(
873 self.goma_dir,
874 "compiler_proxy",
875 datetime.datetime(2018, 9, 21, 12, 0, 0),
876 )
877 self._CreateGomaLogFile(
878 self.goma_dir,
879 "compiler_proxy-subproc",
880 datetime.datetime(2018, 9, 21, 12, 1, 0),
881 )
882 self._CreateGomaLogFile(
883 self.goma_dir, "gomacc", datetime.datetime(2018, 9, 21, 12, 2, 0)
884 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700885
Alex Klein1699fab2022-09-08 08:46:06 -0600886 # Prevent argument validation error.
887 self.PatchObject(
888 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
889 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700890
Alex Klein1699fab2022-09-08 08:46:06 -0600891 in_proto = self._InputProto(
892 build_target=self.build_target,
893 sysroot_path=self.sysroot,
894 goma_dir=self.goma_dir,
895 goma_log_dir=self.goma_out_dir,
896 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700897
Alex Klein1699fab2022-09-08 08:46:06 -0600898 out_proto = self._OutputProto()
899 self.PatchObject(sysroot_service, "BuildPackages")
Michael Mortensen798ee192020-01-17 13:04:43 -0700900
Alex Klein1699fab2022-09-08 08:46:06 -0600901 rc = sysroot_controller.InstallPackages(
902 in_proto, out_proto, self.api_config
903 )
904 self.assertFalse(rc)
905 self.assertFalse(out_proto.failed_package_data)
Alex Kleinab87ceb2023-01-24 12:00:51 -0700906
907 expected = [
908 "compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz",
909 "compiler_proxy.host.log.INFO.20180921-120000.000000.gz",
910 "gomacc.host.log.INFO.20180921-120200.000000.tar.gz",
911 ]
912 self.assertCountEqual(out_proto.goma_artifacts.log_files, expected)
Michael Mortensen798ee192020-01-17 13:04:43 -0700913
Alex Klein1699fab2022-09-08 08:46:06 -0600914 def testSuccessWithGomaLogsAndStatsCounterzFiles(self):
915 """Test successful call with goma including stats and counterz files."""
916 self._CreateGomaLogFile(
917 self.goma_dir,
918 "compiler_proxy",
919 datetime.datetime(2018, 9, 21, 12, 0, 0),
920 )
921 self._CreateGomaLogFile(
922 self.goma_dir,
923 "compiler_proxy-subproc",
924 datetime.datetime(2018, 9, 21, 12, 1, 0),
925 )
926 self._CreateGomaLogFile(
927 self.goma_dir, "gomacc", datetime.datetime(2018, 9, 21, 12, 2, 0)
928 )
929 # Create stats and counterz files.
930 osutils.WriteFile(
931 os.path.join(self.goma_dir, "stats.binaryproto"),
932 "File: stats.binaryproto",
933 )
934 osutils.WriteFile(
935 os.path.join(self.goma_dir, "counterz.binaryproto"),
936 "File: counterz.binaryproto",
937 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700938
Alex Klein1699fab2022-09-08 08:46:06 -0600939 # Prevent argument validation error.
940 self.PatchObject(
941 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
942 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700943
Alex Klein1699fab2022-09-08 08:46:06 -0600944 in_proto = self._InputProto(
945 build_target=self.build_target,
946 sysroot_path=self.sysroot,
947 goma_dir=self.goma_dir,
948 goma_log_dir=self.goma_out_dir,
949 goma_stats_file="stats.binaryproto",
950 goma_counterz_file="counterz.binaryproto",
951 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700952
Alex Klein1699fab2022-09-08 08:46:06 -0600953 out_proto = self._OutputProto()
954 self.PatchObject(sysroot_service, "BuildPackages")
Michael Mortensen798ee192020-01-17 13:04:43 -0700955
Alex Klein1699fab2022-09-08 08:46:06 -0600956 rc = sysroot_controller.InstallPackages(
957 in_proto, out_proto, self.api_config
958 )
959 self.assertFalse(rc)
960 self.assertFalse(out_proto.failed_package_data)
Alex Kleinab87ceb2023-01-24 12:00:51 -0700961 expected_logs = [
962 "compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz",
963 "compiler_proxy.host.log.INFO.20180921-120000.000000.gz",
964 "gomacc.host.log.INFO.20180921-120200.000000.tar.gz",
965 ]
966 self.assertCountEqual(out_proto.goma_artifacts.log_files, expected_logs)
967
Alex Klein1699fab2022-09-08 08:46:06 -0600968 # Verify that the output dir has 5 files -- since there should be 3 log
969 # files, the stats file, and the counterz file.
970 output_files = os.listdir(self.goma_out_dir)
Alex Kleinab87ceb2023-01-24 12:00:51 -0700971 expected_output = [
972 "stats.binaryproto",
973 "counterz.binaryproto",
974 "compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz",
975 "compiler_proxy.host.log.INFO.20180921-120000.000000.gz",
976 "gomacc.host.log.INFO.20180921-120200.000000.tar.gz",
977 ]
978 self.assertCountEqual(output_files, expected_output)
Alex Klein1699fab2022-09-08 08:46:06 -0600979 self.assertEqual(
980 out_proto.goma_artifacts.counterz_file, "counterz.binaryproto"
981 )
982 self.assertEqual(
983 out_proto.goma_artifacts.stats_file, "stats.binaryproto"
984 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700985
Alex Klein1699fab2022-09-08 08:46:06 -0600986 def testFailureMissingGomaStatsCounterzFiles(self):
987 """Test successful call with goma including stats and counterz files."""
988 self._CreateGomaLogFile(
989 self.goma_dir,
990 "compiler_proxy",
991 datetime.datetime(2018, 9, 21, 12, 0, 0),
992 )
993 self._CreateGomaLogFile(
994 self.goma_dir,
995 "compiler_proxy-subproc",
996 datetime.datetime(2018, 9, 21, 12, 1, 0),
997 )
998 self._CreateGomaLogFile(
999 self.goma_dir, "gomacc", datetime.datetime(2018, 9, 21, 12, 2, 0)
1000 )
Alex Kleinab87ceb2023-01-24 12:00:51 -07001001 # Note that stats and counterz files are not created, but are specified
1002 # in the proto below.
Michael Mortensen798ee192020-01-17 13:04:43 -07001003
Alex Klein1699fab2022-09-08 08:46:06 -06001004 # Prevent argument validation error.
1005 self.PatchObject(
1006 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
1007 )
Michael Mortensen798ee192020-01-17 13:04:43 -07001008
Alex Klein1699fab2022-09-08 08:46:06 -06001009 in_proto = self._InputProto(
1010 build_target=self.build_target,
1011 sysroot_path=self.sysroot,
1012 goma_dir=self.goma_dir,
1013 goma_log_dir=self.goma_out_dir,
1014 goma_stats_file="stats.binaryproto",
1015 goma_counterz_file="counterz.binaryproto",
1016 )
Michael Mortensen798ee192020-01-17 13:04:43 -07001017
Alex Klein1699fab2022-09-08 08:46:06 -06001018 out_proto = self._OutputProto()
1019 self.PatchObject(sysroot_service, "BuildPackages")
Michael Mortensen798ee192020-01-17 13:04:43 -07001020
Alex Klein1699fab2022-09-08 08:46:06 -06001021 rc = sysroot_controller.InstallPackages(
1022 in_proto, out_proto, self.api_config
1023 )
1024 self.assertFalse(rc)
1025 self.assertFalse(out_proto.failed_package_data)
Alex Kleinab87ceb2023-01-24 12:00:51 -07001026 expected_logs = [
1027 "compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz",
1028 "compiler_proxy.host.log.INFO.20180921-120000.000000.gz",
1029 "gomacc.host.log.INFO.20180921-120200.000000.tar.gz",
1030 ]
1031 self.assertCountEqual(out_proto.goma_artifacts.log_files, expected_logs)
Alex Klein1699fab2022-09-08 08:46:06 -06001032 self.assertFalse(out_proto.goma_artifacts.counterz_file)
1033 self.assertFalse(out_proto.goma_artifacts.stats_file)
Michael Mortensen798ee192020-01-17 13:04:43 -07001034
Alex Klein1699fab2022-09-08 08:46:06 -06001035 def testFailureOutputHandling(self):
1036 """Test failed package handling."""
1037 # Prevent argument validation error.
1038 self.PatchObject(
1039 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
1040 )
Alex Kleind4e1e422019-03-18 16:00:41 -06001041
Alex Klein1699fab2022-09-08 08:46:06 -06001042 in_proto = self._InputProto(
1043 build_target=self.build_target, sysroot_path=self.sysroot
1044 )
1045 out_proto = self._OutputProto()
Alex Kleind4e1e422019-03-18 16:00:41 -06001046
Alex Klein1699fab2022-09-08 08:46:06 -06001047 # Failed package info and expected list for verification.
1048 err_pkgs = ["cat/pkg-1.0-r3", "cat2/pkg2-1.0-r1"]
1049 err_cpvs = [package_info.parse(cpv) for cpv in err_pkgs]
1050 expected = [("cat", "pkg"), ("cat2", "pkg2")]
Alex Kleind4e1e422019-03-18 16:00:41 -06001051
Alex Klein1699fab2022-09-08 08:46:06 -06001052 new_logs = {}
1053 for i, pkg in enumerate(err_pkgs):
1054 self._CreatePortageLogFile(
1055 self.portage_dir,
1056 err_cpvs[i],
1057 datetime.datetime(2021, 6, 9, 13, 37, 0),
1058 )
1059 new_logs[pkg] = self._CreatePortageLogFile(
1060 self.portage_dir,
1061 err_cpvs[i],
1062 datetime.datetime(2021, 6, 9, 16, 20, 0),
1063 )
1064 # Force error to be raised with the packages.
1065 error = sysroot_lib.PackageInstallError(
1066 "Error", cros_build_lib.CompletedProcess(), packages=err_cpvs
1067 )
1068 self.PatchObject(sysroot_service, "BuildPackages", side_effect=error)
Alex Kleind4e1e422019-03-18 16:00:41 -06001069
Alex Klein1699fab2022-09-08 08:46:06 -06001070 rc = sysroot_controller.InstallPackages(
1071 in_proto, out_proto, self.api_config
1072 )
1073 # This needs to return 2 to indicate the available error response.
1074 self.assertEqual(
1075 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
1076 )
1077 for data in out_proto.failed_package_data:
1078 package = controller_util.deserialize_package_info(data.name)
1079 cat_pkg = (data.name.category, data.name.package_name)
1080 self.assertIn(cat_pkg, expected)
1081 self.assertEqual(data.log_path.path, new_logs[package.cpvr])
Lizzy Presland7e23a612021-11-09 21:49:42 +00001082
Alex Klein1699fab2022-09-08 08:46:06 -06001083 def testNoPackageFailureOutputHandling(self):
1084 """Test failure handling without packages to report."""
1085 # Prevent argument validation error.
1086 self.PatchObject(
1087 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
1088 )
Alex Klein2557b4f2019-07-11 14:34:00 -06001089
Alex Klein1699fab2022-09-08 08:46:06 -06001090 in_proto = self._InputProto(
1091 build_target=self.build_target, sysroot_path=self.sysroot
1092 )
1093 out_proto = self._OutputProto()
Alex Klein2557b4f2019-07-11 14:34:00 -06001094
Alex Klein1699fab2022-09-08 08:46:06 -06001095 # Force error to be raised with no packages.
1096 error = sysroot_lib.PackageInstallError(
1097 "Error", cros_build_lib.CompletedProcess(), packages=[]
1098 )
1099 self.PatchObject(sysroot_service, "BuildPackages", side_effect=error)
Alex Klein2557b4f2019-07-11 14:34:00 -06001100
Alex Klein1699fab2022-09-08 08:46:06 -06001101 rc = sysroot_controller.InstallPackages(
1102 in_proto, out_proto, self.api_config
1103 )
1104 # All we really care about is it's not 0 or 2 (response available), so
1105 # test for that rather than a specific return code.
1106 self.assertTrue(rc)
1107 self.assertNotEqual(
1108 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
1109 )