blob: 75f1c7052231cb5371c9bc79f356a92badcc9973 [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
LaMont Jonesc0343fa2020-08-12 18:58:31 -060017from chromite.lib import binpkg
Alex Kleinda35fcf2019-03-07 16:01:15 -070018from chromite.lib import cros_build_lib
19from chromite.lib import cros_test_lib
20from chromite.lib import osutils
Alex Kleinda35fcf2019-03-07 16:01:15 -070021from chromite.lib import sysroot_lib
Alex Klein18a60af2020-06-11 12:08:47 -060022from chromite.lib.parser import package_info
Alex Kleinda35fcf2019-03-07 16:01:15 -070023from chromite.service import sysroot as sysroot_service
24
25
Alex Klein231d2da2019-07-22 16:44:45 -060026class CreateTest(cros_test_lib.MockTestCase, api_config.ApiConfigMixin):
Alex Klein1699fab2022-09-08 08:46:06 -060027 """Create function tests."""
Alex Kleinda35fcf2019-03-07 16:01:15 -070028
Alex Klein1699fab2022-09-08 08:46:06 -060029 def _InputProto(
30 self,
31 build_target=None,
32 profile=None,
33 replace=False,
34 current=False,
35 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
47 if package_indexes:
48 proto.package_indexes.extend(package_indexes)
Alex Kleinda35fcf2019-03-07 16:01:15 -070049
Alex Klein1699fab2022-09-08 08:46:06 -060050 return proto
Alex Kleinda35fcf2019-03-07 16:01:15 -070051
Alex Klein1699fab2022-09-08 08:46:06 -060052 def _OutputProto(self):
53 """Helper to build output proto instance."""
54 return sysroot_pb2.SysrootCreateResponse()
Alex Kleinda35fcf2019-03-07 16:01:15 -070055
Alex Klein1699fab2022-09-08 08:46:06 -060056 def testValidateOnly(self):
57 """Sanity check that a validate only call does not execute any logic."""
58 patch = self.PatchObject(sysroot_service, "Create")
Alex Klein231d2da2019-07-22 16:44:45 -060059
Alex Klein1699fab2022-09-08 08:46:06 -060060 board = "board"
61 profile = None
62 force = False
63 upgrade_chroot = True
64 in_proto = self._InputProto(
65 build_target=board,
66 profile=profile,
67 replace=force,
68 current=not upgrade_chroot,
69 )
70 sysroot_controller.Create(
71 in_proto, self._OutputProto(), self.validate_only_config
72 )
73 patch.assert_not_called()
Alex Klein231d2da2019-07-22 16:44:45 -060074
Alex Klein1699fab2022-09-08 08:46:06 -060075 def testMockCall(self):
76 """Sanity check that a mock call does not execute any logic."""
77 patch = self.PatchObject(sysroot_service, "Create")
78 request = self._InputProto()
79 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -060080
Alex Klein1699fab2022-09-08 08:46:06 -060081 rc = sysroot_controller.Create(request, response, self.mock_call_config)
Alex Klein076841b2019-08-29 15:19:39 -060082
Alex Klein1699fab2022-09-08 08:46:06 -060083 patch.assert_not_called()
84 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
Alex Klein076841b2019-08-29 15:19:39 -060085
Alex Klein1699fab2022-09-08 08:46:06 -060086 def testMockError(self):
87 """Sanity check that a mock error does not execute any logic."""
88 patch = self.PatchObject(sysroot_service, "Create")
89 request = self._InputProto()
90 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -060091
Alex Klein1699fab2022-09-08 08:46:06 -060092 rc = sysroot_controller.Create(
93 request, response, self.mock_error_config
94 )
Alex Klein076841b2019-08-29 15:19:39 -060095
Alex Klein1699fab2022-09-08 08:46:06 -060096 patch.assert_not_called()
97 self.assertEqual(controller.RETURN_CODE_UNRECOVERABLE, rc)
Alex Klein076841b2019-08-29 15:19:39 -060098
Alex Klein1699fab2022-09-08 08:46:06 -060099 def testArgumentValidation(self):
100 """Test the input argument validation."""
101 # Error when no name provided.
102 in_proto = self._InputProto()
103 out_proto = self._OutputProto()
104 with self.assertRaises(cros_build_lib.DieSystemExit):
105 sysroot_controller.Create(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700106
Alex Klein1699fab2022-09-08 08:46:06 -0600107 # Valid when board passed.
108 result = sysroot_lib.Sysroot("/sysroot/path")
109 patch = self.PatchObject(sysroot_service, "Create", return_value=result)
110 in_proto = self._InputProto("board")
111 out_proto = self._OutputProto()
112 sysroot_controller.Create(in_proto, out_proto, self.api_config)
113 patch.assert_called_once()
Alex Kleinda35fcf2019-03-07 16:01:15 -0700114
Alex Klein1699fab2022-09-08 08:46:06 -0600115 def testArgumentHandling(self):
116 """Test the arguments get processed and passed correctly."""
117 sysroot_path = "/sysroot/path"
Alex Kleinda35fcf2019-03-07 16:01:15 -0700118
Alex Klein1699fab2022-09-08 08:46:06 -0600119 sysroot = sysroot_lib.Sysroot(sysroot_path)
120 create_patch = self.PatchObject(
121 sysroot_service, "Create", return_value=sysroot
122 )
123 rc_patch = self.PatchObject(sysroot_service, "SetupBoardRunConfig")
Alex Kleinda35fcf2019-03-07 16:01:15 -0700124
Alex Klein1699fab2022-09-08 08:46:06 -0600125 # Default values.
126 board = "board"
127 profile = None
128 force = False
129 upgrade_chroot = True
130 in_proto = self._InputProto(
131 build_target=board,
132 profile=profile,
133 replace=force,
134 current=not upgrade_chroot,
135 )
136 out_proto = self._OutputProto()
137 sysroot_controller.Create(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700138
Alex Klein1699fab2022-09-08 08:46:06 -0600139 # Default value checks.
140 rc_patch.assert_called_with(
141 force=force,
142 upgrade_chroot=upgrade_chroot,
143 package_indexes=[],
144 backtrack=sysroot_controller.DEFAULT_BACKTRACK,
145 )
146 self.assertEqual(board, out_proto.sysroot.build_target.name)
147 self.assertEqual(sysroot_path, out_proto.sysroot.path)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700148
Alex Klein1699fab2022-09-08 08:46:06 -0600149 # Not default values.
150 create_patch.reset_mock()
151 board = "board"
152 profile = "profile"
153 force = True
154 upgrade_chroot = False
155 package_indexes = [
156 common_pb2.PackageIndexInfo(
157 snapshot_sha="SHA",
158 snapshot_number=5,
159 build_target=common_pb2.BuildTarget(name=board),
160 location="LOCATION",
161 profile=common_pb2.Profile(name=profile),
162 ),
163 common_pb2.PackageIndexInfo(
164 snapshot_sha="SHA2",
165 snapshot_number=4,
166 build_target=common_pb2.BuildTarget(name=board),
167 location="LOCATION2",
168 profile=common_pb2.Profile(name=profile),
169 ),
170 ]
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600171
Alex Klein1699fab2022-09-08 08:46:06 -0600172 in_proto = self._InputProto(
173 build_target=board,
174 profile=profile,
175 replace=force,
176 current=not upgrade_chroot,
177 package_indexes=package_indexes,
178 )
179 out_proto = self._OutputProto()
180 sysroot_controller.Create(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700181
Alex Klein1699fab2022-09-08 08:46:06 -0600182 # Not default value checks.
183 rc_patch.assert_called_with(
184 force=force,
185 package_indexes=[
186 binpkg.PackageIndexInfo.from_protobuf(x)
187 for x in package_indexes
188 ],
189 upgrade_chroot=upgrade_chroot,
190 backtrack=sysroot_controller.DEFAULT_BACKTRACK,
191 )
192 self.assertEqual(board, out_proto.sysroot.build_target.name)
193 self.assertEqual(sysroot_path, out_proto.sysroot.path)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700194
195
Jack Neus26b94672022-10-27 17:33:21 +0000196class GetArtifactsTest(cros_test_lib.MockTestCase, api_config.ApiConfigMixin):
197 """GetArtifacts function tests."""
198
199 _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,
205 }
206
207 def setUp(self):
208 self._mocks = {}
209 for artifact, func in self._artifact_funcs.items():
210 self._mocks[artifact] = self.PatchObject(
211 sysroot_service, func.__name__
212 )
213
214 def _InputProto(
215 self,
216 artifact_types=_artifact_funcs.keys(),
217 ):
218 """Helper to build an input proto instance."""
219 return common_pb2.ArtifactsByService.Sysroot(
220 output_artifacts=[
221 common_pb2.ArtifactsByService.Sysroot.ArtifactInfo(
222 artifact_types=artifact_types
223 )
224 ]
225 )
226
227 def testNoArtifacts(self):
228 """Test GetArtifacts with no artifact types."""
229 in_proto = self._InputProto(artifact_types=[])
230 sysroot_controller.GetArtifacts(
231 in_proto, None, None, "build_target", ""
232 )
233
234 for _, patch in self._mocks.items():
235 patch.assert_not_called()
236
237 def testArtifactsSuccess(self):
238 """Test GetArtifacts with all artifact types."""
239 sysroot_controller.GetArtifacts(
240 self._InputProto(), None, None, "build_target", ""
241 )
242
243 for _, patch in self._mocks.items():
244 patch.assert_called_once()
245
246 def testArtifactsException(self):
247 """Test GetArtifacts with all artifact types when one type throws an exception."""
248
249 self._mocks[
250 common_pb2.ArtifactsByService.Sysroot.ArtifactType.FUZZER_SYSROOT
251 ].side_effect = Exception("foo bar")
252 generated = sysroot_controller.GetArtifacts(
253 self._InputProto(), None, None, "build_target", ""
254 )
255
256 for _, patch in self._mocks.items():
257 patch.assert_called_once()
258
259 found_artifact = False
260 for data in generated:
261 artifact_type = (
262 common_pb2.ArtifactsByService.Sysroot.ArtifactType.Name(
263 data["type"]
264 )
265 )
266 if artifact_type == "FUZZER_SYSROOT":
267 found_artifact = True
268 self.assertTrue(data["failed"])
269 self.assertEqual(data["failure_reason"], "foo bar")
270 self.assertTrue(found_artifact)
271
272
Alex Klein1699fab2022-09-08 08:46:06 -0600273class GenerateArchiveTest(
274 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin
275):
276 """GenerateArchive function tests."""
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700277
Alex Klein1699fab2022-09-08 08:46:06 -0600278 def setUp(self):
279 self.chroot_path = "/path/to/chroot"
280 self.board = "board"
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700281
Alex Klein1699fab2022-09-08 08:46:06 -0600282 def _InputProto(self, build_target=None, chroot_path=None, pkg_list=None):
283 """Helper to build and input proto instance."""
284 # pkg_list will be a list of category/package strings such as
285 # ['virtual/target-fuzzers'].
286 if pkg_list:
287 package_list = []
288 for pkg in pkg_list:
289 pkg_string_parts = pkg.split("/")
290 package_info_msg = common_pb2.PackageInfo(
291 category=pkg_string_parts[0],
292 package_name=pkg_string_parts[1],
293 )
294 package_list.append(package_info_msg)
295 else:
296 package_list = []
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700297
Alex Klein1699fab2022-09-08 08:46:06 -0600298 return sysroot_pb2.SysrootGenerateArchiveRequest(
299 build_target={"name": build_target},
300 chroot={"path": chroot_path},
301 packages=package_list,
302 )
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700303
Alex Klein1699fab2022-09-08 08:46:06 -0600304 def _OutputProto(self):
305 """Helper to build output proto instance."""
306 return sysroot_pb2.SysrootGenerateArchiveResponse()
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700307
Alex Klein1699fab2022-09-08 08:46:06 -0600308 def testValidateOnly(self):
309 """Sanity check that a validate only call does not execute any logic."""
310 patch = self.PatchObject(sysroot_service, "GenerateArchive")
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700311
Alex Klein1699fab2022-09-08 08:46:06 -0600312 in_proto = self._InputProto(
313 build_target=self.board,
314 chroot_path=self.chroot_path,
315 pkg_list=["virtual/target-fuzzers"],
316 )
317 sysroot_controller.GenerateArchive(
318 in_proto, self._OutputProto(), self.validate_only_config
319 )
320 patch.assert_not_called()
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700321
Alex Klein1699fab2022-09-08 08:46:06 -0600322 def testMockCall(self):
323 """Sanity check that a mock call does not execute any logic."""
324 patch = self.PatchObject(sysroot_service, "GenerateArchive")
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700325
Alex Klein1699fab2022-09-08 08:46:06 -0600326 in_proto = self._InputProto(
327 build_target=self.board,
328 chroot_path=self.chroot_path,
329 pkg_list=["virtual/target-fuzzers"],
330 )
331 sysroot_controller.GenerateArchive(
332 in_proto, self._OutputProto(), self.mock_call_config
333 )
334 patch.assert_not_called()
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700335
Alex Klein1699fab2022-09-08 08:46:06 -0600336 def testArgumentValidation(self):
337 """Test the input argument validation."""
338 # Error when no build target provided.
339 in_proto = self._InputProto()
340 out_proto = self._OutputProto()
341 with self.assertRaises(cros_build_lib.DieSystemExit):
342 sysroot_controller.GenerateArchive(
343 in_proto, out_proto, self.api_config
344 )
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700345
Alex Klein1699fab2022-09-08 08:46:06 -0600346 # Error when packages is not specified.
347 in_proto = self._InputProto(
348 build_target="board", chroot_path=self.chroot_path
349 )
350 with self.assertRaises(cros_build_lib.DieSystemExit):
351 sysroot_controller.GenerateArchive(
352 in_proto, out_proto, self.api_config
353 )
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700354
Alex Klein1699fab2022-09-08 08:46:06 -0600355 # Valid when board, chroot path, and package are specified.
356 patch = self.PatchObject(
357 sysroot_service,
358 "GenerateArchive",
359 return_value="/path/to/sysroot/tar.bz",
360 )
361 in_proto = self._InputProto(
362 build_target="board",
363 chroot_path=self.chroot_path,
364 pkg_list=["virtual/target-fuzzers"],
365 )
366 out_proto = self._OutputProto()
367 sysroot_controller.GenerateArchive(in_proto, out_proto, self.api_config)
368 patch.assert_called_once()
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700369
370
Alex Klein1699fab2022-09-08 08:46:06 -0600371class InstallToolchainTest(
372 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin
373):
374 """Install toolchain function tests."""
Alex Kleinda35fcf2019-03-07 16:01:15 -0700375
Alex Klein1699fab2022-09-08 08:46:06 -0600376 def setUp(self):
377 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=True)
378 # Avoid running the portageq command.
379 self.PatchObject(sysroot_controller, "_LogBinhost")
380 self.board = "board"
381 self.sysroot = os.path.join(self.tempdir, "board")
382 self.invalid_sysroot = os.path.join(self.tempdir, "invalid", "sysroot")
383 osutils.SafeMakedirs(self.sysroot)
384 # Set up portage log directory.
385 self.target_sysroot = sysroot_lib.Sysroot(self.sysroot)
386 self.portage_dir = os.path.join(self.tempdir, "portage_logdir")
387 self.PatchObject(
388 sysroot_lib.Sysroot, "portage_logdir", new=self.portage_dir
389 )
390 osutils.SafeMakedirs(self.portage_dir)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700391
Alex Klein1699fab2022-09-08 08:46:06 -0600392 def _InputProto(
393 self, build_target=None, sysroot_path=None, compile_source=False
394 ):
395 """Helper to build an input proto instance."""
396 proto = sysroot_pb2.InstallToolchainRequest()
397 if build_target:
398 proto.sysroot.build_target.name = build_target
399 if sysroot_path:
400 proto.sysroot.path = sysroot_path
401 if compile_source:
402 proto.flags.compile_source = compile_source
Alex Kleinda35fcf2019-03-07 16:01:15 -0700403
Alex Klein1699fab2022-09-08 08:46:06 -0600404 return proto
Alex Kleinda35fcf2019-03-07 16:01:15 -0700405
Alex Klein1699fab2022-09-08 08:46:06 -0600406 def _OutputProto(self):
407 """Helper to build output proto instance."""
408 return sysroot_pb2.InstallToolchainResponse()
Alex Kleinda35fcf2019-03-07 16:01:15 -0700409
Alex Klein1699fab2022-09-08 08:46:06 -0600410 def _CreatePortageLogFile(
411 self,
412 log_path: Union[str, os.PathLike],
413 pkg_info: package_info.PackageInfo,
414 timestamp: datetime.datetime,
415 ):
416 """Creates a log file for testing for individual packages built by Portage.
Lizzy Presland7e23a612021-11-09 21:49:42 +0000417
Alex Klein1699fab2022-09-08 08:46:06 -0600418 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600419 log_path: The PORTAGE_LOGDIR path.
420 pkg_info: Package name used to name the log file.
421 timestamp: Timestamp used to name the file.
Alex Klein1699fab2022-09-08 08:46:06 -0600422 """
423 path = os.path.join(
424 log_path,
425 f"{pkg_info.category}:{pkg_info.pvr}:"
426 f'{timestamp.strftime("%Y%m%d-%H%M%S")}.log',
427 )
428 osutils.WriteFile(
429 path,
430 f"Test log file for package {pkg_info.category}/"
431 f"{pkg_info.package} written to {path}",
432 )
433 return path
Lizzy Presland7e23a612021-11-09 21:49:42 +0000434
Alex Klein1699fab2022-09-08 08:46:06 -0600435 def testValidateOnly(self):
436 """Sanity check that a validate only call does not execute any logic."""
437 patch = self.PatchObject(sysroot_service, "InstallToolchain")
Alex Klein231d2da2019-07-22 16:44:45 -0600438
Alex Klein1699fab2022-09-08 08:46:06 -0600439 in_proto = self._InputProto(
440 build_target=self.board, sysroot_path=self.sysroot
441 )
442 sysroot_controller.InstallToolchain(
443 in_proto, self._OutputProto(), self.validate_only_config
444 )
445 patch.assert_not_called()
Alex Klein231d2da2019-07-22 16:44:45 -0600446
Alex Klein1699fab2022-09-08 08:46:06 -0600447 def testMockCall(self):
448 """Sanity check that a mock call does not execute any logic."""
449 patch = self.PatchObject(sysroot_service, "InstallToolchain")
450 request = self._InputProto()
451 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -0600452
Alex Klein1699fab2022-09-08 08:46:06 -0600453 rc = sysroot_controller.InstallToolchain(
454 request, response, self.mock_call_config
455 )
Alex Klein076841b2019-08-29 15:19:39 -0600456
Alex Klein1699fab2022-09-08 08:46:06 -0600457 patch.assert_not_called()
458 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
Alex Klein076841b2019-08-29 15:19:39 -0600459
Alex Klein1699fab2022-09-08 08:46:06 -0600460 def testMockError(self):
461 """Sanity check that a mock error does not execute any logic."""
462 patch = self.PatchObject(sysroot_service, "InstallToolchain")
463 request = self._InputProto()
464 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -0600465
Alex Klein1699fab2022-09-08 08:46:06 -0600466 rc = sysroot_controller.InstallToolchain(
467 request, response, self.mock_error_config
468 )
Alex Klein076841b2019-08-29 15:19:39 -0600469
Alex Klein1699fab2022-09-08 08:46:06 -0600470 patch.assert_not_called()
471 self.assertEqual(
472 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
473 )
474 self.assertTrue(response.failed_package_data)
Alex Klein076841b2019-08-29 15:19:39 -0600475
Alex Klein1699fab2022-09-08 08:46:06 -0600476 def testArgumentValidation(self):
477 """Test the argument validation."""
478 # Test errors on missing inputs.
479 out_proto = self._OutputProto()
480 # Both missing.
481 in_proto = self._InputProto()
482 with self.assertRaises(cros_build_lib.DieSystemExit):
483 sysroot_controller.InstallToolchain(
484 in_proto, out_proto, self.api_config
485 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700486
Alex Klein1699fab2022-09-08 08:46:06 -0600487 # Sysroot path missing.
488 in_proto = self._InputProto(build_target=self.board)
489 with self.assertRaises(cros_build_lib.DieSystemExit):
490 sysroot_controller.InstallToolchain(
491 in_proto, out_proto, self.api_config
492 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700493
Alex Klein1699fab2022-09-08 08:46:06 -0600494 # Build target name missing.
495 in_proto = self._InputProto(sysroot_path=self.sysroot)
496 with self.assertRaises(cros_build_lib.DieSystemExit):
497 sysroot_controller.InstallToolchain(
498 in_proto, out_proto, self.api_config
499 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700500
Alex Klein1699fab2022-09-08 08:46:06 -0600501 # Both provided, but invalid sysroot path.
502 in_proto = self._InputProto(
503 build_target=self.board, sysroot_path=self.invalid_sysroot
504 )
505 with self.assertRaises(cros_build_lib.DieSystemExit):
506 sysroot_controller.InstallToolchain(
507 in_proto, out_proto, self.api_config
508 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700509
Alex Klein1699fab2022-09-08 08:46:06 -0600510 def testSuccessOutputHandling(self):
511 """Test the output is processed and recorded correctly."""
512 self.PatchObject(sysroot_service, "InstallToolchain")
513 out_proto = self._OutputProto()
514 in_proto = self._InputProto(
515 build_target=self.board, sysroot_path=self.sysroot
516 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700517
Alex Klein1699fab2022-09-08 08:46:06 -0600518 rc = sysroot_controller.InstallToolchain(
519 in_proto, out_proto, self.api_config
520 )
521 self.assertFalse(rc)
522 self.assertFalse(out_proto.failed_package_data)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700523
Alex Klein1699fab2022-09-08 08:46:06 -0600524 def testErrorOutputHandling(self):
525 """Test the error output is processed and recorded correctly."""
526 out_proto = self._OutputProto()
527 in_proto = self._InputProto(
528 build_target=self.board, sysroot_path=self.sysroot
529 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700530
Alex Klein1699fab2022-09-08 08:46:06 -0600531 err_pkgs = ["cat/pkg-1.0-r1", "cat2/pkg2-1.0-r1"]
532 err_cpvs = [package_info.parse(pkg) for pkg in err_pkgs]
533 expected = [("cat", "pkg"), ("cat2", "pkg2")]
Lizzy Presland7e23a612021-11-09 21:49:42 +0000534
Alex Klein1699fab2022-09-08 08:46:06 -0600535 new_logs = {}
536 for i, pkg in enumerate(err_pkgs):
537 self._CreatePortageLogFile(
538 self.portage_dir,
539 err_cpvs[i],
540 datetime.datetime(2021, 6, 9, 13, 37, 0),
541 )
542 new_logs[pkg] = self._CreatePortageLogFile(
543 self.portage_dir,
544 err_cpvs[i],
545 datetime.datetime(2021, 6, 9, 16, 20, 0),
546 )
Lizzy Presland7e23a612021-11-09 21:49:42 +0000547
Alex Klein1699fab2022-09-08 08:46:06 -0600548 err = sysroot_lib.ToolchainInstallError(
549 "Error", cros_build_lib.CompletedProcess(), tc_info=err_cpvs
550 )
551 self.PatchObject(sysroot_service, "InstallToolchain", side_effect=err)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700552
Alex Klein1699fab2022-09-08 08:46:06 -0600553 rc = sysroot_controller.InstallToolchain(
554 in_proto, out_proto, self.api_config
555 )
556 self.assertEqual(
557 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
558 )
559 self.assertTrue(out_proto.failed_package_data)
560 # This needs to return 2 to indicate the available error response.
561 self.assertEqual(
562 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
563 )
564 for data in out_proto.failed_package_data:
565 package = controller_util.deserialize_package_info(data.name)
566 cat_pkg = (data.name.category, data.name.package_name)
567 self.assertIn(cat_pkg, expected)
568 self.assertEqual(data.log_path.path, new_logs[package.cpvr])
Lizzy Presland7e23a612021-11-09 21:49:42 +0000569
Alex Kleind4e1e422019-03-18 16:00:41 -0600570
Alex Klein1699fab2022-09-08 08:46:06 -0600571class InstallPackagesTest(
572 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin
573):
574 """InstallPackages tests."""
Alex Kleind4e1e422019-03-18 16:00:41 -0600575
Alex Klein1699fab2022-09-08 08:46:06 -0600576 def setUp(self):
577 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=True)
578 # Avoid running the portageq command.
579 self.PatchObject(sysroot_controller, "_LogBinhost")
580 self.build_target = "board"
581 self.sysroot = os.path.join(self.tempdir, "build", "board")
582 osutils.SafeMakedirs(self.sysroot)
583 # Set up portage log directory.
584 self.target_sysroot = sysroot_lib.Sysroot(self.sysroot)
585 self.portage_dir = os.path.join(self.tempdir, "portage_logdir")
586 self.PatchObject(
587 sysroot_lib.Sysroot, "portage_logdir", new=self.portage_dir
588 )
589 osutils.SafeMakedirs(self.portage_dir)
590 # Set up goma directories.
591 self.goma_dir = os.path.join(self.tempdir, "goma_dir")
592 osutils.SafeMakedirs(self.goma_dir)
593 self.goma_out_dir = os.path.join(self.tempdir, "goma_out_dir")
594 osutils.SafeMakedirs(self.goma_out_dir)
595 os.environ["GLOG_log_dir"] = self.goma_dir
Alex Kleind4e1e422019-03-18 16:00:41 -0600596
Alex Klein1699fab2022-09-08 08:46:06 -0600597 def _InputProto(
598 self,
599 build_target=None,
600 sysroot_path=None,
601 build_source=False,
602 goma_dir=None,
603 goma_log_dir=None,
604 goma_stats_file=None,
605 goma_counterz_file=None,
606 package_indexes=None,
607 packages=None,
608 ):
609 """Helper to build an input proto instance."""
610 instance = sysroot_pb2.InstallPackagesRequest()
Alex Kleind4e1e422019-03-18 16:00:41 -0600611
Alex Klein1699fab2022-09-08 08:46:06 -0600612 if build_target:
613 instance.sysroot.build_target.name = build_target
614 if sysroot_path:
615 instance.sysroot.path = sysroot_path
616 if build_source:
617 instance.flags.build_source = build_source
618 if goma_dir:
619 instance.goma_config.goma_dir = goma_dir
620 if goma_log_dir:
621 instance.goma_config.log_dir.dir = goma_log_dir
622 if goma_stats_file:
623 instance.goma_config.stats_file = goma_stats_file
624 if goma_counterz_file:
625 instance.goma_config.counterz_file = goma_counterz_file
626 if package_indexes:
627 instance.package_indexes.extend(package_indexes)
628 if packages:
629 for pkg in packages:
630 pkg_info = package_info.parse(pkg)
631 pkg_info_msg = instance.packages.add()
632 controller_util.serialize_package_info(pkg_info, pkg_info_msg)
633 return instance
Alex Kleind4e1e422019-03-18 16:00:41 -0600634
Alex Klein1699fab2022-09-08 08:46:06 -0600635 def _OutputProto(self):
636 """Helper to build an empty output proto instance."""
637 return sysroot_pb2.InstallPackagesResponse()
Alex Kleind4e1e422019-03-18 16:00:41 -0600638
Alex Klein1699fab2022-09-08 08:46:06 -0600639 def _CreateGomaLogFile(
640 self,
641 goma_log_dir: Union[str, os.PathLike],
642 name: str,
643 timestamp: datetime.datetime,
644 ):
645 """Creates a log file for testing.
Michael Mortensen798ee192020-01-17 13:04:43 -0700646
Alex Klein1699fab2022-09-08 08:46:06 -0600647 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600648 goma_log_dir: Directory where the file will be created.
649 name: Log file 'base' name that is combined with the timestamp.
650 timestamp: Timestamp that is written to the file.
Alex Klein1699fab2022-09-08 08:46:06 -0600651 """
652 path = os.path.join(
653 goma_log_dir,
654 "%s.host.log.INFO.%s"
655 % (name, timestamp.strftime("%Y%m%d-%H%M%S.%f")),
656 )
657 osutils.WriteFile(
658 path,
659 timestamp.strftime("Goma log file created at: %Y/%m/%d %H:%M:%S"),
660 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700661
Alex Klein1699fab2022-09-08 08:46:06 -0600662 def _CreatePortageLogFile(
663 self,
664 log_path: Union[str, os.PathLike],
665 pkg_info: package_info.PackageInfo,
666 timestamp: datetime.datetime,
667 ):
668 """Creates a log file for testing for individual packages built by Portage.
Lizzy Presland7e23a612021-11-09 21:49:42 +0000669
Alex Klein1699fab2022-09-08 08:46:06 -0600670 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600671 log_path: The PORTAGE_LOGDIR path.
672 pkg_info: Package name used to name the log file.
673 timestamp: Timestamp used to name the file.
Alex Klein1699fab2022-09-08 08:46:06 -0600674 """
675 path = os.path.join(
676 log_path,
677 f"{pkg_info.category}:{pkg_info.pvr}:"
678 f'{timestamp.strftime("%Y%m%d-%H%M%S")}.log',
679 )
680 osutils.WriteFile(
681 path,
682 f"Test log file for package {pkg_info.category}/"
683 f"{pkg_info.package} written to {path}",
684 )
685 return path
Lizzy Presland7e23a612021-11-09 21:49:42 +0000686
Alex Klein1699fab2022-09-08 08:46:06 -0600687 def testValidateOnly(self):
688 """Sanity check that a validate only call does not execute any logic."""
689 patch = self.PatchObject(sysroot_service, "BuildPackages")
Alex Klein231d2da2019-07-22 16:44:45 -0600690
Alex Klein1699fab2022-09-08 08:46:06 -0600691 in_proto = self._InputProto(
692 build_target=self.build_target, sysroot_path=self.sysroot
693 )
694 sysroot_controller.InstallPackages(
695 in_proto, self._OutputProto(), self.validate_only_config
696 )
697 patch.assert_not_called()
Alex Klein231d2da2019-07-22 16:44:45 -0600698
Alex Klein1699fab2022-09-08 08:46:06 -0600699 def testMockCall(self):
700 """Sanity check that a mock call does not execute any logic."""
701 patch = self.PatchObject(sysroot_service, "BuildPackages")
702 request = self._InputProto()
703 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -0600704
Alex Klein1699fab2022-09-08 08:46:06 -0600705 rc = sysroot_controller.InstallPackages(
706 request, response, self.mock_call_config
707 )
Alex Klein076841b2019-08-29 15:19:39 -0600708
Alex Klein1699fab2022-09-08 08:46:06 -0600709 patch.assert_not_called()
710 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
Alex Klein076841b2019-08-29 15:19:39 -0600711
Alex Klein1699fab2022-09-08 08:46:06 -0600712 def testMockError(self):
713 """Sanity check that a mock error does not execute any logic."""
714 patch = self.PatchObject(sysroot_service, "BuildPackages")
715 request = self._InputProto()
716 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -0600717
Alex Klein1699fab2022-09-08 08:46:06 -0600718 rc = sysroot_controller.InstallPackages(
719 request, response, self.mock_error_config
720 )
Alex Klein076841b2019-08-29 15:19:39 -0600721
Alex Klein1699fab2022-09-08 08:46:06 -0600722 patch.assert_not_called()
723 self.assertEqual(
724 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
725 )
726 self.assertTrue(response.failed_package_data)
Alex Klein076841b2019-08-29 15:19:39 -0600727
Alex Klein1699fab2022-09-08 08:46:06 -0600728 def testArgumentValidationAllMissing(self):
729 """Test missing all arguments."""
730 out_proto = self._OutputProto()
731 in_proto = self._InputProto()
732 with self.assertRaises(cros_build_lib.DieSystemExit):
733 sysroot_controller.InstallPackages(
734 in_proto, out_proto, self.api_config
735 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600736
Alex Klein1699fab2022-09-08 08:46:06 -0600737 def testArgumentValidationNoSysroot(self):
738 """Test missing sysroot path."""
739 out_proto = self._OutputProto()
740 in_proto = self._InputProto(build_target=self.build_target)
741 with self.assertRaises(cros_build_lib.DieSystemExit):
742 sysroot_controller.InstallPackages(
743 in_proto, out_proto, self.api_config
744 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600745
Alex Klein1699fab2022-09-08 08:46:06 -0600746 def testArgumentValidationNoBuildTarget(self):
747 """Test missing build target name."""
748 out_proto = self._OutputProto()
749 in_proto = self._InputProto(sysroot_path=self.sysroot)
750 with self.assertRaises(cros_build_lib.DieSystemExit):
751 sysroot_controller.InstallPackages(
752 in_proto, out_proto, self.api_config
753 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600754
Alex Klein1699fab2022-09-08 08:46:06 -0600755 def testArgumentValidationInvalidSysroot(self):
756 """Test sysroot that hasn't had the toolchain installed."""
757 out_proto = self._OutputProto()
758 in_proto = self._InputProto(
759 build_target=self.build_target, sysroot_path=self.sysroot
760 )
761 self.PatchObject(
762 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=False
763 )
764 with self.assertRaises(cros_build_lib.DieSystemExit):
765 sysroot_controller.InstallPackages(
766 in_proto, out_proto, self.api_config
767 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600768
Alex Klein1699fab2022-09-08 08:46:06 -0600769 def testArgumentValidationInvalidPackage(self):
770 out_proto = self._OutputProto()
771 in_proto = self._InputProto(
772 build_target=self.build_target,
773 sysroot_path=self.sysroot,
774 packages=["package-1.0.0-r2"],
775 )
776 with self.assertRaises(cros_build_lib.DieSystemExit):
777 sysroot_controller.InstallPackages(
778 in_proto, out_proto, self.api_config
779 )
Alex Kleinca572ee2020-09-03 10:47:14 -0600780
Alex Klein1699fab2022-09-08 08:46:06 -0600781 def testSuccessOutputHandling(self):
782 """Test successful call output handling."""
783 # Prevent argument validation error.
784 self.PatchObject(
785 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
786 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600787
Alex Klein1699fab2022-09-08 08:46:06 -0600788 in_proto = self._InputProto(
789 build_target=self.build_target, sysroot_path=self.sysroot
790 )
791 out_proto = self._OutputProto()
792 self.PatchObject(sysroot_service, "BuildPackages")
Alex Kleind4e1e422019-03-18 16:00:41 -0600793
Alex Klein1699fab2022-09-08 08:46:06 -0600794 rc = sysroot_controller.InstallPackages(
795 in_proto, out_proto, self.api_config
796 )
797 self.assertFalse(rc)
798 self.assertFalse(out_proto.failed_package_data)
Alex Kleind4e1e422019-03-18 16:00:41 -0600799
Alex Klein1699fab2022-09-08 08:46:06 -0600800 def testSuccessPackageIndexes(self):
801 """Test successful call with package_indexes."""
802 # Prevent argument validation error.
803 self.PatchObject(
804 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
805 )
806 package_indexes = [
807 common_pb2.PackageIndexInfo(
808 snapshot_sha="SHA",
809 snapshot_number=5,
810 build_target=common_pb2.BuildTarget(name="board"),
811 location="LOCATION",
812 profile=common_pb2.Profile(name="profile"),
813 ),
814 common_pb2.PackageIndexInfo(
815 snapshot_sha="SHA2",
816 snapshot_number=4,
817 build_target=common_pb2.BuildTarget(name="board"),
818 location="LOCATION2",
819 profile=common_pb2.Profile(name="profile"),
820 ),
821 ]
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600822
Alex Klein1699fab2022-09-08 08:46:06 -0600823 in_proto = self._InputProto(
824 build_target=self.build_target,
825 sysroot_path=self.sysroot,
826 package_indexes=package_indexes,
827 )
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600828
Alex Klein1699fab2022-09-08 08:46:06 -0600829 out_proto = self._OutputProto()
830 rc_patch = self.PatchObject(sysroot_service, "BuildPackagesRunConfig")
831 self.PatchObject(sysroot_service, "BuildPackages")
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600832
Alex Klein1699fab2022-09-08 08:46:06 -0600833 rc = sysroot_controller.InstallPackages(
834 in_proto, out_proto, self.api_config
835 )
836 self.assertFalse(rc)
837 rc_patch.assert_called_with(
838 use_any_chrome=False,
839 usepkg=True,
840 install_debug_symbols=True,
841 packages=[],
842 package_indexes=[
843 binpkg.PackageIndexInfo.from_protobuf(x)
844 for x in package_indexes
845 ],
846 use_flags=[],
847 use_goma=False,
848 use_remoteexec=False,
849 incremental_build=False,
850 dryrun=False,
851 backtrack=sysroot_controller.DEFAULT_BACKTRACK,
852 )
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600853
Alex Klein1699fab2022-09-08 08:46:06 -0600854 def testSuccessWithGomaLogs(self):
855 """Test successful call with goma."""
856 self._CreateGomaLogFile(
857 self.goma_dir,
858 "compiler_proxy",
859 datetime.datetime(2018, 9, 21, 12, 0, 0),
860 )
861 self._CreateGomaLogFile(
862 self.goma_dir,
863 "compiler_proxy-subproc",
864 datetime.datetime(2018, 9, 21, 12, 1, 0),
865 )
866 self._CreateGomaLogFile(
867 self.goma_dir, "gomacc", datetime.datetime(2018, 9, 21, 12, 2, 0)
868 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700869
Alex Klein1699fab2022-09-08 08:46:06 -0600870 # Prevent argument validation error.
871 self.PatchObject(
872 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
873 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700874
Alex Klein1699fab2022-09-08 08:46:06 -0600875 in_proto = self._InputProto(
876 build_target=self.build_target,
877 sysroot_path=self.sysroot,
878 goma_dir=self.goma_dir,
879 goma_log_dir=self.goma_out_dir,
880 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700881
Alex Klein1699fab2022-09-08 08:46:06 -0600882 out_proto = self._OutputProto()
883 self.PatchObject(sysroot_service, "BuildPackages")
Michael Mortensen798ee192020-01-17 13:04:43 -0700884
Alex Klein1699fab2022-09-08 08:46:06 -0600885 rc = sysroot_controller.InstallPackages(
886 in_proto, out_proto, self.api_config
887 )
888 self.assertFalse(rc)
889 self.assertFalse(out_proto.failed_package_data)
890 self.assertCountEqual(
891 out_proto.goma_artifacts.log_files,
892 [
893 "compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz",
894 "compiler_proxy.host.log.INFO.20180921-120000.000000.gz",
895 "gomacc.host.log.INFO.20180921-120200.000000.tar.gz",
896 ],
897 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700898
Alex Klein1699fab2022-09-08 08:46:06 -0600899 def testSuccessWithGomaLogsAndStatsCounterzFiles(self):
900 """Test successful call with goma including stats and counterz files."""
901 self._CreateGomaLogFile(
902 self.goma_dir,
903 "compiler_proxy",
904 datetime.datetime(2018, 9, 21, 12, 0, 0),
905 )
906 self._CreateGomaLogFile(
907 self.goma_dir,
908 "compiler_proxy-subproc",
909 datetime.datetime(2018, 9, 21, 12, 1, 0),
910 )
911 self._CreateGomaLogFile(
912 self.goma_dir, "gomacc", datetime.datetime(2018, 9, 21, 12, 2, 0)
913 )
914 # Create stats and counterz files.
915 osutils.WriteFile(
916 os.path.join(self.goma_dir, "stats.binaryproto"),
917 "File: stats.binaryproto",
918 )
919 osutils.WriteFile(
920 os.path.join(self.goma_dir, "counterz.binaryproto"),
921 "File: counterz.binaryproto",
922 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700923
Alex Klein1699fab2022-09-08 08:46:06 -0600924 # Prevent argument validation error.
925 self.PatchObject(
926 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
927 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700928
Alex Klein1699fab2022-09-08 08:46:06 -0600929 in_proto = self._InputProto(
930 build_target=self.build_target,
931 sysroot_path=self.sysroot,
932 goma_dir=self.goma_dir,
933 goma_log_dir=self.goma_out_dir,
934 goma_stats_file="stats.binaryproto",
935 goma_counterz_file="counterz.binaryproto",
936 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700937
Alex Klein1699fab2022-09-08 08:46:06 -0600938 out_proto = self._OutputProto()
939 self.PatchObject(sysroot_service, "BuildPackages")
Michael Mortensen798ee192020-01-17 13:04:43 -0700940
Alex Klein1699fab2022-09-08 08:46:06 -0600941 rc = sysroot_controller.InstallPackages(
942 in_proto, out_proto, self.api_config
943 )
944 self.assertFalse(rc)
945 self.assertFalse(out_proto.failed_package_data)
946 self.assertCountEqual(
947 out_proto.goma_artifacts.log_files,
948 [
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 )
954 # Verify that the output dir has 5 files -- since there should be 3 log
955 # files, the stats file, and the counterz file.
956 output_files = os.listdir(self.goma_out_dir)
957 self.assertCountEqual(
958 output_files,
959 [
960 "stats.binaryproto",
961 "counterz.binaryproto",
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 )
967 self.assertEqual(
968 out_proto.goma_artifacts.counterz_file, "counterz.binaryproto"
969 )
970 self.assertEqual(
971 out_proto.goma_artifacts.stats_file, "stats.binaryproto"
972 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700973
Alex Klein1699fab2022-09-08 08:46:06 -0600974 def testFailureMissingGomaStatsCounterzFiles(self):
975 """Test successful call with goma including stats and counterz files."""
976 self._CreateGomaLogFile(
977 self.goma_dir,
978 "compiler_proxy",
979 datetime.datetime(2018, 9, 21, 12, 0, 0),
980 )
981 self._CreateGomaLogFile(
982 self.goma_dir,
983 "compiler_proxy-subproc",
984 datetime.datetime(2018, 9, 21, 12, 1, 0),
985 )
986 self._CreateGomaLogFile(
987 self.goma_dir, "gomacc", datetime.datetime(2018, 9, 21, 12, 2, 0)
988 )
989 # Note that stats and counterz files are not created, but are specified in
990 # the proto below.
Michael Mortensen798ee192020-01-17 13:04:43 -0700991
Alex Klein1699fab2022-09-08 08:46:06 -0600992 # Prevent argument validation error.
993 self.PatchObject(
994 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
995 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700996
Alex Klein1699fab2022-09-08 08:46:06 -0600997 in_proto = self._InputProto(
998 build_target=self.build_target,
999 sysroot_path=self.sysroot,
1000 goma_dir=self.goma_dir,
1001 goma_log_dir=self.goma_out_dir,
1002 goma_stats_file="stats.binaryproto",
1003 goma_counterz_file="counterz.binaryproto",
1004 )
Michael Mortensen798ee192020-01-17 13:04:43 -07001005
Alex Klein1699fab2022-09-08 08:46:06 -06001006 out_proto = self._OutputProto()
1007 self.PatchObject(sysroot_service, "BuildPackages")
Michael Mortensen798ee192020-01-17 13:04:43 -07001008
Alex Klein1699fab2022-09-08 08:46:06 -06001009 rc = sysroot_controller.InstallPackages(
1010 in_proto, out_proto, self.api_config
1011 )
1012 self.assertFalse(rc)
1013 self.assertFalse(out_proto.failed_package_data)
1014 self.assertCountEqual(
1015 out_proto.goma_artifacts.log_files,
1016 [
1017 "compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz",
1018 "compiler_proxy.host.log.INFO.20180921-120000.000000.gz",
1019 "gomacc.host.log.INFO.20180921-120200.000000.tar.gz",
1020 ],
1021 )
1022 self.assertFalse(out_proto.goma_artifacts.counterz_file)
1023 self.assertFalse(out_proto.goma_artifacts.stats_file)
Michael Mortensen798ee192020-01-17 13:04:43 -07001024
Alex Klein1699fab2022-09-08 08:46:06 -06001025 def testFailureOutputHandling(self):
1026 """Test failed package handling."""
1027 # Prevent argument validation error.
1028 self.PatchObject(
1029 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
1030 )
Alex Kleind4e1e422019-03-18 16:00:41 -06001031
Alex Klein1699fab2022-09-08 08:46:06 -06001032 in_proto = self._InputProto(
1033 build_target=self.build_target, sysroot_path=self.sysroot
1034 )
1035 out_proto = self._OutputProto()
Alex Kleind4e1e422019-03-18 16:00:41 -06001036
Alex Klein1699fab2022-09-08 08:46:06 -06001037 # Failed package info and expected list for verification.
1038 err_pkgs = ["cat/pkg-1.0-r3", "cat2/pkg2-1.0-r1"]
1039 err_cpvs = [package_info.parse(cpv) for cpv in err_pkgs]
1040 expected = [("cat", "pkg"), ("cat2", "pkg2")]
Alex Kleind4e1e422019-03-18 16:00:41 -06001041
Alex Klein1699fab2022-09-08 08:46:06 -06001042 new_logs = {}
1043 for i, pkg in enumerate(err_pkgs):
1044 self._CreatePortageLogFile(
1045 self.portage_dir,
1046 err_cpvs[i],
1047 datetime.datetime(2021, 6, 9, 13, 37, 0),
1048 )
1049 new_logs[pkg] = self._CreatePortageLogFile(
1050 self.portage_dir,
1051 err_cpvs[i],
1052 datetime.datetime(2021, 6, 9, 16, 20, 0),
1053 )
1054 # Force error to be raised with the packages.
1055 error = sysroot_lib.PackageInstallError(
1056 "Error", cros_build_lib.CompletedProcess(), packages=err_cpvs
1057 )
1058 self.PatchObject(sysroot_service, "BuildPackages", side_effect=error)
Alex Kleind4e1e422019-03-18 16:00:41 -06001059
Alex Klein1699fab2022-09-08 08:46:06 -06001060 rc = sysroot_controller.InstallPackages(
1061 in_proto, out_proto, self.api_config
1062 )
1063 # This needs to return 2 to indicate the available error response.
1064 self.assertEqual(
1065 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
1066 )
1067 for data in out_proto.failed_package_data:
1068 package = controller_util.deserialize_package_info(data.name)
1069 cat_pkg = (data.name.category, data.name.package_name)
1070 self.assertIn(cat_pkg, expected)
1071 self.assertEqual(data.log_path.path, new_logs[package.cpvr])
Lizzy Presland7e23a612021-11-09 21:49:42 +00001072
Alex Klein1699fab2022-09-08 08:46:06 -06001073 def testNoPackageFailureOutputHandling(self):
1074 """Test failure handling without packages to report."""
1075 # Prevent argument validation error.
1076 self.PatchObject(
1077 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
1078 )
Alex Klein2557b4f2019-07-11 14:34:00 -06001079
Alex Klein1699fab2022-09-08 08:46:06 -06001080 in_proto = self._InputProto(
1081 build_target=self.build_target, sysroot_path=self.sysroot
1082 )
1083 out_proto = self._OutputProto()
Alex Klein2557b4f2019-07-11 14:34:00 -06001084
Alex Klein1699fab2022-09-08 08:46:06 -06001085 # Force error to be raised with no packages.
1086 error = sysroot_lib.PackageInstallError(
1087 "Error", cros_build_lib.CompletedProcess(), packages=[]
1088 )
1089 self.PatchObject(sysroot_service, "BuildPackages", side_effect=error)
Alex Klein2557b4f2019-07-11 14:34:00 -06001090
Alex Klein1699fab2022-09-08 08:46:06 -06001091 rc = sysroot_controller.InstallPackages(
1092 in_proto, out_proto, self.api_config
1093 )
1094 # All we really care about is it's not 0 or 2 (response available), so
1095 # test for that rather than a specific return code.
1096 self.assertTrue(rc)
1097 self.assertNotEqual(
1098 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
1099 )