blob: 022587b6a18745cb7f023b6cecb2dcf86cb72b97 [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):
56 """Sanity check that a validate only call does not execute any logic."""
57 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):
75 """Sanity check that a mock call does not execute any logic."""
76 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):
86 """Sanity check that a mock error does not execute any logic."""
87 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
198 _artifact_funcs = {
199 common_pb2.ArtifactsByService.Sysroot.ArtifactType.SIMPLE_CHROME_SYSROOT: sysroot_service.CreateSimpleChromeSysroot,
200 common_pb2.ArtifactsByService.Sysroot.ArtifactType.CHROME_EBUILD_ENV: sysroot_service.CreateChromeEbuildEnv,
201 common_pb2.ArtifactsByService.Sysroot.ArtifactType.BREAKPAD_DEBUG_SYMBOLS: sysroot_service.BundleBreakpadSymbols,
202 common_pb2.ArtifactsByService.Sysroot.ArtifactType.DEBUG_SYMBOLS: sysroot_service.BundleDebugSymbols,
203 common_pb2.ArtifactsByService.Sysroot.ArtifactType.FUZZER_SYSROOT: sysroot_service.CreateFuzzerSysroot,
204 }
205
206 def setUp(self):
207 self._mocks = {}
208 for artifact, func in self._artifact_funcs.items():
209 self._mocks[artifact] = self.PatchObject(
210 sysroot_service, func.__name__
211 )
212
213 def _InputProto(
214 self,
215 artifact_types=_artifact_funcs.keys(),
216 ):
217 """Helper to build an input proto instance."""
218 return common_pb2.ArtifactsByService.Sysroot(
219 output_artifacts=[
220 common_pb2.ArtifactsByService.Sysroot.ArtifactInfo(
221 artifact_types=artifact_types
222 )
223 ]
224 )
225
226 def testNoArtifacts(self):
227 """Test GetArtifacts with no artifact types."""
228 in_proto = self._InputProto(artifact_types=[])
229 sysroot_controller.GetArtifacts(
230 in_proto, None, None, "build_target", ""
231 )
232
233 for _, patch in self._mocks.items():
234 patch.assert_not_called()
235
236 def testArtifactsSuccess(self):
237 """Test GetArtifacts with all artifact types."""
238 sysroot_controller.GetArtifacts(
239 self._InputProto(), None, None, "build_target", ""
240 )
241
242 for _, patch in self._mocks.items():
243 patch.assert_called_once()
244
245 def testArtifactsException(self):
246 """Test GetArtifacts with all artifact types when one type throws an exception."""
247
248 self._mocks[
249 common_pb2.ArtifactsByService.Sysroot.ArtifactType.FUZZER_SYSROOT
250 ].side_effect = Exception("foo bar")
251 generated = sysroot_controller.GetArtifacts(
252 self._InputProto(), None, None, "build_target", ""
253 )
254
255 for _, patch in self._mocks.items():
256 patch.assert_called_once()
257
258 found_artifact = False
259 for data in generated:
260 artifact_type = (
261 common_pb2.ArtifactsByService.Sysroot.ArtifactType.Name(
262 data["type"]
263 )
264 )
265 if artifact_type == "FUZZER_SYSROOT":
266 found_artifact = True
267 self.assertTrue(data["failed"])
268 self.assertEqual(data["failure_reason"], "foo bar")
269 self.assertTrue(found_artifact)
270
271
Alex Klein1699fab2022-09-08 08:46:06 -0600272class GenerateArchiveTest(
273 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin
274):
275 """GenerateArchive function tests."""
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700276
Alex Klein1699fab2022-09-08 08:46:06 -0600277 def setUp(self):
278 self.chroot_path = "/path/to/chroot"
279 self.board = "board"
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700280
Alex Klein1699fab2022-09-08 08:46:06 -0600281 def _InputProto(self, build_target=None, chroot_path=None, pkg_list=None):
282 """Helper to build and input proto instance."""
283 # pkg_list will be a list of category/package strings such as
284 # ['virtual/target-fuzzers'].
285 if pkg_list:
286 package_list = []
287 for pkg in pkg_list:
288 pkg_string_parts = pkg.split("/")
289 package_info_msg = common_pb2.PackageInfo(
290 category=pkg_string_parts[0],
291 package_name=pkg_string_parts[1],
292 )
293 package_list.append(package_info_msg)
294 else:
295 package_list = []
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700296
Alex Klein1699fab2022-09-08 08:46:06 -0600297 return sysroot_pb2.SysrootGenerateArchiveRequest(
298 build_target={"name": build_target},
299 chroot={"path": chroot_path},
300 packages=package_list,
301 )
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700302
Alex Klein1699fab2022-09-08 08:46:06 -0600303 def _OutputProto(self):
304 """Helper to build output proto instance."""
305 return sysroot_pb2.SysrootGenerateArchiveResponse()
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700306
Alex Klein1699fab2022-09-08 08:46:06 -0600307 def testValidateOnly(self):
308 """Sanity check that a validate only call does not execute any logic."""
309 patch = self.PatchObject(sysroot_service, "GenerateArchive")
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700310
Alex Klein1699fab2022-09-08 08:46:06 -0600311 in_proto = self._InputProto(
312 build_target=self.board,
313 chroot_path=self.chroot_path,
314 pkg_list=["virtual/target-fuzzers"],
315 )
316 sysroot_controller.GenerateArchive(
317 in_proto, self._OutputProto(), self.validate_only_config
318 )
319 patch.assert_not_called()
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700320
Alex Klein1699fab2022-09-08 08:46:06 -0600321 def testMockCall(self):
322 """Sanity check that a mock call does not execute any logic."""
323 patch = self.PatchObject(sysroot_service, "GenerateArchive")
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700324
Alex Klein1699fab2022-09-08 08:46:06 -0600325 in_proto = self._InputProto(
326 build_target=self.board,
327 chroot_path=self.chroot_path,
328 pkg_list=["virtual/target-fuzzers"],
329 )
330 sysroot_controller.GenerateArchive(
331 in_proto, self._OutputProto(), self.mock_call_config
332 )
333 patch.assert_not_called()
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700334
Alex Klein1699fab2022-09-08 08:46:06 -0600335 def testArgumentValidation(self):
336 """Test the input argument validation."""
337 # Error when no build target provided.
338 in_proto = self._InputProto()
339 out_proto = self._OutputProto()
340 with self.assertRaises(cros_build_lib.DieSystemExit):
341 sysroot_controller.GenerateArchive(
342 in_proto, out_proto, self.api_config
343 )
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700344
Alex Klein1699fab2022-09-08 08:46:06 -0600345 # Error when packages is not specified.
346 in_proto = self._InputProto(
347 build_target="board", chroot_path=self.chroot_path
348 )
349 with self.assertRaises(cros_build_lib.DieSystemExit):
350 sysroot_controller.GenerateArchive(
351 in_proto, out_proto, self.api_config
352 )
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700353
Alex Klein1699fab2022-09-08 08:46:06 -0600354 # Valid when board, chroot path, and package are specified.
355 patch = self.PatchObject(
356 sysroot_service,
357 "GenerateArchive",
358 return_value="/path/to/sysroot/tar.bz",
359 )
360 in_proto = self._InputProto(
361 build_target="board",
362 chroot_path=self.chroot_path,
363 pkg_list=["virtual/target-fuzzers"],
364 )
365 out_proto = self._OutputProto()
366 sysroot_controller.GenerateArchive(in_proto, out_proto, self.api_config)
367 patch.assert_called_once()
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700368
369
Alex Klein1699fab2022-09-08 08:46:06 -0600370class InstallToolchainTest(
371 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin
372):
373 """Install toolchain function tests."""
Alex Kleinda35fcf2019-03-07 16:01:15 -0700374
Alex Klein1699fab2022-09-08 08:46:06 -0600375 def setUp(self):
376 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=True)
377 # Avoid running the portageq command.
378 self.PatchObject(sysroot_controller, "_LogBinhost")
379 self.board = "board"
380 self.sysroot = os.path.join(self.tempdir, "board")
381 self.invalid_sysroot = os.path.join(self.tempdir, "invalid", "sysroot")
382 osutils.SafeMakedirs(self.sysroot)
383 # Set up portage log directory.
384 self.target_sysroot = sysroot_lib.Sysroot(self.sysroot)
385 self.portage_dir = os.path.join(self.tempdir, "portage_logdir")
386 self.PatchObject(
387 sysroot_lib.Sysroot, "portage_logdir", new=self.portage_dir
388 )
389 osutils.SafeMakedirs(self.portage_dir)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700390
Alex Klein1699fab2022-09-08 08:46:06 -0600391 def _InputProto(
392 self, build_target=None, sysroot_path=None, compile_source=False
393 ):
394 """Helper to build an input proto instance."""
395 proto = sysroot_pb2.InstallToolchainRequest()
396 if build_target:
397 proto.sysroot.build_target.name = build_target
398 if sysroot_path:
399 proto.sysroot.path = sysroot_path
400 if compile_source:
401 proto.flags.compile_source = compile_source
Alex Kleinda35fcf2019-03-07 16:01:15 -0700402
Alex Klein1699fab2022-09-08 08:46:06 -0600403 return proto
Alex Kleinda35fcf2019-03-07 16:01:15 -0700404
Alex Klein1699fab2022-09-08 08:46:06 -0600405 def _OutputProto(self):
406 """Helper to build output proto instance."""
407 return sysroot_pb2.InstallToolchainResponse()
Alex Kleinda35fcf2019-03-07 16:01:15 -0700408
Alex Klein1699fab2022-09-08 08:46:06 -0600409 def _CreatePortageLogFile(
410 self,
411 log_path: Union[str, os.PathLike],
412 pkg_info: package_info.PackageInfo,
413 timestamp: datetime.datetime,
414 ):
415 """Creates a log file for testing for individual packages built by Portage.
Lizzy Presland7e23a612021-11-09 21:49:42 +0000416
Alex Klein1699fab2022-09-08 08:46:06 -0600417 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600418 log_path: The PORTAGE_LOGDIR path.
419 pkg_info: Package name used to name the log file.
420 timestamp: Timestamp used to name the file.
Alex Klein1699fab2022-09-08 08:46:06 -0600421 """
422 path = os.path.join(
423 log_path,
424 f"{pkg_info.category}:{pkg_info.pvr}:"
425 f'{timestamp.strftime("%Y%m%d-%H%M%S")}.log',
426 )
427 osutils.WriteFile(
428 path,
429 f"Test log file for package {pkg_info.category}/"
430 f"{pkg_info.package} written to {path}",
431 )
432 return path
Lizzy Presland7e23a612021-11-09 21:49:42 +0000433
Alex Klein1699fab2022-09-08 08:46:06 -0600434 def testValidateOnly(self):
435 """Sanity check that a validate only call does not execute any logic."""
436 patch = self.PatchObject(sysroot_service, "InstallToolchain")
Alex Klein231d2da2019-07-22 16:44:45 -0600437
Alex Klein1699fab2022-09-08 08:46:06 -0600438 in_proto = self._InputProto(
439 build_target=self.board, sysroot_path=self.sysroot
440 )
441 sysroot_controller.InstallToolchain(
442 in_proto, self._OutputProto(), self.validate_only_config
443 )
444 patch.assert_not_called()
Alex Klein231d2da2019-07-22 16:44:45 -0600445
Alex Klein1699fab2022-09-08 08:46:06 -0600446 def testMockCall(self):
447 """Sanity check that a mock call does not execute any logic."""
448 patch = self.PatchObject(sysroot_service, "InstallToolchain")
449 request = self._InputProto()
450 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -0600451
Alex Klein1699fab2022-09-08 08:46:06 -0600452 rc = sysroot_controller.InstallToolchain(
453 request, response, self.mock_call_config
454 )
Alex Klein076841b2019-08-29 15:19:39 -0600455
Alex Klein1699fab2022-09-08 08:46:06 -0600456 patch.assert_not_called()
457 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
Alex Klein076841b2019-08-29 15:19:39 -0600458
Alex Klein1699fab2022-09-08 08:46:06 -0600459 def testMockError(self):
460 """Sanity check that a mock error does not execute any logic."""
461 patch = self.PatchObject(sysroot_service, "InstallToolchain")
462 request = self._InputProto()
463 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -0600464
Alex Klein1699fab2022-09-08 08:46:06 -0600465 rc = sysroot_controller.InstallToolchain(
466 request, response, self.mock_error_config
467 )
Alex Klein076841b2019-08-29 15:19:39 -0600468
Alex Klein1699fab2022-09-08 08:46:06 -0600469 patch.assert_not_called()
470 self.assertEqual(
471 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
472 )
473 self.assertTrue(response.failed_package_data)
Alex Klein076841b2019-08-29 15:19:39 -0600474
Alex Klein1699fab2022-09-08 08:46:06 -0600475 def testArgumentValidation(self):
476 """Test the argument validation."""
477 # Test errors on missing inputs.
478 out_proto = self._OutputProto()
479 # Both missing.
480 in_proto = self._InputProto()
481 with self.assertRaises(cros_build_lib.DieSystemExit):
482 sysroot_controller.InstallToolchain(
483 in_proto, out_proto, self.api_config
484 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700485
Alex Klein1699fab2022-09-08 08:46:06 -0600486 # Sysroot path missing.
487 in_proto = self._InputProto(build_target=self.board)
488 with self.assertRaises(cros_build_lib.DieSystemExit):
489 sysroot_controller.InstallToolchain(
490 in_proto, out_proto, self.api_config
491 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700492
Alex Klein1699fab2022-09-08 08:46:06 -0600493 # Build target name missing.
494 in_proto = self._InputProto(sysroot_path=self.sysroot)
495 with self.assertRaises(cros_build_lib.DieSystemExit):
496 sysroot_controller.InstallToolchain(
497 in_proto, out_proto, self.api_config
498 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700499
Alex Klein1699fab2022-09-08 08:46:06 -0600500 # Both provided, but invalid sysroot path.
501 in_proto = self._InputProto(
502 build_target=self.board, sysroot_path=self.invalid_sysroot
503 )
504 with self.assertRaises(cros_build_lib.DieSystemExit):
505 sysroot_controller.InstallToolchain(
506 in_proto, out_proto, self.api_config
507 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700508
Alex Klein1699fab2022-09-08 08:46:06 -0600509 def testSuccessOutputHandling(self):
510 """Test the output is processed and recorded correctly."""
511 self.PatchObject(sysroot_service, "InstallToolchain")
512 out_proto = self._OutputProto()
513 in_proto = self._InputProto(
514 build_target=self.board, sysroot_path=self.sysroot
515 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700516
Alex Klein1699fab2022-09-08 08:46:06 -0600517 rc = sysroot_controller.InstallToolchain(
518 in_proto, out_proto, self.api_config
519 )
520 self.assertFalse(rc)
521 self.assertFalse(out_proto.failed_package_data)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700522
Alex Klein1699fab2022-09-08 08:46:06 -0600523 def testErrorOutputHandling(self):
524 """Test the error output is processed and recorded correctly."""
525 out_proto = self._OutputProto()
526 in_proto = self._InputProto(
527 build_target=self.board, sysroot_path=self.sysroot
528 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700529
Alex Klein1699fab2022-09-08 08:46:06 -0600530 err_pkgs = ["cat/pkg-1.0-r1", "cat2/pkg2-1.0-r1"]
531 err_cpvs = [package_info.parse(pkg) for pkg in err_pkgs]
532 expected = [("cat", "pkg"), ("cat2", "pkg2")]
Lizzy Presland7e23a612021-11-09 21:49:42 +0000533
Alex Klein1699fab2022-09-08 08:46:06 -0600534 new_logs = {}
535 for i, pkg in enumerate(err_pkgs):
536 self._CreatePortageLogFile(
537 self.portage_dir,
538 err_cpvs[i],
539 datetime.datetime(2021, 6, 9, 13, 37, 0),
540 )
541 new_logs[pkg] = self._CreatePortageLogFile(
542 self.portage_dir,
543 err_cpvs[i],
544 datetime.datetime(2021, 6, 9, 16, 20, 0),
545 )
Lizzy Presland7e23a612021-11-09 21:49:42 +0000546
Alex Klein1699fab2022-09-08 08:46:06 -0600547 err = sysroot_lib.ToolchainInstallError(
548 "Error", cros_build_lib.CompletedProcess(), tc_info=err_cpvs
549 )
550 self.PatchObject(sysroot_service, "InstallToolchain", side_effect=err)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700551
Alex Klein1699fab2022-09-08 08:46:06 -0600552 rc = sysroot_controller.InstallToolchain(
553 in_proto, out_proto, self.api_config
554 )
555 self.assertEqual(
556 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
557 )
558 self.assertTrue(out_proto.failed_package_data)
559 # This needs to return 2 to indicate the available error response.
560 self.assertEqual(
561 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
562 )
563 for data in out_proto.failed_package_data:
564 package = controller_util.deserialize_package_info(data.name)
565 cat_pkg = (data.name.category, data.name.package_name)
566 self.assertIn(cat_pkg, expected)
567 self.assertEqual(data.log_path.path, new_logs[package.cpvr])
Lizzy Presland7e23a612021-11-09 21:49:42 +0000568
Alex Kleind4e1e422019-03-18 16:00:41 -0600569
Alex Klein1699fab2022-09-08 08:46:06 -0600570class InstallPackagesTest(
571 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin
572):
573 """InstallPackages tests."""
Alex Kleind4e1e422019-03-18 16:00:41 -0600574
Alex Klein1699fab2022-09-08 08:46:06 -0600575 def setUp(self):
576 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=True)
577 # Avoid running the portageq command.
578 self.PatchObject(sysroot_controller, "_LogBinhost")
579 self.build_target = "board"
580 self.sysroot = os.path.join(self.tempdir, "build", "board")
581 osutils.SafeMakedirs(self.sysroot)
582 # Set up portage log directory.
583 self.target_sysroot = sysroot_lib.Sysroot(self.sysroot)
584 self.portage_dir = os.path.join(self.tempdir, "portage_logdir")
585 self.PatchObject(
586 sysroot_lib.Sysroot, "portage_logdir", new=self.portage_dir
587 )
588 osutils.SafeMakedirs(self.portage_dir)
589 # Set up goma directories.
590 self.goma_dir = os.path.join(self.tempdir, "goma_dir")
591 osutils.SafeMakedirs(self.goma_dir)
592 self.goma_out_dir = os.path.join(self.tempdir, "goma_out_dir")
593 osutils.SafeMakedirs(self.goma_out_dir)
594 os.environ["GLOG_log_dir"] = self.goma_dir
Alex Kleind4e1e422019-03-18 16:00:41 -0600595
Alex Klein1699fab2022-09-08 08:46:06 -0600596 def _InputProto(
597 self,
598 build_target=None,
599 sysroot_path=None,
600 build_source=False,
601 goma_dir=None,
602 goma_log_dir=None,
603 goma_stats_file=None,
604 goma_counterz_file=None,
605 package_indexes=None,
606 packages=None,
607 ):
608 """Helper to build an input proto instance."""
609 instance = sysroot_pb2.InstallPackagesRequest()
Alex Kleind4e1e422019-03-18 16:00:41 -0600610
Alex Klein1699fab2022-09-08 08:46:06 -0600611 if build_target:
612 instance.sysroot.build_target.name = build_target
613 if sysroot_path:
614 instance.sysroot.path = sysroot_path
615 if build_source:
616 instance.flags.build_source = build_source
617 if goma_dir:
618 instance.goma_config.goma_dir = goma_dir
619 if goma_log_dir:
620 instance.goma_config.log_dir.dir = goma_log_dir
621 if goma_stats_file:
622 instance.goma_config.stats_file = goma_stats_file
623 if goma_counterz_file:
624 instance.goma_config.counterz_file = goma_counterz_file
625 if package_indexes:
626 instance.package_indexes.extend(package_indexes)
627 if packages:
628 for pkg in packages:
629 pkg_info = package_info.parse(pkg)
630 pkg_info_msg = instance.packages.add()
631 controller_util.serialize_package_info(pkg_info, pkg_info_msg)
632 return instance
Alex Kleind4e1e422019-03-18 16:00:41 -0600633
Alex Klein1699fab2022-09-08 08:46:06 -0600634 def _OutputProto(self):
635 """Helper to build an empty output proto instance."""
636 return sysroot_pb2.InstallPackagesResponse()
Alex Kleind4e1e422019-03-18 16:00:41 -0600637
Alex Klein1699fab2022-09-08 08:46:06 -0600638 def _CreateGomaLogFile(
639 self,
640 goma_log_dir: Union[str, os.PathLike],
641 name: str,
642 timestamp: datetime.datetime,
643 ):
644 """Creates a log file for testing.
Michael Mortensen798ee192020-01-17 13:04:43 -0700645
Alex Klein1699fab2022-09-08 08:46:06 -0600646 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600647 goma_log_dir: Directory where the file will be created.
648 name: Log file 'base' name that is combined with the timestamp.
649 timestamp: Timestamp that is written to the file.
Alex Klein1699fab2022-09-08 08:46:06 -0600650 """
651 path = os.path.join(
652 goma_log_dir,
653 "%s.host.log.INFO.%s"
654 % (name, timestamp.strftime("%Y%m%d-%H%M%S.%f")),
655 )
656 osutils.WriteFile(
657 path,
658 timestamp.strftime("Goma log file created at: %Y/%m/%d %H:%M:%S"),
659 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700660
Alex Klein1699fab2022-09-08 08:46:06 -0600661 def _CreatePortageLogFile(
662 self,
663 log_path: Union[str, os.PathLike],
664 pkg_info: package_info.PackageInfo,
665 timestamp: datetime.datetime,
666 ):
667 """Creates a log file for testing for individual packages built by Portage.
Lizzy Presland7e23a612021-11-09 21:49:42 +0000668
Alex Klein1699fab2022-09-08 08:46:06 -0600669 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600670 log_path: The PORTAGE_LOGDIR path.
671 pkg_info: Package name used to name the log file.
672 timestamp: Timestamp used to name the file.
Alex Klein1699fab2022-09-08 08:46:06 -0600673 """
674 path = os.path.join(
675 log_path,
676 f"{pkg_info.category}:{pkg_info.pvr}:"
677 f'{timestamp.strftime("%Y%m%d-%H%M%S")}.log',
678 )
679 osutils.WriteFile(
680 path,
681 f"Test log file for package {pkg_info.category}/"
682 f"{pkg_info.package} written to {path}",
683 )
684 return path
Lizzy Presland7e23a612021-11-09 21:49:42 +0000685
Alex Klein1699fab2022-09-08 08:46:06 -0600686 def testValidateOnly(self):
687 """Sanity check that a validate only call does not execute any logic."""
688 patch = self.PatchObject(sysroot_service, "BuildPackages")
Alex Klein231d2da2019-07-22 16:44:45 -0600689
Alex Klein1699fab2022-09-08 08:46:06 -0600690 in_proto = self._InputProto(
691 build_target=self.build_target, sysroot_path=self.sysroot
692 )
693 sysroot_controller.InstallPackages(
694 in_proto, self._OutputProto(), self.validate_only_config
695 )
696 patch.assert_not_called()
Alex Klein231d2da2019-07-22 16:44:45 -0600697
Alex Klein1699fab2022-09-08 08:46:06 -0600698 def testMockCall(self):
699 """Sanity check that a mock call does not execute any logic."""
700 patch = self.PatchObject(sysroot_service, "BuildPackages")
701 request = self._InputProto()
702 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -0600703
Alex Klein1699fab2022-09-08 08:46:06 -0600704 rc = sysroot_controller.InstallPackages(
705 request, response, self.mock_call_config
706 )
Alex Klein076841b2019-08-29 15:19:39 -0600707
Alex Klein1699fab2022-09-08 08:46:06 -0600708 patch.assert_not_called()
709 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
Alex Klein076841b2019-08-29 15:19:39 -0600710
Alex Klein1699fab2022-09-08 08:46:06 -0600711 def testMockError(self):
712 """Sanity check that a mock error does not execute any logic."""
713 patch = self.PatchObject(sysroot_service, "BuildPackages")
714 request = self._InputProto()
715 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -0600716
Alex Klein1699fab2022-09-08 08:46:06 -0600717 rc = sysroot_controller.InstallPackages(
718 request, response, self.mock_error_config
719 )
Alex Klein076841b2019-08-29 15:19:39 -0600720
Alex Klein1699fab2022-09-08 08:46:06 -0600721 patch.assert_not_called()
722 self.assertEqual(
723 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
724 )
725 self.assertTrue(response.failed_package_data)
Alex Klein076841b2019-08-29 15:19:39 -0600726
Alex Klein1699fab2022-09-08 08:46:06 -0600727 def testArgumentValidationAllMissing(self):
728 """Test missing all arguments."""
729 out_proto = self._OutputProto()
730 in_proto = self._InputProto()
731 with self.assertRaises(cros_build_lib.DieSystemExit):
732 sysroot_controller.InstallPackages(
733 in_proto, out_proto, self.api_config
734 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600735
Alex Klein1699fab2022-09-08 08:46:06 -0600736 def testArgumentValidationNoSysroot(self):
737 """Test missing sysroot path."""
738 out_proto = self._OutputProto()
739 in_proto = self._InputProto(build_target=self.build_target)
740 with self.assertRaises(cros_build_lib.DieSystemExit):
741 sysroot_controller.InstallPackages(
742 in_proto, out_proto, self.api_config
743 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600744
Alex Klein1699fab2022-09-08 08:46:06 -0600745 def testArgumentValidationNoBuildTarget(self):
746 """Test missing build target name."""
747 out_proto = self._OutputProto()
748 in_proto = self._InputProto(sysroot_path=self.sysroot)
749 with self.assertRaises(cros_build_lib.DieSystemExit):
750 sysroot_controller.InstallPackages(
751 in_proto, out_proto, self.api_config
752 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600753
Alex Klein1699fab2022-09-08 08:46:06 -0600754 def testArgumentValidationInvalidSysroot(self):
755 """Test sysroot that hasn't had the toolchain installed."""
756 out_proto = self._OutputProto()
757 in_proto = self._InputProto(
758 build_target=self.build_target, sysroot_path=self.sysroot
759 )
760 self.PatchObject(
761 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=False
762 )
763 with self.assertRaises(cros_build_lib.DieSystemExit):
764 sysroot_controller.InstallPackages(
765 in_proto, out_proto, self.api_config
766 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600767
Alex Klein1699fab2022-09-08 08:46:06 -0600768 def testArgumentValidationInvalidPackage(self):
769 out_proto = self._OutputProto()
770 in_proto = self._InputProto(
771 build_target=self.build_target,
772 sysroot_path=self.sysroot,
773 packages=["package-1.0.0-r2"],
774 )
775 with self.assertRaises(cros_build_lib.DieSystemExit):
776 sysroot_controller.InstallPackages(
777 in_proto, out_proto, self.api_config
778 )
Alex Kleinca572ee2020-09-03 10:47:14 -0600779
Alex Klein1699fab2022-09-08 08:46:06 -0600780 def testSuccessOutputHandling(self):
781 """Test successful call output handling."""
782 # Prevent argument validation error.
783 self.PatchObject(
784 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
785 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600786
Alex Klein1699fab2022-09-08 08:46:06 -0600787 in_proto = self._InputProto(
788 build_target=self.build_target, sysroot_path=self.sysroot
789 )
790 out_proto = self._OutputProto()
791 self.PatchObject(sysroot_service, "BuildPackages")
Alex Kleind4e1e422019-03-18 16:00:41 -0600792
Alex Klein1699fab2022-09-08 08:46:06 -0600793 rc = sysroot_controller.InstallPackages(
794 in_proto, out_proto, self.api_config
795 )
796 self.assertFalse(rc)
797 self.assertFalse(out_proto.failed_package_data)
Alex Kleind4e1e422019-03-18 16:00:41 -0600798
Alex Klein1699fab2022-09-08 08:46:06 -0600799 def testSuccessPackageIndexes(self):
800 """Test successful call with package_indexes."""
801 # Prevent argument validation error.
802 self.PatchObject(
803 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
804 )
805 package_indexes = [
806 common_pb2.PackageIndexInfo(
807 snapshot_sha="SHA",
808 snapshot_number=5,
809 build_target=common_pb2.BuildTarget(name="board"),
810 location="LOCATION",
811 profile=common_pb2.Profile(name="profile"),
812 ),
813 common_pb2.PackageIndexInfo(
814 snapshot_sha="SHA2",
815 snapshot_number=4,
816 build_target=common_pb2.BuildTarget(name="board"),
817 location="LOCATION2",
818 profile=common_pb2.Profile(name="profile"),
819 ),
820 ]
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600821
Alex Klein1699fab2022-09-08 08:46:06 -0600822 in_proto = self._InputProto(
823 build_target=self.build_target,
824 sysroot_path=self.sysroot,
825 package_indexes=package_indexes,
826 )
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600827
Alex Klein1699fab2022-09-08 08:46:06 -0600828 out_proto = self._OutputProto()
829 rc_patch = self.PatchObject(sysroot_service, "BuildPackagesRunConfig")
830 self.PatchObject(sysroot_service, "BuildPackages")
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600831
Alex Klein1699fab2022-09-08 08:46:06 -0600832 rc = sysroot_controller.InstallPackages(
833 in_proto, out_proto, self.api_config
834 )
835 self.assertFalse(rc)
836 rc_patch.assert_called_with(
837 use_any_chrome=False,
838 usepkg=True,
839 install_debug_symbols=True,
840 packages=[],
841 package_indexes=[
Alex Klein6d718d62023-01-18 15:55:51 -0700842 controller_util.deserialize_package_index_info(x)
Alex Klein1699fab2022-09-08 08:46:06 -0600843 for x in package_indexes
844 ],
845 use_flags=[],
846 use_goma=False,
847 use_remoteexec=False,
848 incremental_build=False,
849 dryrun=False,
850 backtrack=sysroot_controller.DEFAULT_BACKTRACK,
851 )
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600852
Alex Klein1699fab2022-09-08 08:46:06 -0600853 def testSuccessWithGomaLogs(self):
854 """Test successful call with goma."""
855 self._CreateGomaLogFile(
856 self.goma_dir,
857 "compiler_proxy",
858 datetime.datetime(2018, 9, 21, 12, 0, 0),
859 )
860 self._CreateGomaLogFile(
861 self.goma_dir,
862 "compiler_proxy-subproc",
863 datetime.datetime(2018, 9, 21, 12, 1, 0),
864 )
865 self._CreateGomaLogFile(
866 self.goma_dir, "gomacc", datetime.datetime(2018, 9, 21, 12, 2, 0)
867 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700868
Alex Klein1699fab2022-09-08 08:46:06 -0600869 # Prevent argument validation error.
870 self.PatchObject(
871 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
872 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700873
Alex Klein1699fab2022-09-08 08:46:06 -0600874 in_proto = self._InputProto(
875 build_target=self.build_target,
876 sysroot_path=self.sysroot,
877 goma_dir=self.goma_dir,
878 goma_log_dir=self.goma_out_dir,
879 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700880
Alex Klein1699fab2022-09-08 08:46:06 -0600881 out_proto = self._OutputProto()
882 self.PatchObject(sysroot_service, "BuildPackages")
Michael Mortensen798ee192020-01-17 13:04:43 -0700883
Alex Klein1699fab2022-09-08 08:46:06 -0600884 rc = sysroot_controller.InstallPackages(
885 in_proto, out_proto, self.api_config
886 )
887 self.assertFalse(rc)
888 self.assertFalse(out_proto.failed_package_data)
889 self.assertCountEqual(
890 out_proto.goma_artifacts.log_files,
891 [
892 "compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz",
893 "compiler_proxy.host.log.INFO.20180921-120000.000000.gz",
894 "gomacc.host.log.INFO.20180921-120200.000000.tar.gz",
895 ],
896 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700897
Alex Klein1699fab2022-09-08 08:46:06 -0600898 def testSuccessWithGomaLogsAndStatsCounterzFiles(self):
899 """Test successful call with goma including stats and counterz files."""
900 self._CreateGomaLogFile(
901 self.goma_dir,
902 "compiler_proxy",
903 datetime.datetime(2018, 9, 21, 12, 0, 0),
904 )
905 self._CreateGomaLogFile(
906 self.goma_dir,
907 "compiler_proxy-subproc",
908 datetime.datetime(2018, 9, 21, 12, 1, 0),
909 )
910 self._CreateGomaLogFile(
911 self.goma_dir, "gomacc", datetime.datetime(2018, 9, 21, 12, 2, 0)
912 )
913 # Create stats and counterz files.
914 osutils.WriteFile(
915 os.path.join(self.goma_dir, "stats.binaryproto"),
916 "File: stats.binaryproto",
917 )
918 osutils.WriteFile(
919 os.path.join(self.goma_dir, "counterz.binaryproto"),
920 "File: counterz.binaryproto",
921 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700922
Alex Klein1699fab2022-09-08 08:46:06 -0600923 # Prevent argument validation error.
924 self.PatchObject(
925 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
926 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700927
Alex Klein1699fab2022-09-08 08:46:06 -0600928 in_proto = self._InputProto(
929 build_target=self.build_target,
930 sysroot_path=self.sysroot,
931 goma_dir=self.goma_dir,
932 goma_log_dir=self.goma_out_dir,
933 goma_stats_file="stats.binaryproto",
934 goma_counterz_file="counterz.binaryproto",
935 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700936
Alex Klein1699fab2022-09-08 08:46:06 -0600937 out_proto = self._OutputProto()
938 self.PatchObject(sysroot_service, "BuildPackages")
Michael Mortensen798ee192020-01-17 13:04:43 -0700939
Alex Klein1699fab2022-09-08 08:46:06 -0600940 rc = sysroot_controller.InstallPackages(
941 in_proto, out_proto, self.api_config
942 )
943 self.assertFalse(rc)
944 self.assertFalse(out_proto.failed_package_data)
945 self.assertCountEqual(
946 out_proto.goma_artifacts.log_files,
947 [
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 )
953 # Verify that the output dir has 5 files -- since there should be 3 log
954 # files, the stats file, and the counterz file.
955 output_files = os.listdir(self.goma_out_dir)
956 self.assertCountEqual(
957 output_files,
958 [
959 "stats.binaryproto",
960 "counterz.binaryproto",
961 "compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz",
962 "compiler_proxy.host.log.INFO.20180921-120000.000000.gz",
963 "gomacc.host.log.INFO.20180921-120200.000000.tar.gz",
964 ],
965 )
966 self.assertEqual(
967 out_proto.goma_artifacts.counterz_file, "counterz.binaryproto"
968 )
969 self.assertEqual(
970 out_proto.goma_artifacts.stats_file, "stats.binaryproto"
971 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700972
Alex Klein1699fab2022-09-08 08:46:06 -0600973 def testFailureMissingGomaStatsCounterzFiles(self):
974 """Test successful call with goma including stats and counterz files."""
975 self._CreateGomaLogFile(
976 self.goma_dir,
977 "compiler_proxy",
978 datetime.datetime(2018, 9, 21, 12, 0, 0),
979 )
980 self._CreateGomaLogFile(
981 self.goma_dir,
982 "compiler_proxy-subproc",
983 datetime.datetime(2018, 9, 21, 12, 1, 0),
984 )
985 self._CreateGomaLogFile(
986 self.goma_dir, "gomacc", datetime.datetime(2018, 9, 21, 12, 2, 0)
987 )
988 # Note that stats and counterz files are not created, but are specified in
989 # the proto below.
Michael Mortensen798ee192020-01-17 13:04:43 -0700990
Alex Klein1699fab2022-09-08 08:46:06 -0600991 # Prevent argument validation error.
992 self.PatchObject(
993 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
994 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700995
Alex Klein1699fab2022-09-08 08:46:06 -0600996 in_proto = self._InputProto(
997 build_target=self.build_target,
998 sysroot_path=self.sysroot,
999 goma_dir=self.goma_dir,
1000 goma_log_dir=self.goma_out_dir,
1001 goma_stats_file="stats.binaryproto",
1002 goma_counterz_file="counterz.binaryproto",
1003 )
Michael Mortensen798ee192020-01-17 13:04:43 -07001004
Alex Klein1699fab2022-09-08 08:46:06 -06001005 out_proto = self._OutputProto()
1006 self.PatchObject(sysroot_service, "BuildPackages")
Michael Mortensen798ee192020-01-17 13:04:43 -07001007
Alex Klein1699fab2022-09-08 08:46:06 -06001008 rc = sysroot_controller.InstallPackages(
1009 in_proto, out_proto, self.api_config
1010 )
1011 self.assertFalse(rc)
1012 self.assertFalse(out_proto.failed_package_data)
1013 self.assertCountEqual(
1014 out_proto.goma_artifacts.log_files,
1015 [
1016 "compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz",
1017 "compiler_proxy.host.log.INFO.20180921-120000.000000.gz",
1018 "gomacc.host.log.INFO.20180921-120200.000000.tar.gz",
1019 ],
1020 )
1021 self.assertFalse(out_proto.goma_artifacts.counterz_file)
1022 self.assertFalse(out_proto.goma_artifacts.stats_file)
Michael Mortensen798ee192020-01-17 13:04:43 -07001023
Alex Klein1699fab2022-09-08 08:46:06 -06001024 def testFailureOutputHandling(self):
1025 """Test failed package handling."""
1026 # Prevent argument validation error.
1027 self.PatchObject(
1028 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
1029 )
Alex Kleind4e1e422019-03-18 16:00:41 -06001030
Alex Klein1699fab2022-09-08 08:46:06 -06001031 in_proto = self._InputProto(
1032 build_target=self.build_target, sysroot_path=self.sysroot
1033 )
1034 out_proto = self._OutputProto()
Alex Kleind4e1e422019-03-18 16:00:41 -06001035
Alex Klein1699fab2022-09-08 08:46:06 -06001036 # Failed package info and expected list for verification.
1037 err_pkgs = ["cat/pkg-1.0-r3", "cat2/pkg2-1.0-r1"]
1038 err_cpvs = [package_info.parse(cpv) for cpv in err_pkgs]
1039 expected = [("cat", "pkg"), ("cat2", "pkg2")]
Alex Kleind4e1e422019-03-18 16:00:41 -06001040
Alex Klein1699fab2022-09-08 08:46:06 -06001041 new_logs = {}
1042 for i, pkg in enumerate(err_pkgs):
1043 self._CreatePortageLogFile(
1044 self.portage_dir,
1045 err_cpvs[i],
1046 datetime.datetime(2021, 6, 9, 13, 37, 0),
1047 )
1048 new_logs[pkg] = self._CreatePortageLogFile(
1049 self.portage_dir,
1050 err_cpvs[i],
1051 datetime.datetime(2021, 6, 9, 16, 20, 0),
1052 )
1053 # Force error to be raised with the packages.
1054 error = sysroot_lib.PackageInstallError(
1055 "Error", cros_build_lib.CompletedProcess(), packages=err_cpvs
1056 )
1057 self.PatchObject(sysroot_service, "BuildPackages", side_effect=error)
Alex Kleind4e1e422019-03-18 16:00:41 -06001058
Alex Klein1699fab2022-09-08 08:46:06 -06001059 rc = sysroot_controller.InstallPackages(
1060 in_proto, out_proto, self.api_config
1061 )
1062 # This needs to return 2 to indicate the available error response.
1063 self.assertEqual(
1064 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
1065 )
1066 for data in out_proto.failed_package_data:
1067 package = controller_util.deserialize_package_info(data.name)
1068 cat_pkg = (data.name.category, data.name.package_name)
1069 self.assertIn(cat_pkg, expected)
1070 self.assertEqual(data.log_path.path, new_logs[package.cpvr])
Lizzy Presland7e23a612021-11-09 21:49:42 +00001071
Alex Klein1699fab2022-09-08 08:46:06 -06001072 def testNoPackageFailureOutputHandling(self):
1073 """Test failure handling without packages to report."""
1074 # Prevent argument validation error.
1075 self.PatchObject(
1076 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
1077 )
Alex Klein2557b4f2019-07-11 14:34:00 -06001078
Alex Klein1699fab2022-09-08 08:46:06 -06001079 in_proto = self._InputProto(
1080 build_target=self.build_target, sysroot_path=self.sysroot
1081 )
1082 out_proto = self._OutputProto()
Alex Klein2557b4f2019-07-11 14:34:00 -06001083
Alex Klein1699fab2022-09-08 08:46:06 -06001084 # Force error to be raised with no packages.
1085 error = sysroot_lib.PackageInstallError(
1086 "Error", cros_build_lib.CompletedProcess(), packages=[]
1087 )
1088 self.PatchObject(sysroot_service, "BuildPackages", side_effect=error)
Alex Klein2557b4f2019-07-11 14:34:00 -06001089
Alex Klein1699fab2022-09-08 08:46:06 -06001090 rc = sysroot_controller.InstallPackages(
1091 in_proto, out_proto, self.api_config
1092 )
1093 # All we really care about is it's not 0 or 2 (response available), so
1094 # test for that rather than a specific return code.
1095 self.assertTrue(rc)
1096 self.assertNotEqual(
1097 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
1098 )