blob: 69836b595982b679a786105759e8a79c537dd42a [file] [log] [blame]
Mike Frysingerf1ba7ad2022-09-12 05:42:57 -04001# Copyright 2019 The ChromiumOS Authors
Alex Kleinda35fcf2019-03-07 16:01:15 -07002# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Sysroot controller tests."""
6
Michael Mortensen798ee192020-01-17 13:04:43 -07007import datetime
Alex Kleinda35fcf2019-03-07 16:01:15 -07008import os
Lizzy Preslandfc1db002022-05-06 18:19:49 +00009from typing import Union
Alex Kleinda35fcf2019-03-07 16:01:15 -070010
Alex Klein231d2da2019-07-22 16:44:45 -060011from chromite.api import api_config
Alex Klein8cb365a2019-05-15 16:24:53 -060012from chromite.api import controller
Alex Kleinca572ee2020-09-03 10:47:14 -060013from chromite.api.controller import controller_util
Alex Kleinda35fcf2019-03-07 16:01:15 -070014from chromite.api.controller import sysroot as sysroot_controller
15from chromite.api.gen.chromite.api import sysroot_pb2
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -070016from chromite.api.gen.chromiumos import common_pb2
Alex Kleinda35fcf2019-03-07 16:01:15 -070017from chromite.lib import cros_build_lib
18from chromite.lib import cros_test_lib
19from chromite.lib import osutils
Alex Kleinda35fcf2019-03-07 16:01:15 -070020from chromite.lib import sysroot_lib
Alex Klein18a60af2020-06-11 12:08:47 -060021from chromite.lib.parser import package_info
Alex Kleinda35fcf2019-03-07 16:01:15 -070022from chromite.service import sysroot as sysroot_service
23
24
Alex Klein231d2da2019-07-22 16:44:45 -060025class CreateTest(cros_test_lib.MockTestCase, api_config.ApiConfigMixin):
Alex Klein1699fab2022-09-08 08:46:06 -060026 """Create function tests."""
Alex Kleinda35fcf2019-03-07 16:01:15 -070027
Alex Klein1699fab2022-09-08 08:46:06 -060028 def _InputProto(
29 self,
30 build_target=None,
31 profile=None,
32 replace=False,
33 current=False,
Yoshiki Iguchi2f7f0222023-05-17 19:30:09 +090034 use_cq_prebuilts=False,
Alex Klein1699fab2022-09-08 08:46:06 -060035 package_indexes=None,
36 ):
37 """Helper to build and input proto instance."""
38 proto = sysroot_pb2.SysrootCreateRequest()
39 if build_target:
40 proto.build_target.name = build_target
41 if profile:
42 proto.profile.name = profile
43 if replace:
44 proto.flags.replace = replace
45 if current:
46 proto.flags.chroot_current = current
Yoshiki Iguchi2f7f0222023-05-17 19:30:09 +090047 if use_cq_prebuilts:
48 proto.flags.use_cq_prebuilts = use_cq_prebuilts
Alex Klein1699fab2022-09-08 08:46:06 -060049 if package_indexes:
50 proto.package_indexes.extend(package_indexes)
Alex Kleinda35fcf2019-03-07 16:01:15 -070051
Alex Klein1699fab2022-09-08 08:46:06 -060052 return proto
Alex Kleinda35fcf2019-03-07 16:01:15 -070053
Alex Klein1699fab2022-09-08 08:46:06 -060054 def _OutputProto(self):
55 """Helper to build output proto instance."""
56 return sysroot_pb2.SysrootCreateResponse()
Alex Kleinda35fcf2019-03-07 16:01:15 -070057
Alex Klein1699fab2022-09-08 08:46:06 -060058 def testValidateOnly(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -070059 """Verify a validate-only call does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -060060 patch = self.PatchObject(sysroot_service, "Create")
Alex Klein231d2da2019-07-22 16:44:45 -060061
Alex Klein1699fab2022-09-08 08:46:06 -060062 board = "board"
63 profile = None
64 force = False
65 upgrade_chroot = True
66 in_proto = self._InputProto(
67 build_target=board,
68 profile=profile,
69 replace=force,
70 current=not upgrade_chroot,
71 )
72 sysroot_controller.Create(
73 in_proto, self._OutputProto(), self.validate_only_config
74 )
75 patch.assert_not_called()
Alex Klein231d2da2019-07-22 16:44:45 -060076
Alex Klein1699fab2022-09-08 08:46:06 -060077 def testMockCall(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -070078 """Verify a mock call does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -060079 patch = self.PatchObject(sysroot_service, "Create")
80 request = self._InputProto()
81 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -060082
Alex Klein1699fab2022-09-08 08:46:06 -060083 rc = sysroot_controller.Create(request, response, self.mock_call_config)
Alex Klein076841b2019-08-29 15:19:39 -060084
Alex Klein1699fab2022-09-08 08:46:06 -060085 patch.assert_not_called()
86 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
Alex Klein076841b2019-08-29 15:19:39 -060087
Alex Klein1699fab2022-09-08 08:46:06 -060088 def testMockError(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -070089 """Verify a mock error does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -060090 patch = self.PatchObject(sysroot_service, "Create")
91 request = self._InputProto()
92 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -060093
Alex Klein1699fab2022-09-08 08:46:06 -060094 rc = sysroot_controller.Create(
95 request, response, self.mock_error_config
96 )
Alex Klein076841b2019-08-29 15:19:39 -060097
Alex Klein1699fab2022-09-08 08:46:06 -060098 patch.assert_not_called()
99 self.assertEqual(controller.RETURN_CODE_UNRECOVERABLE, rc)
Alex Klein076841b2019-08-29 15:19:39 -0600100
Alex Klein1699fab2022-09-08 08:46:06 -0600101 def testArgumentValidation(self):
102 """Test the input argument validation."""
103 # Error when no name provided.
104 in_proto = self._InputProto()
105 out_proto = self._OutputProto()
106 with self.assertRaises(cros_build_lib.DieSystemExit):
107 sysroot_controller.Create(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700108
Alex Klein1699fab2022-09-08 08:46:06 -0600109 # Valid when board passed.
110 result = sysroot_lib.Sysroot("/sysroot/path")
111 patch = self.PatchObject(sysroot_service, "Create", return_value=result)
112 in_proto = self._InputProto("board")
113 out_proto = self._OutputProto()
114 sysroot_controller.Create(in_proto, out_proto, self.api_config)
115 patch.assert_called_once()
Alex Kleinda35fcf2019-03-07 16:01:15 -0700116
Alex Klein1699fab2022-09-08 08:46:06 -0600117 def testArgumentHandling(self):
118 """Test the arguments get processed and passed correctly."""
119 sysroot_path = "/sysroot/path"
Alex Kleinda35fcf2019-03-07 16:01:15 -0700120
Alex Klein1699fab2022-09-08 08:46:06 -0600121 sysroot = sysroot_lib.Sysroot(sysroot_path)
122 create_patch = self.PatchObject(
123 sysroot_service, "Create", return_value=sysroot
124 )
125 rc_patch = self.PatchObject(sysroot_service, "SetupBoardRunConfig")
Alex Kleinda35fcf2019-03-07 16:01:15 -0700126
Alex Klein1699fab2022-09-08 08:46:06 -0600127 # Default values.
128 board = "board"
129 profile = None
130 force = False
131 upgrade_chroot = True
Yoshiki Iguchi2f7f0222023-05-17 19:30:09 +0900132 use_cq_prebuilts = False
Alex Klein1699fab2022-09-08 08:46:06 -0600133 in_proto = self._InputProto(
134 build_target=board,
135 profile=profile,
136 replace=force,
137 current=not upgrade_chroot,
Yoshiki Iguchi2f7f0222023-05-17 19:30:09 +0900138 use_cq_prebuilts=use_cq_prebuilts,
Alex Klein1699fab2022-09-08 08:46:06 -0600139 )
140 out_proto = self._OutputProto()
141 sysroot_controller.Create(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700142
Alex Klein1699fab2022-09-08 08:46:06 -0600143 # Default value checks.
144 rc_patch.assert_called_with(
145 force=force,
146 upgrade_chroot=upgrade_chroot,
147 package_indexes=[],
Yoshiki Iguchi2f7f0222023-05-17 19:30:09 +0900148 use_cq_prebuilts=use_cq_prebuilts,
Alex Klein1699fab2022-09-08 08:46:06 -0600149 backtrack=sysroot_controller.DEFAULT_BACKTRACK,
150 )
151 self.assertEqual(board, out_proto.sysroot.build_target.name)
152 self.assertEqual(sysroot_path, out_proto.sysroot.path)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700153
Alex Klein1699fab2022-09-08 08:46:06 -0600154 # Not default values.
155 create_patch.reset_mock()
156 board = "board"
157 profile = "profile"
158 force = True
159 upgrade_chroot = False
Yoshiki Iguchi2f7f0222023-05-17 19:30:09 +0900160 use_cq_prebuilts = True
Alex Klein1699fab2022-09-08 08:46:06 -0600161 package_indexes = [
162 common_pb2.PackageIndexInfo(
163 snapshot_sha="SHA",
164 snapshot_number=5,
165 build_target=common_pb2.BuildTarget(name=board),
166 location="LOCATION",
167 profile=common_pb2.Profile(name=profile),
168 ),
169 common_pb2.PackageIndexInfo(
170 snapshot_sha="SHA2",
171 snapshot_number=4,
172 build_target=common_pb2.BuildTarget(name=board),
173 location="LOCATION2",
174 profile=common_pb2.Profile(name=profile),
175 ),
176 ]
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600177
Alex Klein1699fab2022-09-08 08:46:06 -0600178 in_proto = self._InputProto(
179 build_target=board,
180 profile=profile,
181 replace=force,
182 current=not upgrade_chroot,
Yoshiki Iguchi2f7f0222023-05-17 19:30:09 +0900183 use_cq_prebuilts=use_cq_prebuilts,
Alex Klein1699fab2022-09-08 08:46:06 -0600184 package_indexes=package_indexes,
185 )
186 out_proto = self._OutputProto()
187 sysroot_controller.Create(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700188
Alex Klein1699fab2022-09-08 08:46:06 -0600189 # Not default value checks.
190 rc_patch.assert_called_with(
191 force=force,
192 package_indexes=[
Alex Klein6d718d62023-01-18 15:55:51 -0700193 controller_util.deserialize_package_index_info(x)
Alex Klein1699fab2022-09-08 08:46:06 -0600194 for x in package_indexes
195 ],
196 upgrade_chroot=upgrade_chroot,
Yoshiki Iguchi2f7f0222023-05-17 19:30:09 +0900197 use_cq_prebuilts=use_cq_prebuilts,
Alex Klein1699fab2022-09-08 08:46:06 -0600198 backtrack=sysroot_controller.DEFAULT_BACKTRACK,
199 )
200 self.assertEqual(board, out_proto.sysroot.build_target.name)
201 self.assertEqual(sysroot_path, out_proto.sysroot.path)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700202
203
Jack Neus26b94672022-10-27 17:33:21 +0000204class GetArtifactsTest(cros_test_lib.MockTestCase, api_config.ApiConfigMixin):
205 """GetArtifacts function tests."""
206
Alex Kleinab87ceb2023-01-24 12:00:51 -0700207 # pylint: disable=line-too-long
Jack Neus26b94672022-10-27 17:33:21 +0000208 _artifact_funcs = {
209 common_pb2.ArtifactsByService.Sysroot.ArtifactType.SIMPLE_CHROME_SYSROOT: sysroot_service.CreateSimpleChromeSysroot,
210 common_pb2.ArtifactsByService.Sysroot.ArtifactType.CHROME_EBUILD_ENV: sysroot_service.CreateChromeEbuildEnv,
211 common_pb2.ArtifactsByService.Sysroot.ArtifactType.BREAKPAD_DEBUG_SYMBOLS: sysroot_service.BundleBreakpadSymbols,
212 common_pb2.ArtifactsByService.Sysroot.ArtifactType.DEBUG_SYMBOLS: sysroot_service.BundleDebugSymbols,
213 common_pb2.ArtifactsByService.Sysroot.ArtifactType.FUZZER_SYSROOT: sysroot_service.CreateFuzzerSysroot,
Ram Chandrasekar5ba36b22023-03-20 16:10:48 -0600214 common_pb2.ArtifactsByService.Sysroot.ArtifactType.SYSROOT_ARCHIVE: sysroot_service.ArchiveSysroot,
Jack Neus26b94672022-10-27 17:33:21 +0000215 }
216
Alex Kleinab87ceb2023-01-24 12:00:51 -0700217 # pylint: enable=line-too-long
218
Jack Neus26b94672022-10-27 17:33:21 +0000219 def setUp(self):
220 self._mocks = {}
221 for artifact, func in self._artifact_funcs.items():
222 self._mocks[artifact] = self.PatchObject(
223 sysroot_service, func.__name__
224 )
225
226 def _InputProto(
227 self,
228 artifact_types=_artifact_funcs.keys(),
229 ):
230 """Helper to build an input proto instance."""
231 return common_pb2.ArtifactsByService.Sysroot(
232 output_artifacts=[
233 common_pb2.ArtifactsByService.Sysroot.ArtifactInfo(
234 artifact_types=artifact_types
235 )
236 ]
237 )
238
239 def testNoArtifacts(self):
240 """Test GetArtifacts with no artifact types."""
241 in_proto = self._InputProto(artifact_types=[])
242 sysroot_controller.GetArtifacts(
243 in_proto, None, None, "build_target", ""
244 )
245
246 for _, patch in self._mocks.items():
247 patch.assert_not_called()
248
249 def testArtifactsSuccess(self):
250 """Test GetArtifacts with all artifact types."""
251 sysroot_controller.GetArtifacts(
252 self._InputProto(), None, None, "build_target", ""
253 )
254
255 for _, patch in self._mocks.items():
256 patch.assert_called_once()
257
258 def testArtifactsException(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700259 """Test with all artifact types when one type throws an exception."""
Jack Neus26b94672022-10-27 17:33:21 +0000260
261 self._mocks[
262 common_pb2.ArtifactsByService.Sysroot.ArtifactType.FUZZER_SYSROOT
263 ].side_effect = Exception("foo bar")
264 generated = sysroot_controller.GetArtifacts(
265 self._InputProto(), None, None, "build_target", ""
266 )
267
268 for _, patch in self._mocks.items():
269 patch.assert_called_once()
270
271 found_artifact = False
272 for data in generated:
273 artifact_type = (
274 common_pb2.ArtifactsByService.Sysroot.ArtifactType.Name(
275 data["type"]
276 )
277 )
278 if artifact_type == "FUZZER_SYSROOT":
279 found_artifact = True
280 self.assertTrue(data["failed"])
281 self.assertEqual(data["failure_reason"], "foo bar")
282 self.assertTrue(found_artifact)
283
Ian Barkley-Yeungb5274442023-04-28 16:32:20 -0700284 def testArtifactsBreakpadDebugSymbols(self):
285 """Tests the extra parameters to BundleBreakpadSymbols"""
286 proto = common_pb2.ArtifactsByService.Sysroot(
287 output_artifacts=[
288 common_pb2.ArtifactsByService.Sysroot.ArtifactInfo(
289 artifact_types=[
290 # pylint: disable=line-too-long
291 common_pb2.ArtifactsByService.Sysroot.ArtifactType.BREAKPAD_DEBUG_SYMBOLS
292 # pylint: enable=line-too-long
293 ]
294 )
295 ],
296 ignore_breakpad_symbol_generation_errors=True,
297 ignore_breakpad_symbol_generation_expected_files=[
298 # pylint: disable=line-too-long
299 common_pb2.ArtifactsByService.Sysroot.BreakpadSymbolGenerationExpectedFile.EXPECTED_FILE_LIBC,
300 common_pb2.ArtifactsByService.Sysroot.BreakpadSymbolGenerationExpectedFile.EXPECTED_FILE_CRASH_REPORTER,
301 # pylint: enable=line-too-long
302 ],
303 )
304 sysroot_controller.GetArtifacts(
305 proto, None, None, "build_target", "out"
306 )
307 self._mocks[
308 # pylint: disable=line-too-long
309 common_pb2.ArtifactsByService.Sysroot.ArtifactType.BREAKPAD_DEBUG_SYMBOLS
310 # pylint: enable=line-too-long
311 ].assert_called_once_with(
312 None,
313 None,
314 "build_target",
315 "out",
316 True,
317 ["LIBC", "CRASH_REPORTER"],
318 )
319
320 def testArtifactsExpectedFileNames(self):
321 """Verify all BreakpadSymbolGenerationExpectedFile have valid names.
322
323 _BundleBreakpadSymbols inside GetArtifacts assumes that all values of
324 the BreakpadSymbolGenerationExpectedFile enum are named starting with
325 EXPECTED_FILE_. Confirm that assumption.
326 """
327 for enum in (
328 # pylint: disable=line-too-long
329 common_pb2.ArtifactsByService.Sysroot.BreakpadSymbolGenerationExpectedFile.keys()
330 # pylint: enable=line-too-long
331 ):
332 self.assertTrue(enum.startswith("EXPECTED_FILE_"))
333
Jack Neus26b94672022-10-27 17:33:21 +0000334
Alex Klein1699fab2022-09-08 08:46:06 -0600335class GenerateArchiveTest(
336 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin
337):
338 """GenerateArchive function tests."""
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700339
Alex Klein1699fab2022-09-08 08:46:06 -0600340 def setUp(self):
341 self.chroot_path = "/path/to/chroot"
342 self.board = "board"
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700343
Alex Klein1699fab2022-09-08 08:46:06 -0600344 def _InputProto(self, build_target=None, chroot_path=None, pkg_list=None):
345 """Helper to build and input proto instance."""
346 # pkg_list will be a list of category/package strings such as
347 # ['virtual/target-fuzzers'].
348 if pkg_list:
349 package_list = []
350 for pkg in pkg_list:
351 pkg_string_parts = pkg.split("/")
352 package_info_msg = common_pb2.PackageInfo(
353 category=pkg_string_parts[0],
354 package_name=pkg_string_parts[1],
355 )
356 package_list.append(package_info_msg)
357 else:
358 package_list = []
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700359
Alex Klein1699fab2022-09-08 08:46:06 -0600360 return sysroot_pb2.SysrootGenerateArchiveRequest(
361 build_target={"name": build_target},
362 chroot={"path": chroot_path},
363 packages=package_list,
364 )
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700365
Alex Klein1699fab2022-09-08 08:46:06 -0600366 def _OutputProto(self):
367 """Helper to build output proto instance."""
368 return sysroot_pb2.SysrootGenerateArchiveResponse()
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700369
Alex Klein1699fab2022-09-08 08:46:06 -0600370 def testValidateOnly(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700371 """Verify a validate-only call does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -0600372 patch = self.PatchObject(sysroot_service, "GenerateArchive")
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700373
Alex Klein1699fab2022-09-08 08:46:06 -0600374 in_proto = self._InputProto(
375 build_target=self.board,
376 chroot_path=self.chroot_path,
377 pkg_list=["virtual/target-fuzzers"],
378 )
379 sysroot_controller.GenerateArchive(
380 in_proto, self._OutputProto(), self.validate_only_config
381 )
382 patch.assert_not_called()
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700383
Alex Klein1699fab2022-09-08 08:46:06 -0600384 def testMockCall(self):
385 """Sanity check that a mock call does not execute any logic."""
386 patch = self.PatchObject(sysroot_service, "GenerateArchive")
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700387
Alex Klein1699fab2022-09-08 08:46:06 -0600388 in_proto = self._InputProto(
389 build_target=self.board,
390 chroot_path=self.chroot_path,
391 pkg_list=["virtual/target-fuzzers"],
392 )
393 sysroot_controller.GenerateArchive(
394 in_proto, self._OutputProto(), self.mock_call_config
395 )
396 patch.assert_not_called()
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700397
Alex Klein1699fab2022-09-08 08:46:06 -0600398 def testArgumentValidation(self):
399 """Test the input argument validation."""
400 # Error when no build target provided.
401 in_proto = self._InputProto()
402 out_proto = self._OutputProto()
403 with self.assertRaises(cros_build_lib.DieSystemExit):
404 sysroot_controller.GenerateArchive(
405 in_proto, out_proto, self.api_config
406 )
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700407
Alex Klein1699fab2022-09-08 08:46:06 -0600408 # Error when packages is not specified.
409 in_proto = self._InputProto(
410 build_target="board", chroot_path=self.chroot_path
411 )
412 with self.assertRaises(cros_build_lib.DieSystemExit):
413 sysroot_controller.GenerateArchive(
414 in_proto, out_proto, self.api_config
415 )
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700416
Alex Klein1699fab2022-09-08 08:46:06 -0600417 # Valid when board, chroot path, and package are specified.
418 patch = self.PatchObject(
419 sysroot_service,
420 "GenerateArchive",
421 return_value="/path/to/sysroot/tar.bz",
422 )
423 in_proto = self._InputProto(
424 build_target="board",
425 chroot_path=self.chroot_path,
426 pkg_list=["virtual/target-fuzzers"],
427 )
428 out_proto = self._OutputProto()
429 sysroot_controller.GenerateArchive(in_proto, out_proto, self.api_config)
430 patch.assert_called_once()
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700431
432
Alex Klein1699fab2022-09-08 08:46:06 -0600433class InstallToolchainTest(
434 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin
435):
436 """Install toolchain function tests."""
Alex Kleinda35fcf2019-03-07 16:01:15 -0700437
Alex Klein1699fab2022-09-08 08:46:06 -0600438 def setUp(self):
439 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=True)
440 # Avoid running the portageq command.
441 self.PatchObject(sysroot_controller, "_LogBinhost")
442 self.board = "board"
443 self.sysroot = os.path.join(self.tempdir, "board")
444 self.invalid_sysroot = os.path.join(self.tempdir, "invalid", "sysroot")
445 osutils.SafeMakedirs(self.sysroot)
446 # Set up portage log directory.
447 self.target_sysroot = sysroot_lib.Sysroot(self.sysroot)
448 self.portage_dir = os.path.join(self.tempdir, "portage_logdir")
449 self.PatchObject(
450 sysroot_lib.Sysroot, "portage_logdir", new=self.portage_dir
451 )
452 osutils.SafeMakedirs(self.portage_dir)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700453
Alex Klein1699fab2022-09-08 08:46:06 -0600454 def _InputProto(
455 self, build_target=None, sysroot_path=None, compile_source=False
456 ):
457 """Helper to build an input proto instance."""
458 proto = sysroot_pb2.InstallToolchainRequest()
459 if build_target:
460 proto.sysroot.build_target.name = build_target
461 if sysroot_path:
462 proto.sysroot.path = sysroot_path
463 if compile_source:
464 proto.flags.compile_source = compile_source
Alex Kleinda35fcf2019-03-07 16:01:15 -0700465
Alex Klein1699fab2022-09-08 08:46:06 -0600466 return proto
Alex Kleinda35fcf2019-03-07 16:01:15 -0700467
Alex Klein1699fab2022-09-08 08:46:06 -0600468 def _OutputProto(self):
469 """Helper to build output proto instance."""
470 return sysroot_pb2.InstallToolchainResponse()
Alex Kleinda35fcf2019-03-07 16:01:15 -0700471
Alex Klein1699fab2022-09-08 08:46:06 -0600472 def _CreatePortageLogFile(
473 self,
474 log_path: Union[str, os.PathLike],
475 pkg_info: package_info.PackageInfo,
476 timestamp: datetime.datetime,
477 ):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700478 """Creates a log file to test for individual packages built by Portage.
Lizzy Presland7e23a612021-11-09 21:49:42 +0000479
Alex Klein1699fab2022-09-08 08:46:06 -0600480 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600481 log_path: The PORTAGE_LOGDIR path.
482 pkg_info: Package name used to name the log file.
483 timestamp: Timestamp used to name the file.
Alex Klein1699fab2022-09-08 08:46:06 -0600484 """
485 path = os.path.join(
486 log_path,
487 f"{pkg_info.category}:{pkg_info.pvr}:"
488 f'{timestamp.strftime("%Y%m%d-%H%M%S")}.log',
489 )
490 osutils.WriteFile(
491 path,
492 f"Test log file for package {pkg_info.category}/"
493 f"{pkg_info.package} written to {path}",
494 )
495 return path
Lizzy Presland7e23a612021-11-09 21:49:42 +0000496
Alex Klein1699fab2022-09-08 08:46:06 -0600497 def testValidateOnly(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700498 """Verify a validate-only call does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -0600499 patch = self.PatchObject(sysroot_service, "InstallToolchain")
Alex Klein231d2da2019-07-22 16:44:45 -0600500
Alex Klein1699fab2022-09-08 08:46:06 -0600501 in_proto = self._InputProto(
502 build_target=self.board, sysroot_path=self.sysroot
503 )
504 sysroot_controller.InstallToolchain(
505 in_proto, self._OutputProto(), self.validate_only_config
506 )
507 patch.assert_not_called()
Alex Klein231d2da2019-07-22 16:44:45 -0600508
Alex Klein1699fab2022-09-08 08:46:06 -0600509 def testMockCall(self):
510 """Sanity check that a mock call does not execute any logic."""
511 patch = self.PatchObject(sysroot_service, "InstallToolchain")
512 request = self._InputProto()
513 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -0600514
Alex Klein1699fab2022-09-08 08:46:06 -0600515 rc = sysroot_controller.InstallToolchain(
516 request, response, self.mock_call_config
517 )
Alex Klein076841b2019-08-29 15:19:39 -0600518
Alex Klein1699fab2022-09-08 08:46:06 -0600519 patch.assert_not_called()
520 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
Alex Klein076841b2019-08-29 15:19:39 -0600521
Alex Klein1699fab2022-09-08 08:46:06 -0600522 def testMockError(self):
523 """Sanity check that a mock error does not execute any logic."""
524 patch = self.PatchObject(sysroot_service, "InstallToolchain")
525 request = self._InputProto()
526 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -0600527
Alex Klein1699fab2022-09-08 08:46:06 -0600528 rc = sysroot_controller.InstallToolchain(
529 request, response, self.mock_error_config
530 )
Alex Klein076841b2019-08-29 15:19:39 -0600531
Alex Klein1699fab2022-09-08 08:46:06 -0600532 patch.assert_not_called()
533 self.assertEqual(
534 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
535 )
536 self.assertTrue(response.failed_package_data)
Alex Klein076841b2019-08-29 15:19:39 -0600537
Alex Klein1699fab2022-09-08 08:46:06 -0600538 def testArgumentValidation(self):
539 """Test the argument validation."""
540 # Test errors on missing inputs.
541 out_proto = self._OutputProto()
542 # Both missing.
543 in_proto = self._InputProto()
544 with self.assertRaises(cros_build_lib.DieSystemExit):
545 sysroot_controller.InstallToolchain(
546 in_proto, out_proto, self.api_config
547 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700548
Alex Klein1699fab2022-09-08 08:46:06 -0600549 # Sysroot path missing.
550 in_proto = self._InputProto(build_target=self.board)
551 with self.assertRaises(cros_build_lib.DieSystemExit):
552 sysroot_controller.InstallToolchain(
553 in_proto, out_proto, self.api_config
554 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700555
Alex Klein1699fab2022-09-08 08:46:06 -0600556 # Build target name missing.
557 in_proto = self._InputProto(sysroot_path=self.sysroot)
558 with self.assertRaises(cros_build_lib.DieSystemExit):
559 sysroot_controller.InstallToolchain(
560 in_proto, out_proto, self.api_config
561 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700562
Alex Klein1699fab2022-09-08 08:46:06 -0600563 # Both provided, but invalid sysroot path.
564 in_proto = self._InputProto(
565 build_target=self.board, sysroot_path=self.invalid_sysroot
566 )
567 with self.assertRaises(cros_build_lib.DieSystemExit):
568 sysroot_controller.InstallToolchain(
569 in_proto, out_proto, self.api_config
570 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700571
Alex Klein1699fab2022-09-08 08:46:06 -0600572 def testSuccessOutputHandling(self):
573 """Test the output is processed and recorded correctly."""
574 self.PatchObject(sysroot_service, "InstallToolchain")
575 out_proto = self._OutputProto()
576 in_proto = self._InputProto(
577 build_target=self.board, sysroot_path=self.sysroot
578 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700579
Alex Klein1699fab2022-09-08 08:46:06 -0600580 rc = sysroot_controller.InstallToolchain(
581 in_proto, out_proto, self.api_config
582 )
583 self.assertFalse(rc)
584 self.assertFalse(out_proto.failed_package_data)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700585
Alex Klein1699fab2022-09-08 08:46:06 -0600586 def testErrorOutputHandling(self):
587 """Test the error output is processed and recorded correctly."""
588 out_proto = self._OutputProto()
589 in_proto = self._InputProto(
590 build_target=self.board, sysroot_path=self.sysroot
591 )
Alex Kleinda35fcf2019-03-07 16:01:15 -0700592
Alex Klein1699fab2022-09-08 08:46:06 -0600593 err_pkgs = ["cat/pkg-1.0-r1", "cat2/pkg2-1.0-r1"]
594 err_cpvs = [package_info.parse(pkg) for pkg in err_pkgs]
595 expected = [("cat", "pkg"), ("cat2", "pkg2")]
Lizzy Presland7e23a612021-11-09 21:49:42 +0000596
Alex Klein1699fab2022-09-08 08:46:06 -0600597 new_logs = {}
598 for i, pkg in enumerate(err_pkgs):
599 self._CreatePortageLogFile(
600 self.portage_dir,
601 err_cpvs[i],
602 datetime.datetime(2021, 6, 9, 13, 37, 0),
603 )
604 new_logs[pkg] = self._CreatePortageLogFile(
605 self.portage_dir,
606 err_cpvs[i],
607 datetime.datetime(2021, 6, 9, 16, 20, 0),
608 )
Lizzy Presland7e23a612021-11-09 21:49:42 +0000609
Alex Klein1699fab2022-09-08 08:46:06 -0600610 err = sysroot_lib.ToolchainInstallError(
611 "Error", cros_build_lib.CompletedProcess(), tc_info=err_cpvs
612 )
613 self.PatchObject(sysroot_service, "InstallToolchain", side_effect=err)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700614
Alex Klein1699fab2022-09-08 08:46:06 -0600615 rc = sysroot_controller.InstallToolchain(
616 in_proto, out_proto, self.api_config
617 )
618 self.assertEqual(
619 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
620 )
621 self.assertTrue(out_proto.failed_package_data)
622 # This needs to return 2 to indicate the available error response.
623 self.assertEqual(
624 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
625 )
626 for data in out_proto.failed_package_data:
627 package = controller_util.deserialize_package_info(data.name)
628 cat_pkg = (data.name.category, data.name.package_name)
629 self.assertIn(cat_pkg, expected)
630 self.assertEqual(data.log_path.path, new_logs[package.cpvr])
Lizzy Presland7e23a612021-11-09 21:49:42 +0000631
Alex Kleind4e1e422019-03-18 16:00:41 -0600632
Alex Klein1699fab2022-09-08 08:46:06 -0600633class InstallPackagesTest(
634 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin
635):
636 """InstallPackages tests."""
Alex Kleind4e1e422019-03-18 16:00:41 -0600637
Alex Klein1699fab2022-09-08 08:46:06 -0600638 def setUp(self):
639 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=True)
640 # Avoid running the portageq command.
641 self.PatchObject(sysroot_controller, "_LogBinhost")
642 self.build_target = "board"
643 self.sysroot = os.path.join(self.tempdir, "build", "board")
644 osutils.SafeMakedirs(self.sysroot)
645 # Set up portage log directory.
646 self.target_sysroot = sysroot_lib.Sysroot(self.sysroot)
647 self.portage_dir = os.path.join(self.tempdir, "portage_logdir")
648 self.PatchObject(
649 sysroot_lib.Sysroot, "portage_logdir", new=self.portage_dir
650 )
651 osutils.SafeMakedirs(self.portage_dir)
652 # Set up goma directories.
653 self.goma_dir = os.path.join(self.tempdir, "goma_dir")
654 osutils.SafeMakedirs(self.goma_dir)
655 self.goma_out_dir = os.path.join(self.tempdir, "goma_out_dir")
656 osutils.SafeMakedirs(self.goma_out_dir)
657 os.environ["GLOG_log_dir"] = self.goma_dir
Alex Kleind4e1e422019-03-18 16:00:41 -0600658
Alex Klein1699fab2022-09-08 08:46:06 -0600659 def _InputProto(
660 self,
661 build_target=None,
662 sysroot_path=None,
663 build_source=False,
Yoshiki Iguchi2f7f0222023-05-17 19:30:09 +0900664 use_cq_prebuilts=False,
Alex Klein1699fab2022-09-08 08:46:06 -0600665 goma_dir=None,
666 goma_log_dir=None,
667 goma_stats_file=None,
668 goma_counterz_file=None,
669 package_indexes=None,
670 packages=None,
671 ):
672 """Helper to build an input proto instance."""
673 instance = sysroot_pb2.InstallPackagesRequest()
Alex Kleind4e1e422019-03-18 16:00:41 -0600674
Alex Klein1699fab2022-09-08 08:46:06 -0600675 if build_target:
676 instance.sysroot.build_target.name = build_target
677 if sysroot_path:
678 instance.sysroot.path = sysroot_path
679 if build_source:
680 instance.flags.build_source = build_source
Yoshiki Iguchi2f7f0222023-05-17 19:30:09 +0900681 if use_cq_prebuilts:
682 instance.flags.use_cq_prebuilts = use_cq_prebuilts
Alex Klein1699fab2022-09-08 08:46:06 -0600683 if goma_dir:
684 instance.goma_config.goma_dir = goma_dir
685 if goma_log_dir:
686 instance.goma_config.log_dir.dir = goma_log_dir
687 if goma_stats_file:
688 instance.goma_config.stats_file = goma_stats_file
689 if goma_counterz_file:
690 instance.goma_config.counterz_file = goma_counterz_file
691 if package_indexes:
692 instance.package_indexes.extend(package_indexes)
693 if packages:
694 for pkg in packages:
695 pkg_info = package_info.parse(pkg)
696 pkg_info_msg = instance.packages.add()
697 controller_util.serialize_package_info(pkg_info, pkg_info_msg)
698 return instance
Alex Kleind4e1e422019-03-18 16:00:41 -0600699
Alex Klein1699fab2022-09-08 08:46:06 -0600700 def _OutputProto(self):
701 """Helper to build an empty output proto instance."""
702 return sysroot_pb2.InstallPackagesResponse()
Alex Kleind4e1e422019-03-18 16:00:41 -0600703
Alex Klein1699fab2022-09-08 08:46:06 -0600704 def _CreateGomaLogFile(
705 self,
706 goma_log_dir: Union[str, os.PathLike],
707 name: str,
708 timestamp: datetime.datetime,
709 ):
710 """Creates a log file for testing.
Michael Mortensen798ee192020-01-17 13:04:43 -0700711
Alex Klein1699fab2022-09-08 08:46:06 -0600712 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600713 goma_log_dir: Directory where the file will be created.
714 name: Log file 'base' name that is combined with the timestamp.
715 timestamp: Timestamp that is written to the file.
Alex Klein1699fab2022-09-08 08:46:06 -0600716 """
717 path = os.path.join(
718 goma_log_dir,
719 "%s.host.log.INFO.%s"
720 % (name, timestamp.strftime("%Y%m%d-%H%M%S.%f")),
721 )
722 osutils.WriteFile(
723 path,
724 timestamp.strftime("Goma log file created at: %Y/%m/%d %H:%M:%S"),
725 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700726
Alex Klein1699fab2022-09-08 08:46:06 -0600727 def _CreatePortageLogFile(
728 self,
729 log_path: Union[str, os.PathLike],
730 pkg_info: package_info.PackageInfo,
731 timestamp: datetime.datetime,
732 ):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700733 """Creates a log file to test for individual packages built by Portage.
Lizzy Presland7e23a612021-11-09 21:49:42 +0000734
Alex Klein1699fab2022-09-08 08:46:06 -0600735 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600736 log_path: The PORTAGE_LOGDIR path.
737 pkg_info: Package name used to name the log file.
738 timestamp: Timestamp used to name the file.
Alex Klein1699fab2022-09-08 08:46:06 -0600739 """
740 path = os.path.join(
741 log_path,
742 f"{pkg_info.category}:{pkg_info.pvr}:"
743 f'{timestamp.strftime("%Y%m%d-%H%M%S")}.log',
744 )
745 osutils.WriteFile(
746 path,
747 f"Test log file for package {pkg_info.category}/"
748 f"{pkg_info.package} written to {path}",
749 )
750 return path
Lizzy Presland7e23a612021-11-09 21:49:42 +0000751
Alex Klein1699fab2022-09-08 08:46:06 -0600752 def testValidateOnly(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700753 """Verify a validate-only call does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -0600754 patch = self.PatchObject(sysroot_service, "BuildPackages")
Alex Klein231d2da2019-07-22 16:44:45 -0600755
Alex Klein1699fab2022-09-08 08:46:06 -0600756 in_proto = self._InputProto(
757 build_target=self.build_target, sysroot_path=self.sysroot
758 )
759 sysroot_controller.InstallPackages(
760 in_proto, self._OutputProto(), self.validate_only_config
761 )
762 patch.assert_not_called()
Alex Klein231d2da2019-07-22 16:44:45 -0600763
Alex Klein1699fab2022-09-08 08:46:06 -0600764 def testMockCall(self):
765 """Sanity check that a mock call does not execute any logic."""
766 patch = self.PatchObject(sysroot_service, "BuildPackages")
767 request = self._InputProto()
768 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -0600769
Alex Klein1699fab2022-09-08 08:46:06 -0600770 rc = sysroot_controller.InstallPackages(
771 request, response, self.mock_call_config
772 )
Alex Klein076841b2019-08-29 15:19:39 -0600773
Alex Klein1699fab2022-09-08 08:46:06 -0600774 patch.assert_not_called()
775 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
Alex Klein076841b2019-08-29 15:19:39 -0600776
Alex Klein1699fab2022-09-08 08:46:06 -0600777 def testMockError(self):
778 """Sanity check that a mock error does not execute any logic."""
779 patch = self.PatchObject(sysroot_service, "BuildPackages")
780 request = self._InputProto()
781 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -0600782
Alex Klein1699fab2022-09-08 08:46:06 -0600783 rc = sysroot_controller.InstallPackages(
784 request, response, self.mock_error_config
785 )
Alex Klein076841b2019-08-29 15:19:39 -0600786
Alex Klein1699fab2022-09-08 08:46:06 -0600787 patch.assert_not_called()
788 self.assertEqual(
789 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
790 )
791 self.assertTrue(response.failed_package_data)
Alex Klein076841b2019-08-29 15:19:39 -0600792
Alex Klein1699fab2022-09-08 08:46:06 -0600793 def testArgumentValidationAllMissing(self):
794 """Test missing all arguments."""
795 out_proto = self._OutputProto()
796 in_proto = self._InputProto()
797 with self.assertRaises(cros_build_lib.DieSystemExit):
798 sysroot_controller.InstallPackages(
799 in_proto, out_proto, self.api_config
800 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600801
Alex Klein1699fab2022-09-08 08:46:06 -0600802 def testArgumentValidationNoSysroot(self):
803 """Test missing sysroot path."""
804 out_proto = self._OutputProto()
805 in_proto = self._InputProto(build_target=self.build_target)
806 with self.assertRaises(cros_build_lib.DieSystemExit):
807 sysroot_controller.InstallPackages(
808 in_proto, out_proto, self.api_config
809 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600810
Alex Klein1699fab2022-09-08 08:46:06 -0600811 def testArgumentValidationNoBuildTarget(self):
812 """Test missing build target name."""
813 out_proto = self._OutputProto()
814 in_proto = self._InputProto(sysroot_path=self.sysroot)
815 with self.assertRaises(cros_build_lib.DieSystemExit):
816 sysroot_controller.InstallPackages(
817 in_proto, out_proto, self.api_config
818 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600819
Alex Klein1699fab2022-09-08 08:46:06 -0600820 def testArgumentValidationInvalidSysroot(self):
821 """Test sysroot that hasn't had the toolchain installed."""
822 out_proto = self._OutputProto()
823 in_proto = self._InputProto(
824 build_target=self.build_target, sysroot_path=self.sysroot
825 )
826 self.PatchObject(
827 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=False
828 )
829 with self.assertRaises(cros_build_lib.DieSystemExit):
830 sysroot_controller.InstallPackages(
831 in_proto, out_proto, self.api_config
832 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600833
Alex Klein1699fab2022-09-08 08:46:06 -0600834 def testArgumentValidationInvalidPackage(self):
835 out_proto = self._OutputProto()
836 in_proto = self._InputProto(
837 build_target=self.build_target,
838 sysroot_path=self.sysroot,
839 packages=["package-1.0.0-r2"],
840 )
841 with self.assertRaises(cros_build_lib.DieSystemExit):
842 sysroot_controller.InstallPackages(
843 in_proto, out_proto, self.api_config
844 )
Alex Kleinca572ee2020-09-03 10:47:14 -0600845
Alex Klein1699fab2022-09-08 08:46:06 -0600846 def testSuccessOutputHandling(self):
847 """Test successful call output handling."""
848 # Prevent argument validation error.
849 self.PatchObject(
850 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
851 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600852
Alex Klein1699fab2022-09-08 08:46:06 -0600853 in_proto = self._InputProto(
854 build_target=self.build_target, sysroot_path=self.sysroot
855 )
856 out_proto = self._OutputProto()
857 self.PatchObject(sysroot_service, "BuildPackages")
Alex Kleind4e1e422019-03-18 16:00:41 -0600858
Alex Klein1699fab2022-09-08 08:46:06 -0600859 rc = sysroot_controller.InstallPackages(
860 in_proto, out_proto, self.api_config
861 )
862 self.assertFalse(rc)
863 self.assertFalse(out_proto.failed_package_data)
Alex Kleind4e1e422019-03-18 16:00:41 -0600864
Alex Klein1699fab2022-09-08 08:46:06 -0600865 def testSuccessPackageIndexes(self):
866 """Test successful call with package_indexes."""
867 # Prevent argument validation error.
868 self.PatchObject(
869 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
870 )
871 package_indexes = [
872 common_pb2.PackageIndexInfo(
873 snapshot_sha="SHA",
874 snapshot_number=5,
875 build_target=common_pb2.BuildTarget(name="board"),
876 location="LOCATION",
877 profile=common_pb2.Profile(name="profile"),
878 ),
879 common_pb2.PackageIndexInfo(
880 snapshot_sha="SHA2",
881 snapshot_number=4,
882 build_target=common_pb2.BuildTarget(name="board"),
883 location="LOCATION2",
884 profile=common_pb2.Profile(name="profile"),
885 ),
886 ]
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600887
Alex Klein1699fab2022-09-08 08:46:06 -0600888 in_proto = self._InputProto(
889 build_target=self.build_target,
890 sysroot_path=self.sysroot,
891 package_indexes=package_indexes,
892 )
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600893
Alex Klein1699fab2022-09-08 08:46:06 -0600894 out_proto = self._OutputProto()
895 rc_patch = self.PatchObject(sysroot_service, "BuildPackagesRunConfig")
896 self.PatchObject(sysroot_service, "BuildPackages")
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600897
Alex Klein1699fab2022-09-08 08:46:06 -0600898 rc = sysroot_controller.InstallPackages(
899 in_proto, out_proto, self.api_config
900 )
901 self.assertFalse(rc)
902 rc_patch.assert_called_with(
903 use_any_chrome=False,
904 usepkg=True,
905 install_debug_symbols=True,
906 packages=[],
907 package_indexes=[
Alex Klein6d718d62023-01-18 15:55:51 -0700908 controller_util.deserialize_package_index_info(x)
Alex Klein1699fab2022-09-08 08:46:06 -0600909 for x in package_indexes
910 ],
911 use_flags=[],
912 use_goma=False,
913 use_remoteexec=False,
914 incremental_build=False,
915 dryrun=False,
916 backtrack=sysroot_controller.DEFAULT_BACKTRACK,
Alex Klein8393dc22023-03-30 10:54:27 -0600917 workon=False,
Alex Klein1699fab2022-09-08 08:46:06 -0600918 )
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600919
Alex Klein1699fab2022-09-08 08:46:06 -0600920 def testSuccessWithGomaLogs(self):
921 """Test successful call with goma."""
922 self._CreateGomaLogFile(
923 self.goma_dir,
924 "compiler_proxy",
925 datetime.datetime(2018, 9, 21, 12, 0, 0),
926 )
927 self._CreateGomaLogFile(
928 self.goma_dir,
929 "compiler_proxy-subproc",
930 datetime.datetime(2018, 9, 21, 12, 1, 0),
931 )
932 self._CreateGomaLogFile(
933 self.goma_dir, "gomacc", datetime.datetime(2018, 9, 21, 12, 2, 0)
934 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700935
Alex Klein1699fab2022-09-08 08:46:06 -0600936 # Prevent argument validation error.
937 self.PatchObject(
938 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
939 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700940
Alex Klein1699fab2022-09-08 08:46:06 -0600941 in_proto = self._InputProto(
942 build_target=self.build_target,
943 sysroot_path=self.sysroot,
944 goma_dir=self.goma_dir,
945 goma_log_dir=self.goma_out_dir,
946 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700947
Alex Klein1699fab2022-09-08 08:46:06 -0600948 out_proto = self._OutputProto()
949 self.PatchObject(sysroot_service, "BuildPackages")
Michael Mortensen798ee192020-01-17 13:04:43 -0700950
Alex Klein1699fab2022-09-08 08:46:06 -0600951 rc = sysroot_controller.InstallPackages(
952 in_proto, out_proto, self.api_config
953 )
954 self.assertFalse(rc)
955 self.assertFalse(out_proto.failed_package_data)
Alex Kleinab87ceb2023-01-24 12:00:51 -0700956
957 expected = [
958 "compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz",
959 "compiler_proxy.host.log.INFO.20180921-120000.000000.gz",
960 "gomacc.host.log.INFO.20180921-120200.000000.tar.gz",
961 ]
962 self.assertCountEqual(out_proto.goma_artifacts.log_files, expected)
Michael Mortensen798ee192020-01-17 13:04:43 -0700963
Alex Klein1699fab2022-09-08 08:46:06 -0600964 def testSuccessWithGomaLogsAndStatsCounterzFiles(self):
965 """Test successful call with goma including stats and counterz files."""
966 self._CreateGomaLogFile(
967 self.goma_dir,
968 "compiler_proxy",
969 datetime.datetime(2018, 9, 21, 12, 0, 0),
970 )
971 self._CreateGomaLogFile(
972 self.goma_dir,
973 "compiler_proxy-subproc",
974 datetime.datetime(2018, 9, 21, 12, 1, 0),
975 )
976 self._CreateGomaLogFile(
977 self.goma_dir, "gomacc", datetime.datetime(2018, 9, 21, 12, 2, 0)
978 )
979 # Create stats and counterz files.
980 osutils.WriteFile(
981 os.path.join(self.goma_dir, "stats.binaryproto"),
982 "File: stats.binaryproto",
983 )
984 osutils.WriteFile(
985 os.path.join(self.goma_dir, "counterz.binaryproto"),
986 "File: counterz.binaryproto",
987 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700988
Alex Klein1699fab2022-09-08 08:46:06 -0600989 # Prevent argument validation error.
990 self.PatchObject(
991 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
992 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700993
Alex Klein1699fab2022-09-08 08:46:06 -0600994 in_proto = self._InputProto(
995 build_target=self.build_target,
996 sysroot_path=self.sysroot,
997 goma_dir=self.goma_dir,
998 goma_log_dir=self.goma_out_dir,
999 goma_stats_file="stats.binaryproto",
1000 goma_counterz_file="counterz.binaryproto",
1001 )
Michael Mortensen798ee192020-01-17 13:04:43 -07001002
Alex Klein1699fab2022-09-08 08:46:06 -06001003 out_proto = self._OutputProto()
1004 self.PatchObject(sysroot_service, "BuildPackages")
Michael Mortensen798ee192020-01-17 13:04:43 -07001005
Alex Klein1699fab2022-09-08 08:46:06 -06001006 rc = sysroot_controller.InstallPackages(
1007 in_proto, out_proto, self.api_config
1008 )
1009 self.assertFalse(rc)
1010 self.assertFalse(out_proto.failed_package_data)
Alex Kleinab87ceb2023-01-24 12:00:51 -07001011 expected_logs = [
1012 "compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz",
1013 "compiler_proxy.host.log.INFO.20180921-120000.000000.gz",
1014 "gomacc.host.log.INFO.20180921-120200.000000.tar.gz",
1015 ]
1016 self.assertCountEqual(out_proto.goma_artifacts.log_files, expected_logs)
1017
Alex Klein1699fab2022-09-08 08:46:06 -06001018 # Verify that the output dir has 5 files -- since there should be 3 log
1019 # files, the stats file, and the counterz file.
1020 output_files = os.listdir(self.goma_out_dir)
Alex Kleinab87ceb2023-01-24 12:00:51 -07001021 expected_output = [
1022 "stats.binaryproto",
1023 "counterz.binaryproto",
1024 "compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz",
1025 "compiler_proxy.host.log.INFO.20180921-120000.000000.gz",
1026 "gomacc.host.log.INFO.20180921-120200.000000.tar.gz",
1027 ]
1028 self.assertCountEqual(output_files, expected_output)
Alex Klein1699fab2022-09-08 08:46:06 -06001029 self.assertEqual(
1030 out_proto.goma_artifacts.counterz_file, "counterz.binaryproto"
1031 )
1032 self.assertEqual(
1033 out_proto.goma_artifacts.stats_file, "stats.binaryproto"
1034 )
Michael Mortensen798ee192020-01-17 13:04:43 -07001035
Alex Klein1699fab2022-09-08 08:46:06 -06001036 def testFailureMissingGomaStatsCounterzFiles(self):
1037 """Test successful call with goma including stats and counterz files."""
1038 self._CreateGomaLogFile(
1039 self.goma_dir,
1040 "compiler_proxy",
1041 datetime.datetime(2018, 9, 21, 12, 0, 0),
1042 )
1043 self._CreateGomaLogFile(
1044 self.goma_dir,
1045 "compiler_proxy-subproc",
1046 datetime.datetime(2018, 9, 21, 12, 1, 0),
1047 )
1048 self._CreateGomaLogFile(
1049 self.goma_dir, "gomacc", datetime.datetime(2018, 9, 21, 12, 2, 0)
1050 )
Alex Kleinab87ceb2023-01-24 12:00:51 -07001051 # Note that stats and counterz files are not created, but are specified
1052 # in the proto below.
Michael Mortensen798ee192020-01-17 13:04:43 -07001053
Alex Klein1699fab2022-09-08 08:46:06 -06001054 # Prevent argument validation error.
1055 self.PatchObject(
1056 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
1057 )
Michael Mortensen798ee192020-01-17 13:04:43 -07001058
Alex Klein1699fab2022-09-08 08:46:06 -06001059 in_proto = self._InputProto(
1060 build_target=self.build_target,
1061 sysroot_path=self.sysroot,
1062 goma_dir=self.goma_dir,
1063 goma_log_dir=self.goma_out_dir,
1064 goma_stats_file="stats.binaryproto",
1065 goma_counterz_file="counterz.binaryproto",
1066 )
Michael Mortensen798ee192020-01-17 13:04:43 -07001067
Alex Klein1699fab2022-09-08 08:46:06 -06001068 out_proto = self._OutputProto()
1069 self.PatchObject(sysroot_service, "BuildPackages")
Michael Mortensen798ee192020-01-17 13:04:43 -07001070
Alex Klein1699fab2022-09-08 08:46:06 -06001071 rc = sysroot_controller.InstallPackages(
1072 in_proto, out_proto, self.api_config
1073 )
1074 self.assertFalse(rc)
1075 self.assertFalse(out_proto.failed_package_data)
Alex Kleinab87ceb2023-01-24 12:00:51 -07001076 expected_logs = [
1077 "compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz",
1078 "compiler_proxy.host.log.INFO.20180921-120000.000000.gz",
1079 "gomacc.host.log.INFO.20180921-120200.000000.tar.gz",
1080 ]
1081 self.assertCountEqual(out_proto.goma_artifacts.log_files, expected_logs)
Alex Klein1699fab2022-09-08 08:46:06 -06001082 self.assertFalse(out_proto.goma_artifacts.counterz_file)
1083 self.assertFalse(out_proto.goma_artifacts.stats_file)
Michael Mortensen798ee192020-01-17 13:04:43 -07001084
Alex Klein1699fab2022-09-08 08:46:06 -06001085 def testFailureOutputHandling(self):
1086 """Test failed package handling."""
1087 # Prevent argument validation error.
1088 self.PatchObject(
1089 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
1090 )
Alex Kleind4e1e422019-03-18 16:00:41 -06001091
Alex Klein1699fab2022-09-08 08:46:06 -06001092 in_proto = self._InputProto(
1093 build_target=self.build_target, sysroot_path=self.sysroot
1094 )
1095 out_proto = self._OutputProto()
Alex Kleind4e1e422019-03-18 16:00:41 -06001096
Alex Klein1699fab2022-09-08 08:46:06 -06001097 # Failed package info and expected list for verification.
1098 err_pkgs = ["cat/pkg-1.0-r3", "cat2/pkg2-1.0-r1"]
1099 err_cpvs = [package_info.parse(cpv) for cpv in err_pkgs]
1100 expected = [("cat", "pkg"), ("cat2", "pkg2")]
Alex Kleind4e1e422019-03-18 16:00:41 -06001101
Alex Klein1699fab2022-09-08 08:46:06 -06001102 new_logs = {}
1103 for i, pkg in enumerate(err_pkgs):
1104 self._CreatePortageLogFile(
1105 self.portage_dir,
1106 err_cpvs[i],
1107 datetime.datetime(2021, 6, 9, 13, 37, 0),
1108 )
1109 new_logs[pkg] = self._CreatePortageLogFile(
1110 self.portage_dir,
1111 err_cpvs[i],
1112 datetime.datetime(2021, 6, 9, 16, 20, 0),
1113 )
1114 # Force error to be raised with the packages.
1115 error = sysroot_lib.PackageInstallError(
1116 "Error", cros_build_lib.CompletedProcess(), packages=err_cpvs
1117 )
1118 self.PatchObject(sysroot_service, "BuildPackages", side_effect=error)
Alex Kleind4e1e422019-03-18 16:00:41 -06001119
Alex Klein1699fab2022-09-08 08:46:06 -06001120 rc = sysroot_controller.InstallPackages(
1121 in_proto, out_proto, self.api_config
1122 )
1123 # This needs to return 2 to indicate the available error response.
1124 self.assertEqual(
1125 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
1126 )
1127 for data in out_proto.failed_package_data:
1128 package = controller_util.deserialize_package_info(data.name)
1129 cat_pkg = (data.name.category, data.name.package_name)
1130 self.assertIn(cat_pkg, expected)
1131 self.assertEqual(data.log_path.path, new_logs[package.cpvr])
Lizzy Presland7e23a612021-11-09 21:49:42 +00001132
Alex Klein1699fab2022-09-08 08:46:06 -06001133 def testNoPackageFailureOutputHandling(self):
1134 """Test failure handling without packages to report."""
1135 # Prevent argument validation error.
1136 self.PatchObject(
1137 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
1138 )
Alex Klein2557b4f2019-07-11 14:34:00 -06001139
Alex Klein1699fab2022-09-08 08:46:06 -06001140 in_proto = self._InputProto(
1141 build_target=self.build_target, sysroot_path=self.sysroot
1142 )
1143 out_proto = self._OutputProto()
Alex Klein2557b4f2019-07-11 14:34:00 -06001144
Alex Klein1699fab2022-09-08 08:46:06 -06001145 # Force error to be raised with no packages.
1146 error = sysroot_lib.PackageInstallError(
1147 "Error", cros_build_lib.CompletedProcess(), packages=[]
1148 )
1149 self.PatchObject(sysroot_service, "BuildPackages", side_effect=error)
Alex Klein2557b4f2019-07-11 14:34:00 -06001150
Alex Klein1699fab2022-09-08 08:46:06 -06001151 rc = sysroot_controller.InstallPackages(
1152 in_proto, out_proto, self.api_config
1153 )
1154 # All we really care about is it's not 0 or 2 (response available), so
1155 # test for that rather than a specific return code.
1156 self.assertTrue(rc)
1157 self.assertNotEqual(
1158 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
1159 )