blob: 5aad79370612ffc86aa1e9a9a3ea728a27c78fa8 [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.
Alex Kleinda35fcf2019-03-07 16:01:15 -0700124 rc_patch.assert_called_with(force=force, upgrade_chroot=upgrade_chroot)
125 self.assertEqual(board, out_proto.sysroot.build_target.name)
126 self.assertEqual(sysroot_path, out_proto.sysroot.path)
127
128 # Not default values.
129 create_patch.reset_mock()
130 board = 'board'
131 profile = 'profile'
132 force = True
133 upgrade_chroot = False
134 in_proto = self._InputProto(build_target=board, profile=profile,
135 replace=force, current=not upgrade_chroot)
136 out_proto = self._OutputProto()
Alex Klein231d2da2019-07-22 16:44:45 -0600137 sysroot_controller.Create(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700138
139 # Not default value checks.
Alex Kleinda35fcf2019-03-07 16:01:15 -0700140 rc_patch.assert_called_with(force=force, upgrade_chroot=upgrade_chroot)
141 self.assertEqual(board, out_proto.sysroot.build_target.name)
142 self.assertEqual(sysroot_path, out_proto.sysroot.path)
143
144
Michael Mortensen98592f62019-09-27 13:34:18 -0600145class CreateSimpleChromeSysrootTest(cros_test_lib.MockTempDirTestCase,
146 api_config.ApiConfigMixin):
147 """CreateSimpleChromeSysroot function tests."""
148
149 def _InputProto(self, build_target=None, use_flags=None):
150 """Helper to build and input proto instance."""
151 proto = sysroot_pb2.CreateSimpleChromeSysrootRequest()
152 if build_target:
153 proto.build_target.name = build_target
154 if use_flags:
155 proto.use_flags = use_flags
156 return proto
157
158 def _OutputProto(self):
159 """Helper to build output proto instance."""
160 return sysroot_pb2.CreateSimpleChromeSysrootResponse()
161
162 def testValidateOnly(self):
163 """Sanity check that a validate only call does not execute any logic."""
164 patch = self.PatchObject(sysroot_service, 'CreateSimpleChromeSysroot')
165
166 board = 'board'
167 in_proto = self._InputProto(build_target=board, use_flags=[])
168 sysroot_controller.CreateSimpleChromeSysroot(in_proto, self._OutputProto(),
169 self.validate_only_config)
170 patch.assert_not_called()
171
Michael Mortensen3232ab32020-01-05 19:14:36 -0700172 def testMockCall(self):
173 """Sanity check that a mock call does not execute any logic."""
174 patch = self.PatchObject(sysroot_service, 'CreateSimpleChromeSysroot')
175
176 board = 'board'
177 in_proto = self._InputProto(build_target=board, use_flags=[])
178 rc = sysroot_controller.CreateSimpleChromeSysroot(in_proto,
179 self._OutputProto(),
180 self.mock_call_config)
181 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
182 patch.assert_not_called()
183
Michael Mortensen98592f62019-09-27 13:34:18 -0600184 def testArgumentValidation(self):
185 """Test the input argument validation."""
186 # Error when no build target provided.
187 in_proto = self._InputProto()
188 out_proto = self._OutputProto()
189 with self.assertRaises(cros_build_lib.DieSystemExit):
190 sysroot_controller.CreateSimpleChromeSysroot(in_proto, out_proto,
191 self.api_config)
192
193 # Valid when board is specified.
194 patch = self.PatchObject(sysroot_service, 'CreateSimpleChromeSysroot',
195 return_value='/path/to/sysroot/tar.bz')
196 in_proto = self._InputProto(build_target='board')
197 out_proto = self._OutputProto()
198 sysroot_controller.CreateSimpleChromeSysroot(in_proto, out_proto,
199 self.api_config)
200 patch.assert_called_once()
201
202
Michael Mortensen3f6b4bd2020-02-07 14:16:43 -0700203class GenerateArchiveTest(cros_test_lib.MockTempDirTestCase,
204 api_config.ApiConfigMixin):
205 """GenerateArchive function tests."""
206
207 def setUp(self):
208 self.chroot_path = '/path/to/chroot'
209 self.board = 'board'
210
211 def _InputProto(self, build_target=None, chroot_path=None, pkg_list=None):
212 """Helper to build and input proto instance."""
213 # pkg_list will be a list of category/package strings such as
214 # ['virtual/target-fuzzers'].
215 if pkg_list:
216 package_list = []
217 for pkg in pkg_list:
218 pkg_string_parts = pkg.split('/')
219 package_info = common_pb2.PackageInfo(
220 category=pkg_string_parts[0],
221 package_name=pkg_string_parts[1])
222 package_list.append(package_info)
223 else:
224 package_list = []
225
226 return sysroot_pb2.SysrootGenerateArchiveRequest(
227 build_target={'name': build_target},
228 chroot={'path': chroot_path},
229 packages=package_list)
230
231 def _OutputProto(self):
232 """Helper to build output proto instance."""
233 return sysroot_pb2.SysrootGenerateArchiveResponse()
234
235 def testValidateOnly(self):
236 """Sanity check that a validate only call does not execute any logic."""
237 patch = self.PatchObject(sysroot_service, 'GenerateArchive')
238
239 in_proto = self._InputProto(build_target=self.board,
240 chroot_path=self.chroot_path,
241 pkg_list=['virtual/target-fuzzers'])
242 sysroot_controller.GenerateArchive(in_proto, self._OutputProto(),
243 self.validate_only_config)
244 patch.assert_not_called()
245
246 def testMockCall(self):
247 """Sanity check that a mock call does not execute any logic."""
248 patch = self.PatchObject(sysroot_service, 'GenerateArchive')
249
250 in_proto = self._InputProto(build_target=self.board,
251 chroot_path=self.chroot_path,
252 pkg_list=['virtual/target-fuzzers'])
253 sysroot_controller.GenerateArchive(in_proto,
254 self._OutputProto(),
255 self.mock_call_config)
256 patch.assert_not_called()
257
258 def testArgumentValidation(self):
259 """Test the input argument validation."""
260 # Error when no build target provided.
261 in_proto = self._InputProto()
262 out_proto = self._OutputProto()
263 with self.assertRaises(cros_build_lib.DieSystemExit):
264 sysroot_controller.GenerateArchive(in_proto, out_proto, self.api_config)
265
266 # Error when packages is not specified.
267 in_proto = self._InputProto(build_target='board',
268 chroot_path=self.chroot_path)
269 with self.assertRaises(cros_build_lib.DieSystemExit):
270 sysroot_controller.GenerateArchive(in_proto, out_proto, self.api_config)
271
272 # Valid when board, chroot path, and package are specified.
273 patch = self.PatchObject(sysroot_service, 'GenerateArchive',
274 return_value='/path/to/sysroot/tar.bz')
275 in_proto = self._InputProto(build_target='board',
276 chroot_path=self.chroot_path,
277 pkg_list=['virtual/target-fuzzers'])
278 out_proto = self._OutputProto()
279 sysroot_controller.GenerateArchive(in_proto, out_proto, self.api_config)
280 patch.assert_called_once()
281
282
Alex Klein231d2da2019-07-22 16:44:45 -0600283class InstallToolchainTest(cros_test_lib.MockTempDirTestCase,
284 api_config.ApiConfigMixin):
Alex Kleinda35fcf2019-03-07 16:01:15 -0700285 """Install toolchain function tests."""
286
287 def setUp(self):
288 self.PatchObject(cros_build_lib, 'IsInsideChroot', return_value=True)
Alex Kleina9d64602019-05-17 14:55:37 -0600289 # Avoid running the portageq command.
290 self.PatchObject(sysroot_controller, '_LogBinhost')
Alex Kleinda35fcf2019-03-07 16:01:15 -0700291 self.board = 'board'
292 self.sysroot = os.path.join(self.tempdir, 'board')
293 self.invalid_sysroot = os.path.join(self.tempdir, 'invalid', 'sysroot')
294 osutils.SafeMakedirs(self.sysroot)
295
296 def _InputProto(self, build_target=None, sysroot_path=None,
297 compile_source=False):
Alex Kleind4e1e422019-03-18 16:00:41 -0600298 """Helper to build an input proto instance."""
Alex Kleinda35fcf2019-03-07 16:01:15 -0700299 proto = sysroot_pb2.InstallToolchainRequest()
300 if build_target:
301 proto.sysroot.build_target.name = build_target
302 if sysroot_path:
303 proto.sysroot.path = sysroot_path
304 if compile_source:
305 proto.flags.compile_source = compile_source
306
307 return proto
308
309 def _OutputProto(self):
310 """Helper to build output proto instance."""
311 return sysroot_pb2.InstallToolchainResponse()
312
Alex Klein231d2da2019-07-22 16:44:45 -0600313 def testValidateOnly(self):
314 """Sanity check that a validate only call does not execute any logic."""
315 patch = self.PatchObject(sysroot_service, 'InstallToolchain')
316
317 in_proto = self._InputProto(build_target=self.board,
318 sysroot_path=self.sysroot)
319 sysroot_controller.InstallToolchain(in_proto, self._OutputProto(),
320 self.validate_only_config)
321 patch.assert_not_called()
322
Alex Klein076841b2019-08-29 15:19:39 -0600323 def testMockCall(self):
324 """Sanity check that a mock call does not execute any logic."""
325 patch = self.PatchObject(sysroot_service, 'InstallToolchain')
326 request = self._InputProto()
327 response = self._OutputProto()
328
329 rc = sysroot_controller.InstallToolchain(request, response,
330 self.mock_call_config)
331
332 patch.assert_not_called()
333 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
334
335 def testMockError(self):
336 """Sanity check that a mock error does not execute any logic."""
337 patch = self.PatchObject(sysroot_service, 'InstallToolchain')
338 request = self._InputProto()
339 response = self._OutputProto()
340
341 rc = sysroot_controller.InstallToolchain(request, response,
342 self.mock_error_config)
343
344 patch.assert_not_called()
345 self.assertEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
346 self.assertTrue(response.failed_packages)
347
Alex Kleinda35fcf2019-03-07 16:01:15 -0700348 def testArgumentValidation(self):
349 """Test the argument validation."""
350 # Test errors on missing inputs.
351 out_proto = self._OutputProto()
352 # Both missing.
353 in_proto = self._InputProto()
354 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600355 sysroot_controller.InstallToolchain(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700356
357 # Sysroot path missing.
358 in_proto = self._InputProto(build_target=self.board)
359 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600360 sysroot_controller.InstallToolchain(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700361
362 # Build target name missing.
363 in_proto = self._InputProto(sysroot_path=self.sysroot)
364 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600365 sysroot_controller.InstallToolchain(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700366
367 # Both provided, but invalid sysroot path.
368 in_proto = self._InputProto(build_target=self.board,
369 sysroot_path=self.invalid_sysroot)
370 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600371 sysroot_controller.InstallToolchain(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700372
373 def testSuccessOutputHandling(self):
374 """Test the output is processed and recorded correctly."""
375 self.PatchObject(sysroot_service, 'InstallToolchain')
376 out_proto = self._OutputProto()
377 in_proto = self._InputProto(build_target=self.board,
378 sysroot_path=self.sysroot)
379
Alex Klein231d2da2019-07-22 16:44:45 -0600380 rc = sysroot_controller.InstallToolchain(in_proto, out_proto,
381 self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700382 self.assertFalse(rc)
383 self.assertFalse(out_proto.failed_packages)
384
385
386 def testErrorOutputHandling(self):
387 """Test the error output is processed and recorded correctly."""
388 out_proto = self._OutputProto()
389 in_proto = self._InputProto(build_target=self.board,
390 sysroot_path=self.sysroot)
391
392 err_pkgs = ['cat/pkg', 'cat2/pkg2']
393 err_cpvs = [portage_util.SplitCPV(pkg, strict=False) for pkg in err_pkgs]
394 expected = [('cat', 'pkg'), ('cat2', 'pkg2')]
395 err = sysroot_lib.ToolchainInstallError('Error',
396 cros_build_lib.CommandResult(),
397 tc_info=err_cpvs)
398 self.PatchObject(sysroot_service, 'InstallToolchain', side_effect=err)
399
Alex Klein231d2da2019-07-22 16:44:45 -0600400 rc = sysroot_controller.InstallToolchain(in_proto, out_proto,
401 self.api_config)
Alex Klein8cb365a2019-05-15 16:24:53 -0600402 self.assertEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700403 self.assertTrue(out_proto.failed_packages)
404 for package in out_proto.failed_packages:
405 cat_pkg = (package.category, package.package_name)
406 self.assertIn(cat_pkg, expected)
Alex Kleind4e1e422019-03-18 16:00:41 -0600407
408
Alex Klein231d2da2019-07-22 16:44:45 -0600409class InstallPackagesTest(cros_test_lib.MockTempDirTestCase,
410 api_config.ApiConfigMixin):
Alex Kleind4e1e422019-03-18 16:00:41 -0600411 """InstallPackages tests."""
412
413 def setUp(self):
414 self.PatchObject(cros_build_lib, 'IsInsideChroot', return_value=True)
Alex Kleina9d64602019-05-17 14:55:37 -0600415 # Avoid running the portageq command.
416 self.PatchObject(sysroot_controller, '_LogBinhost')
Alex Kleind4e1e422019-03-18 16:00:41 -0600417 self.build_target = 'board'
418 self.sysroot = os.path.join(self.tempdir, 'build', 'board')
419 osutils.SafeMakedirs(self.sysroot)
Michael Mortensen798ee192020-01-17 13:04:43 -0700420 # Set up goma directories.
421 self.goma_dir = os.path.join(self.tempdir, 'goma_dir')
422 osutils.SafeMakedirs(self.goma_dir)
423 self.goma_out_dir = os.path.join(self.tempdir, 'goma_out_dir')
424 osutils.SafeMakedirs(self.goma_out_dir)
Michael Mortensen4ccfb082020-01-22 16:24:03 -0700425 os.environ['GLOG_log_dir'] = self.goma_dir
Alex Kleind4e1e422019-03-18 16:00:41 -0600426
427 def _InputProto(self, build_target=None, sysroot_path=None,
Michael Mortensen798ee192020-01-17 13:04:43 -0700428 build_source=False, goma_dir=None, goma_log_dir=None,
429 goma_stats_file=None, goma_counterz_file=None):
Alex Kleind4e1e422019-03-18 16:00:41 -0600430 """Helper to build an input proto instance."""
431 instance = sysroot_pb2.InstallPackagesRequest()
432
433 if build_target:
434 instance.sysroot.build_target.name = build_target
435 if sysroot_path:
436 instance.sysroot.path = sysroot_path
437 if build_source:
438 instance.flags.build_source = build_source
Michael Mortensen798ee192020-01-17 13:04:43 -0700439 if goma_dir:
440 instance.goma_config.goma_dir = goma_dir
441 if goma_log_dir:
442 instance.goma_config.log_dir.dir = goma_log_dir
443 if goma_stats_file:
444 instance.goma_config.stats_file = goma_stats_file
445 if goma_counterz_file:
446 instance.goma_config.counterz_file = goma_counterz_file
Alex Kleind4e1e422019-03-18 16:00:41 -0600447
448 return instance
449
450 def _OutputProto(self):
451 """Helper to build an empty output proto instance."""
452 return sysroot_pb2.InstallPackagesResponse()
453
Michael Mortensen798ee192020-01-17 13:04:43 -0700454 def _CreateGomaLogFile(self, goma_log_dir, name, timestamp):
455 """Creates a log file for testing.
456
457 Args:
458 goma_log_dir (str): Directory where the file will be created.
459 name (str): Log file 'base' name that is combined with the timestamp.
460 timestamp (datetime): timestamp that is written to the file.
461 """
462 path = os.path.join(
463 goma_log_dir,
464 '%s.host.log.INFO.%s' % (name, timestamp.strftime('%Y%m%d-%H%M%S.%f')))
465 osutils.WriteFile(
466 path,
467 timestamp.strftime('Goma log file created at: %Y/%m/%d %H:%M:%S'))
468
Alex Klein231d2da2019-07-22 16:44:45 -0600469 def testValidateOnly(self):
470 """Sanity check that a validate only call does not execute any logic."""
471 patch = self.PatchObject(sysroot_service, 'BuildPackages')
472
473 in_proto = self._InputProto(build_target=self.build_target,
474 sysroot_path=self.sysroot)
475 sysroot_controller.InstallPackages(in_proto, self._OutputProto(),
476 self.validate_only_config)
477 patch.assert_not_called()
478
Alex Klein076841b2019-08-29 15:19:39 -0600479 def testMockCall(self):
480 """Sanity check that a mock call does not execute any logic."""
481 patch = self.PatchObject(sysroot_service, 'BuildPackages')
482 request = self._InputProto()
483 response = self._OutputProto()
484
485 rc = sysroot_controller.InstallPackages(request, response,
486 self.mock_call_config)
487
488 patch.assert_not_called()
489 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
490
491 def testMockError(self):
492 """Sanity check that a mock error does not execute any logic."""
493 patch = self.PatchObject(sysroot_service, 'BuildPackages')
494 request = self._InputProto()
495 response = self._OutputProto()
496
497 rc = sysroot_controller.InstallPackages(request, response,
498 self.mock_error_config)
499
500 patch.assert_not_called()
501 self.assertEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
502 self.assertTrue(response.failed_packages)
503
Alex Kleind4e1e422019-03-18 16:00:41 -0600504 def testArgumentValidationAllMissing(self):
505 """Test missing all arguments."""
506 out_proto = self._OutputProto()
507 in_proto = self._InputProto()
508 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600509 sysroot_controller.InstallPackages(in_proto, out_proto, self.api_config)
Alex Kleind4e1e422019-03-18 16:00:41 -0600510
511 def testArgumentValidationNoSysroot(self):
512 """Test missing sysroot path."""
513 out_proto = self._OutputProto()
514 in_proto = self._InputProto(build_target=self.build_target)
515 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600516 sysroot_controller.InstallPackages(in_proto, out_proto, self.api_config)
Alex Kleind4e1e422019-03-18 16:00:41 -0600517
518 def testArgumentValidationNoBuildTarget(self):
519 """Test missing build target name."""
520 out_proto = self._OutputProto()
521 in_proto = self._InputProto(sysroot_path=self.sysroot)
522 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600523 sysroot_controller.InstallPackages(in_proto, out_proto, self.api_config)
Alex Kleind4e1e422019-03-18 16:00:41 -0600524
525 def testArgumentValidationInvalidSysroot(self):
526 """Test sysroot that hasn't had the toolchain installed."""
527 out_proto = self._OutputProto()
528 in_proto = self._InputProto(build_target=self.build_target,
529 sysroot_path=self.sysroot)
530 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
531 return_value=False)
532 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600533 sysroot_controller.InstallPackages(in_proto, out_proto, self.api_config)
Alex Kleind4e1e422019-03-18 16:00:41 -0600534
535 def testSuccessOutputHandling(self):
536 """Test successful call output handling."""
537 # Prevent argument validation error.
538 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
539 return_value=True)
540
541 in_proto = self._InputProto(build_target=self.build_target,
542 sysroot_path=self.sysroot)
543 out_proto = self._OutputProto()
544 self.PatchObject(sysroot_service, 'BuildPackages')
545
Alex Klein231d2da2019-07-22 16:44:45 -0600546 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
547 self.api_config)
Alex Kleind4e1e422019-03-18 16:00:41 -0600548 self.assertFalse(rc)
549 self.assertFalse(out_proto.failed_packages)
550
Michael Mortensen798ee192020-01-17 13:04:43 -0700551 def testSuccessWithGomaLogs(self):
552 """Test successful call with goma."""
553 self._CreateGomaLogFile(self.goma_dir, 'compiler_proxy',
554 datetime.datetime(2018, 9, 21, 12, 0, 0))
555 self._CreateGomaLogFile(self.goma_dir, 'compiler_proxy-subproc',
556 datetime.datetime(2018, 9, 21, 12, 1, 0))
557 self._CreateGomaLogFile(self.goma_dir, 'gomacc',
558 datetime.datetime(2018, 9, 21, 12, 2, 0))
559
560 # Prevent argument validation error.
561 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
562 return_value=True)
563
564 in_proto = self._InputProto(build_target=self.build_target,
565 sysroot_path=self.sysroot,
566 goma_dir=self.goma_dir,
567 goma_log_dir=self.goma_out_dir)
568
569 out_proto = self._OutputProto()
570 self.PatchObject(sysroot_service, 'BuildPackages')
571
572 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
573 self.api_config)
574 self.assertFalse(rc)
575 self.assertFalse(out_proto.failed_packages)
576 self.assertCountEqual(out_proto.goma_artifacts.log_files, [
577 'compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz',
578 'compiler_proxy.host.log.INFO.20180921-120000.000000.gz',
579 'gomacc.host.log.INFO.20180921-120200.000000.tar.gz'])
580
581 def testSuccessWithGomaLogsAndStatsCounterzFiles(self):
582 """Test successful call with goma including stats and counterz files."""
583 self._CreateGomaLogFile(self.goma_dir, 'compiler_proxy',
584 datetime.datetime(2018, 9, 21, 12, 0, 0))
585 self._CreateGomaLogFile(self.goma_dir, 'compiler_proxy-subproc',
586 datetime.datetime(2018, 9, 21, 12, 1, 0))
587 self._CreateGomaLogFile(self.goma_dir, 'gomacc',
588 datetime.datetime(2018, 9, 21, 12, 2, 0))
589 # Create stats and counterz files.
590 osutils.WriteFile(os.path.join(self.goma_dir, 'stats.binaryproto'),
591 'File: stats.binaryproto')
592 osutils.WriteFile(os.path.join(self.goma_dir, 'counterz.binaryproto'),
593 'File: counterz.binaryproto')
594
595 # Prevent argument validation error.
596 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
597 return_value=True)
598
599 in_proto = self._InputProto(build_target=self.build_target,
600 sysroot_path=self.sysroot,
601 goma_dir=self.goma_dir,
602 goma_log_dir=self.goma_out_dir,
603 goma_stats_file='stats.binaryproto',
604 goma_counterz_file='counterz.binaryproto')
605
606 out_proto = self._OutputProto()
607 self.PatchObject(sysroot_service, 'BuildPackages')
608
609 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
610 self.api_config)
611 self.assertFalse(rc)
612 self.assertFalse(out_proto.failed_packages)
613 self.assertCountEqual(out_proto.goma_artifacts.log_files, [
614 'compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz',
615 'compiler_proxy.host.log.INFO.20180921-120000.000000.gz',
616 'gomacc.host.log.INFO.20180921-120200.000000.tar.gz'])
617 # Verify that the output dir has 5 files -- since there should be 3 log
618 # files, the stats file, and the counterz file.
619 output_files = os.listdir(self.goma_out_dir)
620 self.assertCountEqual(output_files, [
621 'stats.binaryproto',
622 'counterz.binaryproto',
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'])
Michael Mortensen1c7439c2020-01-24 14:43:19 -0700626 self.assertEqual(out_proto.goma_artifacts.counterz_file,
627 'counterz.binaryproto')
628 self.assertEqual(out_proto.goma_artifacts.stats_file,
629 'stats.binaryproto')
Michael Mortensen798ee192020-01-17 13:04:43 -0700630
631 def testFailureMissingGomaStatsCounterzFiles(self):
632 """Test successful call with goma including stats and counterz files."""
633 self._CreateGomaLogFile(self.goma_dir, 'compiler_proxy',
634 datetime.datetime(2018, 9, 21, 12, 0, 0))
635 self._CreateGomaLogFile(self.goma_dir, 'compiler_proxy-subproc',
636 datetime.datetime(2018, 9, 21, 12, 1, 0))
637 self._CreateGomaLogFile(self.goma_dir, 'gomacc',
638 datetime.datetime(2018, 9, 21, 12, 2, 0))
639 # Note that stats and counterz files are not created, but are specified in
640 # the proto below.
641
642 # Prevent argument validation error.
643 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
644 return_value=True)
645
646 in_proto = self._InputProto(build_target=self.build_target,
647 sysroot_path=self.sysroot,
648 goma_dir=self.goma_dir,
649 goma_log_dir=self.goma_out_dir,
650 goma_stats_file='stats.binaryproto',
651 goma_counterz_file='counterz.binaryproto')
652
653 out_proto = self._OutputProto()
654 self.PatchObject(sysroot_service, 'BuildPackages')
655
Michael Mortensen1d6d5b02020-01-22 07:33:50 -0700656 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
657 self.api_config)
658 self.assertFalse(rc)
659 self.assertFalse(out_proto.failed_packages)
660 self.assertCountEqual(out_proto.goma_artifacts.log_files, [
661 'compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz',
662 'compiler_proxy.host.log.INFO.20180921-120000.000000.gz',
663 'gomacc.host.log.INFO.20180921-120200.000000.tar.gz'])
664 self.assertFalse(out_proto.goma_artifacts.counterz_file)
665 self.assertFalse(out_proto.goma_artifacts.stats_file)
Michael Mortensen798ee192020-01-17 13:04:43 -0700666
Alex Kleind4e1e422019-03-18 16:00:41 -0600667 def testFailureOutputHandling(self):
668 """Test failed package handling."""
669 # Prevent argument validation error.
670 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
671 return_value=True)
672
673 in_proto = self._InputProto(build_target=self.build_target,
674 sysroot_path=self.sysroot)
675 out_proto = self._OutputProto()
676
677 # Failed package info and expected list for verification.
678 err_pkgs = ['cat/pkg', 'cat2/pkg2']
679 err_cpvs = [portage_util.SplitCPV(cpv, strict=False) for cpv in err_pkgs]
680 expected = [('cat', 'pkg'), ('cat2', 'pkg2')]
681
682 # Force error to be raised with the packages.
683 error = sysroot_lib.PackageInstallError('Error',
684 cros_build_lib.CommandResult(),
685 packages=err_cpvs)
686 self.PatchObject(sysroot_service, 'BuildPackages', side_effect=error)
687
Alex Klein231d2da2019-07-22 16:44:45 -0600688 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
689 self.api_config)
Alex Klein2557b4f2019-07-11 14:34:00 -0600690 # This needs to return 2 to indicate the available error response.
691 self.assertEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
Alex Kleind4e1e422019-03-18 16:00:41 -0600692 for package in out_proto.failed_packages:
693 cat_pkg = (package.category, package.package_name)
694 self.assertIn(cat_pkg, expected)
Alex Klein2557b4f2019-07-11 14:34:00 -0600695
696 def testNoPackageFailureOutputHandling(self):
697 """Test failure handling without packages to report."""
698 # Prevent argument validation error.
699 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
700 return_value=True)
701
702 in_proto = self._InputProto(build_target=self.build_target,
703 sysroot_path=self.sysroot)
704 out_proto = self._OutputProto()
705
706 # Force error to be raised with no packages.
707 error = sysroot_lib.PackageInstallError('Error',
708 cros_build_lib.CommandResult(),
709 packages=[])
710 self.PatchObject(sysroot_service, 'BuildPackages', side_effect=error)
711
Alex Klein231d2da2019-07-22 16:44:45 -0600712 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
713 self.api_config)
Alex Klein2557b4f2019-07-11 14:34:00 -0600714 # All we really care about is it's not 0 or 2 (response available), so
715 # test for that rather than a specific return code.
716 self.assertTrue(rc)
717 self.assertNotEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE,
718 rc)