blob: 6d230ec9535bd3ef48a1c669cc73357f8175250b [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
12
Alex Klein231d2da2019-07-22 16:44:45 -060013from chromite.api import api_config
Alex Klein8cb365a2019-05-15 16:24:53 -060014from chromite.api import controller
Alex Kleinda35fcf2019-03-07 16:01:15 -070015from chromite.api.controller import sysroot as sysroot_controller
16from chromite.api.gen.chromite.api import sysroot_pb2
17from chromite.lib import build_target_util
18from chromite.lib import cros_build_lib
19from chromite.lib import cros_test_lib
20from chromite.lib import osutils
21from chromite.lib import portage_util
22from chromite.lib import sysroot_lib
23from chromite.service import sysroot as sysroot_service
24
25
Alex Klein231d2da2019-07-22 16:44:45 -060026class CreateTest(cros_test_lib.MockTestCase, api_config.ApiConfigMixin):
Alex Kleinda35fcf2019-03-07 16:01:15 -070027 """Create function tests."""
28
29 def _InputProto(self, build_target=None, profile=None, replace=False,
30 current=False):
31 """Helper to build and input proto instance."""
32 proto = sysroot_pb2.SysrootCreateRequest()
33 if build_target:
34 proto.build_target.name = build_target
35 if profile:
36 proto.profile.name = profile
37 if replace:
38 proto.flags.replace = replace
39 if current:
40 proto.flags.chroot_current = current
41
42 return proto
43
44 def _OutputProto(self):
45 """Helper to build output proto instance."""
46 return sysroot_pb2.SysrootCreateResponse()
47
Alex Klein231d2da2019-07-22 16:44:45 -060048 def testValidateOnly(self):
49 """Sanity check that a validate only call does not execute any logic."""
50 patch = self.PatchObject(sysroot_service, 'Create')
51
52 board = 'board'
53 profile = None
54 force = False
55 upgrade_chroot = True
56 in_proto = self._InputProto(build_target=board, profile=profile,
57 replace=force, current=not upgrade_chroot)
58 sysroot_controller.Create(in_proto, self._OutputProto(),
59 self.validate_only_config)
60 patch.assert_not_called()
61
Alex Klein076841b2019-08-29 15:19:39 -060062 def testMockCall(self):
63 """Sanity check that a mock call does not execute any logic."""
64 patch = self.PatchObject(sysroot_service, 'Create')
65 request = self._InputProto()
66 response = self._OutputProto()
67
68 rc = sysroot_controller.Create(request, response, self.mock_call_config)
69
70 patch.assert_not_called()
71 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
72
73 def testMockError(self):
74 """Sanity check that a mock error does not execute any logic."""
75 patch = self.PatchObject(sysroot_service, 'Create')
76 request = self._InputProto()
77 response = self._OutputProto()
78
79 rc = sysroot_controller.Create(request, response, self.mock_error_config)
80
81 patch.assert_not_called()
82 self.assertEqual(controller.RETURN_CODE_UNRECOVERABLE, rc)
83
Alex Kleinda35fcf2019-03-07 16:01:15 -070084 def testArgumentValidation(self):
85 """Test the input argument validation."""
86 # Error when no name provided.
87 in_proto = self._InputProto()
88 out_proto = self._OutputProto()
89 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -060090 sysroot_controller.Create(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -070091
92 # Valid when board passed.
93 result = sysroot_lib.Sysroot('/sysroot/path')
94 patch = self.PatchObject(sysroot_service, 'Create', return_value=result)
95 in_proto = self._InputProto('board')
96 out_proto = self._OutputProto()
Alex Klein231d2da2019-07-22 16:44:45 -060097 sysroot_controller.Create(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -070098 patch.assert_called_once()
99
100 def testArgumentHandling(self):
101 """Test the arguments get processed and passed correctly."""
102 sysroot_path = '/sysroot/path'
103
104 sysroot = sysroot_lib.Sysroot(sysroot_path)
105 create_patch = self.PatchObject(sysroot_service, 'Create',
106 return_value=sysroot)
107 target_patch = self.PatchObject(build_target_util, 'BuildTarget')
108 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.
121 target_patch.assert_called_with(name=board, profile=profile)
122 rc_patch.assert_called_with(force=force, upgrade_chroot=upgrade_chroot)
123 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
132 in_proto = self._InputProto(build_target=board, profile=profile,
133 replace=force, current=not upgrade_chroot)
134 out_proto = self._OutputProto()
Alex Klein231d2da2019-07-22 16:44:45 -0600135 sysroot_controller.Create(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700136
137 # Not default value checks.
138 target_patch.assert_called_with(name=board, profile=profile)
139 rc_patch.assert_called_with(force=force, upgrade_chroot=upgrade_chroot)
140 self.assertEqual(board, out_proto.sysroot.build_target.name)
141 self.assertEqual(sysroot_path, out_proto.sysroot.path)
142
143
Michael Mortensen98592f62019-09-27 13:34:18 -0600144class CreateSimpleChromeSysrootTest(cros_test_lib.MockTempDirTestCase,
145 api_config.ApiConfigMixin):
146 """CreateSimpleChromeSysroot function tests."""
147
148 def _InputProto(self, build_target=None, use_flags=None):
149 """Helper to build and input proto instance."""
150 proto = sysroot_pb2.CreateSimpleChromeSysrootRequest()
151 if build_target:
152 proto.build_target.name = build_target
153 if use_flags:
154 proto.use_flags = use_flags
155 return proto
156
157 def _OutputProto(self):
158 """Helper to build output proto instance."""
159 return sysroot_pb2.CreateSimpleChromeSysrootResponse()
160
161 def testValidateOnly(self):
162 """Sanity check that a validate only call does not execute any logic."""
163 patch = self.PatchObject(sysroot_service, 'CreateSimpleChromeSysroot')
164
165 board = 'board'
166 in_proto = self._InputProto(build_target=board, use_flags=[])
167 sysroot_controller.CreateSimpleChromeSysroot(in_proto, self._OutputProto(),
168 self.validate_only_config)
169 patch.assert_not_called()
170
Michael Mortensen3232ab32020-01-05 19:14:36 -0700171 def testMockCall(self):
172 """Sanity check that a mock call does not execute any logic."""
173 patch = self.PatchObject(sysroot_service, 'CreateSimpleChromeSysroot')
174
175 board = 'board'
176 in_proto = self._InputProto(build_target=board, use_flags=[])
177 rc = sysroot_controller.CreateSimpleChromeSysroot(in_proto,
178 self._OutputProto(),
179 self.mock_call_config)
180 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
181 patch.assert_not_called()
182
Michael Mortensen98592f62019-09-27 13:34:18 -0600183 def testArgumentValidation(self):
184 """Test the input argument validation."""
185 # Error when no build target provided.
186 in_proto = self._InputProto()
187 out_proto = self._OutputProto()
188 with self.assertRaises(cros_build_lib.DieSystemExit):
189 sysroot_controller.CreateSimpleChromeSysroot(in_proto, out_proto,
190 self.api_config)
191
192 # Valid when board is specified.
193 patch = self.PatchObject(sysroot_service, 'CreateSimpleChromeSysroot',
194 return_value='/path/to/sysroot/tar.bz')
195 in_proto = self._InputProto(build_target='board')
196 out_proto = self._OutputProto()
197 sysroot_controller.CreateSimpleChromeSysroot(in_proto, out_proto,
198 self.api_config)
199 patch.assert_called_once()
200
201
Alex Klein231d2da2019-07-22 16:44:45 -0600202class InstallToolchainTest(cros_test_lib.MockTempDirTestCase,
203 api_config.ApiConfigMixin):
Alex Kleinda35fcf2019-03-07 16:01:15 -0700204 """Install toolchain function tests."""
205
206 def setUp(self):
207 self.PatchObject(cros_build_lib, 'IsInsideChroot', return_value=True)
Alex Kleina9d64602019-05-17 14:55:37 -0600208 # Avoid running the portageq command.
209 self.PatchObject(sysroot_controller, '_LogBinhost')
Alex Kleinda35fcf2019-03-07 16:01:15 -0700210 self.board = 'board'
211 self.sysroot = os.path.join(self.tempdir, 'board')
212 self.invalid_sysroot = os.path.join(self.tempdir, 'invalid', 'sysroot')
213 osutils.SafeMakedirs(self.sysroot)
214
215 def _InputProto(self, build_target=None, sysroot_path=None,
216 compile_source=False):
Alex Kleind4e1e422019-03-18 16:00:41 -0600217 """Helper to build an input proto instance."""
Alex Kleinda35fcf2019-03-07 16:01:15 -0700218 proto = sysroot_pb2.InstallToolchainRequest()
219 if build_target:
220 proto.sysroot.build_target.name = build_target
221 if sysroot_path:
222 proto.sysroot.path = sysroot_path
223 if compile_source:
224 proto.flags.compile_source = compile_source
225
226 return proto
227
228 def _OutputProto(self):
229 """Helper to build output proto instance."""
230 return sysroot_pb2.InstallToolchainResponse()
231
Alex Klein231d2da2019-07-22 16:44:45 -0600232 def testValidateOnly(self):
233 """Sanity check that a validate only call does not execute any logic."""
234 patch = self.PatchObject(sysroot_service, 'InstallToolchain')
235
236 in_proto = self._InputProto(build_target=self.board,
237 sysroot_path=self.sysroot)
238 sysroot_controller.InstallToolchain(in_proto, self._OutputProto(),
239 self.validate_only_config)
240 patch.assert_not_called()
241
Alex Klein076841b2019-08-29 15:19:39 -0600242 def testMockCall(self):
243 """Sanity check that a mock call does not execute any logic."""
244 patch = self.PatchObject(sysroot_service, 'InstallToolchain')
245 request = self._InputProto()
246 response = self._OutputProto()
247
248 rc = sysroot_controller.InstallToolchain(request, response,
249 self.mock_call_config)
250
251 patch.assert_not_called()
252 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
253
254 def testMockError(self):
255 """Sanity check that a mock error does not execute any logic."""
256 patch = self.PatchObject(sysroot_service, 'InstallToolchain')
257 request = self._InputProto()
258 response = self._OutputProto()
259
260 rc = sysroot_controller.InstallToolchain(request, response,
261 self.mock_error_config)
262
263 patch.assert_not_called()
264 self.assertEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
265 self.assertTrue(response.failed_packages)
266
Alex Kleinda35fcf2019-03-07 16:01:15 -0700267 def testArgumentValidation(self):
268 """Test the argument validation."""
269 # Test errors on missing inputs.
270 out_proto = self._OutputProto()
271 # Both missing.
272 in_proto = self._InputProto()
273 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600274 sysroot_controller.InstallToolchain(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700275
276 # Sysroot path missing.
277 in_proto = self._InputProto(build_target=self.board)
278 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600279 sysroot_controller.InstallToolchain(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700280
281 # Build target name missing.
282 in_proto = self._InputProto(sysroot_path=self.sysroot)
283 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600284 sysroot_controller.InstallToolchain(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700285
286 # Both provided, but invalid sysroot path.
287 in_proto = self._InputProto(build_target=self.board,
288 sysroot_path=self.invalid_sysroot)
289 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600290 sysroot_controller.InstallToolchain(in_proto, out_proto, self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700291
292 def testSuccessOutputHandling(self):
293 """Test the output is processed and recorded correctly."""
294 self.PatchObject(sysroot_service, 'InstallToolchain')
295 out_proto = self._OutputProto()
296 in_proto = self._InputProto(build_target=self.board,
297 sysroot_path=self.sysroot)
298
Alex Klein231d2da2019-07-22 16:44:45 -0600299 rc = sysroot_controller.InstallToolchain(in_proto, out_proto,
300 self.api_config)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700301 self.assertFalse(rc)
302 self.assertFalse(out_proto.failed_packages)
303
304
305 def testErrorOutputHandling(self):
306 """Test the error output is processed and recorded correctly."""
307 out_proto = self._OutputProto()
308 in_proto = self._InputProto(build_target=self.board,
309 sysroot_path=self.sysroot)
310
311 err_pkgs = ['cat/pkg', 'cat2/pkg2']
312 err_cpvs = [portage_util.SplitCPV(pkg, strict=False) for pkg in err_pkgs]
313 expected = [('cat', 'pkg'), ('cat2', 'pkg2')]
314 err = sysroot_lib.ToolchainInstallError('Error',
315 cros_build_lib.CommandResult(),
316 tc_info=err_cpvs)
317 self.PatchObject(sysroot_service, 'InstallToolchain', side_effect=err)
318
Alex Klein231d2da2019-07-22 16:44:45 -0600319 rc = sysroot_controller.InstallToolchain(in_proto, out_proto,
320 self.api_config)
Alex Klein8cb365a2019-05-15 16:24:53 -0600321 self.assertEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
Alex Kleinda35fcf2019-03-07 16:01:15 -0700322 self.assertTrue(out_proto.failed_packages)
323 for package in out_proto.failed_packages:
324 cat_pkg = (package.category, package.package_name)
325 self.assertIn(cat_pkg, expected)
Alex Kleind4e1e422019-03-18 16:00:41 -0600326
327
Alex Klein231d2da2019-07-22 16:44:45 -0600328class InstallPackagesTest(cros_test_lib.MockTempDirTestCase,
329 api_config.ApiConfigMixin):
Alex Kleind4e1e422019-03-18 16:00:41 -0600330 """InstallPackages tests."""
331
332 def setUp(self):
333 self.PatchObject(cros_build_lib, 'IsInsideChroot', return_value=True)
Alex Kleina9d64602019-05-17 14:55:37 -0600334 # Avoid running the portageq command.
335 self.PatchObject(sysroot_controller, '_LogBinhost')
Alex Kleind4e1e422019-03-18 16:00:41 -0600336 self.build_target = 'board'
337 self.sysroot = os.path.join(self.tempdir, 'build', 'board')
338 osutils.SafeMakedirs(self.sysroot)
Michael Mortensen798ee192020-01-17 13:04:43 -0700339 # Set up goma directories.
340 self.goma_dir = os.path.join(self.tempdir, 'goma_dir')
341 osutils.SafeMakedirs(self.goma_dir)
342 self.goma_out_dir = os.path.join(self.tempdir, 'goma_out_dir')
343 osutils.SafeMakedirs(self.goma_out_dir)
Michael Mortensen4ccfb082020-01-22 16:24:03 -0700344 os.environ['GLOG_log_dir'] = self.goma_dir
Alex Kleind4e1e422019-03-18 16:00:41 -0600345
346 def _InputProto(self, build_target=None, sysroot_path=None,
Michael Mortensen798ee192020-01-17 13:04:43 -0700347 build_source=False, goma_dir=None, goma_log_dir=None,
348 goma_stats_file=None, goma_counterz_file=None):
Alex Kleind4e1e422019-03-18 16:00:41 -0600349 """Helper to build an input proto instance."""
350 instance = sysroot_pb2.InstallPackagesRequest()
351
352 if build_target:
353 instance.sysroot.build_target.name = build_target
354 if sysroot_path:
355 instance.sysroot.path = sysroot_path
356 if build_source:
357 instance.flags.build_source = build_source
Michael Mortensen798ee192020-01-17 13:04:43 -0700358 if goma_dir:
359 instance.goma_config.goma_dir = goma_dir
360 if goma_log_dir:
361 instance.goma_config.log_dir.dir = goma_log_dir
362 if goma_stats_file:
363 instance.goma_config.stats_file = goma_stats_file
364 if goma_counterz_file:
365 instance.goma_config.counterz_file = goma_counterz_file
Alex Kleind4e1e422019-03-18 16:00:41 -0600366
367 return instance
368
369 def _OutputProto(self):
370 """Helper to build an empty output proto instance."""
371 return sysroot_pb2.InstallPackagesResponse()
372
Michael Mortensen798ee192020-01-17 13:04:43 -0700373 def _CreateGomaLogFile(self, goma_log_dir, name, timestamp):
374 """Creates a log file for testing.
375
376 Args:
377 goma_log_dir (str): Directory where the file will be created.
378 name (str): Log file 'base' name that is combined with the timestamp.
379 timestamp (datetime): timestamp that is written to the file.
380 """
381 path = os.path.join(
382 goma_log_dir,
383 '%s.host.log.INFO.%s' % (name, timestamp.strftime('%Y%m%d-%H%M%S.%f')))
384 osutils.WriteFile(
385 path,
386 timestamp.strftime('Goma log file created at: %Y/%m/%d %H:%M:%S'))
387
Alex Klein231d2da2019-07-22 16:44:45 -0600388 def testValidateOnly(self):
389 """Sanity check that a validate only call does not execute any logic."""
390 patch = self.PatchObject(sysroot_service, 'BuildPackages')
391
392 in_proto = self._InputProto(build_target=self.build_target,
393 sysroot_path=self.sysroot)
394 sysroot_controller.InstallPackages(in_proto, self._OutputProto(),
395 self.validate_only_config)
396 patch.assert_not_called()
397
Alex Klein076841b2019-08-29 15:19:39 -0600398 def testMockCall(self):
399 """Sanity check that a mock call does not execute any logic."""
400 patch = self.PatchObject(sysroot_service, 'BuildPackages')
401 request = self._InputProto()
402 response = self._OutputProto()
403
404 rc = sysroot_controller.InstallPackages(request, response,
405 self.mock_call_config)
406
407 patch.assert_not_called()
408 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
409
410 def testMockError(self):
411 """Sanity check that a mock error does not execute any logic."""
412 patch = self.PatchObject(sysroot_service, 'BuildPackages')
413 request = self._InputProto()
414 response = self._OutputProto()
415
416 rc = sysroot_controller.InstallPackages(request, response,
417 self.mock_error_config)
418
419 patch.assert_not_called()
420 self.assertEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
421 self.assertTrue(response.failed_packages)
422
Alex Kleind4e1e422019-03-18 16:00:41 -0600423 def testArgumentValidationAllMissing(self):
424 """Test missing all arguments."""
425 out_proto = self._OutputProto()
426 in_proto = self._InputProto()
427 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600428 sysroot_controller.InstallPackages(in_proto, out_proto, self.api_config)
Alex Kleind4e1e422019-03-18 16:00:41 -0600429
430 def testArgumentValidationNoSysroot(self):
431 """Test missing sysroot path."""
432 out_proto = self._OutputProto()
433 in_proto = self._InputProto(build_target=self.build_target)
434 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600435 sysroot_controller.InstallPackages(in_proto, out_proto, self.api_config)
Alex Kleind4e1e422019-03-18 16:00:41 -0600436
437 def testArgumentValidationNoBuildTarget(self):
438 """Test missing build target name."""
439 out_proto = self._OutputProto()
440 in_proto = self._InputProto(sysroot_path=self.sysroot)
441 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600442 sysroot_controller.InstallPackages(in_proto, out_proto, self.api_config)
Alex Kleind4e1e422019-03-18 16:00:41 -0600443
444 def testArgumentValidationInvalidSysroot(self):
445 """Test sysroot that hasn't had the toolchain installed."""
446 out_proto = self._OutputProto()
447 in_proto = self._InputProto(build_target=self.build_target,
448 sysroot_path=self.sysroot)
449 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
450 return_value=False)
451 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600452 sysroot_controller.InstallPackages(in_proto, out_proto, self.api_config)
Alex Kleind4e1e422019-03-18 16:00:41 -0600453
454 def testSuccessOutputHandling(self):
455 """Test successful call output handling."""
456 # Prevent argument validation error.
457 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
458 return_value=True)
459
460 in_proto = self._InputProto(build_target=self.build_target,
461 sysroot_path=self.sysroot)
462 out_proto = self._OutputProto()
463 self.PatchObject(sysroot_service, 'BuildPackages')
464
Alex Klein231d2da2019-07-22 16:44:45 -0600465 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
466 self.api_config)
Alex Kleind4e1e422019-03-18 16:00:41 -0600467 self.assertFalse(rc)
468 self.assertFalse(out_proto.failed_packages)
469
Michael Mortensen798ee192020-01-17 13:04:43 -0700470 def testSuccessWithGomaLogs(self):
471 """Test successful call with goma."""
472 self._CreateGomaLogFile(self.goma_dir, 'compiler_proxy',
473 datetime.datetime(2018, 9, 21, 12, 0, 0))
474 self._CreateGomaLogFile(self.goma_dir, 'compiler_proxy-subproc',
475 datetime.datetime(2018, 9, 21, 12, 1, 0))
476 self._CreateGomaLogFile(self.goma_dir, 'gomacc',
477 datetime.datetime(2018, 9, 21, 12, 2, 0))
478
479 # Prevent argument validation error.
480 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
481 return_value=True)
482
483 in_proto = self._InputProto(build_target=self.build_target,
484 sysroot_path=self.sysroot,
485 goma_dir=self.goma_dir,
486 goma_log_dir=self.goma_out_dir)
487
488 out_proto = self._OutputProto()
489 self.PatchObject(sysroot_service, 'BuildPackages')
490
491 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
492 self.api_config)
493 self.assertFalse(rc)
494 self.assertFalse(out_proto.failed_packages)
495 self.assertCountEqual(out_proto.goma_artifacts.log_files, [
496 'compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz',
497 'compiler_proxy.host.log.INFO.20180921-120000.000000.gz',
498 'gomacc.host.log.INFO.20180921-120200.000000.tar.gz'])
499
500 def testSuccessWithGomaLogsAndStatsCounterzFiles(self):
501 """Test successful call with goma including stats and counterz files."""
502 self._CreateGomaLogFile(self.goma_dir, 'compiler_proxy',
503 datetime.datetime(2018, 9, 21, 12, 0, 0))
504 self._CreateGomaLogFile(self.goma_dir, 'compiler_proxy-subproc',
505 datetime.datetime(2018, 9, 21, 12, 1, 0))
506 self._CreateGomaLogFile(self.goma_dir, 'gomacc',
507 datetime.datetime(2018, 9, 21, 12, 2, 0))
508 # Create stats and counterz files.
509 osutils.WriteFile(os.path.join(self.goma_dir, 'stats.binaryproto'),
510 'File: stats.binaryproto')
511 osutils.WriteFile(os.path.join(self.goma_dir, 'counterz.binaryproto'),
512 'File: counterz.binaryproto')
513
514 # Prevent argument validation error.
515 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
516 return_value=True)
517
518 in_proto = self._InputProto(build_target=self.build_target,
519 sysroot_path=self.sysroot,
520 goma_dir=self.goma_dir,
521 goma_log_dir=self.goma_out_dir,
522 goma_stats_file='stats.binaryproto',
523 goma_counterz_file='counterz.binaryproto')
524
525 out_proto = self._OutputProto()
526 self.PatchObject(sysroot_service, 'BuildPackages')
527
528 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
529 self.api_config)
530 self.assertFalse(rc)
531 self.assertFalse(out_proto.failed_packages)
532 self.assertCountEqual(out_proto.goma_artifacts.log_files, [
533 'compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz',
534 'compiler_proxy.host.log.INFO.20180921-120000.000000.gz',
535 'gomacc.host.log.INFO.20180921-120200.000000.tar.gz'])
536 # Verify that the output dir has 5 files -- since there should be 3 log
537 # files, the stats file, and the counterz file.
538 output_files = os.listdir(self.goma_out_dir)
539 self.assertCountEqual(output_files, [
540 'stats.binaryproto',
541 'counterz.binaryproto',
542 'compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz',
543 'compiler_proxy.host.log.INFO.20180921-120000.000000.gz',
544 'gomacc.host.log.INFO.20180921-120200.000000.tar.gz'])
545
546 def testFailureMissingGomaStatsCounterzFiles(self):
547 """Test successful call with goma including stats and counterz files."""
548 self._CreateGomaLogFile(self.goma_dir, 'compiler_proxy',
549 datetime.datetime(2018, 9, 21, 12, 0, 0))
550 self._CreateGomaLogFile(self.goma_dir, 'compiler_proxy-subproc',
551 datetime.datetime(2018, 9, 21, 12, 1, 0))
552 self._CreateGomaLogFile(self.goma_dir, 'gomacc',
553 datetime.datetime(2018, 9, 21, 12, 2, 0))
554 # Note that stats and counterz files are not created, but are specified in
555 # the proto below.
556
557 # Prevent argument validation error.
558 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
559 return_value=True)
560
561 in_proto = self._InputProto(build_target=self.build_target,
562 sysroot_path=self.sysroot,
563 goma_dir=self.goma_dir,
564 goma_log_dir=self.goma_out_dir,
565 goma_stats_file='stats.binaryproto',
566 goma_counterz_file='counterz.binaryproto')
567
568 out_proto = self._OutputProto()
569 self.PatchObject(sysroot_service, 'BuildPackages')
570
Michael Mortensen1d6d5b02020-01-22 07:33:50 -0700571 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
572 self.api_config)
573 self.assertFalse(rc)
574 self.assertFalse(out_proto.failed_packages)
575 self.assertCountEqual(out_proto.goma_artifacts.log_files, [
576 'compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz',
577 'compiler_proxy.host.log.INFO.20180921-120000.000000.gz',
578 'gomacc.host.log.INFO.20180921-120200.000000.tar.gz'])
579 self.assertFalse(out_proto.goma_artifacts.counterz_file)
580 self.assertFalse(out_proto.goma_artifacts.stats_file)
Michael Mortensen798ee192020-01-17 13:04:43 -0700581
Alex Kleind4e1e422019-03-18 16:00:41 -0600582 def testFailureOutputHandling(self):
583 """Test failed package handling."""
584 # Prevent argument validation error.
585 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
586 return_value=True)
587
588 in_proto = self._InputProto(build_target=self.build_target,
589 sysroot_path=self.sysroot)
590 out_proto = self._OutputProto()
591
592 # Failed package info and expected list for verification.
593 err_pkgs = ['cat/pkg', 'cat2/pkg2']
594 err_cpvs = [portage_util.SplitCPV(cpv, strict=False) for cpv in err_pkgs]
595 expected = [('cat', 'pkg'), ('cat2', 'pkg2')]
596
597 # Force error to be raised with the packages.
598 error = sysroot_lib.PackageInstallError('Error',
599 cros_build_lib.CommandResult(),
600 packages=err_cpvs)
601 self.PatchObject(sysroot_service, 'BuildPackages', side_effect=error)
602
Alex Klein231d2da2019-07-22 16:44:45 -0600603 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
604 self.api_config)
Alex Klein2557b4f2019-07-11 14:34:00 -0600605 # This needs to return 2 to indicate the available error response.
606 self.assertEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
Alex Kleind4e1e422019-03-18 16:00:41 -0600607 for package in out_proto.failed_packages:
608 cat_pkg = (package.category, package.package_name)
609 self.assertIn(cat_pkg, expected)
Alex Klein2557b4f2019-07-11 14:34:00 -0600610
611 def testNoPackageFailureOutputHandling(self):
612 """Test failure handling without packages to report."""
613 # Prevent argument validation error.
614 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
615 return_value=True)
616
617 in_proto = self._InputProto(build_target=self.build_target,
618 sysroot_path=self.sysroot)
619 out_proto = self._OutputProto()
620
621 # Force error to be raised with no packages.
622 error = sysroot_lib.PackageInstallError('Error',
623 cros_build_lib.CommandResult(),
624 packages=[])
625 self.PatchObject(sysroot_service, 'BuildPackages', side_effect=error)
626
Alex Klein231d2da2019-07-22 16:44:45 -0600627 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
628 self.api_config)
Alex Klein2557b4f2019-07-11 14:34:00 -0600629 # All we really care about is it's not 0 or 2 (response available), so
630 # test for that rather than a specific return code.
631 self.assertTrue(rc)
632 self.assertNotEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE,
633 rc)