blob: eb5f65bcebe18cbb674f9f67ea70fbc51b094209 [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,
205 }
206
Alex Kleinab87ceb2023-01-24 12:00:51 -0700207 # pylint: enable=line-too-long
208
Jack Neus26b94672022-10-27 17:33:21 +0000209 def setUp(self):
210 self._mocks = {}
211 for artifact, func in self._artifact_funcs.items():
212 self._mocks[artifact] = self.PatchObject(
213 sysroot_service, func.__name__
214 )
215
216 def _InputProto(
217 self,
218 artifact_types=_artifact_funcs.keys(),
219 ):
220 """Helper to build an input proto instance."""
221 return common_pb2.ArtifactsByService.Sysroot(
222 output_artifacts=[
223 common_pb2.ArtifactsByService.Sysroot.ArtifactInfo(
224 artifact_types=artifact_types
225 )
226 ]
227 )
228
229 def testNoArtifacts(self):
230 """Test GetArtifacts with no artifact types."""
231 in_proto = self._InputProto(artifact_types=[])
232 sysroot_controller.GetArtifacts(
233 in_proto, None, None, "build_target", ""
234 )
235
236 for _, patch in self._mocks.items():
237 patch.assert_not_called()
238
239 def testArtifactsSuccess(self):
240 """Test GetArtifacts with all artifact types."""
241 sysroot_controller.GetArtifacts(
242 self._InputProto(), None, None, "build_target", ""
243 )
244
245 for _, patch in self._mocks.items():
246 patch.assert_called_once()
247
248 def testArtifactsException(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700249 """Test with all artifact types when one type throws an exception."""
Jack Neus26b94672022-10-27 17:33:21 +0000250
251 self._mocks[
252 common_pb2.ArtifactsByService.Sysroot.ArtifactType.FUZZER_SYSROOT
253 ].side_effect = Exception("foo bar")
254 generated = sysroot_controller.GetArtifacts(
255 self._InputProto(), None, None, "build_target", ""
256 )
257
258 for _, patch in self._mocks.items():
259 patch.assert_called_once()
260
261 found_artifact = False
262 for data in generated:
263 artifact_type = (
264 common_pb2.ArtifactsByService.Sysroot.ArtifactType.Name(
265 data["type"]
266 )
267 )
268 if artifact_type == "FUZZER_SYSROOT":
269 found_artifact = True
270 self.assertTrue(data["failed"])
271 self.assertEqual(data["failure_reason"], "foo bar")
272 self.assertTrue(found_artifact)
273
274
Alex Klein1699fab2022-09-08 08:46:06 -0600275class GenerateArchiveTest(
276 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin
277):
278 """GenerateArchive function tests."""
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700279
Alex Klein1699fab2022-09-08 08:46:06 -0600280 def setUp(self):
281 self.chroot_path = "/path/to/chroot"
282 self.board = "board"
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700283
Alex Klein1699fab2022-09-08 08:46:06 -0600284 def _InputProto(self, build_target=None, chroot_path=None, pkg_list=None):
285 """Helper to build and input proto instance."""
286 # pkg_list will be a list of category/package strings such as
287 # ['virtual/target-fuzzers'].
288 if pkg_list:
289 package_list = []
290 for pkg in pkg_list:
291 pkg_string_parts = pkg.split("/")
292 package_info_msg = common_pb2.PackageInfo(
293 category=pkg_string_parts[0],
294 package_name=pkg_string_parts[1],
295 )
296 package_list.append(package_info_msg)
297 else:
298 package_list = []
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700299
Alex Klein1699fab2022-09-08 08:46:06 -0600300 return sysroot_pb2.SysrootGenerateArchiveRequest(
301 build_target={"name": build_target},
302 chroot={"path": chroot_path},
303 packages=package_list,
304 )
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700305
Alex Klein1699fab2022-09-08 08:46:06 -0600306 def _OutputProto(self):
307 """Helper to build output proto instance."""
308 return sysroot_pb2.SysrootGenerateArchiveResponse()
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700309
Alex Klein1699fab2022-09-08 08:46:06 -0600310 def testValidateOnly(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700311 """Verify a validate-only call does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -0600312 patch = self.PatchObject(sysroot_service, "GenerateArchive")
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700313
Alex Klein1699fab2022-09-08 08:46:06 -0600314 in_proto = self._InputProto(
315 build_target=self.board,
316 chroot_path=self.chroot_path,
317 pkg_list=["virtual/target-fuzzers"],
318 )
319 sysroot_controller.GenerateArchive(
320 in_proto, self._OutputProto(), self.validate_only_config
321 )
322 patch.assert_not_called()
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700323
Alex Klein1699fab2022-09-08 08:46:06 -0600324 def testMockCall(self):
325 """Sanity check that a mock call does not execute any logic."""
326 patch = self.PatchObject(sysroot_service, "GenerateArchive")
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700327
Alex Klein1699fab2022-09-08 08:46:06 -0600328 in_proto = self._InputProto(
329 build_target=self.board,
330 chroot_path=self.chroot_path,
331 pkg_list=["virtual/target-fuzzers"],
332 )
333 sysroot_controller.GenerateArchive(
334 in_proto, self._OutputProto(), self.mock_call_config
335 )
336 patch.assert_not_called()
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700337
Alex Klein1699fab2022-09-08 08:46:06 -0600338 def testArgumentValidation(self):
339 """Test the input argument validation."""
340 # Error when no build target provided.
341 in_proto = self._InputProto()
342 out_proto = self._OutputProto()
343 with self.assertRaises(cros_build_lib.DieSystemExit):
344 sysroot_controller.GenerateArchive(
345 in_proto, out_proto, self.api_config
346 )
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700347
Alex Klein1699fab2022-09-08 08:46:06 -0600348 # Error when packages is not specified.
349 in_proto = self._InputProto(
350 build_target="board", chroot_path=self.chroot_path
351 )
352 with self.assertRaises(cros_build_lib.DieSystemExit):
353 sysroot_controller.GenerateArchive(
354 in_proto, out_proto, self.api_config
355 )
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700356
Alex Klein1699fab2022-09-08 08:46:06 -0600357 # Valid when board, chroot path, and package are specified.
358 patch = self.PatchObject(
359 sysroot_service,
360 "GenerateArchive",
361 return_value="/path/to/sysroot/tar.bz",
362 )
363 in_proto = self._InputProto(
364 build_target="board",
365 chroot_path=self.chroot_path,
366 pkg_list=["virtual/target-fuzzers"],
367 )
368 out_proto = self._OutputProto()
369 sysroot_controller.GenerateArchive(in_proto, out_proto, self.api_config)
370 patch.assert_called_once()
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700371
372
Alex Klein1699fab2022-09-08 08:46:06 -0600373class InstallToolchainTest(
374 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin
375):
376 """Install toolchain function tests."""
Alex Kleinda35fcf2019-03-07 16:01:15 -0700377
Alex Klein1699fab2022-09-08 08:46:06 -0600378 def setUp(self):
379 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=True)
380 # Avoid running the portageq command.
381 self.PatchObject(sysroot_controller, "_LogBinhost")
382 self.board = "board"
383 self.sysroot = os.path.join(self.tempdir, "board")
384 self.invalid_sysroot = os.path.join(self.tempdir, "invalid", "sysroot")
385 osutils.SafeMakedirs(self.sysroot)
386 # Set up portage log directory.
387 self.target_sysroot = sysroot_lib.Sysroot(self.sysroot)
388 self.portage_dir = os.path.join(self.tempdir, "portage_logdir")
389 self.PatchObject(
390 sysroot_lib.Sysroot, "portage_logdir", new=self.portage_dir
391 )
392 osutils.SafeMakedirs(self.portage_dir)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700393
Alex Klein1699fab2022-09-08 08:46:06 -0600394 def _InputProto(
395 self, build_target=None, sysroot_path=None, compile_source=False
396 ):
397 """Helper to build an input proto instance."""
398 proto = sysroot_pb2.InstallToolchainRequest()
399 if build_target:
400 proto.sysroot.build_target.name = build_target
401 if sysroot_path:
402 proto.sysroot.path = sysroot_path
403 if compile_source:
404 proto.flags.compile_source = compile_source
Alex Kleinda35fcf2019-03-07 16:01:15 -0700405
Alex Klein1699fab2022-09-08 08:46:06 -0600406 return proto
Alex Kleinda35fcf2019-03-07 16:01:15 -0700407
Alex Klein1699fab2022-09-08 08:46:06 -0600408 def _OutputProto(self):
409 """Helper to build output proto instance."""
410 return sysroot_pb2.InstallToolchainResponse()
Alex Kleinda35fcf2019-03-07 16:01:15 -0700411
Alex Klein1699fab2022-09-08 08:46:06 -0600412 def _CreatePortageLogFile(
413 self,
414 log_path: Union[str, os.PathLike],
415 pkg_info: package_info.PackageInfo,
416 timestamp: datetime.datetime,
417 ):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700418 """Creates a log file to test for individual packages built by Portage.
Lizzy Presland7e23a612021-11-09 21:49:42 +0000419
Alex Klein1699fab2022-09-08 08:46:06 -0600420 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600421 log_path: The PORTAGE_LOGDIR path.
422 pkg_info: Package name used to name the log file.
423 timestamp: Timestamp used to name the file.
Alex Klein1699fab2022-09-08 08:46:06 -0600424 """
425 path = os.path.join(
426 log_path,
427 f"{pkg_info.category}:{pkg_info.pvr}:"
428 f'{timestamp.strftime("%Y%m%d-%H%M%S")}.log',
429 )
430 osutils.WriteFile(
431 path,
432 f"Test log file for package {pkg_info.category}/"
433 f"{pkg_info.package} written to {path}",
434 )
435 return path
Lizzy Presland7e23a612021-11-09 21:49:42 +0000436
Alex Klein1699fab2022-09-08 08:46:06 -0600437 def testValidateOnly(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700438 """Verify a validate-only call does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -0600439 patch = self.PatchObject(sysroot_service, "InstallToolchain")
Alex Klein231d2da2019-07-22 16:44:45 -0600440
Alex Klein1699fab2022-09-08 08:46:06 -0600441 in_proto = self._InputProto(
442 build_target=self.board, sysroot_path=self.sysroot
443 )
444 sysroot_controller.InstallToolchain(
445 in_proto, self._OutputProto(), self.validate_only_config
446 )
447 patch.assert_not_called()
Alex Klein231d2da2019-07-22 16:44:45 -0600448
Alex Klein1699fab2022-09-08 08:46:06 -0600449 def testMockCall(self):
450 """Sanity check that a mock call does not execute any logic."""
451 patch = self.PatchObject(sysroot_service, "InstallToolchain")
452 request = self._InputProto()
453 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -0600454
Alex Klein1699fab2022-09-08 08:46:06 -0600455 rc = sysroot_controller.InstallToolchain(
456 request, response, self.mock_call_config
457 )
Alex Klein076841b2019-08-29 15:19:39 -0600458
Alex Klein1699fab2022-09-08 08:46:06 -0600459 patch.assert_not_called()
460 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
Alex Klein076841b2019-08-29 15:19:39 -0600461
Alex Klein1699fab2022-09-08 08:46:06 -0600462 def testMockError(self):
463 """Sanity check that a mock error does not execute any logic."""
464 patch = self.PatchObject(sysroot_service, "InstallToolchain")
465 request = self._InputProto()
466 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -0600467
Alex Klein1699fab2022-09-08 08:46:06 -0600468 rc = sysroot_controller.InstallToolchain(
469 request, response, self.mock_error_config
470 )
Alex Klein076841b2019-08-29 15:19:39 -0600471
Alex Klein1699fab2022-09-08 08:46:06 -0600472 patch.assert_not_called()
473 self.assertEqual(
474 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
475 )
476 self.assertTrue(response.failed_package_data)
Alex Klein076841b2019-08-29 15:19:39 -0600477
Alex Klein1699fab2022-09-08 08:46:06 -0600478 def testArgumentValidation(self):
479 """Test the argument validation."""
480 # Test errors on missing inputs.
481 out_proto = self._OutputProto()
482 # Both missing.
483 in_proto = self._InputProto()
484 with self.assertRaises(cros_build_lib.DieSystemExit):
485 sysroot_controller.InstallToolchain(
486 in_proto, out_proto, self.api_config
487 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700488
Alex Klein1699fab2022-09-08 08:46:06 -0600489 # Sysroot path missing.
490 in_proto = self._InputProto(build_target=self.board)
491 with self.assertRaises(cros_build_lib.DieSystemExit):
492 sysroot_controller.InstallToolchain(
493 in_proto, out_proto, self.api_config
494 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700495
Alex Klein1699fab2022-09-08 08:46:06 -0600496 # Build target name missing.
497 in_proto = self._InputProto(sysroot_path=self.sysroot)
498 with self.assertRaises(cros_build_lib.DieSystemExit):
499 sysroot_controller.InstallToolchain(
500 in_proto, out_proto, self.api_config
501 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700502
Alex Klein1699fab2022-09-08 08:46:06 -0600503 # Both provided, but invalid sysroot path.
504 in_proto = self._InputProto(
505 build_target=self.board, sysroot_path=self.invalid_sysroot
506 )
507 with self.assertRaises(cros_build_lib.DieSystemExit):
508 sysroot_controller.InstallToolchain(
509 in_proto, out_proto, self.api_config
510 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700511
Alex Klein1699fab2022-09-08 08:46:06 -0600512 def testSuccessOutputHandling(self):
513 """Test the output is processed and recorded correctly."""
514 self.PatchObject(sysroot_service, "InstallToolchain")
515 out_proto = self._OutputProto()
516 in_proto = self._InputProto(
517 build_target=self.board, sysroot_path=self.sysroot
518 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700519
Alex Klein1699fab2022-09-08 08:46:06 -0600520 rc = sysroot_controller.InstallToolchain(
521 in_proto, out_proto, self.api_config
522 )
523 self.assertFalse(rc)
524 self.assertFalse(out_proto.failed_package_data)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700525
Alex Klein1699fab2022-09-08 08:46:06 -0600526 def testErrorOutputHandling(self):
527 """Test the error output is processed and recorded correctly."""
528 out_proto = self._OutputProto()
529 in_proto = self._InputProto(
530 build_target=self.board, sysroot_path=self.sysroot
531 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700532
Alex Klein1699fab2022-09-08 08:46:06 -0600533 err_pkgs = ["cat/pkg-1.0-r1", "cat2/pkg2-1.0-r1"]
534 err_cpvs = [package_info.parse(pkg) for pkg in err_pkgs]
535 expected = [("cat", "pkg"), ("cat2", "pkg2")]
Lizzy Presland7e23a612021-11-09 21:49:42 +0000536
Alex Klein1699fab2022-09-08 08:46:06 -0600537 new_logs = {}
538 for i, pkg in enumerate(err_pkgs):
539 self._CreatePortageLogFile(
540 self.portage_dir,
541 err_cpvs[i],
542 datetime.datetime(2021, 6, 9, 13, 37, 0),
543 )
544 new_logs[pkg] = self._CreatePortageLogFile(
545 self.portage_dir,
546 err_cpvs[i],
547 datetime.datetime(2021, 6, 9, 16, 20, 0),
548 )
Lizzy Presland7e23a612021-11-09 21:49:42 +0000549
Alex Klein1699fab2022-09-08 08:46:06 -0600550 err = sysroot_lib.ToolchainInstallError(
551 "Error", cros_build_lib.CompletedProcess(), tc_info=err_cpvs
552 )
553 self.PatchObject(sysroot_service, "InstallToolchain", side_effect=err)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700554
Alex Klein1699fab2022-09-08 08:46:06 -0600555 rc = sysroot_controller.InstallToolchain(
556 in_proto, out_proto, self.api_config
557 )
558 self.assertEqual(
559 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
560 )
561 self.assertTrue(out_proto.failed_package_data)
562 # This needs to return 2 to indicate the available error response.
563 self.assertEqual(
564 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
565 )
566 for data in out_proto.failed_package_data:
567 package = controller_util.deserialize_package_info(data.name)
568 cat_pkg = (data.name.category, data.name.package_name)
569 self.assertIn(cat_pkg, expected)
570 self.assertEqual(data.log_path.path, new_logs[package.cpvr])
Lizzy Presland7e23a612021-11-09 21:49:42 +0000571
Alex Kleind4e1e422019-03-18 16:00:41 -0600572
Alex Klein1699fab2022-09-08 08:46:06 -0600573class InstallPackagesTest(
574 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin
575):
576 """InstallPackages tests."""
Alex Kleind4e1e422019-03-18 16:00:41 -0600577
Alex Klein1699fab2022-09-08 08:46:06 -0600578 def setUp(self):
579 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=True)
580 # Avoid running the portageq command.
581 self.PatchObject(sysroot_controller, "_LogBinhost")
582 self.build_target = "board"
583 self.sysroot = os.path.join(self.tempdir, "build", "board")
584 osutils.SafeMakedirs(self.sysroot)
585 # Set up portage log directory.
586 self.target_sysroot = sysroot_lib.Sysroot(self.sysroot)
587 self.portage_dir = os.path.join(self.tempdir, "portage_logdir")
588 self.PatchObject(
589 sysroot_lib.Sysroot, "portage_logdir", new=self.portage_dir
590 )
591 osutils.SafeMakedirs(self.portage_dir)
592 # Set up goma directories.
593 self.goma_dir = os.path.join(self.tempdir, "goma_dir")
594 osutils.SafeMakedirs(self.goma_dir)
595 self.goma_out_dir = os.path.join(self.tempdir, "goma_out_dir")
596 osutils.SafeMakedirs(self.goma_out_dir)
597 os.environ["GLOG_log_dir"] = self.goma_dir
Alex Kleind4e1e422019-03-18 16:00:41 -0600598
Alex Klein1699fab2022-09-08 08:46:06 -0600599 def _InputProto(
600 self,
601 build_target=None,
602 sysroot_path=None,
603 build_source=False,
604 goma_dir=None,
605 goma_log_dir=None,
606 goma_stats_file=None,
607 goma_counterz_file=None,
608 package_indexes=None,
609 packages=None,
610 ):
611 """Helper to build an input proto instance."""
612 instance = sysroot_pb2.InstallPackagesRequest()
Alex Kleind4e1e422019-03-18 16:00:41 -0600613
Alex Klein1699fab2022-09-08 08:46:06 -0600614 if build_target:
615 instance.sysroot.build_target.name = build_target
616 if sysroot_path:
617 instance.sysroot.path = sysroot_path
618 if build_source:
619 instance.flags.build_source = build_source
620 if goma_dir:
621 instance.goma_config.goma_dir = goma_dir
622 if goma_log_dir:
623 instance.goma_config.log_dir.dir = goma_log_dir
624 if goma_stats_file:
625 instance.goma_config.stats_file = goma_stats_file
626 if goma_counterz_file:
627 instance.goma_config.counterz_file = goma_counterz_file
628 if package_indexes:
629 instance.package_indexes.extend(package_indexes)
630 if packages:
631 for pkg in packages:
632 pkg_info = package_info.parse(pkg)
633 pkg_info_msg = instance.packages.add()
634 controller_util.serialize_package_info(pkg_info, pkg_info_msg)
635 return instance
Alex Kleind4e1e422019-03-18 16:00:41 -0600636
Alex Klein1699fab2022-09-08 08:46:06 -0600637 def _OutputProto(self):
638 """Helper to build an empty output proto instance."""
639 return sysroot_pb2.InstallPackagesResponse()
Alex Kleind4e1e422019-03-18 16:00:41 -0600640
Alex Klein1699fab2022-09-08 08:46:06 -0600641 def _CreateGomaLogFile(
642 self,
643 goma_log_dir: Union[str, os.PathLike],
644 name: str,
645 timestamp: datetime.datetime,
646 ):
647 """Creates a log file for testing.
Michael Mortensen798ee192020-01-17 13:04:43 -0700648
Alex Klein1699fab2022-09-08 08:46:06 -0600649 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600650 goma_log_dir: Directory where the file will be created.
651 name: Log file 'base' name that is combined with the timestamp.
652 timestamp: Timestamp that is written to the file.
Alex Klein1699fab2022-09-08 08:46:06 -0600653 """
654 path = os.path.join(
655 goma_log_dir,
656 "%s.host.log.INFO.%s"
657 % (name, timestamp.strftime("%Y%m%d-%H%M%S.%f")),
658 )
659 osutils.WriteFile(
660 path,
661 timestamp.strftime("Goma log file created at: %Y/%m/%d %H:%M:%S"),
662 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700663
Alex Klein1699fab2022-09-08 08:46:06 -0600664 def _CreatePortageLogFile(
665 self,
666 log_path: Union[str, os.PathLike],
667 pkg_info: package_info.PackageInfo,
668 timestamp: datetime.datetime,
669 ):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700670 """Creates a log file to test for individual packages built by Portage.
Lizzy Presland7e23a612021-11-09 21:49:42 +0000671
Alex Klein1699fab2022-09-08 08:46:06 -0600672 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600673 log_path: The PORTAGE_LOGDIR path.
674 pkg_info: Package name used to name the log file.
675 timestamp: Timestamp used to name the file.
Alex Klein1699fab2022-09-08 08:46:06 -0600676 """
677 path = os.path.join(
678 log_path,
679 f"{pkg_info.category}:{pkg_info.pvr}:"
680 f'{timestamp.strftime("%Y%m%d-%H%M%S")}.log',
681 )
682 osutils.WriteFile(
683 path,
684 f"Test log file for package {pkg_info.category}/"
685 f"{pkg_info.package} written to {path}",
686 )
687 return path
Lizzy Presland7e23a612021-11-09 21:49:42 +0000688
Alex Klein1699fab2022-09-08 08:46:06 -0600689 def testValidateOnly(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700690 """Verify a validate-only call does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -0600691 patch = self.PatchObject(sysroot_service, "BuildPackages")
Alex Klein231d2da2019-07-22 16:44:45 -0600692
Alex Klein1699fab2022-09-08 08:46:06 -0600693 in_proto = self._InputProto(
694 build_target=self.build_target, sysroot_path=self.sysroot
695 )
696 sysroot_controller.InstallPackages(
697 in_proto, self._OutputProto(), self.validate_only_config
698 )
699 patch.assert_not_called()
Alex Klein231d2da2019-07-22 16:44:45 -0600700
Alex Klein1699fab2022-09-08 08:46:06 -0600701 def testMockCall(self):
702 """Sanity check that a mock call does not execute any logic."""
703 patch = self.PatchObject(sysroot_service, "BuildPackages")
704 request = self._InputProto()
705 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -0600706
Alex Klein1699fab2022-09-08 08:46:06 -0600707 rc = sysroot_controller.InstallPackages(
708 request, response, self.mock_call_config
709 )
Alex Klein076841b2019-08-29 15:19:39 -0600710
Alex Klein1699fab2022-09-08 08:46:06 -0600711 patch.assert_not_called()
712 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
Alex Klein076841b2019-08-29 15:19:39 -0600713
Alex Klein1699fab2022-09-08 08:46:06 -0600714 def testMockError(self):
715 """Sanity check that a mock error does not execute any logic."""
716 patch = self.PatchObject(sysroot_service, "BuildPackages")
717 request = self._InputProto()
718 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -0600719
Alex Klein1699fab2022-09-08 08:46:06 -0600720 rc = sysroot_controller.InstallPackages(
721 request, response, self.mock_error_config
722 )
Alex Klein076841b2019-08-29 15:19:39 -0600723
Alex Klein1699fab2022-09-08 08:46:06 -0600724 patch.assert_not_called()
725 self.assertEqual(
726 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
727 )
728 self.assertTrue(response.failed_package_data)
Alex Klein076841b2019-08-29 15:19:39 -0600729
Alex Klein1699fab2022-09-08 08:46:06 -0600730 def testArgumentValidationAllMissing(self):
731 """Test missing all arguments."""
732 out_proto = self._OutputProto()
733 in_proto = self._InputProto()
734 with self.assertRaises(cros_build_lib.DieSystemExit):
735 sysroot_controller.InstallPackages(
736 in_proto, out_proto, self.api_config
737 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600738
Alex Klein1699fab2022-09-08 08:46:06 -0600739 def testArgumentValidationNoSysroot(self):
740 """Test missing sysroot path."""
741 out_proto = self._OutputProto()
742 in_proto = self._InputProto(build_target=self.build_target)
743 with self.assertRaises(cros_build_lib.DieSystemExit):
744 sysroot_controller.InstallPackages(
745 in_proto, out_proto, self.api_config
746 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600747
Alex Klein1699fab2022-09-08 08:46:06 -0600748 def testArgumentValidationNoBuildTarget(self):
749 """Test missing build target name."""
750 out_proto = self._OutputProto()
751 in_proto = self._InputProto(sysroot_path=self.sysroot)
752 with self.assertRaises(cros_build_lib.DieSystemExit):
753 sysroot_controller.InstallPackages(
754 in_proto, out_proto, self.api_config
755 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600756
Alex Klein1699fab2022-09-08 08:46:06 -0600757 def testArgumentValidationInvalidSysroot(self):
758 """Test sysroot that hasn't had the toolchain installed."""
759 out_proto = self._OutputProto()
760 in_proto = self._InputProto(
761 build_target=self.build_target, sysroot_path=self.sysroot
762 )
763 self.PatchObject(
764 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=False
765 )
766 with self.assertRaises(cros_build_lib.DieSystemExit):
767 sysroot_controller.InstallPackages(
768 in_proto, out_proto, self.api_config
769 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600770
Alex Klein1699fab2022-09-08 08:46:06 -0600771 def testArgumentValidationInvalidPackage(self):
772 out_proto = self._OutputProto()
773 in_proto = self._InputProto(
774 build_target=self.build_target,
775 sysroot_path=self.sysroot,
776 packages=["package-1.0.0-r2"],
777 )
778 with self.assertRaises(cros_build_lib.DieSystemExit):
779 sysroot_controller.InstallPackages(
780 in_proto, out_proto, self.api_config
781 )
Alex Kleinca572ee2020-09-03 10:47:14 -0600782
Alex Klein1699fab2022-09-08 08:46:06 -0600783 def testSuccessOutputHandling(self):
784 """Test successful call output handling."""
785 # Prevent argument validation error.
786 self.PatchObject(
787 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
788 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600789
Alex Klein1699fab2022-09-08 08:46:06 -0600790 in_proto = self._InputProto(
791 build_target=self.build_target, sysroot_path=self.sysroot
792 )
793 out_proto = self._OutputProto()
794 self.PatchObject(sysroot_service, "BuildPackages")
Alex Kleind4e1e422019-03-18 16:00:41 -0600795
Alex Klein1699fab2022-09-08 08:46:06 -0600796 rc = sysroot_controller.InstallPackages(
797 in_proto, out_proto, self.api_config
798 )
799 self.assertFalse(rc)
800 self.assertFalse(out_proto.failed_package_data)
Alex Kleind4e1e422019-03-18 16:00:41 -0600801
Alex Klein1699fab2022-09-08 08:46:06 -0600802 def testSuccessPackageIndexes(self):
803 """Test successful call with package_indexes."""
804 # Prevent argument validation error.
805 self.PatchObject(
806 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
807 )
808 package_indexes = [
809 common_pb2.PackageIndexInfo(
810 snapshot_sha="SHA",
811 snapshot_number=5,
812 build_target=common_pb2.BuildTarget(name="board"),
813 location="LOCATION",
814 profile=common_pb2.Profile(name="profile"),
815 ),
816 common_pb2.PackageIndexInfo(
817 snapshot_sha="SHA2",
818 snapshot_number=4,
819 build_target=common_pb2.BuildTarget(name="board"),
820 location="LOCATION2",
821 profile=common_pb2.Profile(name="profile"),
822 ),
823 ]
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600824
Alex Klein1699fab2022-09-08 08:46:06 -0600825 in_proto = self._InputProto(
826 build_target=self.build_target,
827 sysroot_path=self.sysroot,
828 package_indexes=package_indexes,
829 )
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600830
Alex Klein1699fab2022-09-08 08:46:06 -0600831 out_proto = self._OutputProto()
832 rc_patch = self.PatchObject(sysroot_service, "BuildPackagesRunConfig")
833 self.PatchObject(sysroot_service, "BuildPackages")
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600834
Alex Klein1699fab2022-09-08 08:46:06 -0600835 rc = sysroot_controller.InstallPackages(
836 in_proto, out_proto, self.api_config
837 )
838 self.assertFalse(rc)
839 rc_patch.assert_called_with(
840 use_any_chrome=False,
841 usepkg=True,
842 install_debug_symbols=True,
843 packages=[],
844 package_indexes=[
Alex Klein6d718d62023-01-18 15:55:51 -0700845 controller_util.deserialize_package_index_info(x)
Alex Klein1699fab2022-09-08 08:46:06 -0600846 for x in package_indexes
847 ],
848 use_flags=[],
849 use_goma=False,
850 use_remoteexec=False,
851 incremental_build=False,
852 dryrun=False,
853 backtrack=sysroot_controller.DEFAULT_BACKTRACK,
854 )
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600855
Alex Klein1699fab2022-09-08 08:46:06 -0600856 def testSuccessWithGomaLogs(self):
857 """Test successful call with goma."""
858 self._CreateGomaLogFile(
859 self.goma_dir,
860 "compiler_proxy",
861 datetime.datetime(2018, 9, 21, 12, 0, 0),
862 )
863 self._CreateGomaLogFile(
864 self.goma_dir,
865 "compiler_proxy-subproc",
866 datetime.datetime(2018, 9, 21, 12, 1, 0),
867 )
868 self._CreateGomaLogFile(
869 self.goma_dir, "gomacc", datetime.datetime(2018, 9, 21, 12, 2, 0)
870 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700871
Alex Klein1699fab2022-09-08 08:46:06 -0600872 # Prevent argument validation error.
873 self.PatchObject(
874 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
875 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700876
Alex Klein1699fab2022-09-08 08:46:06 -0600877 in_proto = self._InputProto(
878 build_target=self.build_target,
879 sysroot_path=self.sysroot,
880 goma_dir=self.goma_dir,
881 goma_log_dir=self.goma_out_dir,
882 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700883
Alex Klein1699fab2022-09-08 08:46:06 -0600884 out_proto = self._OutputProto()
885 self.PatchObject(sysroot_service, "BuildPackages")
Michael Mortensen798ee192020-01-17 13:04:43 -0700886
Alex Klein1699fab2022-09-08 08:46:06 -0600887 rc = sysroot_controller.InstallPackages(
888 in_proto, out_proto, self.api_config
889 )
890 self.assertFalse(rc)
891 self.assertFalse(out_proto.failed_package_data)
Alex Kleinab87ceb2023-01-24 12:00:51 -0700892
893 expected = [
894 "compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz",
895 "compiler_proxy.host.log.INFO.20180921-120000.000000.gz",
896 "gomacc.host.log.INFO.20180921-120200.000000.tar.gz",
897 ]
898 self.assertCountEqual(out_proto.goma_artifacts.log_files, expected)
Michael Mortensen798ee192020-01-17 13:04:43 -0700899
Alex Klein1699fab2022-09-08 08:46:06 -0600900 def testSuccessWithGomaLogsAndStatsCounterzFiles(self):
901 """Test successful call with goma including stats and counterz files."""
902 self._CreateGomaLogFile(
903 self.goma_dir,
904 "compiler_proxy",
905 datetime.datetime(2018, 9, 21, 12, 0, 0),
906 )
907 self._CreateGomaLogFile(
908 self.goma_dir,
909 "compiler_proxy-subproc",
910 datetime.datetime(2018, 9, 21, 12, 1, 0),
911 )
912 self._CreateGomaLogFile(
913 self.goma_dir, "gomacc", datetime.datetime(2018, 9, 21, 12, 2, 0)
914 )
915 # Create stats and counterz files.
916 osutils.WriteFile(
917 os.path.join(self.goma_dir, "stats.binaryproto"),
918 "File: stats.binaryproto",
919 )
920 osutils.WriteFile(
921 os.path.join(self.goma_dir, "counterz.binaryproto"),
922 "File: counterz.binaryproto",
923 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700924
Alex Klein1699fab2022-09-08 08:46:06 -0600925 # Prevent argument validation error.
926 self.PatchObject(
927 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
928 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700929
Alex Klein1699fab2022-09-08 08:46:06 -0600930 in_proto = self._InputProto(
931 build_target=self.build_target,
932 sysroot_path=self.sysroot,
933 goma_dir=self.goma_dir,
934 goma_log_dir=self.goma_out_dir,
935 goma_stats_file="stats.binaryproto",
936 goma_counterz_file="counterz.binaryproto",
937 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700938
Alex Klein1699fab2022-09-08 08:46:06 -0600939 out_proto = self._OutputProto()
940 self.PatchObject(sysroot_service, "BuildPackages")
Michael Mortensen798ee192020-01-17 13:04:43 -0700941
Alex Klein1699fab2022-09-08 08:46:06 -0600942 rc = sysroot_controller.InstallPackages(
943 in_proto, out_proto, self.api_config
944 )
945 self.assertFalse(rc)
946 self.assertFalse(out_proto.failed_package_data)
Alex Kleinab87ceb2023-01-24 12:00:51 -0700947 expected_logs = [
948 "compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz",
949 "compiler_proxy.host.log.INFO.20180921-120000.000000.gz",
950 "gomacc.host.log.INFO.20180921-120200.000000.tar.gz",
951 ]
952 self.assertCountEqual(out_proto.goma_artifacts.log_files, expected_logs)
953
Alex Klein1699fab2022-09-08 08:46:06 -0600954 # 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)
Alex Kleinab87ceb2023-01-24 12:00:51 -0700957 expected_output = [
958 "stats.binaryproto",
959 "counterz.binaryproto",
960 "compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz",
961 "compiler_proxy.host.log.INFO.20180921-120000.000000.gz",
962 "gomacc.host.log.INFO.20180921-120200.000000.tar.gz",
963 ]
964 self.assertCountEqual(output_files, expected_output)
Alex Klein1699fab2022-09-08 08:46:06 -0600965 self.assertEqual(
966 out_proto.goma_artifacts.counterz_file, "counterz.binaryproto"
967 )
968 self.assertEqual(
969 out_proto.goma_artifacts.stats_file, "stats.binaryproto"
970 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700971
Alex Klein1699fab2022-09-08 08:46:06 -0600972 def testFailureMissingGomaStatsCounterzFiles(self):
973 """Test successful call with goma including stats and counterz files."""
974 self._CreateGomaLogFile(
975 self.goma_dir,
976 "compiler_proxy",
977 datetime.datetime(2018, 9, 21, 12, 0, 0),
978 )
979 self._CreateGomaLogFile(
980 self.goma_dir,
981 "compiler_proxy-subproc",
982 datetime.datetime(2018, 9, 21, 12, 1, 0),
983 )
984 self._CreateGomaLogFile(
985 self.goma_dir, "gomacc", datetime.datetime(2018, 9, 21, 12, 2, 0)
986 )
Alex Kleinab87ceb2023-01-24 12:00:51 -0700987 # Note that stats and counterz files are not created, but are specified
988 # in the proto below.
Michael Mortensen798ee192020-01-17 13:04:43 -0700989
Alex Klein1699fab2022-09-08 08:46:06 -0600990 # Prevent argument validation error.
991 self.PatchObject(
992 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
993 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700994
Alex Klein1699fab2022-09-08 08:46:06 -0600995 in_proto = self._InputProto(
996 build_target=self.build_target,
997 sysroot_path=self.sysroot,
998 goma_dir=self.goma_dir,
999 goma_log_dir=self.goma_out_dir,
1000 goma_stats_file="stats.binaryproto",
1001 goma_counterz_file="counterz.binaryproto",
1002 )
Michael Mortensen798ee192020-01-17 13:04:43 -07001003
Alex Klein1699fab2022-09-08 08:46:06 -06001004 out_proto = self._OutputProto()
1005 self.PatchObject(sysroot_service, "BuildPackages")
Michael Mortensen798ee192020-01-17 13:04:43 -07001006
Alex Klein1699fab2022-09-08 08:46:06 -06001007 rc = sysroot_controller.InstallPackages(
1008 in_proto, out_proto, self.api_config
1009 )
1010 self.assertFalse(rc)
1011 self.assertFalse(out_proto.failed_package_data)
Alex Kleinab87ceb2023-01-24 12:00:51 -07001012 expected_logs = [
1013 "compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz",
1014 "compiler_proxy.host.log.INFO.20180921-120000.000000.gz",
1015 "gomacc.host.log.INFO.20180921-120200.000000.tar.gz",
1016 ]
1017 self.assertCountEqual(out_proto.goma_artifacts.log_files, expected_logs)
Alex Klein1699fab2022-09-08 08:46:06 -06001018 self.assertFalse(out_proto.goma_artifacts.counterz_file)
1019 self.assertFalse(out_proto.goma_artifacts.stats_file)
Michael Mortensen798ee192020-01-17 13:04:43 -07001020
Alex Klein1699fab2022-09-08 08:46:06 -06001021 def testFailureOutputHandling(self):
1022 """Test failed package handling."""
1023 # Prevent argument validation error.
1024 self.PatchObject(
1025 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
1026 )
Alex Kleind4e1e422019-03-18 16:00:41 -06001027
Alex Klein1699fab2022-09-08 08:46:06 -06001028 in_proto = self._InputProto(
1029 build_target=self.build_target, sysroot_path=self.sysroot
1030 )
1031 out_proto = self._OutputProto()
Alex Kleind4e1e422019-03-18 16:00:41 -06001032
Alex Klein1699fab2022-09-08 08:46:06 -06001033 # Failed package info and expected list for verification.
1034 err_pkgs = ["cat/pkg-1.0-r3", "cat2/pkg2-1.0-r1"]
1035 err_cpvs = [package_info.parse(cpv) for cpv in err_pkgs]
1036 expected = [("cat", "pkg"), ("cat2", "pkg2")]
Alex Kleind4e1e422019-03-18 16:00:41 -06001037
Alex Klein1699fab2022-09-08 08:46:06 -06001038 new_logs = {}
1039 for i, pkg in enumerate(err_pkgs):
1040 self._CreatePortageLogFile(
1041 self.portage_dir,
1042 err_cpvs[i],
1043 datetime.datetime(2021, 6, 9, 13, 37, 0),
1044 )
1045 new_logs[pkg] = self._CreatePortageLogFile(
1046 self.portage_dir,
1047 err_cpvs[i],
1048 datetime.datetime(2021, 6, 9, 16, 20, 0),
1049 )
1050 # Force error to be raised with the packages.
1051 error = sysroot_lib.PackageInstallError(
1052 "Error", cros_build_lib.CompletedProcess(), packages=err_cpvs
1053 )
1054 self.PatchObject(sysroot_service, "BuildPackages", side_effect=error)
Alex Kleind4e1e422019-03-18 16:00:41 -06001055
Alex Klein1699fab2022-09-08 08:46:06 -06001056 rc = sysroot_controller.InstallPackages(
1057 in_proto, out_proto, self.api_config
1058 )
1059 # This needs to return 2 to indicate the available error response.
1060 self.assertEqual(
1061 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
1062 )
1063 for data in out_proto.failed_package_data:
1064 package = controller_util.deserialize_package_info(data.name)
1065 cat_pkg = (data.name.category, data.name.package_name)
1066 self.assertIn(cat_pkg, expected)
1067 self.assertEqual(data.log_path.path, new_logs[package.cpvr])
Lizzy Presland7e23a612021-11-09 21:49:42 +00001068
Alex Klein1699fab2022-09-08 08:46:06 -06001069 def testNoPackageFailureOutputHandling(self):
1070 """Test failure handling without packages to report."""
1071 # Prevent argument validation error.
1072 self.PatchObject(
1073 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
1074 )
Alex Klein2557b4f2019-07-11 14:34:00 -06001075
Alex Klein1699fab2022-09-08 08:46:06 -06001076 in_proto = self._InputProto(
1077 build_target=self.build_target, sysroot_path=self.sysroot
1078 )
1079 out_proto = self._OutputProto()
Alex Klein2557b4f2019-07-11 14:34:00 -06001080
Alex Klein1699fab2022-09-08 08:46:06 -06001081 # Force error to be raised with no packages.
1082 error = sysroot_lib.PackageInstallError(
1083 "Error", cros_build_lib.CompletedProcess(), packages=[]
1084 )
1085 self.PatchObject(sysroot_service, "BuildPackages", side_effect=error)
Alex Klein2557b4f2019-07-11 14:34:00 -06001086
Alex Klein1699fab2022-09-08 08:46:06 -06001087 rc = sysroot_controller.InstallPackages(
1088 in_proto, out_proto, self.api_config
1089 )
1090 # All we really care about is it's not 0 or 2 (response available), so
1091 # test for that rather than a specific return code.
1092 self.assertTrue(rc)
1093 self.assertNotEqual(
1094 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
1095 )