blob: a9e75449450eecb2c72d7c125eff6b9ac2daea01 [file] [log] [blame]
Alex Kleinda35fcf2019-03-07 16:01:15 -07001# Copyright 2019 The Chromium OS Authors. All rights reserved.
2# 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
9
Alex Klein231d2da2019-07-22 16:44:45 -060010from chromite.api import api_config
Alex Klein8cb365a2019-05-15 16:24:53 -060011from chromite.api import controller
Alex Kleinca572ee2020-09-03 10:47:14 -060012from chromite.api.controller import controller_util
Alex Kleinda35fcf2019-03-07 16:01:15 -070013from chromite.api.controller import sysroot as sysroot_controller
14from chromite.api.gen.chromite.api import sysroot_pb2
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -070015from chromite.api.gen.chromiumos import common_pb2
LaMont Jonesc0343fa2020-08-12 18:58:31 -060016from chromite.lib import binpkg
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 Kleinda35fcf2019-03-07 16:01:15 -070026 """Create function tests."""
27
28 def _InputProto(self, build_target=None, profile=None, replace=False,
LaMont Jonesc0343fa2020-08-12 18:58:31 -060029 current=False, package_indexes=None):
Alex Kleinda35fcf2019-03-07 16:01:15 -070030 """Helper to build and input proto instance."""
31 proto = sysroot_pb2.SysrootCreateRequest()
32 if build_target:
33 proto.build_target.name = build_target
34 if profile:
35 proto.profile.name = profile
36 if replace:
37 proto.flags.replace = replace
38 if current:
39 proto.flags.chroot_current = current
LaMont Jonesc0343fa2020-08-12 18:58:31 -060040 if package_indexes:
41 proto.package_indexes.extend(package_indexes)
Alex Kleinda35fcf2019-03-07 16:01:15 -070042
43 return proto
44
45 def _OutputProto(self):
46 """Helper to build output proto instance."""
47 return sysroot_pb2.SysrootCreateResponse()
48
Alex Klein231d2da2019-07-22 16:44:45 -060049 def testValidateOnly(self):
50 """Sanity check that a validate only call does not execute any logic."""
51 patch = self.PatchObject(sysroot_service, 'Create')
52
53 board = 'board'
54 profile = None
55 force = False
56 upgrade_chroot = True
57 in_proto = self._InputProto(build_target=board, profile=profile,
58 replace=force, current=not upgrade_chroot)
59 sysroot_controller.Create(in_proto, self._OutputProto(),
60 self.validate_only_config)
61 patch.assert_not_called()
62
Alex Klein076841b2019-08-29 15:19:39 -060063 def testMockCall(self):
64 """Sanity check that a mock call does not execute any logic."""
65 patch = self.PatchObject(sysroot_service, 'Create')
66 request = self._InputProto()
67 response = self._OutputProto()
68
69 rc = sysroot_controller.Create(request, response, self.mock_call_config)
70
71 patch.assert_not_called()
72 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
73
74 def testMockError(self):
75 """Sanity check that a mock error does not execute any logic."""
76 patch = self.PatchObject(sysroot_service, 'Create')
77 request = self._InputProto()
78 response = self._OutputProto()
79
80 rc = sysroot_controller.Create(request, response, self.mock_error_config)
81
82 patch.assert_not_called()
83 self.assertEqual(controller.RETURN_CODE_UNRECOVERABLE, rc)
84
Alex Kleinda35fcf2019-03-07 16:01:15 -070085 def testArgumentValidation(self):
86 """Test the input argument validation."""
87 # Error when no name provided.
88 in_proto = self._InputProto()
89 out_proto = self._OutputProto()
90 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -060091 sysroot_controller.Create(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -070092
93 # Valid when board passed.
94 result = sysroot_lib.Sysroot('/sysroot/path')
95 patch = self.PatchObject(sysroot_service, 'Create', return_value=result)
96 in_proto = self._InputProto('board')
97 out_proto = self._OutputProto()
Alex Klein231d2da2019-07-22 16:44:45 -060098 sysroot_controller.Create(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -070099 patch.assert_called_once()
100
101 def testArgumentHandling(self):
102 """Test the arguments get processed and passed correctly."""
103 sysroot_path = '/sysroot/path'
104
105 sysroot = sysroot_lib.Sysroot(sysroot_path)
106 create_patch = self.PatchObject(sysroot_service, 'Create',
107 return_value=sysroot)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700108 rc_patch = self.PatchObject(sysroot_service, 'SetupBoardRunConfig')
109
110 # Default values.
111 board = 'board'
112 profile = None
113 force = False
114 upgrade_chroot = True
115 in_proto = self._InputProto(build_target=board, profile=profile,
116 replace=force, current=not upgrade_chroot)
117 out_proto = self._OutputProto()
Alex Klein231d2da2019-07-22 16:44:45 -0600118 sysroot_controller.Create(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700119
120 # Default value checks.
LaMont Jonesfeffd1b2020-08-05 18:24:59 -0600121 rc_patch.assert_called_with(force=force, upgrade_chroot=upgrade_chroot,
122 package_indexes=[])
Alex Kleinda35fcf2019-03-07 16:01:15 -0700123 self.assertEqual(board, out_proto.sysroot.build_target.name)
124 self.assertEqual(sysroot_path, out_proto.sysroot.path)
125
126 # Not default values.
127 create_patch.reset_mock()
128 board = 'board'
129 profile = 'profile'
130 force = True
131 upgrade_chroot = False
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600132 package_indexes = [
133 common_pb2.PackageIndexInfo(
134 snapshot_sha='SHA', snapshot_number=5,
135 build_target=common_pb2.BuildTarget(name=board),
136 location='LOCATION', profile=common_pb2.Profile(name=profile)),
137 common_pb2.PackageIndexInfo(
138 snapshot_sha='SHA2', snapshot_number=4,
139 build_target=common_pb2.BuildTarget(name=board),
140 location='LOCATION2', profile=common_pb2.Profile(name=profile))]
141
Alex Kleinda35fcf2019-03-07 16:01:15 -0700142 in_proto = self._InputProto(build_target=board, profile=profile,
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600143 replace=force, current=not upgrade_chroot,
144 package_indexes=package_indexes)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700145 out_proto = self._OutputProto()
Alex Klein231d2da2019-07-22 16:44:45 -0600146 sysroot_controller.Create(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700147
148 # Not default value checks.
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600149 rc_patch.assert_called_with(
150 force=force, package_indexes=[
151 binpkg.PackageIndexInfo.from_protobuf(x)
152 for x in package_indexes
153 ], upgrade_chroot=upgrade_chroot)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700154 self.assertEqual(board, out_proto.sysroot.build_target.name)
155 self.assertEqual(sysroot_path, out_proto.sysroot.path)
156
157
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700158class GenerateArchiveTest(cros_test_lib.MockTempDirTestCase,
159 api_config.ApiConfigMixin):
160 """GenerateArchive function tests."""
161
162 def setUp(self):
163 self.chroot_path = '/path/to/chroot'
164 self.board = 'board'
165
166 def _InputProto(self, build_target=None, chroot_path=None, pkg_list=None):
167 """Helper to build and input proto instance."""
168 # pkg_list will be a list of category/package strings such as
169 # ['virtual/target-fuzzers'].
170 if pkg_list:
171 package_list = []
172 for pkg in pkg_list:
173 pkg_string_parts = pkg.split('/')
Alex Klein18a60af2020-06-11 12:08:47 -0600174 package_info_msg = common_pb2.PackageInfo(
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700175 category=pkg_string_parts[0],
176 package_name=pkg_string_parts[1])
Alex Klein18a60af2020-06-11 12:08:47 -0600177 package_list.append(package_info_msg)
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700178 else:
179 package_list = []
180
181 return sysroot_pb2.SysrootGenerateArchiveRequest(
182 build_target={'name': build_target},
183 chroot={'path': chroot_path},
184 packages=package_list)
185
186 def _OutputProto(self):
187 """Helper to build output proto instance."""
188 return sysroot_pb2.SysrootGenerateArchiveResponse()
189
190 def testValidateOnly(self):
191 """Sanity check that a validate only call does not execute any logic."""
192 patch = self.PatchObject(sysroot_service, 'GenerateArchive')
193
194 in_proto = self._InputProto(build_target=self.board,
195 chroot_path=self.chroot_path,
196 pkg_list=['virtual/target-fuzzers'])
197 sysroot_controller.GenerateArchive(in_proto, self._OutputProto(),
198 self.validate_only_config)
199 patch.assert_not_called()
200
201 def testMockCall(self):
202 """Sanity check that a mock call does not execute any logic."""
203 patch = self.PatchObject(sysroot_service, 'GenerateArchive')
204
205 in_proto = self._InputProto(build_target=self.board,
206 chroot_path=self.chroot_path,
207 pkg_list=['virtual/target-fuzzers'])
208 sysroot_controller.GenerateArchive(in_proto,
209 self._OutputProto(),
210 self.mock_call_config)
211 patch.assert_not_called()
212
213 def testArgumentValidation(self):
214 """Test the input argument validation."""
215 # Error when no build target provided.
216 in_proto = self._InputProto()
217 out_proto = self._OutputProto()
218 with self.assertRaises(cros_build_lib.DieSystemExit):
219 sysroot_controller.GenerateArchive(in_proto, out_proto, self.api_config)
220
221 # Error when packages is not specified.
222 in_proto = self._InputProto(build_target='board',
223 chroot_path=self.chroot_path)
224 with self.assertRaises(cros_build_lib.DieSystemExit):
225 sysroot_controller.GenerateArchive(in_proto, out_proto, self.api_config)
226
227 # Valid when board, chroot path, and package are specified.
228 patch = self.PatchObject(sysroot_service, 'GenerateArchive',
229 return_value='/path/to/sysroot/tar.bz')
230 in_proto = self._InputProto(build_target='board',
231 chroot_path=self.chroot_path,
232 pkg_list=['virtual/target-fuzzers'])
233 out_proto = self._OutputProto()
234 sysroot_controller.GenerateArchive(in_proto, out_proto, self.api_config)
235 patch.assert_called_once()
236
237
Alex Klein231d2da2019-07-22 16:44:45 -0600238class InstallToolchainTest(cros_test_lib.MockTempDirTestCase,
239 api_config.ApiConfigMixin):
Alex Kleinda35fcf2019-03-07 16:01:15 -0700240 """Install toolchain function tests."""
241
242 def setUp(self):
243 self.PatchObject(cros_build_lib, 'IsInsideChroot', return_value=True)
Alex Kleina9d64602019-05-17 14:55:37 -0600244 # Avoid running the portageq command.
245 self.PatchObject(sysroot_controller, '_LogBinhost')
Alex Kleinda35fcf2019-03-07 16:01:15 -0700246 self.board = 'board'
247 self.sysroot = os.path.join(self.tempdir, 'board')
248 self.invalid_sysroot = os.path.join(self.tempdir, 'invalid', 'sysroot')
249 osutils.SafeMakedirs(self.sysroot)
250
251 def _InputProto(self, build_target=None, sysroot_path=None,
252 compile_source=False):
Alex Kleind4e1e422019-03-18 16:00:41 -0600253 """Helper to build an input proto instance."""
Alex Kleinda35fcf2019-03-07 16:01:15 -0700254 proto = sysroot_pb2.InstallToolchainRequest()
255 if build_target:
256 proto.sysroot.build_target.name = build_target
257 if sysroot_path:
258 proto.sysroot.path = sysroot_path
259 if compile_source:
260 proto.flags.compile_source = compile_source
261
262 return proto
263
264 def _OutputProto(self):
265 """Helper to build output proto instance."""
266 return sysroot_pb2.InstallToolchainResponse()
267
Alex Klein231d2da2019-07-22 16:44:45 -0600268 def testValidateOnly(self):
269 """Sanity check that a validate only call does not execute any logic."""
270 patch = self.PatchObject(sysroot_service, 'InstallToolchain')
271
272 in_proto = self._InputProto(build_target=self.board,
273 sysroot_path=self.sysroot)
274 sysroot_controller.InstallToolchain(in_proto, self._OutputProto(),
275 self.validate_only_config)
276 patch.assert_not_called()
277
Alex Klein076841b2019-08-29 15:19:39 -0600278 def testMockCall(self):
279 """Sanity check that a mock call does not execute any logic."""
280 patch = self.PatchObject(sysroot_service, 'InstallToolchain')
281 request = self._InputProto()
282 response = self._OutputProto()
283
284 rc = sysroot_controller.InstallToolchain(request, response,
285 self.mock_call_config)
286
287 patch.assert_not_called()
288 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
289
290 def testMockError(self):
291 """Sanity check that a mock error does not execute any logic."""
292 patch = self.PatchObject(sysroot_service, 'InstallToolchain')
293 request = self._InputProto()
294 response = self._OutputProto()
295
296 rc = sysroot_controller.InstallToolchain(request, response,
297 self.mock_error_config)
298
299 patch.assert_not_called()
300 self.assertEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
301 self.assertTrue(response.failed_packages)
302
Alex Kleinda35fcf2019-03-07 16:01:15 -0700303 def testArgumentValidation(self):
304 """Test the argument validation."""
305 # Test errors on missing inputs.
306 out_proto = self._OutputProto()
307 # Both missing.
308 in_proto = self._InputProto()
309 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600310 sysroot_controller.InstallToolchain(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700311
312 # Sysroot path missing.
313 in_proto = self._InputProto(build_target=self.board)
314 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600315 sysroot_controller.InstallToolchain(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700316
317 # Build target name missing.
318 in_proto = self._InputProto(sysroot_path=self.sysroot)
319 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600320 sysroot_controller.InstallToolchain(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700321
322 # Both provided, but invalid sysroot path.
323 in_proto = self._InputProto(build_target=self.board,
324 sysroot_path=self.invalid_sysroot)
325 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600326 sysroot_controller.InstallToolchain(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700327
328 def testSuccessOutputHandling(self):
329 """Test the output is processed and recorded correctly."""
330 self.PatchObject(sysroot_service, 'InstallToolchain')
331 out_proto = self._OutputProto()
332 in_proto = self._InputProto(build_target=self.board,
333 sysroot_path=self.sysroot)
334
Alex Klein231d2da2019-07-22 16:44:45 -0600335 rc = sysroot_controller.InstallToolchain(in_proto, out_proto,
336 self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700337 self.assertFalse(rc)
338 self.assertFalse(out_proto.failed_packages)
339
340
341 def testErrorOutputHandling(self):
342 """Test the error output is processed and recorded correctly."""
343 out_proto = self._OutputProto()
344 in_proto = self._InputProto(build_target=self.board,
345 sysroot_path=self.sysroot)
346
347 err_pkgs = ['cat/pkg', 'cat2/pkg2']
Alex Kleinea0c89e2021-09-09 15:17:35 -0600348 err_cpvs = [package_info.parse(pkg) for pkg in err_pkgs]
Alex Kleinda35fcf2019-03-07 16:01:15 -0700349 expected = [('cat', 'pkg'), ('cat2', 'pkg2')]
350 err = sysroot_lib.ToolchainInstallError('Error',
351 cros_build_lib.CommandResult(),
352 tc_info=err_cpvs)
353 self.PatchObject(sysroot_service, 'InstallToolchain', side_effect=err)
354
Alex Klein231d2da2019-07-22 16:44:45 -0600355 rc = sysroot_controller.InstallToolchain(in_proto, out_proto,
356 self.api_config)
Alex Klein8cb365a2019-05-15 16:24:53 -0600357 self.assertEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700358 self.assertTrue(out_proto.failed_packages)
359 for package in out_proto.failed_packages:
360 cat_pkg = (package.category, package.package_name)
361 self.assertIn(cat_pkg, expected)
Alex Kleind4e1e422019-03-18 16:00:41 -0600362
363
Alex Klein231d2da2019-07-22 16:44:45 -0600364class InstallPackagesTest(cros_test_lib.MockTempDirTestCase,
365 api_config.ApiConfigMixin):
Alex Kleind4e1e422019-03-18 16:00:41 -0600366 """InstallPackages tests."""
367
368 def setUp(self):
369 self.PatchObject(cros_build_lib, 'IsInsideChroot', return_value=True)
Alex Kleina9d64602019-05-17 14:55:37 -0600370 # Avoid running the portageq command.
371 self.PatchObject(sysroot_controller, '_LogBinhost')
Alex Kleind4e1e422019-03-18 16:00:41 -0600372 self.build_target = 'board'
373 self.sysroot = os.path.join(self.tempdir, 'build', 'board')
374 osutils.SafeMakedirs(self.sysroot)
Michael Mortensen798ee192020-01-17 13:04:43 -0700375 # Set up goma directories.
376 self.goma_dir = os.path.join(self.tempdir, 'goma_dir')
377 osutils.SafeMakedirs(self.goma_dir)
378 self.goma_out_dir = os.path.join(self.tempdir, 'goma_out_dir')
379 osutils.SafeMakedirs(self.goma_out_dir)
Michael Mortensen4ccfb082020-01-22 16:24:03 -0700380 os.environ['GLOG_log_dir'] = self.goma_dir
Alex Kleind4e1e422019-03-18 16:00:41 -0600381
382 def _InputProto(self, build_target=None, sysroot_path=None,
Michael Mortensen798ee192020-01-17 13:04:43 -0700383 build_source=False, goma_dir=None, goma_log_dir=None,
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600384 goma_stats_file=None, goma_counterz_file=None,
Alex Kleinca572ee2020-09-03 10:47:14 -0600385 package_indexes=None, packages=None):
Alex Kleind4e1e422019-03-18 16:00:41 -0600386 """Helper to build an input proto instance."""
387 instance = sysroot_pb2.InstallPackagesRequest()
388
389 if build_target:
390 instance.sysroot.build_target.name = build_target
391 if sysroot_path:
392 instance.sysroot.path = sysroot_path
393 if build_source:
394 instance.flags.build_source = build_source
Michael Mortensen798ee192020-01-17 13:04:43 -0700395 if goma_dir:
396 instance.goma_config.goma_dir = goma_dir
397 if goma_log_dir:
398 instance.goma_config.log_dir.dir = goma_log_dir
399 if goma_stats_file:
400 instance.goma_config.stats_file = goma_stats_file
401 if goma_counterz_file:
402 instance.goma_config.counterz_file = goma_counterz_file
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600403 if package_indexes:
404 instance.package_indexes.extend(package_indexes)
Alex Kleinca572ee2020-09-03 10:47:14 -0600405 if packages:
406 for pkg in packages:
407 pkg_info = instance.packages.add()
Alex Klein18a60af2020-06-11 12:08:47 -0600408 cpv = package_info.SplitCPV(pkg, strict=False)
Alex Kleinca572ee2020-09-03 10:47:14 -0600409 controller_util.CPVToPackageInfo(cpv, pkg_info)
Alex Kleind4e1e422019-03-18 16:00:41 -0600410 return instance
411
412 def _OutputProto(self):
413 """Helper to build an empty output proto instance."""
414 return sysroot_pb2.InstallPackagesResponse()
415
Michael Mortensen798ee192020-01-17 13:04:43 -0700416 def _CreateGomaLogFile(self, goma_log_dir, name, timestamp):
417 """Creates a log file for testing.
418
419 Args:
420 goma_log_dir (str): Directory where the file will be created.
421 name (str): Log file 'base' name that is combined with the timestamp.
422 timestamp (datetime): timestamp that is written to the file.
423 """
424 path = os.path.join(
425 goma_log_dir,
426 '%s.host.log.INFO.%s' % (name, timestamp.strftime('%Y%m%d-%H%M%S.%f')))
427 osutils.WriteFile(
428 path,
429 timestamp.strftime('Goma log file created at: %Y/%m/%d %H:%M:%S'))
430
Alex Klein231d2da2019-07-22 16:44:45 -0600431 def testValidateOnly(self):
432 """Sanity check that a validate only call does not execute any logic."""
433 patch = self.PatchObject(sysroot_service, 'BuildPackages')
434
435 in_proto = self._InputProto(build_target=self.build_target,
436 sysroot_path=self.sysroot)
437 sysroot_controller.InstallPackages(in_proto, self._OutputProto(),
438 self.validate_only_config)
439 patch.assert_not_called()
440
Alex Klein076841b2019-08-29 15:19:39 -0600441 def testMockCall(self):
442 """Sanity check that a mock call does not execute any logic."""
443 patch = self.PatchObject(sysroot_service, 'BuildPackages')
444 request = self._InputProto()
445 response = self._OutputProto()
446
447 rc = sysroot_controller.InstallPackages(request, response,
448 self.mock_call_config)
449
450 patch.assert_not_called()
451 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
452
453 def testMockError(self):
454 """Sanity check that a mock error does not execute any logic."""
455 patch = self.PatchObject(sysroot_service, 'BuildPackages')
456 request = self._InputProto()
457 response = self._OutputProto()
458
459 rc = sysroot_controller.InstallPackages(request, response,
460 self.mock_error_config)
461
462 patch.assert_not_called()
463 self.assertEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
464 self.assertTrue(response.failed_packages)
465
Alex Kleind4e1e422019-03-18 16:00:41 -0600466 def testArgumentValidationAllMissing(self):
467 """Test missing all arguments."""
468 out_proto = self._OutputProto()
469 in_proto = self._InputProto()
470 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600471 sysroot_controller.InstallPackages(in_proto, out_proto, self.api_config)
Alex Kleind4e1e422019-03-18 16:00:41 -0600472
473 def testArgumentValidationNoSysroot(self):
474 """Test missing sysroot path."""
475 out_proto = self._OutputProto()
476 in_proto = self._InputProto(build_target=self.build_target)
477 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600478 sysroot_controller.InstallPackages(in_proto, out_proto, self.api_config)
Alex Kleind4e1e422019-03-18 16:00:41 -0600479
480 def testArgumentValidationNoBuildTarget(self):
481 """Test missing build target name."""
482 out_proto = self._OutputProto()
483 in_proto = self._InputProto(sysroot_path=self.sysroot)
484 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600485 sysroot_controller.InstallPackages(in_proto, out_proto, self.api_config)
Alex Kleind4e1e422019-03-18 16:00:41 -0600486
487 def testArgumentValidationInvalidSysroot(self):
488 """Test sysroot that hasn't had the toolchain installed."""
489 out_proto = self._OutputProto()
490 in_proto = self._InputProto(build_target=self.build_target,
491 sysroot_path=self.sysroot)
492 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
493 return_value=False)
494 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600495 sysroot_controller.InstallPackages(in_proto, out_proto, self.api_config)
Alex Kleind4e1e422019-03-18 16:00:41 -0600496
Alex Kleinca572ee2020-09-03 10:47:14 -0600497 def testArgumentValidationInvalidPackage(self):
498 out_proto = self._OutputProto()
499 in_proto = self._InputProto(build_target=self.build_target,
500 sysroot_path=self.sysroot,
501 packages=['package-1.0.0-r2'])
502 with self.assertRaises(cros_build_lib.DieSystemExit):
503 sysroot_controller.InstallPackages(in_proto, out_proto, self.api_config)
504
Alex Kleind4e1e422019-03-18 16:00:41 -0600505 def testSuccessOutputHandling(self):
506 """Test successful call output handling."""
507 # Prevent argument validation error.
508 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
509 return_value=True)
510
511 in_proto = self._InputProto(build_target=self.build_target,
512 sysroot_path=self.sysroot)
513 out_proto = self._OutputProto()
514 self.PatchObject(sysroot_service, 'BuildPackages')
515
Alex Klein231d2da2019-07-22 16:44:45 -0600516 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
517 self.api_config)
Alex Kleind4e1e422019-03-18 16:00:41 -0600518 self.assertFalse(rc)
519 self.assertFalse(out_proto.failed_packages)
520
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600521 def testSuccessPackageIndexes(self):
522 """Test successful call with package_indexes."""
523 # Prevent argument validation error.
524 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
525 return_value=True)
526 package_indexes = [
527 common_pb2.PackageIndexInfo(
528 snapshot_sha='SHA', snapshot_number=5,
529 build_target=common_pb2.BuildTarget(name='board'),
530 location='LOCATION', profile=common_pb2.Profile(name='profile')),
531 common_pb2.PackageIndexInfo(
532 snapshot_sha='SHA2', snapshot_number=4,
533 build_target=common_pb2.BuildTarget(name='board'),
534 location='LOCATION2', profile=common_pb2.Profile(name='profile'))]
535
536 in_proto = self._InputProto(build_target=self.build_target,
537 sysroot_path=self.sysroot,
538 package_indexes=package_indexes)
539
540 out_proto = self._OutputProto()
541 rc_patch = self.PatchObject(sysroot_service, 'BuildPackagesRunConfig')
542 self.PatchObject(sysroot_service, 'BuildPackages')
543
544 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
545 self.api_config)
546 self.assertFalse(rc)
Alex Kleineb76da72021-03-19 10:43:09 -0600547 rc_patch.assert_called_with(
548 usepkg=True,
549 install_debug_symbols=True,
550 packages=[],
551 package_indexes=[
552 binpkg.PackageIndexInfo.from_protobuf(x) for x in package_indexes
553 ],
554 use_flags=[],
555 use_goma=False,
556 incremental_build=False,
Navil Perez5766d1b2021-05-26 17:38:15 +0000557 setup_board=False,
558 dryrun=False)
LaMont Jonesc0343fa2020-08-12 18:58:31 -0600559
Michael Mortensen798ee192020-01-17 13:04:43 -0700560 def testSuccessWithGomaLogs(self):
561 """Test successful call with goma."""
562 self._CreateGomaLogFile(self.goma_dir, 'compiler_proxy',
563 datetime.datetime(2018, 9, 21, 12, 0, 0))
564 self._CreateGomaLogFile(self.goma_dir, 'compiler_proxy-subproc',
565 datetime.datetime(2018, 9, 21, 12, 1, 0))
566 self._CreateGomaLogFile(self.goma_dir, 'gomacc',
567 datetime.datetime(2018, 9, 21, 12, 2, 0))
568
569 # Prevent argument validation error.
570 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
571 return_value=True)
572
573 in_proto = self._InputProto(build_target=self.build_target,
574 sysroot_path=self.sysroot,
575 goma_dir=self.goma_dir,
576 goma_log_dir=self.goma_out_dir)
577
578 out_proto = self._OutputProto()
579 self.PatchObject(sysroot_service, 'BuildPackages')
580
581 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
582 self.api_config)
583 self.assertFalse(rc)
584 self.assertFalse(out_proto.failed_packages)
585 self.assertCountEqual(out_proto.goma_artifacts.log_files, [
586 'compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz',
587 'compiler_proxy.host.log.INFO.20180921-120000.000000.gz',
588 'gomacc.host.log.INFO.20180921-120200.000000.tar.gz'])
589
590 def testSuccessWithGomaLogsAndStatsCounterzFiles(self):
591 """Test successful call with goma including stats and counterz files."""
592 self._CreateGomaLogFile(self.goma_dir, 'compiler_proxy',
593 datetime.datetime(2018, 9, 21, 12, 0, 0))
594 self._CreateGomaLogFile(self.goma_dir, 'compiler_proxy-subproc',
595 datetime.datetime(2018, 9, 21, 12, 1, 0))
596 self._CreateGomaLogFile(self.goma_dir, 'gomacc',
597 datetime.datetime(2018, 9, 21, 12, 2, 0))
598 # Create stats and counterz files.
599 osutils.WriteFile(os.path.join(self.goma_dir, 'stats.binaryproto'),
600 'File: stats.binaryproto')
601 osutils.WriteFile(os.path.join(self.goma_dir, 'counterz.binaryproto'),
602 'File: counterz.binaryproto')
603
604 # Prevent argument validation error.
605 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
606 return_value=True)
607
608 in_proto = self._InputProto(build_target=self.build_target,
609 sysroot_path=self.sysroot,
610 goma_dir=self.goma_dir,
611 goma_log_dir=self.goma_out_dir,
612 goma_stats_file='stats.binaryproto',
613 goma_counterz_file='counterz.binaryproto')
614
615 out_proto = self._OutputProto()
616 self.PatchObject(sysroot_service, 'BuildPackages')
617
618 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
619 self.api_config)
620 self.assertFalse(rc)
621 self.assertFalse(out_proto.failed_packages)
622 self.assertCountEqual(out_proto.goma_artifacts.log_files, [
623 'compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz',
624 'compiler_proxy.host.log.INFO.20180921-120000.000000.gz',
625 'gomacc.host.log.INFO.20180921-120200.000000.tar.gz'])
626 # Verify that the output dir has 5 files -- since there should be 3 log
627 # files, the stats file, and the counterz file.
628 output_files = os.listdir(self.goma_out_dir)
629 self.assertCountEqual(output_files, [
630 'stats.binaryproto',
631 'counterz.binaryproto',
632 'compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz',
633 'compiler_proxy.host.log.INFO.20180921-120000.000000.gz',
634 'gomacc.host.log.INFO.20180921-120200.000000.tar.gz'])
Michael Mortensen1c7439c2020-01-24 14:43:19 -0700635 self.assertEqual(out_proto.goma_artifacts.counterz_file,
636 'counterz.binaryproto')
637 self.assertEqual(out_proto.goma_artifacts.stats_file,
638 'stats.binaryproto')
Michael Mortensen798ee192020-01-17 13:04:43 -0700639
640 def testFailureMissingGomaStatsCounterzFiles(self):
641 """Test successful call with goma including stats and counterz files."""
642 self._CreateGomaLogFile(self.goma_dir, 'compiler_proxy',
643 datetime.datetime(2018, 9, 21, 12, 0, 0))
644 self._CreateGomaLogFile(self.goma_dir, 'compiler_proxy-subproc',
645 datetime.datetime(2018, 9, 21, 12, 1, 0))
646 self._CreateGomaLogFile(self.goma_dir, 'gomacc',
647 datetime.datetime(2018, 9, 21, 12, 2, 0))
648 # Note that stats and counterz files are not created, but are specified in
649 # the proto below.
650
651 # Prevent argument validation error.
652 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
653 return_value=True)
654
655 in_proto = self._InputProto(build_target=self.build_target,
656 sysroot_path=self.sysroot,
657 goma_dir=self.goma_dir,
658 goma_log_dir=self.goma_out_dir,
659 goma_stats_file='stats.binaryproto',
660 goma_counterz_file='counterz.binaryproto')
661
662 out_proto = self._OutputProto()
663 self.PatchObject(sysroot_service, 'BuildPackages')
664
Michael Mortensen1d6d5b02020-01-22 07:33:50 -0700665 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
666 self.api_config)
667 self.assertFalse(rc)
668 self.assertFalse(out_proto.failed_packages)
669 self.assertCountEqual(out_proto.goma_artifacts.log_files, [
670 'compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz',
671 'compiler_proxy.host.log.INFO.20180921-120000.000000.gz',
672 'gomacc.host.log.INFO.20180921-120200.000000.tar.gz'])
673 self.assertFalse(out_proto.goma_artifacts.counterz_file)
674 self.assertFalse(out_proto.goma_artifacts.stats_file)
Michael Mortensen798ee192020-01-17 13:04:43 -0700675
Alex Kleind4e1e422019-03-18 16:00:41 -0600676 def testFailureOutputHandling(self):
677 """Test failed package handling."""
678 # Prevent argument validation error.
679 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
680 return_value=True)
681
682 in_proto = self._InputProto(build_target=self.build_target,
683 sysroot_path=self.sysroot)
684 out_proto = self._OutputProto()
685
686 # Failed package info and expected list for verification.
687 err_pkgs = ['cat/pkg', 'cat2/pkg2']
Alex Klein18a60af2020-06-11 12:08:47 -0600688 err_cpvs = [package_info.SplitCPV(cpv, strict=False) for cpv in err_pkgs]
Alex Kleind4e1e422019-03-18 16:00:41 -0600689 expected = [('cat', 'pkg'), ('cat2', 'pkg2')]
690
691 # Force error to be raised with the packages.
692 error = sysroot_lib.PackageInstallError('Error',
693 cros_build_lib.CommandResult(),
694 packages=err_cpvs)
695 self.PatchObject(sysroot_service, 'BuildPackages', side_effect=error)
696
Alex Klein231d2da2019-07-22 16:44:45 -0600697 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
698 self.api_config)
Alex Klein2557b4f2019-07-11 14:34:00 -0600699 # This needs to return 2 to indicate the available error response.
700 self.assertEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
Alex Kleind4e1e422019-03-18 16:00:41 -0600701 for package in out_proto.failed_packages:
702 cat_pkg = (package.category, package.package_name)
703 self.assertIn(cat_pkg, expected)
Alex Klein2557b4f2019-07-11 14:34:00 -0600704
705 def testNoPackageFailureOutputHandling(self):
706 """Test failure handling without packages to report."""
707 # Prevent argument validation error.
708 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
709 return_value=True)
710
711 in_proto = self._InputProto(build_target=self.build_target,
712 sysroot_path=self.sysroot)
713 out_proto = self._OutputProto()
714
715 # Force error to be raised with no packages.
716 error = sysroot_lib.PackageInstallError('Error',
717 cros_build_lib.CommandResult(),
718 packages=[])
719 self.PatchObject(sysroot_service, 'BuildPackages', side_effect=error)
720
Alex Klein231d2da2019-07-22 16:44:45 -0600721 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
722 self.api_config)
Alex Klein2557b4f2019-07-11 14:34:00 -0600723 # All we really care about is it's not 0 or 2 (response available), so
724 # test for that rather than a specific return code.
725 self.assertTrue(rc)
726 self.assertNotEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE,
727 rc)