blob: f852abc2b47b10b903d0258c5014f9ba8f91cc98 [file] [log] [blame]
Alex Kleinda35fcf2019-03-07 16:01:15 -07001# -*- coding: utf-8 -*-
2# Copyright 2019 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Sysroot controller tests."""
7
8from __future__ import print_function
9
Michael Mortensen798ee192020-01-17 13:04:43 -070010import datetime
Alex Kleinda35fcf2019-03-07 16:01:15 -070011import os
Mike Frysingeref94e4c2020-02-10 23:59:54 -050012import sys
Alex Kleinda35fcf2019-03-07 16:01:15 -070013
Alex Klein231d2da2019-07-22 16:44:45 -060014from chromite.api import api_config
Alex Klein8cb365a2019-05-15 16:24:53 -060015from chromite.api import controller
Alex Kleinda35fcf2019-03-07 16:01:15 -070016from chromite.api.controller import sysroot as sysroot_controller
17from chromite.api.gen.chromite.api import sysroot_pb2
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -070018from chromite.api.gen.chromiumos import common_pb2
Alex Kleinda35fcf2019-03-07 16:01:15 -070019from chromite.lib import cros_build_lib
20from chromite.lib import cros_test_lib
21from chromite.lib import osutils
22from chromite.lib import portage_util
23from chromite.lib import sysroot_lib
24from chromite.service import sysroot as sysroot_service
25
26
Mike Frysingeref94e4c2020-02-10 23:59:54 -050027assert sys.version_info >= (3, 6), 'This module requires Python 3.6+'
28
29
Alex Klein231d2da2019-07-22 16:44:45 -060030class CreateTest(cros_test_lib.MockTestCase, api_config.ApiConfigMixin):
Alex Kleinda35fcf2019-03-07 16:01:15 -070031 """Create function tests."""
32
33 def _InputProto(self, build_target=None, profile=None, replace=False,
34 current=False):
35 """Helper to build and input proto instance."""
36 proto = sysroot_pb2.SysrootCreateRequest()
37 if build_target:
38 proto.build_target.name = build_target
39 if profile:
40 proto.profile.name = profile
41 if replace:
42 proto.flags.replace = replace
43 if current:
44 proto.flags.chroot_current = current
45
46 return proto
47
48 def _OutputProto(self):
49 """Helper to build output proto instance."""
50 return sysroot_pb2.SysrootCreateResponse()
51
Alex Klein231d2da2019-07-22 16:44:45 -060052 def testValidateOnly(self):
53 """Sanity check that a validate only call does not execute any logic."""
54 patch = self.PatchObject(sysroot_service, 'Create')
55
56 board = 'board'
57 profile = None
58 force = False
59 upgrade_chroot = True
60 in_proto = self._InputProto(build_target=board, profile=profile,
61 replace=force, current=not upgrade_chroot)
62 sysroot_controller.Create(in_proto, self._OutputProto(),
63 self.validate_only_config)
64 patch.assert_not_called()
65
Alex Klein076841b2019-08-29 15:19:39 -060066 def testMockCall(self):
67 """Sanity check that a mock call does not execute any logic."""
68 patch = self.PatchObject(sysroot_service, 'Create')
69 request = self._InputProto()
70 response = self._OutputProto()
71
72 rc = sysroot_controller.Create(request, response, self.mock_call_config)
73
74 patch.assert_not_called()
75 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
76
77 def testMockError(self):
78 """Sanity check that a mock error does not execute any logic."""
79 patch = self.PatchObject(sysroot_service, 'Create')
80 request = self._InputProto()
81 response = self._OutputProto()
82
83 rc = sysroot_controller.Create(request, response, self.mock_error_config)
84
85 patch.assert_not_called()
86 self.assertEqual(controller.RETURN_CODE_UNRECOVERABLE, rc)
87
Alex Kleinda35fcf2019-03-07 16:01:15 -070088 def testArgumentValidation(self):
89 """Test the input argument validation."""
90 # Error when no name provided.
91 in_proto = self._InputProto()
92 out_proto = self._OutputProto()
93 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -060094 sysroot_controller.Create(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -070095
96 # Valid when board passed.
97 result = sysroot_lib.Sysroot('/sysroot/path')
98 patch = self.PatchObject(sysroot_service, 'Create', return_value=result)
99 in_proto = self._InputProto('board')
100 out_proto = self._OutputProto()
Alex Klein231d2da2019-07-22 16:44:45 -0600101 sysroot_controller.Create(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700102 patch.assert_called_once()
103
104 def testArgumentHandling(self):
105 """Test the arguments get processed and passed correctly."""
106 sysroot_path = '/sysroot/path'
107
108 sysroot = sysroot_lib.Sysroot(sysroot_path)
109 create_patch = self.PatchObject(sysroot_service, 'Create',
110 return_value=sysroot)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700111 rc_patch = self.PatchObject(sysroot_service, 'SetupBoardRunConfig')
112
113 # Default values.
114 board = 'board'
115 profile = None
116 force = False
117 upgrade_chroot = True
118 in_proto = self._InputProto(build_target=board, profile=profile,
119 replace=force, current=not upgrade_chroot)
120 out_proto = self._OutputProto()
Alex Klein231d2da2019-07-22 16:44:45 -0600121 sysroot_controller.Create(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700122
123 # Default value checks.
LaMont Jonesfeffd1b2020-08-05 18:24:59 -0600124 rc_patch.assert_called_with(force=force, upgrade_chroot=upgrade_chroot,
125 package_indexes=[])
Alex Kleinda35fcf2019-03-07 16:01:15 -0700126 self.assertEqual(board, out_proto.sysroot.build_target.name)
127 self.assertEqual(sysroot_path, out_proto.sysroot.path)
128
129 # Not default values.
130 create_patch.reset_mock()
131 board = 'board'
132 profile = 'profile'
133 force = True
134 upgrade_chroot = False
135 in_proto = self._InputProto(build_target=board, profile=profile,
136 replace=force, current=not upgrade_chroot)
137 out_proto = self._OutputProto()
Alex Klein231d2da2019-07-22 16:44:45 -0600138 sysroot_controller.Create(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700139
140 # Not default value checks.
LaMont Jonesfeffd1b2020-08-05 18:24:59 -0600141 rc_patch.assert_called_with(force=force, upgrade_chroot=upgrade_chroot,
142 package_indexes=[])
Alex Kleinda35fcf2019-03-07 16:01:15 -0700143 self.assertEqual(board, out_proto.sysroot.build_target.name)
144 self.assertEqual(sysroot_path, out_proto.sysroot.path)
145
146
Michael Mortensen98592f62019-09-27 13:34:18 -0600147class CreateSimpleChromeSysrootTest(cros_test_lib.MockTempDirTestCase,
148 api_config.ApiConfigMixin):
149 """CreateSimpleChromeSysroot function tests."""
150
151 def _InputProto(self, build_target=None, use_flags=None):
152 """Helper to build and input proto instance."""
153 proto = sysroot_pb2.CreateSimpleChromeSysrootRequest()
154 if build_target:
155 proto.build_target.name = build_target
156 if use_flags:
157 proto.use_flags = use_flags
158 return proto
159
160 def _OutputProto(self):
161 """Helper to build output proto instance."""
162 return sysroot_pb2.CreateSimpleChromeSysrootResponse()
163
164 def testValidateOnly(self):
165 """Sanity check that a validate only call does not execute any logic."""
166 patch = self.PatchObject(sysroot_service, 'CreateSimpleChromeSysroot')
167
168 board = 'board'
169 in_proto = self._InputProto(build_target=board, use_flags=[])
170 sysroot_controller.CreateSimpleChromeSysroot(in_proto, self._OutputProto(),
171 self.validate_only_config)
172 patch.assert_not_called()
173
Michael Mortensen3232ab32020-01-05 19:14:36 -0700174 def testMockCall(self):
175 """Sanity check that a mock call does not execute any logic."""
176 patch = self.PatchObject(sysroot_service, 'CreateSimpleChromeSysroot')
177
178 board = 'board'
179 in_proto = self._InputProto(build_target=board, use_flags=[])
180 rc = sysroot_controller.CreateSimpleChromeSysroot(in_proto,
181 self._OutputProto(),
182 self.mock_call_config)
183 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
184 patch.assert_not_called()
185
Michael Mortensen98592f62019-09-27 13:34:18 -0600186 def testArgumentValidation(self):
187 """Test the input argument validation."""
188 # Error when no build target provided.
189 in_proto = self._InputProto()
190 out_proto = self._OutputProto()
191 with self.assertRaises(cros_build_lib.DieSystemExit):
192 sysroot_controller.CreateSimpleChromeSysroot(in_proto, out_proto,
193 self.api_config)
194
195 # Valid when board is specified.
196 patch = self.PatchObject(sysroot_service, 'CreateSimpleChromeSysroot',
197 return_value='/path/to/sysroot/tar.bz')
198 in_proto = self._InputProto(build_target='board')
199 out_proto = self._OutputProto()
200 sysroot_controller.CreateSimpleChromeSysroot(in_proto, out_proto,
201 self.api_config)
202 patch.assert_called_once()
203
204
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700205class GenerateArchiveTest(cros_test_lib.MockTempDirTestCase,
206 api_config.ApiConfigMixin):
207 """GenerateArchive function tests."""
208
209 def setUp(self):
210 self.chroot_path = '/path/to/chroot'
211 self.board = 'board'
212
213 def _InputProto(self, build_target=None, chroot_path=None, pkg_list=None):
214 """Helper to build and input proto instance."""
215 # pkg_list will be a list of category/package strings such as
216 # ['virtual/target-fuzzers'].
217 if pkg_list:
218 package_list = []
219 for pkg in pkg_list:
220 pkg_string_parts = pkg.split('/')
221 package_info = common_pb2.PackageInfo(
222 category=pkg_string_parts[0],
223 package_name=pkg_string_parts[1])
224 package_list.append(package_info)
225 else:
226 package_list = []
227
228 return sysroot_pb2.SysrootGenerateArchiveRequest(
229 build_target={'name': build_target},
230 chroot={'path': chroot_path},
231 packages=package_list)
232
233 def _OutputProto(self):
234 """Helper to build output proto instance."""
235 return sysroot_pb2.SysrootGenerateArchiveResponse()
236
237 def testValidateOnly(self):
238 """Sanity check that a validate only call does not execute any logic."""
239 patch = self.PatchObject(sysroot_service, 'GenerateArchive')
240
241 in_proto = self._InputProto(build_target=self.board,
242 chroot_path=self.chroot_path,
243 pkg_list=['virtual/target-fuzzers'])
244 sysroot_controller.GenerateArchive(in_proto, self._OutputProto(),
245 self.validate_only_config)
246 patch.assert_not_called()
247
248 def testMockCall(self):
249 """Sanity check that a mock call does not execute any logic."""
250 patch = self.PatchObject(sysroot_service, 'GenerateArchive')
251
252 in_proto = self._InputProto(build_target=self.board,
253 chroot_path=self.chroot_path,
254 pkg_list=['virtual/target-fuzzers'])
255 sysroot_controller.GenerateArchive(in_proto,
256 self._OutputProto(),
257 self.mock_call_config)
258 patch.assert_not_called()
259
260 def testArgumentValidation(self):
261 """Test the input argument validation."""
262 # Error when no build target provided.
263 in_proto = self._InputProto()
264 out_proto = self._OutputProto()
265 with self.assertRaises(cros_build_lib.DieSystemExit):
266 sysroot_controller.GenerateArchive(in_proto, out_proto, self.api_config)
267
268 # Error when packages is not specified.
269 in_proto = self._InputProto(build_target='board',
270 chroot_path=self.chroot_path)
271 with self.assertRaises(cros_build_lib.DieSystemExit):
272 sysroot_controller.GenerateArchive(in_proto, out_proto, self.api_config)
273
274 # Valid when board, chroot path, and package are specified.
275 patch = self.PatchObject(sysroot_service, 'GenerateArchive',
276 return_value='/path/to/sysroot/tar.bz')
277 in_proto = self._InputProto(build_target='board',
278 chroot_path=self.chroot_path,
279 pkg_list=['virtual/target-fuzzers'])
280 out_proto = self._OutputProto()
281 sysroot_controller.GenerateArchive(in_proto, out_proto, self.api_config)
282 patch.assert_called_once()
283
284
Alex Klein231d2da2019-07-22 16:44:45 -0600285class InstallToolchainTest(cros_test_lib.MockTempDirTestCase,
286 api_config.ApiConfigMixin):
Alex Kleinda35fcf2019-03-07 16:01:15 -0700287 """Install toolchain function tests."""
288
289 def setUp(self):
290 self.PatchObject(cros_build_lib, 'IsInsideChroot', return_value=True)
Alex Kleina9d64602019-05-17 14:55:37 -0600291 # Avoid running the portageq command.
292 self.PatchObject(sysroot_controller, '_LogBinhost')
Alex Kleinda35fcf2019-03-07 16:01:15 -0700293 self.board = 'board'
294 self.sysroot = os.path.join(self.tempdir, 'board')
295 self.invalid_sysroot = os.path.join(self.tempdir, 'invalid', 'sysroot')
296 osutils.SafeMakedirs(self.sysroot)
297
298 def _InputProto(self, build_target=None, sysroot_path=None,
299 compile_source=False):
Alex Kleind4e1e422019-03-18 16:00:41 -0600300 """Helper to build an input proto instance."""
Alex Kleinda35fcf2019-03-07 16:01:15 -0700301 proto = sysroot_pb2.InstallToolchainRequest()
302 if build_target:
303 proto.sysroot.build_target.name = build_target
304 if sysroot_path:
305 proto.sysroot.path = sysroot_path
306 if compile_source:
307 proto.flags.compile_source = compile_source
308
309 return proto
310
311 def _OutputProto(self):
312 """Helper to build output proto instance."""
313 return sysroot_pb2.InstallToolchainResponse()
314
Alex Klein231d2da2019-07-22 16:44:45 -0600315 def testValidateOnly(self):
316 """Sanity check that a validate only call does not execute any logic."""
317 patch = self.PatchObject(sysroot_service, 'InstallToolchain')
318
319 in_proto = self._InputProto(build_target=self.board,
320 sysroot_path=self.sysroot)
321 sysroot_controller.InstallToolchain(in_proto, self._OutputProto(),
322 self.validate_only_config)
323 patch.assert_not_called()
324
Alex Klein076841b2019-08-29 15:19:39 -0600325 def testMockCall(self):
326 """Sanity check that a mock call does not execute any logic."""
327 patch = self.PatchObject(sysroot_service, 'InstallToolchain')
328 request = self._InputProto()
329 response = self._OutputProto()
330
331 rc = sysroot_controller.InstallToolchain(request, response,
332 self.mock_call_config)
333
334 patch.assert_not_called()
335 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
336
337 def testMockError(self):
338 """Sanity check that a mock error does not execute any logic."""
339 patch = self.PatchObject(sysroot_service, 'InstallToolchain')
340 request = self._InputProto()
341 response = self._OutputProto()
342
343 rc = sysroot_controller.InstallToolchain(request, response,
344 self.mock_error_config)
345
346 patch.assert_not_called()
347 self.assertEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
348 self.assertTrue(response.failed_packages)
349
Alex Kleinda35fcf2019-03-07 16:01:15 -0700350 def testArgumentValidation(self):
351 """Test the argument validation."""
352 # Test errors on missing inputs.
353 out_proto = self._OutputProto()
354 # Both missing.
355 in_proto = self._InputProto()
356 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600357 sysroot_controller.InstallToolchain(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700358
359 # Sysroot path missing.
360 in_proto = self._InputProto(build_target=self.board)
361 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600362 sysroot_controller.InstallToolchain(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700363
364 # Build target name missing.
365 in_proto = self._InputProto(sysroot_path=self.sysroot)
366 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600367 sysroot_controller.InstallToolchain(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700368
369 # Both provided, but invalid sysroot path.
370 in_proto = self._InputProto(build_target=self.board,
371 sysroot_path=self.invalid_sysroot)
372 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600373 sysroot_controller.InstallToolchain(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700374
375 def testSuccessOutputHandling(self):
376 """Test the output is processed and recorded correctly."""
377 self.PatchObject(sysroot_service, 'InstallToolchain')
378 out_proto = self._OutputProto()
379 in_proto = self._InputProto(build_target=self.board,
380 sysroot_path=self.sysroot)
381
Alex Klein231d2da2019-07-22 16:44:45 -0600382 rc = sysroot_controller.InstallToolchain(in_proto, out_proto,
383 self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700384 self.assertFalse(rc)
385 self.assertFalse(out_proto.failed_packages)
386
387
388 def testErrorOutputHandling(self):
389 """Test the error output is processed and recorded correctly."""
390 out_proto = self._OutputProto()
391 in_proto = self._InputProto(build_target=self.board,
392 sysroot_path=self.sysroot)
393
394 err_pkgs = ['cat/pkg', 'cat2/pkg2']
395 err_cpvs = [portage_util.SplitCPV(pkg, strict=False) for pkg in err_pkgs]
396 expected = [('cat', 'pkg'), ('cat2', 'pkg2')]
397 err = sysroot_lib.ToolchainInstallError('Error',
398 cros_build_lib.CommandResult(),
399 tc_info=err_cpvs)
400 self.PatchObject(sysroot_service, 'InstallToolchain', side_effect=err)
401
Alex Klein231d2da2019-07-22 16:44:45 -0600402 rc = sysroot_controller.InstallToolchain(in_proto, out_proto,
403 self.api_config)
Alex Klein8cb365a2019-05-15 16:24:53 -0600404 self.assertEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700405 self.assertTrue(out_proto.failed_packages)
406 for package in out_proto.failed_packages:
407 cat_pkg = (package.category, package.package_name)
408 self.assertIn(cat_pkg, expected)
Alex Kleind4e1e422019-03-18 16:00:41 -0600409
410
Alex Klein231d2da2019-07-22 16:44:45 -0600411class InstallPackagesTest(cros_test_lib.MockTempDirTestCase,
412 api_config.ApiConfigMixin):
Alex Kleind4e1e422019-03-18 16:00:41 -0600413 """InstallPackages tests."""
414
415 def setUp(self):
416 self.PatchObject(cros_build_lib, 'IsInsideChroot', return_value=True)
Alex Kleina9d64602019-05-17 14:55:37 -0600417 # Avoid running the portageq command.
418 self.PatchObject(sysroot_controller, '_LogBinhost')
Alex Kleind4e1e422019-03-18 16:00:41 -0600419 self.build_target = 'board'
420 self.sysroot = os.path.join(self.tempdir, 'build', 'board')
421 osutils.SafeMakedirs(self.sysroot)
Michael Mortensen798ee192020-01-17 13:04:43 -0700422 # Set up goma directories.
423 self.goma_dir = os.path.join(self.tempdir, 'goma_dir')
424 osutils.SafeMakedirs(self.goma_dir)
425 self.goma_out_dir = os.path.join(self.tempdir, 'goma_out_dir')
426 osutils.SafeMakedirs(self.goma_out_dir)
Michael Mortensen4ccfb082020-01-22 16:24:03 -0700427 os.environ['GLOG_log_dir'] = self.goma_dir
Alex Kleind4e1e422019-03-18 16:00:41 -0600428
429 def _InputProto(self, build_target=None, sysroot_path=None,
Michael Mortensen798ee192020-01-17 13:04:43 -0700430 build_source=False, goma_dir=None, goma_log_dir=None,
431 goma_stats_file=None, goma_counterz_file=None):
Alex Kleind4e1e422019-03-18 16:00:41 -0600432 """Helper to build an input proto instance."""
433 instance = sysroot_pb2.InstallPackagesRequest()
434
435 if build_target:
436 instance.sysroot.build_target.name = build_target
437 if sysroot_path:
438 instance.sysroot.path = sysroot_path
439 if build_source:
440 instance.flags.build_source = build_source
Michael Mortensen798ee192020-01-17 13:04:43 -0700441 if goma_dir:
442 instance.goma_config.goma_dir = goma_dir
443 if goma_log_dir:
444 instance.goma_config.log_dir.dir = goma_log_dir
445 if goma_stats_file:
446 instance.goma_config.stats_file = goma_stats_file
447 if goma_counterz_file:
448 instance.goma_config.counterz_file = goma_counterz_file
Alex Kleind4e1e422019-03-18 16:00:41 -0600449
450 return instance
451
452 def _OutputProto(self):
453 """Helper to build an empty output proto instance."""
454 return sysroot_pb2.InstallPackagesResponse()
455
Michael Mortensen798ee192020-01-17 13:04:43 -0700456 def _CreateGomaLogFile(self, goma_log_dir, name, timestamp):
457 """Creates a log file for testing.
458
459 Args:
460 goma_log_dir (str): Directory where the file will be created.
461 name (str): Log file 'base' name that is combined with the timestamp.
462 timestamp (datetime): timestamp that is written to the file.
463 """
464 path = os.path.join(
465 goma_log_dir,
466 '%s.host.log.INFO.%s' % (name, timestamp.strftime('%Y%m%d-%H%M%S.%f')))
467 osutils.WriteFile(
468 path,
469 timestamp.strftime('Goma log file created at: %Y/%m/%d %H:%M:%S'))
470
Alex Klein231d2da2019-07-22 16:44:45 -0600471 def testValidateOnly(self):
472 """Sanity check that a validate only call does not execute any logic."""
473 patch = self.PatchObject(sysroot_service, 'BuildPackages')
474
475 in_proto = self._InputProto(build_target=self.build_target,
476 sysroot_path=self.sysroot)
477 sysroot_controller.InstallPackages(in_proto, self._OutputProto(),
478 self.validate_only_config)
479 patch.assert_not_called()
480
Alex Klein076841b2019-08-29 15:19:39 -0600481 def testMockCall(self):
482 """Sanity check that a mock call does not execute any logic."""
483 patch = self.PatchObject(sysroot_service, 'BuildPackages')
484 request = self._InputProto()
485 response = self._OutputProto()
486
487 rc = sysroot_controller.InstallPackages(request, response,
488 self.mock_call_config)
489
490 patch.assert_not_called()
491 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
492
493 def testMockError(self):
494 """Sanity check that a mock error does not execute any logic."""
495 patch = self.PatchObject(sysroot_service, 'BuildPackages')
496 request = self._InputProto()
497 response = self._OutputProto()
498
499 rc = sysroot_controller.InstallPackages(request, response,
500 self.mock_error_config)
501
502 patch.assert_not_called()
503 self.assertEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
504 self.assertTrue(response.failed_packages)
505
Alex Kleind4e1e422019-03-18 16:00:41 -0600506 def testArgumentValidationAllMissing(self):
507 """Test missing all arguments."""
508 out_proto = self._OutputProto()
509 in_proto = self._InputProto()
510 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600511 sysroot_controller.InstallPackages(in_proto, out_proto, self.api_config)
Alex Kleind4e1e422019-03-18 16:00:41 -0600512
513 def testArgumentValidationNoSysroot(self):
514 """Test missing sysroot path."""
515 out_proto = self._OutputProto()
516 in_proto = self._InputProto(build_target=self.build_target)
517 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600518 sysroot_controller.InstallPackages(in_proto, out_proto, self.api_config)
Alex Kleind4e1e422019-03-18 16:00:41 -0600519
520 def testArgumentValidationNoBuildTarget(self):
521 """Test missing build target name."""
522 out_proto = self._OutputProto()
523 in_proto = self._InputProto(sysroot_path=self.sysroot)
524 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600525 sysroot_controller.InstallPackages(in_proto, out_proto, self.api_config)
Alex Kleind4e1e422019-03-18 16:00:41 -0600526
527 def testArgumentValidationInvalidSysroot(self):
528 """Test sysroot that hasn't had the toolchain installed."""
529 out_proto = self._OutputProto()
530 in_proto = self._InputProto(build_target=self.build_target,
531 sysroot_path=self.sysroot)
532 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
533 return_value=False)
534 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600535 sysroot_controller.InstallPackages(in_proto, out_proto, self.api_config)
Alex Kleind4e1e422019-03-18 16:00:41 -0600536
537 def testSuccessOutputHandling(self):
538 """Test successful call output handling."""
539 # Prevent argument validation error.
540 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
541 return_value=True)
542
543 in_proto = self._InputProto(build_target=self.build_target,
544 sysroot_path=self.sysroot)
545 out_proto = self._OutputProto()
546 self.PatchObject(sysroot_service, 'BuildPackages')
547
Alex Klein231d2da2019-07-22 16:44:45 -0600548 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
549 self.api_config)
Alex Kleind4e1e422019-03-18 16:00:41 -0600550 self.assertFalse(rc)
551 self.assertFalse(out_proto.failed_packages)
552
Michael Mortensen798ee192020-01-17 13:04:43 -0700553 def testSuccessWithGomaLogs(self):
554 """Test successful call with goma."""
555 self._CreateGomaLogFile(self.goma_dir, 'compiler_proxy',
556 datetime.datetime(2018, 9, 21, 12, 0, 0))
557 self._CreateGomaLogFile(self.goma_dir, 'compiler_proxy-subproc',
558 datetime.datetime(2018, 9, 21, 12, 1, 0))
559 self._CreateGomaLogFile(self.goma_dir, 'gomacc',
560 datetime.datetime(2018, 9, 21, 12, 2, 0))
561
562 # Prevent argument validation error.
563 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
564 return_value=True)
565
566 in_proto = self._InputProto(build_target=self.build_target,
567 sysroot_path=self.sysroot,
568 goma_dir=self.goma_dir,
569 goma_log_dir=self.goma_out_dir)
570
571 out_proto = self._OutputProto()
572 self.PatchObject(sysroot_service, 'BuildPackages')
573
574 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
575 self.api_config)
576 self.assertFalse(rc)
577 self.assertFalse(out_proto.failed_packages)
578 self.assertCountEqual(out_proto.goma_artifacts.log_files, [
579 'compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz',
580 'compiler_proxy.host.log.INFO.20180921-120000.000000.gz',
581 'gomacc.host.log.INFO.20180921-120200.000000.tar.gz'])
582
583 def testSuccessWithGomaLogsAndStatsCounterzFiles(self):
584 """Test successful call with goma including stats and counterz files."""
585 self._CreateGomaLogFile(self.goma_dir, 'compiler_proxy',
586 datetime.datetime(2018, 9, 21, 12, 0, 0))
587 self._CreateGomaLogFile(self.goma_dir, 'compiler_proxy-subproc',
588 datetime.datetime(2018, 9, 21, 12, 1, 0))
589 self._CreateGomaLogFile(self.goma_dir, 'gomacc',
590 datetime.datetime(2018, 9, 21, 12, 2, 0))
591 # Create stats and counterz files.
592 osutils.WriteFile(os.path.join(self.goma_dir, 'stats.binaryproto'),
593 'File: stats.binaryproto')
594 osutils.WriteFile(os.path.join(self.goma_dir, 'counterz.binaryproto'),
595 'File: counterz.binaryproto')
596
597 # Prevent argument validation error.
598 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
599 return_value=True)
600
601 in_proto = self._InputProto(build_target=self.build_target,
602 sysroot_path=self.sysroot,
603 goma_dir=self.goma_dir,
604 goma_log_dir=self.goma_out_dir,
605 goma_stats_file='stats.binaryproto',
606 goma_counterz_file='counterz.binaryproto')
607
608 out_proto = self._OutputProto()
609 self.PatchObject(sysroot_service, 'BuildPackages')
610
611 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
612 self.api_config)
613 self.assertFalse(rc)
614 self.assertFalse(out_proto.failed_packages)
615 self.assertCountEqual(out_proto.goma_artifacts.log_files, [
616 'compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz',
617 'compiler_proxy.host.log.INFO.20180921-120000.000000.gz',
618 'gomacc.host.log.INFO.20180921-120200.000000.tar.gz'])
619 # Verify that the output dir has 5 files -- since there should be 3 log
620 # files, the stats file, and the counterz file.
621 output_files = os.listdir(self.goma_out_dir)
622 self.assertCountEqual(output_files, [
623 'stats.binaryproto',
624 'counterz.binaryproto',
625 'compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz',
626 'compiler_proxy.host.log.INFO.20180921-120000.000000.gz',
627 'gomacc.host.log.INFO.20180921-120200.000000.tar.gz'])
Michael Mortensen1c7439c2020-01-24 14:43:19 -0700628 self.assertEqual(out_proto.goma_artifacts.counterz_file,
629 'counterz.binaryproto')
630 self.assertEqual(out_proto.goma_artifacts.stats_file,
631 'stats.binaryproto')
Michael Mortensen798ee192020-01-17 13:04:43 -0700632
633 def testFailureMissingGomaStatsCounterzFiles(self):
634 """Test successful call with goma including stats and counterz files."""
635 self._CreateGomaLogFile(self.goma_dir, 'compiler_proxy',
636 datetime.datetime(2018, 9, 21, 12, 0, 0))
637 self._CreateGomaLogFile(self.goma_dir, 'compiler_proxy-subproc',
638 datetime.datetime(2018, 9, 21, 12, 1, 0))
639 self._CreateGomaLogFile(self.goma_dir, 'gomacc',
640 datetime.datetime(2018, 9, 21, 12, 2, 0))
641 # Note that stats and counterz files are not created, but are specified in
642 # the proto below.
643
644 # Prevent argument validation error.
645 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
646 return_value=True)
647
648 in_proto = self._InputProto(build_target=self.build_target,
649 sysroot_path=self.sysroot,
650 goma_dir=self.goma_dir,
651 goma_log_dir=self.goma_out_dir,
652 goma_stats_file='stats.binaryproto',
653 goma_counterz_file='counterz.binaryproto')
654
655 out_proto = self._OutputProto()
656 self.PatchObject(sysroot_service, 'BuildPackages')
657
Michael Mortensen1d6d5b02020-01-22 07:33:50 -0700658 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
659 self.api_config)
660 self.assertFalse(rc)
661 self.assertFalse(out_proto.failed_packages)
662 self.assertCountEqual(out_proto.goma_artifacts.log_files, [
663 'compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz',
664 'compiler_proxy.host.log.INFO.20180921-120000.000000.gz',
665 'gomacc.host.log.INFO.20180921-120200.000000.tar.gz'])
666 self.assertFalse(out_proto.goma_artifacts.counterz_file)
667 self.assertFalse(out_proto.goma_artifacts.stats_file)
Michael Mortensen798ee192020-01-17 13:04:43 -0700668
Alex Kleind4e1e422019-03-18 16:00:41 -0600669 def testFailureOutputHandling(self):
670 """Test failed package handling."""
671 # Prevent argument validation error.
672 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
673 return_value=True)
674
675 in_proto = self._InputProto(build_target=self.build_target,
676 sysroot_path=self.sysroot)
677 out_proto = self._OutputProto()
678
679 # Failed package info and expected list for verification.
680 err_pkgs = ['cat/pkg', 'cat2/pkg2']
681 err_cpvs = [portage_util.SplitCPV(cpv, strict=False) for cpv in err_pkgs]
682 expected = [('cat', 'pkg'), ('cat2', 'pkg2')]
683
684 # Force error to be raised with the packages.
685 error = sysroot_lib.PackageInstallError('Error',
686 cros_build_lib.CommandResult(),
687 packages=err_cpvs)
688 self.PatchObject(sysroot_service, 'BuildPackages', side_effect=error)
689
Alex Klein231d2da2019-07-22 16:44:45 -0600690 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
691 self.api_config)
Alex Klein2557b4f2019-07-11 14:34:00 -0600692 # This needs to return 2 to indicate the available error response.
693 self.assertEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
Alex Kleind4e1e422019-03-18 16:00:41 -0600694 for package in out_proto.failed_packages:
695 cat_pkg = (package.category, package.package_name)
696 self.assertIn(cat_pkg, expected)
Alex Klein2557b4f2019-07-11 14:34:00 -0600697
698 def testNoPackageFailureOutputHandling(self):
699 """Test failure handling without packages to report."""
700 # Prevent argument validation error.
701 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
702 return_value=True)
703
704 in_proto = self._InputProto(build_target=self.build_target,
705 sysroot_path=self.sysroot)
706 out_proto = self._OutputProto()
707
708 # Force error to be raised with no packages.
709 error = sysroot_lib.PackageInstallError('Error',
710 cros_build_lib.CommandResult(),
711 packages=[])
712 self.PatchObject(sysroot_service, 'BuildPackages', side_effect=error)
713
Alex Klein231d2da2019-07-22 16:44:45 -0600714 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
715 self.api_config)
Alex Klein2557b4f2019-07-11 14:34:00 -0600716 # All we really care about is it's not 0 or 2 (response available), so
717 # test for that rather than a specific return code.
718 self.assertTrue(rc)
719 self.assertNotEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE,
720 rc)