blob: 1846027f53d7525e451b5474ef5d22d0890ebb76 [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,
Ryo Hashimoto0845ebf2023-06-06 19:21:13 +0900671 bazel=False,
Alex Klein1699fab2022-09-08 08:46:06 -0600672 ):
673 """Helper to build an input proto instance."""
674 instance = sysroot_pb2.InstallPackagesRequest()
Alex Kleind4e1e422019-03-18 16:00:41 -0600675
Alex Klein1699fab2022-09-08 08:46:06 -0600676 if build_target:
677 instance.sysroot.build_target.name = build_target
678 if sysroot_path:
679 instance.sysroot.path = sysroot_path
680 if build_source:
681 instance.flags.build_source = build_source
Yoshiki Iguchi2f7f0222023-05-17 19:30:09 +0900682 if use_cq_prebuilts:
683 instance.flags.use_cq_prebuilts = use_cq_prebuilts
Alex Klein1699fab2022-09-08 08:46:06 -0600684 if goma_dir:
685 instance.goma_config.goma_dir = goma_dir
686 if goma_log_dir:
687 instance.goma_config.log_dir.dir = goma_log_dir
688 if goma_stats_file:
689 instance.goma_config.stats_file = goma_stats_file
690 if goma_counterz_file:
691 instance.goma_config.counterz_file = goma_counterz_file
692 if package_indexes:
693 instance.package_indexes.extend(package_indexes)
694 if packages:
695 for pkg in packages:
696 pkg_info = package_info.parse(pkg)
697 pkg_info_msg = instance.packages.add()
698 controller_util.serialize_package_info(pkg_info, pkg_info_msg)
Ryo Hashimoto0845ebf2023-06-06 19:21:13 +0900699 if bazel:
700 instance.flags.bazel = bazel
Alex Klein1699fab2022-09-08 08:46:06 -0600701 return instance
Alex Kleind4e1e422019-03-18 16:00:41 -0600702
Alex Klein1699fab2022-09-08 08:46:06 -0600703 def _OutputProto(self):
704 """Helper to build an empty output proto instance."""
705 return sysroot_pb2.InstallPackagesResponse()
Alex Kleind4e1e422019-03-18 16:00:41 -0600706
Alex Klein1699fab2022-09-08 08:46:06 -0600707 def _CreateGomaLogFile(
708 self,
709 goma_log_dir: Union[str, os.PathLike],
710 name: str,
711 timestamp: datetime.datetime,
712 ):
713 """Creates a log file for testing.
Michael Mortensen798ee192020-01-17 13:04:43 -0700714
Alex Klein1699fab2022-09-08 08:46:06 -0600715 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600716 goma_log_dir: Directory where the file will be created.
717 name: Log file 'base' name that is combined with the timestamp.
718 timestamp: Timestamp that is written to the file.
Alex Klein1699fab2022-09-08 08:46:06 -0600719 """
720 path = os.path.join(
721 goma_log_dir,
722 "%s.host.log.INFO.%s"
723 % (name, timestamp.strftime("%Y%m%d-%H%M%S.%f")),
724 )
725 osutils.WriteFile(
726 path,
727 timestamp.strftime("Goma log file created at: %Y/%m/%d %H:%M:%S"),
728 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700729
Alex Klein1699fab2022-09-08 08:46:06 -0600730 def _CreatePortageLogFile(
731 self,
732 log_path: Union[str, os.PathLike],
733 pkg_info: package_info.PackageInfo,
734 timestamp: datetime.datetime,
735 ):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700736 """Creates a log file to test for individual packages built by Portage.
Lizzy Presland7e23a612021-11-09 21:49:42 +0000737
Alex Klein1699fab2022-09-08 08:46:06 -0600738 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600739 log_path: The PORTAGE_LOGDIR path.
740 pkg_info: Package name used to name the log file.
741 timestamp: Timestamp used to name the file.
Alex Klein1699fab2022-09-08 08:46:06 -0600742 """
743 path = os.path.join(
744 log_path,
745 f"{pkg_info.category}:{pkg_info.pvr}:"
746 f'{timestamp.strftime("%Y%m%d-%H%M%S")}.log',
747 )
748 osutils.WriteFile(
749 path,
750 f"Test log file for package {pkg_info.category}/"
751 f"{pkg_info.package} written to {path}",
752 )
753 return path
Lizzy Presland7e23a612021-11-09 21:49:42 +0000754
Alex Klein1699fab2022-09-08 08:46:06 -0600755 def testValidateOnly(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700756 """Verify a validate-only call does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -0600757 patch = self.PatchObject(sysroot_service, "BuildPackages")
Alex Klein231d2da2019-07-22 16:44:45 -0600758
Alex Klein1699fab2022-09-08 08:46:06 -0600759 in_proto = self._InputProto(
760 build_target=self.build_target, sysroot_path=self.sysroot
761 )
762 sysroot_controller.InstallPackages(
763 in_proto, self._OutputProto(), self.validate_only_config
764 )
765 patch.assert_not_called()
Alex Klein231d2da2019-07-22 16:44:45 -0600766
Alex Klein1699fab2022-09-08 08:46:06 -0600767 def testMockCall(self):
768 """Sanity check that a mock call does not execute any logic."""
769 patch = self.PatchObject(sysroot_service, "BuildPackages")
770 request = self._InputProto()
771 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -0600772
Alex Klein1699fab2022-09-08 08:46:06 -0600773 rc = sysroot_controller.InstallPackages(
774 request, response, self.mock_call_config
775 )
Alex Klein076841b2019-08-29 15:19:39 -0600776
Alex Klein1699fab2022-09-08 08:46:06 -0600777 patch.assert_not_called()
778 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
Alex Klein076841b2019-08-29 15:19:39 -0600779
Alex Klein1699fab2022-09-08 08:46:06 -0600780 def testMockError(self):
781 """Sanity check that a mock error does not execute any logic."""
782 patch = self.PatchObject(sysroot_service, "BuildPackages")
783 request = self._InputProto()
784 response = self._OutputProto()
Alex Klein076841b2019-08-29 15:19:39 -0600785
Alex Klein1699fab2022-09-08 08:46:06 -0600786 rc = sysroot_controller.InstallPackages(
787 request, response, self.mock_error_config
788 )
Alex Klein076841b2019-08-29 15:19:39 -0600789
Alex Klein1699fab2022-09-08 08:46:06 -0600790 patch.assert_not_called()
791 self.assertEqual(
792 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
793 )
794 self.assertTrue(response.failed_package_data)
Alex Klein076841b2019-08-29 15:19:39 -0600795
Alex Klein1699fab2022-09-08 08:46:06 -0600796 def testArgumentValidationAllMissing(self):
797 """Test missing all arguments."""
798 out_proto = self._OutputProto()
799 in_proto = self._InputProto()
800 with self.assertRaises(cros_build_lib.DieSystemExit):
801 sysroot_controller.InstallPackages(
802 in_proto, out_proto, self.api_config
803 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600804
Alex Klein1699fab2022-09-08 08:46:06 -0600805 def testArgumentValidationNoSysroot(self):
806 """Test missing sysroot path."""
807 out_proto = self._OutputProto()
808 in_proto = self._InputProto(build_target=self.build_target)
809 with self.assertRaises(cros_build_lib.DieSystemExit):
810 sysroot_controller.InstallPackages(
811 in_proto, out_proto, self.api_config
812 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600813
Alex Klein1699fab2022-09-08 08:46:06 -0600814 def testArgumentValidationNoBuildTarget(self):
815 """Test missing build target name."""
816 out_proto = self._OutputProto()
817 in_proto = self._InputProto(sysroot_path=self.sysroot)
818 with self.assertRaises(cros_build_lib.DieSystemExit):
819 sysroot_controller.InstallPackages(
820 in_proto, out_proto, self.api_config
821 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600822
Alex Klein1699fab2022-09-08 08:46:06 -0600823 def testArgumentValidationInvalidSysroot(self):
824 """Test sysroot that hasn't had the toolchain installed."""
825 out_proto = self._OutputProto()
826 in_proto = self._InputProto(
827 build_target=self.build_target, sysroot_path=self.sysroot
828 )
829 self.PatchObject(
830 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=False
831 )
832 with self.assertRaises(cros_build_lib.DieSystemExit):
833 sysroot_controller.InstallPackages(
834 in_proto, out_proto, self.api_config
835 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600836
Alex Klein1699fab2022-09-08 08:46:06 -0600837 def testArgumentValidationInvalidPackage(self):
838 out_proto = self._OutputProto()
839 in_proto = self._InputProto(
840 build_target=self.build_target,
841 sysroot_path=self.sysroot,
842 packages=["package-1.0.0-r2"],
843 )
844 with self.assertRaises(cros_build_lib.DieSystemExit):
845 sysroot_controller.InstallPackages(
846 in_proto, out_proto, self.api_config
847 )
Alex Kleinca572ee2020-09-03 10:47:14 -0600848
Alex Klein1699fab2022-09-08 08:46:06 -0600849 def testSuccessOutputHandling(self):
850 """Test successful call output handling."""
851 # Prevent argument validation error.
852 self.PatchObject(
853 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
854 )
Alex Kleind4e1e422019-03-18 16:00:41 -0600855
Alex Klein1699fab2022-09-08 08:46:06 -0600856 in_proto = self._InputProto(
857 build_target=self.build_target, sysroot_path=self.sysroot
858 )
859 out_proto = self._OutputProto()
860 self.PatchObject(sysroot_service, "BuildPackages")
Alex Kleind4e1e422019-03-18 16:00:41 -0600861
Alex Klein1699fab2022-09-08 08:46:06 -0600862 rc = sysroot_controller.InstallPackages(
863 in_proto, out_proto, self.api_config
864 )
865 self.assertFalse(rc)
866 self.assertFalse(out_proto.failed_package_data)
Alex Kleind4e1e422019-03-18 16:00:41 -0600867
Alex Klein1699fab2022-09-08 08:46:06 -0600868 def testSuccessPackageIndexes(self):
869 """Test successful call with package_indexes."""
870 # Prevent argument validation error.
871 self.PatchObject(
872 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
873 )
874 package_indexes = [
875 common_pb2.PackageIndexInfo(
876 snapshot_sha="SHA",
877 snapshot_number=5,
878 build_target=common_pb2.BuildTarget(name="board"),
879 location="LOCATION",
880 profile=common_pb2.Profile(name="profile"),
881 ),
882 common_pb2.PackageIndexInfo(
883 snapshot_sha="SHA2",
884 snapshot_number=4,
885 build_target=common_pb2.BuildTarget(name="board"),
886 location="LOCATION2",
887 profile=common_pb2.Profile(name="profile"),
888 ),
889 ]
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600890
Alex Klein1699fab2022-09-08 08:46:06 -0600891 in_proto = self._InputProto(
892 build_target=self.build_target,
893 sysroot_path=self.sysroot,
894 package_indexes=package_indexes,
895 )
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600896
Alex Klein1699fab2022-09-08 08:46:06 -0600897 out_proto = self._OutputProto()
898 rc_patch = self.PatchObject(sysroot_service, "BuildPackagesRunConfig")
899 self.PatchObject(sysroot_service, "BuildPackages")
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600900
Alex Klein1699fab2022-09-08 08:46:06 -0600901 rc = sysroot_controller.InstallPackages(
902 in_proto, out_proto, self.api_config
903 )
904 self.assertFalse(rc)
905 rc_patch.assert_called_with(
906 use_any_chrome=False,
907 usepkg=True,
908 install_debug_symbols=True,
909 packages=[],
910 package_indexes=[
Alex Klein6d718d62023-01-18 15:55:51 -0700911 controller_util.deserialize_package_index_info(x)
Alex Klein1699fab2022-09-08 08:46:06 -0600912 for x in package_indexes
913 ],
914 use_flags=[],
915 use_goma=False,
916 use_remoteexec=False,
917 incremental_build=False,
918 dryrun=False,
919 backtrack=sysroot_controller.DEFAULT_BACKTRACK,
Alex Klein8393dc22023-03-30 10:54:27 -0600920 workon=False,
Ryo Hashimoto0845ebf2023-06-06 19:21:13 +0900921 bazel=False,
Alex Klein1699fab2022-09-08 08:46:06 -0600922 )
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600923
Alex Klein1699fab2022-09-08 08:46:06 -0600924 def testSuccessWithGomaLogs(self):
925 """Test successful call with goma."""
926 self._CreateGomaLogFile(
927 self.goma_dir,
928 "compiler_proxy",
929 datetime.datetime(2018, 9, 21, 12, 0, 0),
930 )
931 self._CreateGomaLogFile(
932 self.goma_dir,
933 "compiler_proxy-subproc",
934 datetime.datetime(2018, 9, 21, 12, 1, 0),
935 )
936 self._CreateGomaLogFile(
937 self.goma_dir, "gomacc", datetime.datetime(2018, 9, 21, 12, 2, 0)
938 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700939
Alex Klein1699fab2022-09-08 08:46:06 -0600940 # Prevent argument validation error.
941 self.PatchObject(
942 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
943 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700944
Alex Klein1699fab2022-09-08 08:46:06 -0600945 in_proto = self._InputProto(
946 build_target=self.build_target,
947 sysroot_path=self.sysroot,
948 goma_dir=self.goma_dir,
949 goma_log_dir=self.goma_out_dir,
950 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700951
Alex Klein1699fab2022-09-08 08:46:06 -0600952 out_proto = self._OutputProto()
953 self.PatchObject(sysroot_service, "BuildPackages")
Michael Mortensen798ee192020-01-17 13:04:43 -0700954
Alex Klein1699fab2022-09-08 08:46:06 -0600955 rc = sysroot_controller.InstallPackages(
956 in_proto, out_proto, self.api_config
957 )
958 self.assertFalse(rc)
959 self.assertFalse(out_proto.failed_package_data)
Alex Kleinab87ceb2023-01-24 12:00:51 -0700960
961 expected = [
962 "compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz",
963 "compiler_proxy.host.log.INFO.20180921-120000.000000.gz",
964 "gomacc.host.log.INFO.20180921-120200.000000.tar.gz",
965 ]
966 self.assertCountEqual(out_proto.goma_artifacts.log_files, expected)
Michael Mortensen798ee192020-01-17 13:04:43 -0700967
Alex Klein1699fab2022-09-08 08:46:06 -0600968 def testSuccessWithGomaLogsAndStatsCounterzFiles(self):
969 """Test successful call with goma including stats and counterz files."""
970 self._CreateGomaLogFile(
971 self.goma_dir,
972 "compiler_proxy",
973 datetime.datetime(2018, 9, 21, 12, 0, 0),
974 )
975 self._CreateGomaLogFile(
976 self.goma_dir,
977 "compiler_proxy-subproc",
978 datetime.datetime(2018, 9, 21, 12, 1, 0),
979 )
980 self._CreateGomaLogFile(
981 self.goma_dir, "gomacc", datetime.datetime(2018, 9, 21, 12, 2, 0)
982 )
983 # Create stats and counterz files.
984 osutils.WriteFile(
985 os.path.join(self.goma_dir, "stats.binaryproto"),
986 "File: stats.binaryproto",
987 )
988 osutils.WriteFile(
989 os.path.join(self.goma_dir, "counterz.binaryproto"),
990 "File: counterz.binaryproto",
991 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700992
Alex Klein1699fab2022-09-08 08:46:06 -0600993 # Prevent argument validation error.
994 self.PatchObject(
995 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
996 )
Michael Mortensen798ee192020-01-17 13:04:43 -0700997
Alex Klein1699fab2022-09-08 08:46:06 -0600998 in_proto = self._InputProto(
999 build_target=self.build_target,
1000 sysroot_path=self.sysroot,
1001 goma_dir=self.goma_dir,
1002 goma_log_dir=self.goma_out_dir,
1003 goma_stats_file="stats.binaryproto",
1004 goma_counterz_file="counterz.binaryproto",
1005 )
Michael Mortensen798ee192020-01-17 13:04:43 -07001006
Alex Klein1699fab2022-09-08 08:46:06 -06001007 out_proto = self._OutputProto()
1008 self.PatchObject(sysroot_service, "BuildPackages")
Michael Mortensen798ee192020-01-17 13:04:43 -07001009
Alex Klein1699fab2022-09-08 08:46:06 -06001010 rc = sysroot_controller.InstallPackages(
1011 in_proto, out_proto, self.api_config
1012 )
1013 self.assertFalse(rc)
1014 self.assertFalse(out_proto.failed_package_data)
Alex Kleinab87ceb2023-01-24 12:00:51 -07001015 expected_logs = [
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 self.assertCountEqual(out_proto.goma_artifacts.log_files, expected_logs)
1021
Alex Klein1699fab2022-09-08 08:46:06 -06001022 # Verify that the output dir has 5 files -- since there should be 3 log
1023 # files, the stats file, and the counterz file.
1024 output_files = os.listdir(self.goma_out_dir)
Alex Kleinab87ceb2023-01-24 12:00:51 -07001025 expected_output = [
1026 "stats.binaryproto",
1027 "counterz.binaryproto",
1028 "compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz",
1029 "compiler_proxy.host.log.INFO.20180921-120000.000000.gz",
1030 "gomacc.host.log.INFO.20180921-120200.000000.tar.gz",
1031 ]
1032 self.assertCountEqual(output_files, expected_output)
Alex Klein1699fab2022-09-08 08:46:06 -06001033 self.assertEqual(
1034 out_proto.goma_artifacts.counterz_file, "counterz.binaryproto"
1035 )
1036 self.assertEqual(
1037 out_proto.goma_artifacts.stats_file, "stats.binaryproto"
1038 )
Michael Mortensen798ee192020-01-17 13:04:43 -07001039
Alex Klein1699fab2022-09-08 08:46:06 -06001040 def testFailureMissingGomaStatsCounterzFiles(self):
1041 """Test successful call with goma including stats and counterz files."""
1042 self._CreateGomaLogFile(
1043 self.goma_dir,
1044 "compiler_proxy",
1045 datetime.datetime(2018, 9, 21, 12, 0, 0),
1046 )
1047 self._CreateGomaLogFile(
1048 self.goma_dir,
1049 "compiler_proxy-subproc",
1050 datetime.datetime(2018, 9, 21, 12, 1, 0),
1051 )
1052 self._CreateGomaLogFile(
1053 self.goma_dir, "gomacc", datetime.datetime(2018, 9, 21, 12, 2, 0)
1054 )
Alex Kleinab87ceb2023-01-24 12:00:51 -07001055 # Note that stats and counterz files are not created, but are specified
1056 # in the proto below.
Michael Mortensen798ee192020-01-17 13:04:43 -07001057
Alex Klein1699fab2022-09-08 08:46:06 -06001058 # Prevent argument validation error.
1059 self.PatchObject(
1060 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
1061 )
Michael Mortensen798ee192020-01-17 13:04:43 -07001062
Alex Klein1699fab2022-09-08 08:46:06 -06001063 in_proto = self._InputProto(
1064 build_target=self.build_target,
1065 sysroot_path=self.sysroot,
1066 goma_dir=self.goma_dir,
1067 goma_log_dir=self.goma_out_dir,
1068 goma_stats_file="stats.binaryproto",
1069 goma_counterz_file="counterz.binaryproto",
1070 )
Michael Mortensen798ee192020-01-17 13:04:43 -07001071
Alex Klein1699fab2022-09-08 08:46:06 -06001072 out_proto = self._OutputProto()
1073 self.PatchObject(sysroot_service, "BuildPackages")
Michael Mortensen798ee192020-01-17 13:04:43 -07001074
Alex Klein1699fab2022-09-08 08:46:06 -06001075 rc = sysroot_controller.InstallPackages(
1076 in_proto, out_proto, self.api_config
1077 )
1078 self.assertFalse(rc)
1079 self.assertFalse(out_proto.failed_package_data)
Alex Kleinab87ceb2023-01-24 12:00:51 -07001080 expected_logs = [
1081 "compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz",
1082 "compiler_proxy.host.log.INFO.20180921-120000.000000.gz",
1083 "gomacc.host.log.INFO.20180921-120200.000000.tar.gz",
1084 ]
1085 self.assertCountEqual(out_proto.goma_artifacts.log_files, expected_logs)
Alex Klein1699fab2022-09-08 08:46:06 -06001086 self.assertFalse(out_proto.goma_artifacts.counterz_file)
1087 self.assertFalse(out_proto.goma_artifacts.stats_file)
Michael Mortensen798ee192020-01-17 13:04:43 -07001088
Alex Klein1699fab2022-09-08 08:46:06 -06001089 def testFailureOutputHandling(self):
1090 """Test failed package handling."""
1091 # Prevent argument validation error.
1092 self.PatchObject(
1093 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
1094 )
Alex Kleind4e1e422019-03-18 16:00:41 -06001095
Alex Klein1699fab2022-09-08 08:46:06 -06001096 in_proto = self._InputProto(
1097 build_target=self.build_target, sysroot_path=self.sysroot
1098 )
1099 out_proto = self._OutputProto()
Alex Kleind4e1e422019-03-18 16:00:41 -06001100
Alex Klein1699fab2022-09-08 08:46:06 -06001101 # Failed package info and expected list for verification.
1102 err_pkgs = ["cat/pkg-1.0-r3", "cat2/pkg2-1.0-r1"]
1103 err_cpvs = [package_info.parse(cpv) for cpv in err_pkgs]
1104 expected = [("cat", "pkg"), ("cat2", "pkg2")]
Alex Kleind4e1e422019-03-18 16:00:41 -06001105
Alex Klein1699fab2022-09-08 08:46:06 -06001106 new_logs = {}
1107 for i, pkg in enumerate(err_pkgs):
1108 self._CreatePortageLogFile(
1109 self.portage_dir,
1110 err_cpvs[i],
1111 datetime.datetime(2021, 6, 9, 13, 37, 0),
1112 )
1113 new_logs[pkg] = self._CreatePortageLogFile(
1114 self.portage_dir,
1115 err_cpvs[i],
1116 datetime.datetime(2021, 6, 9, 16, 20, 0),
1117 )
1118 # Force error to be raised with the packages.
1119 error = sysroot_lib.PackageInstallError(
1120 "Error", cros_build_lib.CompletedProcess(), packages=err_cpvs
1121 )
1122 self.PatchObject(sysroot_service, "BuildPackages", side_effect=error)
Alex Kleind4e1e422019-03-18 16:00:41 -06001123
Alex Klein1699fab2022-09-08 08:46:06 -06001124 rc = sysroot_controller.InstallPackages(
1125 in_proto, out_proto, self.api_config
1126 )
1127 # This needs to return 2 to indicate the available error response.
1128 self.assertEqual(
1129 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
1130 )
1131 for data in out_proto.failed_package_data:
1132 package = controller_util.deserialize_package_info(data.name)
1133 cat_pkg = (data.name.category, data.name.package_name)
1134 self.assertIn(cat_pkg, expected)
1135 self.assertEqual(data.log_path.path, new_logs[package.cpvr])
Lizzy Presland7e23a612021-11-09 21:49:42 +00001136
Alex Klein1699fab2022-09-08 08:46:06 -06001137 def testNoPackageFailureOutputHandling(self):
1138 """Test failure handling without packages to report."""
1139 # Prevent argument validation error.
1140 self.PatchObject(
1141 sysroot_lib.Sysroot, "IsToolchainInstalled", return_value=True
1142 )
Alex Klein2557b4f2019-07-11 14:34:00 -06001143
Alex Klein1699fab2022-09-08 08:46:06 -06001144 in_proto = self._InputProto(
1145 build_target=self.build_target, sysroot_path=self.sysroot
1146 )
1147 out_proto = self._OutputProto()
Alex Klein2557b4f2019-07-11 14:34:00 -06001148
Alex Klein1699fab2022-09-08 08:46:06 -06001149 # Force error to be raised with no packages.
1150 error = sysroot_lib.PackageInstallError(
1151 "Error", cros_build_lib.CompletedProcess(), packages=[]
1152 )
1153 self.PatchObject(sysroot_service, "BuildPackages", side_effect=error)
Alex Klein2557b4f2019-07-11 14:34:00 -06001154
Alex Klein1699fab2022-09-08 08:46:06 -06001155 rc = sysroot_controller.InstallPackages(
1156 in_proto, out_proto, self.api_config
1157 )
1158 # All we really care about is it's not 0 or 2 (response available), so
1159 # test for that rather than a specific return code.
1160 self.assertTrue(rc)
1161 self.assertNotEqual(
1162 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
1163 )