blob: 6f38a03b016e3373edda2b0db4c1e911c507567e [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)
Alex Kleind4e1e422019-03-18 16:00:41 -0600344
345 def _InputProto(self, build_target=None, sysroot_path=None,
Michael Mortensen798ee192020-01-17 13:04:43 -0700346 build_source=False, goma_dir=None, goma_log_dir=None,
347 goma_stats_file=None, goma_counterz_file=None):
Alex Kleind4e1e422019-03-18 16:00:41 -0600348 """Helper to build an input proto instance."""
349 instance = sysroot_pb2.InstallPackagesRequest()
350
351 if build_target:
352 instance.sysroot.build_target.name = build_target
353 if sysroot_path:
354 instance.sysroot.path = sysroot_path
355 if build_source:
356 instance.flags.build_source = build_source
Michael Mortensen798ee192020-01-17 13:04:43 -0700357 if goma_dir:
358 instance.goma_config.goma_dir = goma_dir
359 if goma_log_dir:
360 instance.goma_config.log_dir.dir = goma_log_dir
361 if goma_stats_file:
362 instance.goma_config.stats_file = goma_stats_file
363 if goma_counterz_file:
364 instance.goma_config.counterz_file = goma_counterz_file
Alex Kleind4e1e422019-03-18 16:00:41 -0600365
366 return instance
367
368 def _OutputProto(self):
369 """Helper to build an empty output proto instance."""
370 return sysroot_pb2.InstallPackagesResponse()
371
Michael Mortensen798ee192020-01-17 13:04:43 -0700372 def _CreateGomaLogFile(self, goma_log_dir, name, timestamp):
373 """Creates a log file for testing.
374
375 Args:
376 goma_log_dir (str): Directory where the file will be created.
377 name (str): Log file 'base' name that is combined with the timestamp.
378 timestamp (datetime): timestamp that is written to the file.
379 """
380 path = os.path.join(
381 goma_log_dir,
382 '%s.host.log.INFO.%s' % (name, timestamp.strftime('%Y%m%d-%H%M%S.%f')))
383 osutils.WriteFile(
384 path,
385 timestamp.strftime('Goma log file created at: %Y/%m/%d %H:%M:%S'))
386
Alex Klein231d2da2019-07-22 16:44:45 -0600387 def testValidateOnly(self):
388 """Sanity check that a validate only call does not execute any logic."""
389 patch = self.PatchObject(sysroot_service, 'BuildPackages')
390
391 in_proto = self._InputProto(build_target=self.build_target,
392 sysroot_path=self.sysroot)
393 sysroot_controller.InstallPackages(in_proto, self._OutputProto(),
394 self.validate_only_config)
395 patch.assert_not_called()
396
Alex Klein076841b2019-08-29 15:19:39 -0600397 def testMockCall(self):
398 """Sanity check that a mock call does not execute any logic."""
399 patch = self.PatchObject(sysroot_service, 'BuildPackages')
400 request = self._InputProto()
401 response = self._OutputProto()
402
403 rc = sysroot_controller.InstallPackages(request, response,
404 self.mock_call_config)
405
406 patch.assert_not_called()
407 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
408
409 def testMockError(self):
410 """Sanity check that a mock error does not execute any logic."""
411 patch = self.PatchObject(sysroot_service, 'BuildPackages')
412 request = self._InputProto()
413 response = self._OutputProto()
414
415 rc = sysroot_controller.InstallPackages(request, response,
416 self.mock_error_config)
417
418 patch.assert_not_called()
419 self.assertEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
420 self.assertTrue(response.failed_packages)
421
Alex Kleind4e1e422019-03-18 16:00:41 -0600422 def testArgumentValidationAllMissing(self):
423 """Test missing all arguments."""
424 out_proto = self._OutputProto()
425 in_proto = self._InputProto()
426 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600427 sysroot_controller.InstallPackages(in_proto, out_proto, self.api_config)
Alex Kleind4e1e422019-03-18 16:00:41 -0600428
429 def testArgumentValidationNoSysroot(self):
430 """Test missing sysroot path."""
431 out_proto = self._OutputProto()
432 in_proto = self._InputProto(build_target=self.build_target)
433 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600434 sysroot_controller.InstallPackages(in_proto, out_proto, self.api_config)
Alex Kleind4e1e422019-03-18 16:00:41 -0600435
436 def testArgumentValidationNoBuildTarget(self):
437 """Test missing build target name."""
438 out_proto = self._OutputProto()
439 in_proto = self._InputProto(sysroot_path=self.sysroot)
440 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600441 sysroot_controller.InstallPackages(in_proto, out_proto, self.api_config)
Alex Kleind4e1e422019-03-18 16:00:41 -0600442
443 def testArgumentValidationInvalidSysroot(self):
444 """Test sysroot that hasn't had the toolchain installed."""
445 out_proto = self._OutputProto()
446 in_proto = self._InputProto(build_target=self.build_target,
447 sysroot_path=self.sysroot)
448 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
449 return_value=False)
450 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600451 sysroot_controller.InstallPackages(in_proto, out_proto, self.api_config)
Alex Kleind4e1e422019-03-18 16:00:41 -0600452
453 def testSuccessOutputHandling(self):
454 """Test successful call output handling."""
455 # Prevent argument validation error.
456 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
457 return_value=True)
458
459 in_proto = self._InputProto(build_target=self.build_target,
460 sysroot_path=self.sysroot)
461 out_proto = self._OutputProto()
462 self.PatchObject(sysroot_service, 'BuildPackages')
463
Alex Klein231d2da2019-07-22 16:44:45 -0600464 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
465 self.api_config)
Alex Kleind4e1e422019-03-18 16:00:41 -0600466 self.assertFalse(rc)
467 self.assertFalse(out_proto.failed_packages)
468
Michael Mortensen798ee192020-01-17 13:04:43 -0700469 def testSuccessWithGomaLogs(self):
470 """Test successful call with goma."""
471 self._CreateGomaLogFile(self.goma_dir, 'compiler_proxy',
472 datetime.datetime(2018, 9, 21, 12, 0, 0))
473 self._CreateGomaLogFile(self.goma_dir, 'compiler_proxy-subproc',
474 datetime.datetime(2018, 9, 21, 12, 1, 0))
475 self._CreateGomaLogFile(self.goma_dir, 'gomacc',
476 datetime.datetime(2018, 9, 21, 12, 2, 0))
477
478 # Prevent argument validation error.
479 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
480 return_value=True)
481
482 in_proto = self._InputProto(build_target=self.build_target,
483 sysroot_path=self.sysroot,
484 goma_dir=self.goma_dir,
485 goma_log_dir=self.goma_out_dir)
486
487 out_proto = self._OutputProto()
488 self.PatchObject(sysroot_service, 'BuildPackages')
489
490 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
491 self.api_config)
492 self.assertFalse(rc)
493 self.assertFalse(out_proto.failed_packages)
494 self.assertCountEqual(out_proto.goma_artifacts.log_files, [
495 'compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz',
496 'compiler_proxy.host.log.INFO.20180921-120000.000000.gz',
497 'gomacc.host.log.INFO.20180921-120200.000000.tar.gz'])
498
499 def testSuccessWithGomaLogsAndStatsCounterzFiles(self):
500 """Test successful call with goma including stats and counterz files."""
501 self._CreateGomaLogFile(self.goma_dir, 'compiler_proxy',
502 datetime.datetime(2018, 9, 21, 12, 0, 0))
503 self._CreateGomaLogFile(self.goma_dir, 'compiler_proxy-subproc',
504 datetime.datetime(2018, 9, 21, 12, 1, 0))
505 self._CreateGomaLogFile(self.goma_dir, 'gomacc',
506 datetime.datetime(2018, 9, 21, 12, 2, 0))
507 # Create stats and counterz files.
508 osutils.WriteFile(os.path.join(self.goma_dir, 'stats.binaryproto'),
509 'File: stats.binaryproto')
510 osutils.WriteFile(os.path.join(self.goma_dir, 'counterz.binaryproto'),
511 'File: counterz.binaryproto')
512
513 # Prevent argument validation error.
514 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
515 return_value=True)
516
517 in_proto = self._InputProto(build_target=self.build_target,
518 sysroot_path=self.sysroot,
519 goma_dir=self.goma_dir,
520 goma_log_dir=self.goma_out_dir,
521 goma_stats_file='stats.binaryproto',
522 goma_counterz_file='counterz.binaryproto')
523
524 out_proto = self._OutputProto()
525 self.PatchObject(sysroot_service, 'BuildPackages')
526
527 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
528 self.api_config)
529 self.assertFalse(rc)
530 self.assertFalse(out_proto.failed_packages)
531 self.assertCountEqual(out_proto.goma_artifacts.log_files, [
532 'compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz',
533 'compiler_proxy.host.log.INFO.20180921-120000.000000.gz',
534 'gomacc.host.log.INFO.20180921-120200.000000.tar.gz'])
535 # Verify that the output dir has 5 files -- since there should be 3 log
536 # files, the stats file, and the counterz file.
537 output_files = os.listdir(self.goma_out_dir)
538 self.assertCountEqual(output_files, [
539 'stats.binaryproto',
540 'counterz.binaryproto',
541 'compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz',
542 'compiler_proxy.host.log.INFO.20180921-120000.000000.gz',
543 'gomacc.host.log.INFO.20180921-120200.000000.tar.gz'])
544
545 def testFailureMissingGomaStatsCounterzFiles(self):
546 """Test successful call with goma including stats and counterz files."""
547 self._CreateGomaLogFile(self.goma_dir, 'compiler_proxy',
548 datetime.datetime(2018, 9, 21, 12, 0, 0))
549 self._CreateGomaLogFile(self.goma_dir, 'compiler_proxy-subproc',
550 datetime.datetime(2018, 9, 21, 12, 1, 0))
551 self._CreateGomaLogFile(self.goma_dir, 'gomacc',
552 datetime.datetime(2018, 9, 21, 12, 2, 0))
553 # Note that stats and counterz files are not created, but are specified in
554 # the proto below.
555
556 # Prevent argument validation error.
557 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
558 return_value=True)
559
560 in_proto = self._InputProto(build_target=self.build_target,
561 sysroot_path=self.sysroot,
562 goma_dir=self.goma_dir,
563 goma_log_dir=self.goma_out_dir,
564 goma_stats_file='stats.binaryproto',
565 goma_counterz_file='counterz.binaryproto')
566
567 out_proto = self._OutputProto()
568 self.PatchObject(sysroot_service, 'BuildPackages')
569
Michael Mortensen1d6d5b02020-01-22 07:33:50 -0700570 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
571 self.api_config)
572 self.assertFalse(rc)
573 self.assertFalse(out_proto.failed_packages)
574 self.assertCountEqual(out_proto.goma_artifacts.log_files, [
575 'compiler_proxy-subproc.host.log.INFO.20180921-120100.000000.gz',
576 'compiler_proxy.host.log.INFO.20180921-120000.000000.gz',
577 'gomacc.host.log.INFO.20180921-120200.000000.tar.gz'])
578 self.assertFalse(out_proto.goma_artifacts.counterz_file)
579 self.assertFalse(out_proto.goma_artifacts.stats_file)
Michael Mortensen798ee192020-01-17 13:04:43 -0700580
Alex Kleind4e1e422019-03-18 16:00:41 -0600581 def testFailureOutputHandling(self):
582 """Test failed package handling."""
583 # Prevent argument validation error.
584 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
585 return_value=True)
586
587 in_proto = self._InputProto(build_target=self.build_target,
588 sysroot_path=self.sysroot)
589 out_proto = self._OutputProto()
590
591 # Failed package info and expected list for verification.
592 err_pkgs = ['cat/pkg', 'cat2/pkg2']
593 err_cpvs = [portage_util.SplitCPV(cpv, strict=False) for cpv in err_pkgs]
594 expected = [('cat', 'pkg'), ('cat2', 'pkg2')]
595
596 # Force error to be raised with the packages.
597 error = sysroot_lib.PackageInstallError('Error',
598 cros_build_lib.CommandResult(),
599 packages=err_cpvs)
600 self.PatchObject(sysroot_service, 'BuildPackages', side_effect=error)
601
Alex Klein231d2da2019-07-22 16:44:45 -0600602 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
603 self.api_config)
Alex Klein2557b4f2019-07-11 14:34:00 -0600604 # This needs to return 2 to indicate the available error response.
605 self.assertEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
Alex Kleind4e1e422019-03-18 16:00:41 -0600606 for package in out_proto.failed_packages:
607 cat_pkg = (package.category, package.package_name)
608 self.assertIn(cat_pkg, expected)
Alex Klein2557b4f2019-07-11 14:34:00 -0600609
610 def testNoPackageFailureOutputHandling(self):
611 """Test failure handling without packages to report."""
612 # Prevent argument validation error.
613 self.PatchObject(sysroot_lib.Sysroot, 'IsToolchainInstalled',
614 return_value=True)
615
616 in_proto = self._InputProto(build_target=self.build_target,
617 sysroot_path=self.sysroot)
618 out_proto = self._OutputProto()
619
620 # Force error to be raised with no packages.
621 error = sysroot_lib.PackageInstallError('Error',
622 cros_build_lib.CommandResult(),
623 packages=[])
624 self.PatchObject(sysroot_service, 'BuildPackages', side_effect=error)
625
Alex Klein231d2da2019-07-22 16:44:45 -0600626 rc = sysroot_controller.InstallPackages(in_proto, out_proto,
627 self.api_config)
Alex Klein2557b4f2019-07-11 14:34:00 -0600628 # All we really care about is it's not 0 or 2 (response available), so
629 # test for that rather than a specific return code.
630 self.assertTrue(rc)
631 self.assertNotEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE,
632 rc)