blob: 6d75e5d811f2e4538029a158b8203422bedc0ccb [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,
34 package_indexes=None,
35 ):
36 """Helper to build and input proto instance."""
37 proto = sysroot_pb2.SysrootCreateRequest()
38 if build_target:
39 proto.build_target.name = build_target
40 if profile:
41 proto.profile.name = profile
42 if replace:
43 proto.flags.replace = replace
44 if current:
45 proto.flags.chroot_current = current
46 if package_indexes:
47 proto.package_indexes.extend(package_indexes)
Alex Kleinda35fcf2019-03-07 16:01:15 -070048
Alex Klein1699fab2022-09-08 08:46:06 -060049 return proto
Alex Kleinda35fcf2019-03-07 16:01:15 -070050
Alex Klein1699fab2022-09-08 08:46:06 -060051 def _OutputProto(self):
52 """Helper to build output proto instance."""
53 return sysroot_pb2.SysrootCreateResponse()
Alex Kleinda35fcf2019-03-07 16:01:15 -070054
Alex Klein1699fab2022-09-08 08:46:06 -060055 def testValidateOnly(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -070056 """Verify a validate-only call does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -060057 patch = self.PatchObject(sysroot_service, "Create")
Alex Klein231d2da2019-07-22 16:44:45 -060058
Alex Klein1699fab2022-09-08 08:46:06 -060059 board = "board"
60 profile = None
61 force = False
62 upgrade_chroot = True
63 in_proto = self._InputProto(
64 build_target=board,
65 profile=profile,
66 replace=force,
67 current=not upgrade_chroot,
68 )
69 sysroot_controller.Create(
70 in_proto, self._OutputProto(), self.validate_only_config
71 )
72 patch.assert_not_called()
Alex Klein231d2da2019-07-22 16:44:45 -060073
Alex Klein1699fab2022-09-08 08:46:06 -060074 def testMockCall(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -070075 """Verify a mock call does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -060076 patch = self.PatchObject(sysroot_service, "Create")
77 request = self._InputProto()
78 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -060079
Alex Klein1699fab2022-09-08 08:46:06 -060080 rc = sysroot_controller.Create(request, response, self.mock_call_config)
Alex Klein076841b2019-08-29 15:19:39 -060081
Alex Klein1699fab2022-09-08 08:46:06 -060082 patch.assert_not_called()
83 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
Alex Klein076841b2019-08-29 15:19:39 -060084
Alex Klein1699fab2022-09-08 08:46:06 -060085 def testMockError(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -070086 """Verify a mock error does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -060087 patch = self.PatchObject(sysroot_service, "Create")
88 request = self._InputProto()
89 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -060090
Alex Klein1699fab2022-09-08 08:46:06 -060091 rc = sysroot_controller.Create(
92 request, response, self.mock_error_config
93 )
Alex Klein076841b2019-08-29 15:19:39 -060094
Alex Klein1699fab2022-09-08 08:46:06 -060095 patch.assert_not_called()
96 self.assertEqual(controller.RETURN_CODE_UNRECOVERABLE, rc)
Alex Klein076841b2019-08-29 15:19:39 -060097
Alex Klein1699fab2022-09-08 08:46:06 -060098 def testArgumentValidation(self):
99 """Test the input argument validation."""
100 # Error when no name provided.
101 in_proto = self._InputProto()
102 out_proto = self._OutputProto()
103 with self.assertRaises(cros_build_lib.DieSystemExit):
104 sysroot_controller.Create(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700105
Alex Klein1699fab2022-09-08 08:46:06 -0600106 # Valid when board passed.
107 result = sysroot_lib.Sysroot("/sysroot/path")
108 patch = self.PatchObject(sysroot_service, "Create", return_value=result)
109 in_proto = self._InputProto("board")
110 out_proto = self._OutputProto()
111 sysroot_controller.Create(in_proto, out_proto, self.api_config)
112 patch.assert_called_once()
Alex Kleinda35fcf2019-03-07 16:01:15 -0700113
Alex Klein1699fab2022-09-08 08:46:06 -0600114 def testArgumentHandling(self):
115 """Test the arguments get processed and passed correctly."""
116 sysroot_path = "/sysroot/path"
Alex Kleinda35fcf2019-03-07 16:01:15 -0700117
Alex Klein1699fab2022-09-08 08:46:06 -0600118 sysroot = sysroot_lib.Sysroot(sysroot_path)
119 create_patch = self.PatchObject(
120 sysroot_service, "Create", return_value=sysroot
121 )
122 rc_patch = self.PatchObject(sysroot_service, "SetupBoardRunConfig")
Alex Kleinda35fcf2019-03-07 16:01:15 -0700123
Alex Klein1699fab2022-09-08 08:46:06 -0600124 # Default values.
125 board = "board"
126 profile = None
127 force = False
128 upgrade_chroot = True
129 in_proto = self._InputProto(
130 build_target=board,
131 profile=profile,
132 replace=force,
133 current=not upgrade_chroot,
134 )
135 out_proto = self._OutputProto()
136 sysroot_controller.Create(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700137
Alex Klein1699fab2022-09-08 08:46:06 -0600138 # Default value checks.
139 rc_patch.assert_called_with(
140 force=force,
141 upgrade_chroot=upgrade_chroot,
142 package_indexes=[],
143 backtrack=sysroot_controller.DEFAULT_BACKTRACK,
144 )
145 self.assertEqual(board, out_proto.sysroot.build_target.name)
146 self.assertEqual(sysroot_path, out_proto.sysroot.path)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700147
Alex Klein1699fab2022-09-08 08:46:06 -0600148 # Not default values.
149 create_patch.reset_mock()
150 board = "board"
151 profile = "profile"
152 force = True
153 upgrade_chroot = False
154 package_indexes = [
155 common_pb2.PackageIndexInfo(
156 snapshot_sha="SHA",
157 snapshot_number=5,
158 build_target=common_pb2.BuildTarget(name=board),
159 location="LOCATION",
160 profile=common_pb2.Profile(name=profile),
161 ),
162 common_pb2.PackageIndexInfo(
163 snapshot_sha="SHA2",
164 snapshot_number=4,
165 build_target=common_pb2.BuildTarget(name=board),
166 location="LOCATION2",
167 profile=common_pb2.Profile(name=profile),
168 ),
169 ]
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600170
Alex Klein1699fab2022-09-08 08:46:06 -0600171 in_proto = self._InputProto(
172 build_target=board,
173 profile=profile,
174 replace=force,
175 current=not upgrade_chroot,
176 package_indexes=package_indexes,
177 )
178 out_proto = self._OutputProto()
179 sysroot_controller.Create(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700180
Alex Klein1699fab2022-09-08 08:46:06 -0600181 # Not default value checks.
182 rc_patch.assert_called_with(
183 force=force,
184 package_indexes=[
Alex Klein6d718d62023-01-18 15:55:51 -0700185 controller_util.deserialize_package_index_info(x)
Alex Klein1699fab2022-09-08 08:46:06 -0600186 for x in package_indexes
187 ],
188 upgrade_chroot=upgrade_chroot,
189 backtrack=sysroot_controller.DEFAULT_BACKTRACK,
190 )
191 self.assertEqual(board, out_proto.sysroot.build_target.name)
192 self.assertEqual(sysroot_path, out_proto.sysroot.path)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700193
194
Jack Neus26b94672022-10-27 17:33:21 +0000195class GetArtifactsTest(cros_test_lib.MockTestCase, api_config.ApiConfigMixin):
196 """GetArtifacts function tests."""
197
Alex Kleinab87ceb2023-01-24 12:00:51 -0700198 # pylint: disable=line-too-long
Jack Neus26b94672022-10-27 17:33:21 +0000199 _artifact_funcs = {
200 common_pb2.ArtifactsByService.Sysroot.ArtifactType.SIMPLE_CHROME_SYSROOT: sysroot_service.CreateSimpleChromeSysroot,
201 common_pb2.ArtifactsByService.Sysroot.ArtifactType.CHROME_EBUILD_ENV: sysroot_service.CreateChromeEbuildEnv,
202 common_pb2.ArtifactsByService.Sysroot.ArtifactType.BREAKPAD_DEBUG_SYMBOLS: sysroot_service.BundleBreakpadSymbols,
203 common_pb2.ArtifactsByService.Sysroot.ArtifactType.DEBUG_SYMBOLS: sysroot_service.BundleDebugSymbols,
204 common_pb2.ArtifactsByService.Sysroot.ArtifactType.FUZZER_SYSROOT: sysroot_service.CreateFuzzerSysroot,
Ram Chandrasekar5ba36b22023-03-20 16:10:48 -0600205 common_pb2.ArtifactsByService.Sysroot.ArtifactType.SYSROOT_ARCHIVE: sysroot_service.ArchiveSysroot,
Jack Neus26b94672022-10-27 17:33:21 +0000206 }
207
Alex Kleinab87ceb2023-01-24 12:00:51 -0700208 # pylint: enable=line-too-long
209
Jack Neus26b94672022-10-27 17:33:21 +0000210 def setUp(self):
211 self._mocks = {}
212 for artifact, func in self._artifact_funcs.items():
213 self._mocks[artifact] = self.PatchObject(
214 sysroot_service, func.__name__
215 )
216
217 def _InputProto(
218 self,
219 artifact_types=_artifact_funcs.keys(),
220 ):
221 """Helper to build an input proto instance."""
222 return common_pb2.ArtifactsByService.Sysroot(
223 output_artifacts=[
224 common_pb2.ArtifactsByService.Sysroot.ArtifactInfo(
225 artifact_types=artifact_types
226 )
227 ]
228 )
229
230 def testNoArtifacts(self):
231 """Test GetArtifacts with no artifact types."""
232 in_proto = self._InputProto(artifact_types=[])
233 sysroot_controller.GetArtifacts(
234 in_proto, None, None, "build_target", ""
235 )
236
237 for _, patch in self._mocks.items():
238 patch.assert_not_called()
239
240 def testArtifactsSuccess(self):
241 """Test GetArtifacts with all artifact types."""
242 sysroot_controller.GetArtifacts(
243 self._InputProto(), None, None, "build_target", ""
244 )
245
246 for _, patch in self._mocks.items():
247 patch.assert_called_once()
248
249 def testArtifactsException(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700250 """Test with all artifact types when one type throws an exception."""
Jack Neus26b94672022-10-27 17:33:21 +0000251
252 self._mocks[
253 common_pb2.ArtifactsByService.Sysroot.ArtifactType.FUZZER_SYSROOT
254 ].side_effect = Exception("foo bar")
255 generated = sysroot_controller.GetArtifacts(
256 self._InputProto(), None, None, "build_target", ""
257 )
258
259 for _, patch in self._mocks.items():
260 patch.assert_called_once()
261
262 found_artifact = False
263 for data in generated:
264 artifact_type = (
265 common_pb2.ArtifactsByService.Sysroot.ArtifactType.Name(
266 data["type"]
267 )
268 )
269 if artifact_type == "FUZZER_SYSROOT":
270 found_artifact = True
271 self.assertTrue(data["failed"])
272 self.assertEqual(data["failure_reason"], "foo bar")
273 self.assertTrue(found_artifact)
274
275
Alex Klein1699fab2022-09-08 08:46:06 -0600276class GenerateArchiveTest(
277 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin
278):
279 """GenerateArchive function tests."""
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700280
Alex Klein1699fab2022-09-08 08:46:06 -0600281 def setUp(self):
282 self.chroot_path = "/path/to/chroot"
283 self.board = "board"
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700284
Alex Klein1699fab2022-09-08 08:46:06 -0600285 def _InputProto(self, build_target=None, chroot_path=None, pkg_list=None):
286 """Helper to build and input proto instance."""
287 # pkg_list will be a list of category/package strings such as
288 # ['virtual/target-fuzzers'].
289 if pkg_list:
290 package_list = []
291 for pkg in pkg_list:
292 pkg_string_parts = pkg.split("/")
293 package_info_msg = common_pb2.PackageInfo(
294 category=pkg_string_parts[0],
295 package_name=pkg_string_parts[1],
296 )
297 package_list.append(package_info_msg)
298 else:
299 package_list = []
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700300
Alex Klein1699fab2022-09-08 08:46:06 -0600301 return sysroot_pb2.SysrootGenerateArchiveRequest(
302 build_target={"name": build_target},
303 chroot={"path": chroot_path},
304 packages=package_list,
305 )
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700306
Alex Klein1699fab2022-09-08 08:46:06 -0600307 def _OutputProto(self):
308 """Helper to build output proto instance."""
309 return sysroot_pb2.SysrootGenerateArchiveResponse()
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700310
Alex Klein1699fab2022-09-08 08:46:06 -0600311 def testValidateOnly(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700312 """Verify a validate-only call does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -0600313 patch = self.PatchObject(sysroot_service, "GenerateArchive")
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700314
Alex Klein1699fab2022-09-08 08:46:06 -0600315 in_proto = self._InputProto(
316 build_target=self.board,
317 chroot_path=self.chroot_path,
318 pkg_list=["virtual/target-fuzzers"],
319 )
320 sysroot_controller.GenerateArchive(
321 in_proto, self._OutputProto(), self.validate_only_config
322 )
323 patch.assert_not_called()
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700324
Alex Klein1699fab2022-09-08 08:46:06 -0600325 def testMockCall(self):
326 """Sanity check that a mock call does not execute any logic."""
327 patch = self.PatchObject(sysroot_service, "GenerateArchive")
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700328
Alex Klein1699fab2022-09-08 08:46:06 -0600329 in_proto = self._InputProto(
330 build_target=self.board,
331 chroot_path=self.chroot_path,
332 pkg_list=["virtual/target-fuzzers"],
333 )
334 sysroot_controller.GenerateArchive(
335 in_proto, self._OutputProto(), self.mock_call_config
336 )
337 patch.assert_not_called()
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700338
Alex Klein1699fab2022-09-08 08:46:06 -0600339 def testArgumentValidation(self):
340 """Test the input argument validation."""
341 # Error when no build target provided.
342 in_proto = self._InputProto()
343 out_proto = self._OutputProto()
344 with self.assertRaises(cros_build_lib.DieSystemExit):
345 sysroot_controller.GenerateArchive(
346 in_proto, out_proto, self.api_config
347 )
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700348
Alex Klein1699fab2022-09-08 08:46:06 -0600349 # Error when packages is not specified.
350 in_proto = self._InputProto(
351 build_target="board", chroot_path=self.chroot_path
352 )
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 # Valid when board, chroot path, and package are specified.
359 patch = self.PatchObject(
360 sysroot_service,
361 "GenerateArchive",
362 return_value="/path/to/sysroot/tar.bz",
363 )
364 in_proto = self._InputProto(
365 build_target="board",
366 chroot_path=self.chroot_path,
367 pkg_list=["virtual/target-fuzzers"],
368 )
369 out_proto = self._OutputProto()
370 sysroot_controller.GenerateArchive(in_proto, out_proto, self.api_config)
371 patch.assert_called_once()
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700372
373
Alex Klein1699fab2022-09-08 08:46:06 -0600374class InstallToolchainTest(
375 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin
376):
377 """Install toolchain function tests."""
Alex Kleinda35fcf2019-03-07 16:01:15 -0700378
Alex Klein1699fab2022-09-08 08:46:06 -0600379 def setUp(self):
380 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=True)
381 # Avoid running the portageq command.
382 self.PatchObject(sysroot_controller, "_LogBinhost")
383 self.board = "board"
384 self.sysroot = os.path.join(self.tempdir, "board")
385 self.invalid_sysroot = os.path.join(self.tempdir, "invalid", "sysroot")
386 osutils.SafeMakedirs(self.sysroot)
387 # Set up portage log directory.
388 self.target_sysroot = sysroot_lib.Sysroot(self.sysroot)
389 self.portage_dir = os.path.join(self.tempdir, "portage_logdir")
390 self.PatchObject(
391 sysroot_lib.Sysroot, "portage_logdir", new=self.portage_dir
392 )
393 osutils.SafeMakedirs(self.portage_dir)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700394
Alex Klein1699fab2022-09-08 08:46:06 -0600395 def _InputProto(
396 self, build_target=None, sysroot_path=None, compile_source=False
397 ):
398 """Helper to build an input proto instance."""
399 proto = sysroot_pb2.InstallToolchainRequest()
400 if build_target:
401 proto.sysroot.build_target.name = build_target
402 if sysroot_path:
403 proto.sysroot.path = sysroot_path
404 if compile_source:
405 proto.flags.compile_source = compile_source
Alex Kleinda35fcf2019-03-07 16:01:15 -0700406
Alex Klein1699fab2022-09-08 08:46:06 -0600407 return proto
Alex Kleinda35fcf2019-03-07 16:01:15 -0700408
Alex Klein1699fab2022-09-08 08:46:06 -0600409 def _OutputProto(self):
410 """Helper to build output proto instance."""
411 return sysroot_pb2.InstallToolchainResponse()
Alex Kleinda35fcf2019-03-07 16:01:15 -0700412
Alex Klein1699fab2022-09-08 08:46:06 -0600413 def _CreatePortageLogFile(
414 self,
415 log_path: Union[str, os.PathLike],
416 pkg_info: package_info.PackageInfo,
417 timestamp: datetime.datetime,
418 ):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700419 """Creates a log file to test for individual packages built by Portage.
Lizzy Presland7e23a612021-11-09 21:49:42 +0000420
Alex Klein1699fab2022-09-08 08:46:06 -0600421 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600422 log_path: The PORTAGE_LOGDIR path.
423 pkg_info: Package name used to name the log file.
424 timestamp: Timestamp used to name the file.
Alex Klein1699fab2022-09-08 08:46:06 -0600425 """
426 path = os.path.join(
427 log_path,
428 f"{pkg_info.category}:{pkg_info.pvr}:"
429 f'{timestamp.strftime("%Y%m%d-%H%M%S")}.log',
430 )
431 osutils.WriteFile(
432 path,
433 f"Test log file for package {pkg_info.category}/"
434 f"{pkg_info.package} written to {path}",
435 )
436 return path
Lizzy Presland7e23a612021-11-09 21:49:42 +0000437
Alex Klein1699fab2022-09-08 08:46:06 -0600438 def testValidateOnly(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700439 """Verify a validate-only call does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -0600440 patch = self.PatchObject(sysroot_service, "InstallToolchain")
Alex Klein231d2da2019-07-22 16:44:45 -0600441
Alex Klein1699fab2022-09-08 08:46:06 -0600442 in_proto = self._InputProto(
443 build_target=self.board, sysroot_path=self.sysroot
444 )
445 sysroot_controller.InstallToolchain(
446 in_proto, self._OutputProto(), self.validate_only_config
447 )
448 patch.assert_not_called()
Alex Klein231d2da2019-07-22 16:44:45 -0600449
Alex Klein1699fab2022-09-08 08:46:06 -0600450 def testMockCall(self):
451 """Sanity check that a mock call does not execute any logic."""
452 patch = self.PatchObject(sysroot_service, "InstallToolchain")
453 request = self._InputProto()
454 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -0600455
Alex Klein1699fab2022-09-08 08:46:06 -0600456 rc = sysroot_controller.InstallToolchain(
457 request, response, self.mock_call_config
458 )
Alex Klein076841b2019-08-29 15:19:39 -0600459
Alex Klein1699fab2022-09-08 08:46:06 -0600460 patch.assert_not_called()
461 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
Alex Klein076841b2019-08-29 15:19:39 -0600462
Alex Klein1699fab2022-09-08 08:46:06 -0600463 def testMockError(self):
464 """Sanity check that a mock error does not execute any logic."""
465 patch = self.PatchObject(sysroot_service, "InstallToolchain")
466 request = self._InputProto()
467 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -0600468
Alex Klein1699fab2022-09-08 08:46:06 -0600469 rc = sysroot_controller.InstallToolchain(
470 request, response, self.mock_error_config
471 )
Alex Klein076841b2019-08-29 15:19:39 -0600472
Alex Klein1699fab2022-09-08 08:46:06 -0600473 patch.assert_not_called()
474 self.assertEqual(
475 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
476 )
477 self.assertTrue(response.failed_package_data)
Alex Klein076841b2019-08-29 15:19:39 -0600478
Alex Klein1699fab2022-09-08 08:46:06 -0600479 def testArgumentValidation(self):
480 """Test the argument validation."""
481 # Test errors on missing inputs.
482 out_proto = self._OutputProto()
483 # Both missing.
484 in_proto = self._InputProto()
485 with self.assertRaises(cros_build_lib.DieSystemExit):
486 sysroot_controller.InstallToolchain(
487 in_proto, out_proto, self.api_config
488 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700489
Alex Klein1699fab2022-09-08 08:46:06 -0600490 # Sysroot path missing.
491 in_proto = self._InputProto(build_target=self.board)
492 with self.assertRaises(cros_build_lib.DieSystemExit):
493 sysroot_controller.InstallToolchain(
494 in_proto, out_proto, self.api_config
495 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700496
Alex Klein1699fab2022-09-08 08:46:06 -0600497 # Build target name missing.
498 in_proto = self._InputProto(sysroot_path=self.sysroot)
499 with self.assertRaises(cros_build_lib.DieSystemExit):
500 sysroot_controller.InstallToolchain(
501 in_proto, out_proto, self.api_config
502 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700503
Alex Klein1699fab2022-09-08 08:46:06 -0600504 # Both provided, but invalid sysroot path.
505 in_proto = self._InputProto(
506 build_target=self.board, sysroot_path=self.invalid_sysroot
507 )
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 def testSuccessOutputHandling(self):
514 """Test the output is processed and recorded correctly."""
515 self.PatchObject(sysroot_service, "InstallToolchain")
516 out_proto = self._OutputProto()
517 in_proto = self._InputProto(
518 build_target=self.board, sysroot_path=self.sysroot
519 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700520
Alex Klein1699fab2022-09-08 08:46:06 -0600521 rc = sysroot_controller.InstallToolchain(
522 in_proto, out_proto, self.api_config
523 )
524 self.assertFalse(rc)
525 self.assertFalse(out_proto.failed_package_data)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700526
Alex Klein1699fab2022-09-08 08:46:06 -0600527 def testErrorOutputHandling(self):
528 """Test the error output is processed and recorded correctly."""
529 out_proto = self._OutputProto()
530 in_proto = self._InputProto(
531 build_target=self.board, sysroot_path=self.sysroot
532 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700533
Alex Klein1699fab2022-09-08 08:46:06 -0600534 err_pkgs = ["cat/pkg-1.0-r1", "cat2/pkg2-1.0-r1"]
535 err_cpvs = [package_info.parse(pkg) for pkg in err_pkgs]
536 expected = [("cat", "pkg"), ("cat2", "pkg2")]
Lizzy Presland7e23a612021-11-09 21:49:42 +0000537
Alex Klein1699fab2022-09-08 08:46:06 -0600538 new_logs = {}
539 for i, pkg in enumerate(err_pkgs):
540 self._CreatePortageLogFile(
541 self.portage_dir,
542 err_cpvs[i],
543 datetime.datetime(2021, 6, 9, 13, 37, 0),
544 )
545 new_logs[pkg] = self._CreatePortageLogFile(
546 self.portage_dir,
547 err_cpvs[i],
548 datetime.datetime(2021, 6, 9, 16, 20, 0),
549 )
Lizzy Presland7e23a612021-11-09 21:49:42 +0000550
Alex Klein1699fab2022-09-08 08:46:06 -0600551 err = sysroot_lib.ToolchainInstallError(
552 "Error", cros_build_lib.CompletedProcess(), tc_info=err_cpvs
553 )
554 self.PatchObject(sysroot_service, "InstallToolchain", side_effect=err)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700555
Alex Klein1699fab2022-09-08 08:46:06 -0600556 rc = sysroot_controller.InstallToolchain(
557 in_proto, out_proto, self.api_config
558 )
559 self.assertEqual(
560 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
561 )
562 self.assertTrue(out_proto.failed_package_data)
563 # This needs to return 2 to indicate the available error response.
564 self.assertEqual(
565 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
566 )
567 for data in out_proto.failed_package_data:
568 package = controller_util.deserialize_package_info(data.name)
569 cat_pkg = (data.name.category, data.name.package_name)
570 self.assertIn(cat_pkg, expected)
571 self.assertEqual(data.log_path.path, new_logs[package.cpvr])
Lizzy Presland7e23a612021-11-09 21:49:42 +0000572
Alex Kleind4e1e422019-03-18 16:00:41 -0600573
Alex Klein1699fab2022-09-08 08:46:06 -0600574class InstallPackagesTest(
575 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin
576):
577 """InstallPackages tests."""
Alex Kleind4e1e422019-03-18 16:00:41 -0600578
Alex Klein1699fab2022-09-08 08:46:06 -0600579 def setUp(self):
580 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=True)
581 # Avoid running the portageq command.
582 self.PatchObject(sysroot_controller, "_LogBinhost")
583 self.build_target = "board"
584 self.sysroot = os.path.join(self.tempdir, "build", "board")
585 osutils.SafeMakedirs(self.sysroot)
586 # Set up portage log directory.
587 self.target_sysroot = sysroot_lib.Sysroot(self.sysroot)
588 self.portage_dir = os.path.join(self.tempdir, "portage_logdir")
589 self.PatchObject(
590 sysroot_lib.Sysroot, "portage_logdir", new=self.portage_dir
591 )
592 osutils.SafeMakedirs(self.portage_dir)
593 # Set up goma directories.
594 self.goma_dir = os.path.join(self.tempdir, "goma_dir")
595 osutils.SafeMakedirs(self.goma_dir)
596 self.goma_out_dir = os.path.join(self.tempdir, "goma_out_dir")
597 osutils.SafeMakedirs(self.goma_out_dir)
598 os.environ["GLOG_log_dir"] = self.goma_dir
Alex Kleind4e1e422019-03-18 16:00:41 -0600599
Alex Klein1699fab2022-09-08 08:46:06 -0600600 def _InputProto(
601 self,
602 build_target=None,
603 sysroot_path=None,
604 build_source=False,
605 goma_dir=None,
606 goma_log_dir=None,
607 goma_stats_file=None,
608 goma_counterz_file=None,
609 package_indexes=None,
610 packages=None,
611 ):
612 """Helper to build an input proto instance."""
613 instance = sysroot_pb2.InstallPackagesRequest()
Alex Kleind4e1e422019-03-18 16:00:41 -0600614
Alex Klein1699fab2022-09-08 08:46:06 -0600615 if build_target:
616 instance.sysroot.build_target.name = build_target
617 if sysroot_path:
618 instance.sysroot.path = sysroot_path
619 if build_source:
620 instance.flags.build_source = build_source
621 if goma_dir:
622 instance.goma_config.goma_dir = goma_dir
623 if goma_log_dir:
624 instance.goma_config.log_dir.dir = goma_log_dir
625 if goma_stats_file:
626 instance.goma_config.stats_file = goma_stats_file
627 if goma_counterz_file:
628 instance.goma_config.counterz_file = goma_counterz_file
629 if package_indexes:
630 instance.package_indexes.extend(package_indexes)
631 if packages:
632 for pkg in packages:
633 pkg_info = package_info.parse(pkg)
634 pkg_info_msg = instance.packages.add()
635 controller_util.serialize_package_info(pkg_info, pkg_info_msg)
636 return instance
Alex Kleind4e1e422019-03-18 16:00:41 -0600637
Alex Klein1699fab2022-09-08 08:46:06 -0600638 def _OutputProto(self):
639 """Helper to build an empty output proto instance."""
640 return sysroot_pb2.InstallPackagesResponse()
Alex Kleind4e1e422019-03-18 16:00:41 -0600641
Alex Klein1699fab2022-09-08 08:46:06 -0600642 def _CreateGomaLogFile(
643 self,
644 goma_log_dir: Union[str, os.PathLike],
645 name: str,
646 timestamp: datetime.datetime,
647 ):
648 """Creates a log file for testing.
Michael Mortensen798ee192020-01-17 13:04:43 -0700649
Alex Klein1699fab2022-09-08 08:46:06 -0600650 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600651 goma_log_dir: Directory where the file will be created.
652 name: Log file 'base' name that is combined with the timestamp.
653 timestamp: Timestamp that is written to the file.
Alex Klein1699fab2022-09-08 08:46:06 -0600654 """
655 path = os.path.join(
656 goma_log_dir,
657 "%s.host.log.INFO.%s"
658 % (name, timestamp.strftime("%Y%m%d-%H%M%S.%f")),
659 )
660 osutils.WriteFile(
661 path,
662 timestamp.strftime("Goma log file created at: %Y/%m/%d %H:%M:%S"),
663 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700664
Alex Klein1699fab2022-09-08 08:46:06 -0600665 def _CreatePortageLogFile(
666 self,
667 log_path: Union[str, os.PathLike],
668 pkg_info: package_info.PackageInfo,
669 timestamp: datetime.datetime,
670 ):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700671 """Creates a log file to test for individual packages built by Portage.
Lizzy Presland7e23a612021-11-09 21:49:42 +0000672
Alex Klein1699fab2022-09-08 08:46:06 -0600673 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600674 log_path: The PORTAGE_LOGDIR path.
675 pkg_info: Package name used to name the log file.
676 timestamp: Timestamp used to name the file.
Alex Klein1699fab2022-09-08 08:46:06 -0600677 """
678 path = os.path.join(
679 log_path,
680 f"{pkg_info.category}:{pkg_info.pvr}:"
681 f'{timestamp.strftime("%Y%m%d-%H%M%S")}.log',
682 )
683 osutils.WriteFile(
684 path,
685 f"Test log file for package {pkg_info.category}/"
686 f"{pkg_info.package} written to {path}",
687 )
688 return path
Lizzy Presland7e23a612021-11-09 21:49:42 +0000689
Alex Klein1699fab2022-09-08 08:46:06 -0600690 def testValidateOnly(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700691 """Verify a validate-only call does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -0600692 patch = self.PatchObject(sysroot_service, "BuildPackages")
Alex Klein231d2da2019-07-22 16:44:45 -0600693
Alex Klein1699fab2022-09-08 08:46:06 -0600694 in_proto = self._InputProto(
695 build_target=self.build_target, sysroot_path=self.sysroot
696 )
697 sysroot_controller.InstallPackages(
698 in_proto, self._OutputProto(), self.validate_only_config
699 )
700 patch.assert_not_called()
Alex Klein231d2da2019-07-22 16:44:45 -0600701
Alex Klein1699fab2022-09-08 08:46:06 -0600702 def testMockCall(self):
703 """Sanity check that a mock call does not execute any logic."""
704 patch = self.PatchObject(sysroot_service, "BuildPackages")
705 request = self._InputProto()
706 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -0600707
Alex Klein1699fab2022-09-08 08:46:06 -0600708 rc = sysroot_controller.InstallPackages(
709 request, response, self.mock_call_config
710 )
Alex Klein076841b2019-08-29 15:19:39 -0600711
Alex Klein1699fab2022-09-08 08:46:06 -0600712 patch.assert_not_called()
713 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
Alex Klein076841b2019-08-29 15:19:39 -0600714
Alex Klein1699fab2022-09-08 08:46:06 -0600715 def testMockError(self):
716 """Sanity check that a mock error does not execute any logic."""
717 patch = self.PatchObject(sysroot_service, "BuildPackages")
718 request = self._InputProto()
719 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -0600720
Alex Klein1699fab2022-09-08 08:46:06 -0600721 rc = sysroot_controller.InstallPackages(
722 request, response, self.mock_error_config
723 )
Alex Klein076841b2019-08-29 15:19:39 -0600724
Alex Klein1699fab2022-09-08 08:46:06 -0600725 patch.assert_not_called()
726 self.assertEqual(
727 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
728 )
729 self.assertTrue(response.failed_package_data)
Alex Klein076841b2019-08-29 15:19:39 -0600730
Alex Klein1699fab2022-09-08 08:46:06 -0600731 def testArgumentValidationAllMissing(self):
732 """Test missing all arguments."""
733 out_proto = self._OutputProto()
734 in_proto = self._InputProto()
735 with self.assertRaises(cros_build_lib.DieSystemExit):
736 sysroot_controller.InstallPackages(
737 in_proto, out_proto, self.api_config
738 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600739
Alex Klein1699fab2022-09-08 08:46:06 -0600740 def testArgumentValidationNoSysroot(self):
741 """Test missing sysroot path."""
742 out_proto = self._OutputProto()
743 in_proto = self._InputProto(build_target=self.build_target)
744 with self.assertRaises(cros_build_lib.DieSystemExit):
745 sysroot_controller.InstallPackages(
746 in_proto, out_proto, self.api_config
747 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600748
Alex Klein1699fab2022-09-08 08:46:06 -0600749 def testArgumentValidationNoBuildTarget(self):
750 """Test missing build target name."""
751 out_proto = self._OutputProto()
752 in_proto = self._InputProto(sysroot_path=self.sysroot)
753 with self.assertRaises(cros_build_lib.DieSystemExit):
754 sysroot_controller.InstallPackages(
755 in_proto, out_proto, self.api_config
756 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600757
Alex Klein1699fab2022-09-08 08:46:06 -0600758 def testArgumentValidationInvalidSysroot(self):
759 """Test sysroot that hasn't had the toolchain installed."""
760 out_proto = self._OutputProto()
761 in_proto = self._InputProto(
762 build_target=self.build_target, sysroot_path=self.sysroot
763 )
764 self.PatchObject(
765 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=False
766 )
767 with self.assertRaises(cros_build_lib.DieSystemExit):
768 sysroot_controller.InstallPackages(
769 in_proto, out_proto, self.api_config
770 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600771
Alex Klein1699fab2022-09-08 08:46:06 -0600772 def testArgumentValidationInvalidPackage(self):
773 out_proto = self._OutputProto()
774 in_proto = self._InputProto(
775 build_target=self.build_target,
776 sysroot_path=self.sysroot,
777 packages=["package-1.0.0-r2"],
778 )
779 with self.assertRaises(cros_build_lib.DieSystemExit):
780 sysroot_controller.InstallPackages(
781 in_proto, out_proto, self.api_config
782 )
Alex Kleinca572ee2020-09-03 10:47:14 -0600783
Alex Klein1699fab2022-09-08 08:46:06 -0600784 def testSuccessOutputHandling(self):
785 """Test successful call output handling."""
786 # Prevent argument validation error.
787 self.PatchObject(
788 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
789 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600790
Alex Klein1699fab2022-09-08 08:46:06 -0600791 in_proto = self._InputProto(
792 build_target=self.build_target, sysroot_path=self.sysroot
793 )
794 out_proto = self._OutputProto()
795 self.PatchObject(sysroot_service, "BuildPackages")
Alex Kleind4e1e422019-03-18 16:00:41 -0600796
Alex Klein1699fab2022-09-08 08:46:06 -0600797 rc = sysroot_controller.InstallPackages(
798 in_proto, out_proto, self.api_config
799 )
800 self.assertFalse(rc)
801 self.assertFalse(out_proto.failed_package_data)
Alex Kleind4e1e422019-03-18 16:00:41 -0600802
Alex Klein1699fab2022-09-08 08:46:06 -0600803 def testSuccessPackageIndexes(self):
804 """Test successful call with package_indexes."""
805 # Prevent argument validation error.
806 self.PatchObject(
807 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
808 )
809 package_indexes = [
810 common_pb2.PackageIndexInfo(
811 snapshot_sha="SHA",
812 snapshot_number=5,
813 build_target=common_pb2.BuildTarget(name="board"),
814 location="LOCATION",
815 profile=common_pb2.Profile(name="profile"),
816 ),
817 common_pb2.PackageIndexInfo(
818 snapshot_sha="SHA2",
819 snapshot_number=4,
820 build_target=common_pb2.BuildTarget(name="board"),
821 location="LOCATION2",
822 profile=common_pb2.Profile(name="profile"),
823 ),
824 ]
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600825
Alex Klein1699fab2022-09-08 08:46:06 -0600826 in_proto = self._InputProto(
827 build_target=self.build_target,
828 sysroot_path=self.sysroot,
829 package_indexes=package_indexes,
830 )
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600831
Alex Klein1699fab2022-09-08 08:46:06 -0600832 out_proto = self._OutputProto()
833 rc_patch = self.PatchObject(sysroot_service, "BuildPackagesRunConfig")
834 self.PatchObject(sysroot_service, "BuildPackages")
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600835
Alex Klein1699fab2022-09-08 08:46:06 -0600836 rc = sysroot_controller.InstallPackages(
837 in_proto, out_proto, self.api_config
838 )
839 self.assertFalse(rc)
840 rc_patch.assert_called_with(
841 use_any_chrome=False,
842 usepkg=True,
843 install_debug_symbols=True,
844 packages=[],
845 package_indexes=[
Alex Klein6d718d62023-01-18 15:55:51 -0700846 controller_util.deserialize_package_index_info(x)
Alex Klein1699fab2022-09-08 08:46:06 -0600847 for x in package_indexes
848 ],
849 use_flags=[],
850 use_goma=False,
851 use_remoteexec=False,
852 incremental_build=False,
853 dryrun=False,
854 backtrack=sysroot_controller.DEFAULT_BACKTRACK,
855 )
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600856
Alex Klein1699fab2022-09-08 08:46:06 -0600857 def testSuccessWithGomaLogs(self):
858 """Test successful call with goma."""
859 self._CreateGomaLogFile(
860 self.goma_dir,
861 "compiler_proxy",
862 datetime.datetime(2018, 9, 21, 12, 0, 0),
863 )
864 self._CreateGomaLogFile(
865 self.goma_dir,
866 "compiler_proxy-subproc",
867 datetime.datetime(2018, 9, 21, 12, 1, 0),
868 )
869 self._CreateGomaLogFile(
870 self.goma_dir, "gomacc", datetime.datetime(2018, 9, 21, 12, 2, 0)
871 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700872
Alex Klein1699fab2022-09-08 08:46:06 -0600873 # Prevent argument validation error.
874 self.PatchObject(
875 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
876 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700877
Alex Klein1699fab2022-09-08 08:46:06 -0600878 in_proto = self._InputProto(
879 build_target=self.build_target,
880 sysroot_path=self.sysroot,
881 goma_dir=self.goma_dir,
882 goma_log_dir=self.goma_out_dir,
883 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700884
Alex Klein1699fab2022-09-08 08:46:06 -0600885 out_proto = self._OutputProto()
886 self.PatchObject(sysroot_service, "BuildPackages")
Michael Mortensen798ee192020-01-17 13:04:43 -0700887
Alex Klein1699fab2022-09-08 08:46:06 -0600888 rc = sysroot_controller.InstallPackages(
889 in_proto, out_proto, self.api_config
890 )
891 self.assertFalse(rc)
892 self.assertFalse(out_proto.failed_package_data)
Alex Kleinab87ceb2023-01-24 12:00:51 -0700893
894 expected = [
895 "compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz",
896 "compiler_proxy.host.log.INFO.20180921-120000.000000.gz",
897 "gomacc.host.log.INFO.20180921-120200.000000.tar.gz",
898 ]
899 self.assertCountEqual(out_proto.goma_artifacts.log_files, expected)
Michael Mortensen798ee192020-01-17 13:04:43 -0700900
Alex Klein1699fab2022-09-08 08:46:06 -0600901 def testSuccessWithGomaLogsAndStatsCounterzFiles(self):
902 """Test successful call with goma including stats and counterz files."""
903 self._CreateGomaLogFile(
904 self.goma_dir,
905 "compiler_proxy",
906 datetime.datetime(2018, 9, 21, 12, 0, 0),
907 )
908 self._CreateGomaLogFile(
909 self.goma_dir,
910 "compiler_proxy-subproc",
911 datetime.datetime(2018, 9, 21, 12, 1, 0),
912 )
913 self._CreateGomaLogFile(
914 self.goma_dir, "gomacc", datetime.datetime(2018, 9, 21, 12, 2, 0)
915 )
916 # Create stats and counterz files.
917 osutils.WriteFile(
918 os.path.join(self.goma_dir, "stats.binaryproto"),
919 "File: stats.binaryproto",
920 )
921 osutils.WriteFile(
922 os.path.join(self.goma_dir, "counterz.binaryproto"),
923 "File: counterz.binaryproto",
924 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700925
Alex Klein1699fab2022-09-08 08:46:06 -0600926 # Prevent argument validation error.
927 self.PatchObject(
928 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
929 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700930
Alex Klein1699fab2022-09-08 08:46:06 -0600931 in_proto = self._InputProto(
932 build_target=self.build_target,
933 sysroot_path=self.sysroot,
934 goma_dir=self.goma_dir,
935 goma_log_dir=self.goma_out_dir,
936 goma_stats_file="stats.binaryproto",
937 goma_counterz_file="counterz.binaryproto",
938 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700939
Alex Klein1699fab2022-09-08 08:46:06 -0600940 out_proto = self._OutputProto()
941 self.PatchObject(sysroot_service, "BuildPackages")
Michael Mortensen798ee192020-01-17 13:04:43 -0700942
Alex Klein1699fab2022-09-08 08:46:06 -0600943 rc = sysroot_controller.InstallPackages(
944 in_proto, out_proto, self.api_config
945 )
946 self.assertFalse(rc)
947 self.assertFalse(out_proto.failed_package_data)
Alex Kleinab87ceb2023-01-24 12:00:51 -0700948 expected_logs = [
949 "compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz",
950 "compiler_proxy.host.log.INFO.20180921-120000.000000.gz",
951 "gomacc.host.log.INFO.20180921-120200.000000.tar.gz",
952 ]
953 self.assertCountEqual(out_proto.goma_artifacts.log_files, expected_logs)
954
Alex Klein1699fab2022-09-08 08:46:06 -0600955 # Verify that the output dir has 5 files -- since there should be 3 log
956 # files, the stats file, and the counterz file.
957 output_files = os.listdir(self.goma_out_dir)
Alex Kleinab87ceb2023-01-24 12:00:51 -0700958 expected_output = [
959 "stats.binaryproto",
960 "counterz.binaryproto",
961 "compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz",
962 "compiler_proxy.host.log.INFO.20180921-120000.000000.gz",
963 "gomacc.host.log.INFO.20180921-120200.000000.tar.gz",
964 ]
965 self.assertCountEqual(output_files, expected_output)
Alex Klein1699fab2022-09-08 08:46:06 -0600966 self.assertEqual(
967 out_proto.goma_artifacts.counterz_file, "counterz.binaryproto"
968 )
969 self.assertEqual(
970 out_proto.goma_artifacts.stats_file, "stats.binaryproto"
971 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700972
Alex Klein1699fab2022-09-08 08:46:06 -0600973 def testFailureMissingGomaStatsCounterzFiles(self):
974 """Test successful call with goma including stats and counterz files."""
975 self._CreateGomaLogFile(
976 self.goma_dir,
977 "compiler_proxy",
978 datetime.datetime(2018, 9, 21, 12, 0, 0),
979 )
980 self._CreateGomaLogFile(
981 self.goma_dir,
982 "compiler_proxy-subproc",
983 datetime.datetime(2018, 9, 21, 12, 1, 0),
984 )
985 self._CreateGomaLogFile(
986 self.goma_dir, "gomacc", datetime.datetime(2018, 9, 21, 12, 2, 0)
987 )
Alex Kleinab87ceb2023-01-24 12:00:51 -0700988 # Note that stats and counterz files are not created, but are specified
989 # in the proto below.
Michael Mortensen798ee192020-01-17 13:04:43 -0700990
Alex Klein1699fab2022-09-08 08:46:06 -0600991 # Prevent argument validation error.
992 self.PatchObject(
993 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
994 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700995
Alex Klein1699fab2022-09-08 08:46:06 -0600996 in_proto = self._InputProto(
997 build_target=self.build_target,
998 sysroot_path=self.sysroot,
999 goma_dir=self.goma_dir,
1000 goma_log_dir=self.goma_out_dir,
1001 goma_stats_file="stats.binaryproto",
1002 goma_counterz_file="counterz.binaryproto",
1003 )
Michael Mortensen798ee192020-01-17 13:04:43 -07001004
Alex Klein1699fab2022-09-08 08:46:06 -06001005 out_proto = self._OutputProto()
1006 self.PatchObject(sysroot_service, "BuildPackages")
Michael Mortensen798ee192020-01-17 13:04:43 -07001007
Alex Klein1699fab2022-09-08 08:46:06 -06001008 rc = sysroot_controller.InstallPackages(
1009 in_proto, out_proto, self.api_config
1010 )
1011 self.assertFalse(rc)
1012 self.assertFalse(out_proto.failed_package_data)
Alex Kleinab87ceb2023-01-24 12:00:51 -07001013 expected_logs = [
1014 "compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz",
1015 "compiler_proxy.host.log.INFO.20180921-120000.000000.gz",
1016 "gomacc.host.log.INFO.20180921-120200.000000.tar.gz",
1017 ]
1018 self.assertCountEqual(out_proto.goma_artifacts.log_files, expected_logs)
Alex Klein1699fab2022-09-08 08:46:06 -06001019 self.assertFalse(out_proto.goma_artifacts.counterz_file)
1020 self.assertFalse(out_proto.goma_artifacts.stats_file)
Michael Mortensen798ee192020-01-17 13:04:43 -07001021
Alex Klein1699fab2022-09-08 08:46:06 -06001022 def testFailureOutputHandling(self):
1023 """Test failed package handling."""
1024 # Prevent argument validation error.
1025 self.PatchObject(
1026 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
1027 )
Alex Kleind4e1e422019-03-18 16:00:41 -06001028
Alex Klein1699fab2022-09-08 08:46:06 -06001029 in_proto = self._InputProto(
1030 build_target=self.build_target, sysroot_path=self.sysroot
1031 )
1032 out_proto = self._OutputProto()
Alex Kleind4e1e422019-03-18 16:00:41 -06001033
Alex Klein1699fab2022-09-08 08:46:06 -06001034 # Failed package info and expected list for verification.
1035 err_pkgs = ["cat/pkg-1.0-r3", "cat2/pkg2-1.0-r1"]
1036 err_cpvs = [package_info.parse(cpv) for cpv in err_pkgs]
1037 expected = [("cat", "pkg"), ("cat2", "pkg2")]
Alex Kleind4e1e422019-03-18 16:00:41 -06001038
Alex Klein1699fab2022-09-08 08:46:06 -06001039 new_logs = {}
1040 for i, pkg in enumerate(err_pkgs):
1041 self._CreatePortageLogFile(
1042 self.portage_dir,
1043 err_cpvs[i],
1044 datetime.datetime(2021, 6, 9, 13, 37, 0),
1045 )
1046 new_logs[pkg] = self._CreatePortageLogFile(
1047 self.portage_dir,
1048 err_cpvs[i],
1049 datetime.datetime(2021, 6, 9, 16, 20, 0),
1050 )
1051 # Force error to be raised with the packages.
1052 error = sysroot_lib.PackageInstallError(
1053 "Error", cros_build_lib.CompletedProcess(), packages=err_cpvs
1054 )
1055 self.PatchObject(sysroot_service, "BuildPackages", side_effect=error)
Alex Kleind4e1e422019-03-18 16:00:41 -06001056
Alex Klein1699fab2022-09-08 08:46:06 -06001057 rc = sysroot_controller.InstallPackages(
1058 in_proto, out_proto, self.api_config
1059 )
1060 # This needs to return 2 to indicate the available error response.
1061 self.assertEqual(
1062 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
1063 )
1064 for data in out_proto.failed_package_data:
1065 package = controller_util.deserialize_package_info(data.name)
1066 cat_pkg = (data.name.category, data.name.package_name)
1067 self.assertIn(cat_pkg, expected)
1068 self.assertEqual(data.log_path.path, new_logs[package.cpvr])
Lizzy Presland7e23a612021-11-09 21:49:42 +00001069
Alex Klein1699fab2022-09-08 08:46:06 -06001070 def testNoPackageFailureOutputHandling(self):
1071 """Test failure handling without packages to report."""
1072 # Prevent argument validation error.
1073 self.PatchObject(
1074 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
1075 )
Alex Klein2557b4f2019-07-11 14:34:00 -06001076
Alex Klein1699fab2022-09-08 08:46:06 -06001077 in_proto = self._InputProto(
1078 build_target=self.build_target, sysroot_path=self.sysroot
1079 )
1080 out_proto = self._OutputProto()
Alex Klein2557b4f2019-07-11 14:34:00 -06001081
Alex Klein1699fab2022-09-08 08:46:06 -06001082 # Force error to be raised with no packages.
1083 error = sysroot_lib.PackageInstallError(
1084 "Error", cros_build_lib.CompletedProcess(), packages=[]
1085 )
1086 self.PatchObject(sysroot_service, "BuildPackages", side_effect=error)
Alex Klein2557b4f2019-07-11 14:34:00 -06001087
Alex Klein1699fab2022-09-08 08:46:06 -06001088 rc = sysroot_controller.InstallPackages(
1089 in_proto, out_proto, self.api_config
1090 )
1091 # All we really care about is it's not 0 or 2 (response available), so
1092 # test for that rather than a specific return code.
1093 self.assertTrue(rc)
1094 self.assertNotEqual(
1095 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
1096 )