blob: c12a608c9db7c7959becd0a8858ae536f3ef1e8e [file] [log] [blame]
Alex Kleina2e42c42019-04-17 16:13:19 -06001# Copyright 2019 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""The test controller tests."""
6
Alex Klein9f915782020-02-14 23:15:09 +00007import contextlib
Lizzy Presland4feb2372022-01-20 05:16:30 +00008import datetime
Mike Frysingeref94e4c2020-02-10 23:59:54 -05009import os
Mike Frysinger166fea02021-02-12 05:30:33 -050010from unittest import mock
Mike Frysingeref94e4c2020-02-10 23:59:54 -050011
Alex Klein231d2da2019-07-22 16:44:45 -060012from chromite.api import api_config
Alex Klein8cb365a2019-05-15 16:24:53 -060013from chromite.api import controller
Lizzy Presland4feb2372022-01-20 05:16:30 +000014from chromite.api.controller import controller_util
Alex Kleina2e42c42019-04-17 16:13:19 -060015from chromite.api.controller import test as test_controller
Evan Hernandez4e388a52019-05-01 12:16:33 -060016from chromite.api.gen.chromiumos import common_pb2
Alex Kleina2e42c42019-04-17 16:13:19 -060017from chromite.api.gen.chromite.api import test_pb2
Sean McAllister3834fef2021-10-08 15:45:18 -060018from chromite.api.gen.chromiumos.build.api import container_metadata_pb2
Jack Neusc9707c32021-07-23 21:48:54 +000019from chromite.lib import build_target_lib
Evan Hernandeze1e05d32019-07-19 12:32:18 -060020from chromite.lib import chroot_lib
Alex Kleina2e42c42019-04-17 16:13:19 -060021from chromite.lib import cros_build_lib
22from chromite.lib import cros_test_lib
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -060023from chromite.lib import image_lib
Alex Kleina2e42c42019-04-17 16:13:19 -060024from chromite.lib import osutils
David Wellingc1433c22021-06-25 16:29:48 +000025from chromite.lib import sysroot_lib
Alex Klein18a60af2020-06-11 12:08:47 -060026from chromite.lib.parser import package_info
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -060027from chromite.scripts import cros_set_lsb_release
28from chromite.service import test as test_service
Andrew Lamb763e3be2021-07-27 17:22:02 -060029from chromite.third_party.google.protobuf import json_format
Mike Frysingere652ba12019-09-08 00:57:43 -040030from chromite.utils import key_value_store
Alex Kleina2e42c42019-04-17 16:13:19 -060031
32
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -070033class DebugInfoTestTest(cros_test_lib.MockTempDirTestCase,
34 api_config.ApiConfigMixin):
35 """Tests for the DebugInfoTest function."""
36
37 def setUp(self):
38 self.board = 'board'
39 self.chroot_path = os.path.join(self.tempdir, 'chroot')
40 self.sysroot_path = '/build/board'
41 self.full_sysroot_path = os.path.join(self.chroot_path,
42 self.sysroot_path.lstrip(os.sep))
43 osutils.SafeMakedirs(self.full_sysroot_path)
44
45 def _GetInput(self, sysroot_path=None, build_target=None):
46 """Helper to build an input message instance."""
47 proto = test_pb2.DebugInfoTestRequest()
48 if sysroot_path:
49 proto.sysroot.path = sysroot_path
50 if build_target:
51 proto.sysroot.build_target.name = build_target
52 return proto
53
54 def _GetOutput(self):
55 """Helper to get an empty output message instance."""
56 return test_pb2.DebugInfoTestResponse()
57
58 def testValidateOnly(self):
59 """Sanity check that a validate only call does not execute any logic."""
60 patch = self.PatchObject(test_service, 'DebugInfoTest')
61 input_msg = self._GetInput(sysroot_path=self.full_sysroot_path)
62 test_controller.DebugInfoTest(input_msg, self._GetOutput(),
63 self.validate_only_config)
64 patch.assert_not_called()
65
Michael Mortensen85d38402019-12-12 09:50:29 -070066 def testMockError(self):
67 """Test mock error call does not execute any logic, returns error."""
68 patch = self.PatchObject(test_service, 'DebugInfoTest')
69
70 input_msg = self._GetInput(sysroot_path=self.full_sysroot_path)
71 rc = test_controller.DebugInfoTest(input_msg, self._GetOutput(),
72 self.mock_error_config)
73 patch.assert_not_called()
74 self.assertEqual(controller.RETURN_CODE_COMPLETED_UNSUCCESSFULLY, rc)
75
76 def testMockCall(self):
77 """Test mock call does not execute any logic, returns success."""
78 patch = self.PatchObject(test_service, 'DebugInfoTest')
79
80 input_msg = self._GetInput(sysroot_path=self.full_sysroot_path)
81 rc = test_controller.DebugInfoTest(input_msg, self._GetOutput(),
82 self.mock_call_config)
83 patch.assert_not_called()
84 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
85
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -070086 def testNoBuildTargetNoSysrootFails(self):
87 """Test missing build target name and sysroot path fails."""
88 input_msg = self._GetInput()
89 output_msg = self._GetOutput()
90 with self.assertRaises(cros_build_lib.DieSystemExit):
91 test_controller.DebugInfoTest(input_msg, output_msg, self.api_config)
92
93 def testDebugInfoTest(self):
94 """Call DebugInfoTest with valid sysroot_path."""
95 request = self._GetInput(sysroot_path=self.full_sysroot_path)
96
97 test_controller.DebugInfoTest(request, self._GetOutput(), self.api_config)
98
99
Alex Klein231d2da2019-07-22 16:44:45 -0600100class BuildTargetUnitTestTest(cros_test_lib.MockTempDirTestCase,
101 api_config.ApiConfigMixin):
Alex Kleina2e42c42019-04-17 16:13:19 -0600102 """Tests for the UnitTest function."""
103
Lizzy Presland4feb2372022-01-20 05:16:30 +0000104 def setUp(self):
105 # Set up portage log directory.
106 self.sysroot = os.path.join(self.tempdir, 'build', 'board')
107 osutils.SafeMakedirs(self.sysroot)
108 self.target_sysroot = sysroot_lib.Sysroot(self.sysroot)
109 self.portage_dir = os.path.join(self.tempdir, 'portage_logdir')
110 self.PatchObject(
111 sysroot_lib.Sysroot, 'portage_logdir', new=self.portage_dir)
112 osutils.SafeMakedirs(self.portage_dir)
113
Navil Perezc0b29a82020-07-07 14:17:48 +0000114 def _GetInput(self,
115 board=None,
116 result_path=None,
117 chroot_path=None,
118 cache_dir=None,
119 empty_sysroot=None,
120 packages=None,
Alex Kleinb64e5f82020-09-23 10:55:31 -0600121 blocklist=None):
Alex Kleina2e42c42019-04-17 16:13:19 -0600122 """Helper to build an input message instance."""
Navil Perezc0b29a82020-07-07 14:17:48 +0000123 formatted_packages = []
124 for pkg in packages or []:
125 formatted_packages.append({
126 'category': pkg.category,
127 'package_name': pkg.package
128 })
Alex Kleinb64e5f82020-09-23 10:55:31 -0600129 formatted_blocklist = []
130 for pkg in blocklist or []:
131 formatted_blocklist.append({'category': pkg.category,
Alex Kleinf2674462019-05-16 16:47:24 -0600132 'package_name': pkg.package})
133
Alex Kleina2e42c42019-04-17 16:13:19 -0600134 return test_pb2.BuildTargetUnitTestRequest(
135 build_target={'name': board}, result_path=result_path,
Alex Kleinfa6ebdc2019-05-10 10:57:31 -0600136 chroot={'path': chroot_path, 'cache_dir': cache_dir},
Alex Kleinf2674462019-05-16 16:47:24 -0600137 flags={'empty_sysroot': empty_sysroot},
Alex Klein64ac34c2020-09-23 10:21:33 -0600138 packages=formatted_packages,
Alex Klein157caf42021-07-01 14:36:43 -0600139 package_blocklist=formatted_blocklist,
Alex Kleina2e42c42019-04-17 16:13:19 -0600140 )
141
142 def _GetOutput(self):
143 """Helper to get an empty output message instance."""
144 return test_pb2.BuildTargetUnitTestResponse()
145
Lizzy Presland4feb2372022-01-20 05:16:30 +0000146 def _CreatePortageLogFile(self, log_path, pkg_info, timestamp):
147 """Creates a log file for testing for individual packages built by Portage.
148
149 Args:
150 log_path (pathlike): the PORTAGE_LOGDIR path
151 pkg_info (PackageInfo): name components for log file.
152 timestamp (datetime): timestamp used to name the file.
153 """
154 path = os.path.join(log_path,
155 f'{pkg_info.category}:{pkg_info.pvr}:' \
156 f'{timestamp.strftime("%Y%m%d-%H%M%S")}.log')
157 osutils.WriteFile(path,
158 f'Test log file for package {pkg_info.category}/'
159 f'{pkg_info.package} written to {path}')
160 return path
161
Alex Klein231d2da2019-07-22 16:44:45 -0600162 def testValidateOnly(self):
163 """Sanity check that a validate only call does not execute any logic."""
164 patch = self.PatchObject(test_service, 'BuildTargetUnitTest')
165
166 input_msg = self._GetInput(board='board', result_path=self.tempdir)
167 test_controller.BuildTargetUnitTest(input_msg, self._GetOutput(),
168 self.validate_only_config)
169 patch.assert_not_called()
170
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700171 def testMockCall(self):
172 """Test that a mock call does not execute logic, returns mocked value."""
173 patch = self.PatchObject(test_service, 'BuildTargetUnitTest')
174
175 input_msg = self._GetInput(board='board', result_path=self.tempdir)
176 response = self._GetOutput()
177 test_controller.BuildTargetUnitTest(input_msg, response,
178 self.mock_call_config)
179 patch.assert_not_called()
180 self.assertEqual(response.tarball_path,
181 os.path.join(input_msg.result_path, 'unit_tests.tar'))
182
183 def testMockError(self):
Michael Mortensen85d38402019-12-12 09:50:29 -0700184 """Test that a mock error does not execute logic, returns error."""
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700185 patch = self.PatchObject(test_service, 'BuildTargetUnitTest')
186
187 input_msg = self._GetInput(board='board', result_path=self.tempdir)
188 response = self._GetOutput()
189 rc = test_controller.BuildTargetUnitTest(input_msg, response,
190 self.mock_error_config)
191 patch.assert_not_called()
192 self.assertEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
193 self.assertTrue(response.failed_packages)
194 self.assertEqual(response.failed_packages[0].category, 'foo')
195 self.assertEqual(response.failed_packages[0].package_name, 'bar')
196 self.assertEqual(response.failed_packages[1].category, 'cat')
197 self.assertEqual(response.failed_packages[1].package_name, 'pkg')
198
Alex Kleina2e42c42019-04-17 16:13:19 -0600199 def testNoArgumentFails(self):
200 """Test no arguments fails."""
201 input_msg = self._GetInput()
202 output_msg = self._GetOutput()
203 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600204 test_controller.BuildTargetUnitTest(input_msg, output_msg,
205 self.api_config)
Alex Kleina2e42c42019-04-17 16:13:19 -0600206
Alex Kleina2e42c42019-04-17 16:13:19 -0600207 def testNoResultPathFails(self):
208 """Test missing result path fails."""
209 # Missing result_path.
210 input_msg = self._GetInput(board='board')
211 output_msg = self._GetOutput()
212 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600213 test_controller.BuildTargetUnitTest(input_msg, output_msg,
214 self.api_config)
Alex Kleina2e42c42019-04-17 16:13:19 -0600215
Alex Klein64ac34c2020-09-23 10:21:33 -0600216 def testInvalidPackageFails(self):
217 """Test missing result path fails."""
218 # Missing result_path.
219 pkg = package_info.PackageInfo(package='bar')
220 input_msg = self._GetInput(board='board', result_path=self.tempdir,
221 packages=[pkg])
222 output_msg = self._GetOutput()
223 with self.assertRaises(cros_build_lib.DieSystemExit):
224 test_controller.BuildTargetUnitTest(input_msg, output_msg,
225 self.api_config)
226
Alex Kleina2e42c42019-04-17 16:13:19 -0600227 def testPackageBuildFailure(self):
228 """Test handling of raised BuildPackageFailure."""
229 tempdir = osutils.TempDir(base_dir=self.tempdir)
230 self.PatchObject(osutils, 'TempDir', return_value=tempdir)
231
Lizzy Presland4feb2372022-01-20 05:16:30 +0000232 pkgs = ['cat/pkg-1.0-r1', 'foo/bar-2.0-r1']
233 cpvrs = [package_info.parse(pkg) for pkg in pkgs]
Alex Kleina2e42c42019-04-17 16:13:19 -0600234 expected = [('cat', 'pkg'), ('foo', 'bar')]
Lizzy Presland4feb2372022-01-20 05:16:30 +0000235 new_logs = {}
236 for i, pkg in enumerate(pkgs):
237 self._CreatePortageLogFile(self.portage_dir, cpvrs[i],
238 datetime.datetime(2021, 6, 9, 13, 37, 0))
239 new_logs[pkg] = self._CreatePortageLogFile(self.portage_dir, cpvrs[i],
240 datetime.datetime(2021, 6, 9,
241 16, 20, 0))
Alex Kleina2e42c42019-04-17 16:13:19 -0600242
Alex Klein38c7d9e2019-05-08 09:31:19 -0600243 result = test_service.BuildTargetUnitTestResult(1, None)
Alex Kleinea0c89e2021-09-09 15:17:35 -0600244 result.failed_pkgs = [package_info.parse(p) for p in pkgs]
Alex Klein38c7d9e2019-05-08 09:31:19 -0600245 self.PatchObject(test_service, 'BuildTargetUnitTest', return_value=result)
Alex Kleina2e42c42019-04-17 16:13:19 -0600246
247 input_msg = self._GetInput(board='board', result_path=self.tempdir)
248 output_msg = self._GetOutput()
249
Alex Klein231d2da2019-07-22 16:44:45 -0600250 rc = test_controller.BuildTargetUnitTest(input_msg, output_msg,
251 self.api_config)
Alex Kleina2e42c42019-04-17 16:13:19 -0600252
Alex Klein8cb365a2019-05-15 16:24:53 -0600253 self.assertEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
Alex Kleina2e42c42019-04-17 16:13:19 -0600254 self.assertTrue(output_msg.failed_packages)
Lizzy Presland4feb2372022-01-20 05:16:30 +0000255 self.assertTrue(output_msg.failed_package_data)
256 # TODO(b/206514844): remove when field is deleted
Alex Kleina2e42c42019-04-17 16:13:19 -0600257 failed = []
258 for pi in output_msg.failed_packages:
259 failed.append((pi.category, pi.package_name))
Mike Frysinger678735c2019-09-28 18:23:28 -0400260 self.assertCountEqual(expected, failed)
Alex Kleina2e42c42019-04-17 16:13:19 -0600261
Lizzy Presland4feb2372022-01-20 05:16:30 +0000262 failed_with_logs = []
263 for data in output_msg.failed_package_data:
264 failed_with_logs.append((data.name.category, data.name.package_name))
265 package = controller_util.deserialize_package_info(data.name)
266 self.assertEqual(data.log_path.path, new_logs[package.cpvr])
267 self.assertCountEqual(expected, failed_with_logs)
268
269
Alex Kleina2e42c42019-04-17 16:13:19 -0600270 def testOtherBuildScriptFailure(self):
271 """Test build script failure due to non-package emerge error."""
272 tempdir = osutils.TempDir(base_dir=self.tempdir)
273 self.PatchObject(osutils, 'TempDir', return_value=tempdir)
274
Alex Klein38c7d9e2019-05-08 09:31:19 -0600275 result = test_service.BuildTargetUnitTestResult(1, None)
276 self.PatchObject(test_service, 'BuildTargetUnitTest', return_value=result)
Alex Kleina2e42c42019-04-17 16:13:19 -0600277
Alex Kleinf2674462019-05-16 16:47:24 -0600278 pkgs = ['foo/bar', 'cat/pkg']
Alex Kleinb64e5f82020-09-23 10:55:31 -0600279 blocklist = [package_info.SplitCPV(p, strict=False) for p in pkgs]
Alex Kleinfa6ebdc2019-05-10 10:57:31 -0600280 input_msg = self._GetInput(board='board', result_path=self.tempdir,
Alex Kleinb64e5f82020-09-23 10:55:31 -0600281 empty_sysroot=True, blocklist=blocklist)
Alex Kleina2e42c42019-04-17 16:13:19 -0600282 output_msg = self._GetOutput()
283
Alex Klein231d2da2019-07-22 16:44:45 -0600284 rc = test_controller.BuildTargetUnitTest(input_msg, output_msg,
285 self.api_config)
Alex Kleina2e42c42019-04-17 16:13:19 -0600286
Alex Klein8cb365a2019-05-15 16:24:53 -0600287 self.assertEqual(controller.RETURN_CODE_COMPLETED_UNSUCCESSFULLY, rc)
Alex Kleina2e42c42019-04-17 16:13:19 -0600288 self.assertFalse(output_msg.failed_packages)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600289
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700290 def testBuildTargetUnitTest(self):
291 """Test BuildTargetUnitTest successful call."""
Navil Perezc0b29a82020-07-07 14:17:48 +0000292 pkgs = ['foo/bar', 'cat/pkg']
Alex Klein18a60af2020-06-11 12:08:47 -0600293 packages = [package_info.SplitCPV(p, strict=False) for p in pkgs]
Navil Perezc0b29a82020-07-07 14:17:48 +0000294 input_msg = self._GetInput(
295 board='board', result_path=self.tempdir, packages=packages)
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700296
297 result = test_service.BuildTargetUnitTestResult(0, None)
298 self.PatchObject(test_service, 'BuildTargetUnitTest', return_value=result)
299
300 tarball_result = os.path.join(input_msg.result_path, 'unit_tests.tar')
301 self.PatchObject(test_service, 'BuildTargetUnitTestTarball',
302 return_value=tarball_result)
303
304 response = self._GetOutput()
305 test_controller.BuildTargetUnitTest(input_msg, response,
306 self.api_config)
307 self.assertEqual(response.tarball_path,
308 os.path.join(input_msg.result_path, 'unit_tests.tar'))
309
Evan Hernandez4e388a52019-05-01 12:16:33 -0600310
Sean McAllister17eed8d2021-09-21 10:41:16 -0600311class DockerConstraintsTest(cros_test_lib.MockTestCase):
312 """Tests for Docker argument constraints."""
313
314 def assertValid(self, output):
315 return output is None
316
317 def assertInvalid(self, output):
318 return not self.assertValid(output)
319
320 def testValidDockerTag(self):
321 """Check logic for validating docker tag format."""
322 # pylint: disable=protected-access
323
324 invalid_tags = [
325 '.invalid-tag',
326 '-invalid-tag',
327 'invalid-tag;',
328 'invalid'*100,
329 ]
330
331 for tag in invalid_tags:
332 self.assertInvalid(test_controller._ValidDockerTag(tag))
333
334 valid_tags = [
335 'valid-tag',
336 'valid-tag-',
337 'valid.tag.',
338 ]
339
340 for tag in valid_tags:
341 self.assertValid(test_controller._ValidDockerTag(tag))
342
343
344 def testValidDockerLabelKey(self):
345 """Check logic for validating docker label key format."""
346 # pylint: disable=protected-access
347
348 invalid_keys = [
349 'Invalid-keY',
350 'Invalid-key',
351 'invalid-keY',
352 'iNVALID-KEy',
353 'invalid_key',
354 'invalid-key;',
355 ]
356
357 for key in invalid_keys:
358 self.assertInvalid(test_controller._ValidDockerLabelKey(key))
359
360 valid_keys = [
361 'chromeos.valid-key',
362 'chromeos.valid-key-2',
363 ]
364
365 for key in valid_keys:
366 self.assertValid(test_controller._ValidDockerLabelKey(key))
367
368
Sean McAllister3834fef2021-10-08 15:45:18 -0600369class BuildTestServiceContainers(cros_test_lib.RunCommandTempDirTestCase,
David Wellingc1433c22021-06-25 16:29:48 +0000370 api_config.ApiConfigMixin):
C Shapiro91af1ce2021-06-17 12:42:09 -0500371 """Tests for the BuildTestServiceContainers function."""
372
373 def setUp(self):
374 self.request = test_pb2.BuildTestServiceContainersRequest(
375 chroot={'path': '/path/to/chroot'},
376 build_target={'name': 'build_target'},
David Wellingc1433c22021-06-25 16:29:48 +0000377 version='R93-14033.0.0',
C Shapiro91af1ce2021-06-17 12:42:09 -0500378 )
379
C Shapiro91af1ce2021-06-17 12:42:09 -0500380 def testSuccess(self):
381 """Check passing case with mocked cros_build_lib.run."""
Sean McAllister3834fef2021-10-08 15:45:18 -0600382
383 def ContainerMetadata():
384 """Return mocked ContainerImageInfo proto"""
385 metadata = container_metadata_pb2.ContainerImageInfo()
386 metadata.repository.hostname = 'gcr.io'
387 metadata.repository.project = 'chromeos-bot'
388 metadata.name = 'random-container-name'
389 metadata.digest = (
390 '09b730f8b6a862f9c2705cb3acf3554563325f5fca5c784bf5c98beb2e56f6db')
391 metadata.tags[:] = [
392 'staging-cq-amd64-generic.R96-1.2.3',
393 '8834106026340379089',
394 ]
395 return metadata
396
397 def WriteContainerMetadata(path):
398 """Write json formatted metadata to the given file."""
399 osutils.WriteFile(
400 path,
401 json_format.MessageToJson(ContainerMetadata()),
402 )
403
404 # Write out mocked container metadata to a temporary file.
405 output_path = os.path.join(self.tempdir, 'metadata.jsonpb')
406 self.rc.SetDefaultCmdResult(
407 returncode=0,
408 side_effect=lambda *_, **__: WriteContainerMetadata(output_path)
409 )
410
411 # Patch TempDir so that we always use this test's directory.
412 self.PatchObject(osutils.TempDir, '__enter__', return_value=self.tempdir)
C Shapiro91af1ce2021-06-17 12:42:09 -0500413
414 response = test_pb2.BuildTestServiceContainersResponse()
415 test_controller.BuildTestServiceContainers(
416 self.request,
417 response,
418 self.api_config)
Sean McAllister3834fef2021-10-08 15:45:18 -0600419
420 self.assertTrue(self.rc.called)
C Shapiro91af1ce2021-06-17 12:42:09 -0500421 for result in response.results:
422 self.assertEqual(result.WhichOneof('result'), 'success')
Sean McAllister3834fef2021-10-08 15:45:18 -0600423 self.assertEqual(result.success.image_info, ContainerMetadata())
C Shapiro91af1ce2021-06-17 12:42:09 -0500424
C Shapiro91af1ce2021-06-17 12:42:09 -0500425 def testFailure(self):
426 """Check failure case with mocked cros_build_lib.run."""
427 patch = self.PatchObject(
428 cros_build_lib, 'run',
429 return_value=cros_build_lib.CommandResult(returncode=1))
430
431 response = test_pb2.BuildTestServiceContainersResponse()
432 test_controller.BuildTestServiceContainers(
433 self.request,
434 response,
435 self.api_config)
436 patch.assert_called()
437 for result in response.results:
438 self.assertEqual(result.WhichOneof('result'), 'failure')
439
440
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -0700441class ChromiteUnitTestTest(cros_test_lib.MockTestCase,
442 api_config.ApiConfigMixin):
443 """Tests for the ChromiteInfoTest function."""
444
445 def setUp(self):
446 self.board = 'board'
447 self.chroot_path = '/path/to/chroot'
448
449 def _GetInput(self, chroot_path=None):
450 """Helper to build an input message instance."""
451 proto = test_pb2.ChromiteUnitTestRequest(
452 chroot={'path': chroot_path},
453 )
454 return proto
455
456 def _GetOutput(self):
457 """Helper to get an empty output message instance."""
458 return test_pb2.ChromiteUnitTestResponse()
459
460 def testValidateOnly(self):
461 """Sanity check that a validate only call does not execute any logic."""
462 patch = self.PatchObject(cros_build_lib, 'run')
463
464 input_msg = self._GetInput(chroot_path=self.chroot_path)
465 test_controller.ChromiteUnitTest(input_msg, self._GetOutput(),
466 self.validate_only_config)
467 patch.assert_not_called()
468
Michael Mortensen7a860eb2019-12-03 20:25:15 -0700469 def testMockError(self):
470 """Test mock error call does not execute any logic, returns error."""
471 patch = self.PatchObject(cros_build_lib, 'run')
472
473 input_msg = self._GetInput(chroot_path=self.chroot_path)
474 rc = test_controller.ChromiteUnitTest(input_msg, self._GetOutput(),
475 self.mock_error_config)
476 patch.assert_not_called()
477 self.assertEqual(controller.RETURN_CODE_COMPLETED_UNSUCCESSFULLY, rc)
478
479 def testMockCall(self):
480 """Test mock call does not execute any logic, returns success."""
481 patch = self.PatchObject(cros_build_lib, 'run')
482
483 input_msg = self._GetInput(chroot_path=self.chroot_path)
484 rc = test_controller.ChromiteUnitTest(input_msg, self._GetOutput(),
485 self.mock_call_config)
486 patch.assert_not_called()
487 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
488
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -0700489 def testChromiteUnitTest(self):
490 """Call ChromiteUnitTest with mocked cros_build_lib.run."""
491 request = self._GetInput(chroot_path=self.chroot_path)
492 patch = self.PatchObject(
493 cros_build_lib, 'run',
494 return_value=cros_build_lib.CommandResult(returncode=0))
495
496 test_controller.ChromiteUnitTest(request, self._GetOutput(),
497 self.api_config)
498 patch.assert_called_once()
499
500
Alex Klein4bc8f4f2019-08-16 14:53:30 -0600501class CrosSigningTestTest(cros_test_lib.RunCommandTestCase,
502 api_config.ApiConfigMixin):
503 """CrosSigningTest tests."""
504
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700505 def setUp(self):
506 self.chroot_path = '/path/to/chroot'
507
508 def _GetInput(self, chroot_path=None):
509 """Helper to build an input message instance."""
510 proto = test_pb2.CrosSigningTestRequest(
511 chroot={'path': chroot_path},
512 )
513 return proto
514
515 def _GetOutput(self):
516 """Helper to get an empty output message instance."""
517 return test_pb2.CrosSigningTestResponse()
518
Alex Klein4bc8f4f2019-08-16 14:53:30 -0600519 def testValidateOnly(self):
520 """Sanity check that a validate only call does not execute any logic."""
521 test_controller.CrosSigningTest(None, None, self.validate_only_config)
522 self.assertFalse(self.rc.call_count)
523
Michael Mortensen7a7646d2019-12-12 15:36:14 -0700524 def testMockCall(self):
525 """Test mock call does not execute any logic, returns success."""
526 rc = test_controller.CrosSigningTest(None, None, self.mock_call_config)
527 self.assertFalse(self.rc.call_count)
528 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
529
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700530 def testCrosSigningTest(self):
531 """Call CrosSigningTest with mocked cros_build_lib.run."""
532 request = self._GetInput(chroot_path=self.chroot_path)
533 patch = self.PatchObject(
534 cros_build_lib, 'run',
535 return_value=cros_build_lib.CommandResult(returncode=0))
536
537 test_controller.CrosSigningTest(request, self._GetOutput(),
538 self.api_config)
539 patch.assert_called_once()
540
Alex Klein4bc8f4f2019-08-16 14:53:30 -0600541
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600542class SimpleChromeWorkflowTestTest(cros_test_lib.MockTestCase,
543 api_config.ApiConfigMixin):
544 """Test the SimpleChromeWorkflowTest endpoint."""
545
546 @staticmethod
547 def _Output():
548 return test_pb2.SimpleChromeWorkflowTestResponse()
549
David Wellingc1433c22021-06-25 16:29:48 +0000550 def _Input(self,
551 sysroot_path=None,
552 build_target=None,
553 chrome_root=None,
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600554 goma_config=None):
555 proto = test_pb2.SimpleChromeWorkflowTestRequest()
556 if sysroot_path:
557 proto.sysroot.path = sysroot_path
558 if build_target:
559 proto.sysroot.build_target.name = build_target
560 if chrome_root:
561 proto.chrome_root = chrome_root
562 if goma_config:
563 proto.goma_config = goma_config
564 return proto
565
566 def setUp(self):
567 self.chrome_path = 'path/to/chrome'
568 self.sysroot_dir = 'build/board'
569 self.build_target = 'amd64'
570 self.mock_simple_chrome_workflow_test = self.PatchObject(
571 test_service, 'SimpleChromeWorkflowTest')
572
573 def testMissingBuildTarget(self):
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700574 """Test SimpleChromeWorkflowTest dies when build_target not set."""
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600575 input_proto = self._Input(build_target=None, sysroot_path='/sysroot/dir',
576 chrome_root='/chrome/path')
577 with self.assertRaises(cros_build_lib.DieSystemExit):
578 test_controller.SimpleChromeWorkflowTest(input_proto, None,
579 self.api_config)
580
581 def testMissingSysrootPath(self):
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700582 """Test SimpleChromeWorkflowTest dies when build_target not set."""
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600583 input_proto = self._Input(build_target='board', sysroot_path=None,
584 chrome_root='/chrome/path')
585 with self.assertRaises(cros_build_lib.DieSystemExit):
586 test_controller.SimpleChromeWorkflowTest(input_proto, None,
587 self.api_config)
588
589 def testMissingChromeRoot(self):
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700590 """Test SimpleChromeWorkflowTest dies when build_target not set."""
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600591 input_proto = self._Input(build_target='board', sysroot_path='/sysroot/dir',
592 chrome_root=None)
593 with self.assertRaises(cros_build_lib.DieSystemExit):
594 test_controller.SimpleChromeWorkflowTest(input_proto, None,
595 self.api_config)
596
597 def testSimpleChromeWorkflowTest(self):
598 """Call SimpleChromeWorkflowTest with valid args and temp dir."""
599 request = self._Input(sysroot_path='sysroot_path', build_target='board',
600 chrome_root='/path/to/chrome')
601 response = self._Output()
602
603 test_controller.SimpleChromeWorkflowTest(request, response, self.api_config)
604 self.mock_simple_chrome_workflow_test.assert_called()
605
606 def testValidateOnly(self):
607 request = self._Input(sysroot_path='sysroot_path', build_target='board',
608 chrome_root='/path/to/chrome')
609 test_controller.SimpleChromeWorkflowTest(request, self._Output(),
610 self.validate_only_config)
611 self.mock_simple_chrome_workflow_test.assert_not_called()
612
Michael Mortensen7a7646d2019-12-12 15:36:14 -0700613 def testMockCall(self):
614 """Test mock call does not execute any logic, returns success."""
615 patch = self.mock_simple_chrome_workflow_test = self.PatchObject(
616 test_service, 'SimpleChromeWorkflowTest')
617
618 request = self._Input(sysroot_path='sysroot_path', build_target='board',
619 chrome_root='/path/to/chrome')
620 rc = test_controller.SimpleChromeWorkflowTest(request, self._Output(),
621 self.mock_call_config)
622 patch.assert_not_called()
623 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
624
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600625
Alex Klein231d2da2019-07-22 16:44:45 -0600626class VmTestTest(cros_test_lib.RunCommandTestCase, api_config.ApiConfigMixin):
Evan Hernandez4e388a52019-05-01 12:16:33 -0600627 """Test the VmTest endpoint."""
628
629 def _GetInput(self, **kwargs):
630 values = dict(
631 build_target=common_pb2.BuildTarget(name='target'),
Alex Klein311b8022019-06-05 16:00:07 -0600632 vm_path=common_pb2.Path(path='/path/to/image.bin',
633 location=common_pb2.Path.INSIDE),
Evan Hernandez4e388a52019-05-01 12:16:33 -0600634 test_harness=test_pb2.VmTestRequest.TAST,
635 vm_tests=[test_pb2.VmTestRequest.VmTest(pattern='suite')],
636 ssh_options=test_pb2.VmTestRequest.SshOptions(
Alex Klein231d2da2019-07-22 16:44:45 -0600637 port=1234, private_key_path={'path': '/path/to/id_rsa',
Alex Kleinaa705412019-06-04 15:00:30 -0600638 'location': common_pb2.Path.INSIDE}),
Evan Hernandez4e388a52019-05-01 12:16:33 -0600639 )
640 values.update(kwargs)
641 return test_pb2.VmTestRequest(**values)
642
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700643 def _Output(self):
644 return test_pb2.VmTestResponse()
645
Alex Klein231d2da2019-07-22 16:44:45 -0600646 def testValidateOnly(self):
647 """Sanity check that a validate only call does not execute any logic."""
648 test_controller.VmTest(self._GetInput(), None, self.validate_only_config)
649 self.assertEqual(0, self.rc.call_count)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600650
Michael Mortensen7a7646d2019-12-12 15:36:14 -0700651 def testMockCall(self):
652 """Test mock call does not execute any logic."""
653 patch = self.PatchObject(cros_build_lib, 'run')
654
655 request = self._GetInput()
656 response = self._Output()
657 # VmTest does not return a value, checking mocked value is flagged by lint.
658 test_controller.VmTest(request, response, self.mock_call_config)
659 patch.assert_not_called()
660
Evan Hernandez4e388a52019-05-01 12:16:33 -0600661 def testTastAllOptions(self):
662 """Test VmTest for Tast with all options set."""
Alex Klein231d2da2019-07-22 16:44:45 -0600663 test_controller.VmTest(self._GetInput(), None, self.api_config)
664 self.assertCommandContains([
Achuith Bhandarkara9e9c3d2019-05-22 13:56:11 -0700665 'cros_run_test', '--debug', '--no-display', '--copy-on-write',
Evan Hernandez4e388a52019-05-01 12:16:33 -0600666 '--board', 'target',
667 '--image-path', '/path/to/image.bin',
668 '--tast', 'suite',
669 '--ssh-port', '1234',
670 '--private-key', '/path/to/id_rsa',
671 ])
672
673 def testAutotestAllOptions(self):
674 """Test VmTest for Autotest with all options set."""
675 input_proto = self._GetInput(test_harness=test_pb2.VmTestRequest.AUTOTEST)
Alex Klein231d2da2019-07-22 16:44:45 -0600676 test_controller.VmTest(input_proto, None, self.api_config)
677 self.assertCommandContains([
Achuith Bhandarkara9e9c3d2019-05-22 13:56:11 -0700678 'cros_run_test', '--debug', '--no-display', '--copy-on-write',
Evan Hernandez4e388a52019-05-01 12:16:33 -0600679 '--board', 'target',
680 '--image-path', '/path/to/image.bin',
681 '--autotest', 'suite',
682 '--ssh-port', '1234',
683 '--private-key', '/path/to/id_rsa',
Greg Edelstondcb0e912020-08-31 11:09:40 -0600684 '--test_that-args=--allow-chrome-crashes',
Evan Hernandez4e388a52019-05-01 12:16:33 -0600685 ])
686
687 def testMissingBuildTarget(self):
688 """Test VmTest dies when build_target not set."""
689 input_proto = self._GetInput(build_target=None)
690 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600691 test_controller.VmTest(input_proto, None, self.api_config)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600692
693 def testMissingVmImage(self):
694 """Test VmTest dies when vm_image not set."""
Alex Klein311b8022019-06-05 16:00:07 -0600695 input_proto = self._GetInput(vm_path=None)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600696 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600697 test_controller.VmTest(input_proto, None, self.api_config)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600698
699 def testMissingTestHarness(self):
700 """Test VmTest dies when test_harness not specified."""
701 input_proto = self._GetInput(
702 test_harness=test_pb2.VmTestRequest.UNSPECIFIED)
703 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600704 test_controller.VmTest(input_proto, None, self.api_config)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600705
706 def testMissingVmTests(self):
707 """Test VmTest dies when vm_tests not set."""
708 input_proto = self._GetInput(vm_tests=[])
709 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600710 test_controller.VmTest(input_proto, None, self.api_config)
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600711
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700712 def testVmTest(self):
713 """Call VmTest with valid args and temp dir."""
714 request = self._GetInput()
715 response = self._Output()
716 patch = self.PatchObject(
717 cros_build_lib, 'run',
718 return_value=cros_build_lib.CommandResult(returncode=0))
719
720 test_controller.VmTest(request, response, self.api_config)
721 patch.assert_called()
722
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600723
Alex Klein231d2da2019-07-22 16:44:45 -0600724class MoblabVmTestTest(cros_test_lib.MockTestCase, api_config.ApiConfigMixin):
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600725 """Test the MoblabVmTest endpoint."""
726
727 @staticmethod
728 def _Payload(path):
729 return test_pb2.MoblabVmTestRequest.Payload(
730 path=common_pb2.Path(path=path))
731
732 @staticmethod
733 def _Output():
734 return test_pb2.MoblabVmTestResponse()
735
736 def _Input(self):
737 return test_pb2.MoblabVmTestRequest(
Evan Hernandeze1e05d32019-07-19 12:32:18 -0600738 chroot=common_pb2.Chroot(path=self.chroot_dir),
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600739 image_payload=self._Payload(self.image_payload_dir),
740 cache_payloads=[self._Payload(self.autotest_payload_dir)])
741
742 def setUp(self):
Evan Hernandeze1e05d32019-07-19 12:32:18 -0600743 self.chroot_dir = '/chroot'
744 self.chroot_tmp_dir = '/chroot/tmp'
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600745 self.image_payload_dir = '/payloads/image'
746 self.autotest_payload_dir = '/payloads/autotest'
747 self.builder = 'moblab-generic-vm/R12-3.4.5-67.890'
748 self.image_cache_dir = '/mnt/moblab/cache'
749 self.image_mount_dir = '/mnt/image'
750
Evan Hernandeze1e05d32019-07-19 12:32:18 -0600751 self.PatchObject(chroot_lib.Chroot, 'tempdir', osutils.TempDir)
Evan Hernandez655e8042019-06-13 12:50:44 -0600752
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600753 self.mock_create_moblab_vms = self.PatchObject(
754 test_service, 'CreateMoblabVm')
755 self.mock_prepare_moblab_vm_image_cache = self.PatchObject(
756 test_service, 'PrepareMoblabVmImageCache',
757 return_value=self.image_cache_dir)
758 self.mock_run_moblab_vm_tests = self.PatchObject(
759 test_service, 'RunMoblabVmTest')
760 self.mock_validate_moblab_vm_tests = self.PatchObject(
761 test_service, 'ValidateMoblabVmTest')
762
763 @contextlib.contextmanager
Alex Klein38c7d9e2019-05-08 09:31:19 -0600764 def MockLoopbackPartitions(*_args, **_kwargs):
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600765 mount = mock.MagicMock()
Evan Hernandez40ee7452019-06-13 12:51:43 -0600766 mount.Mount.return_value = [self.image_mount_dir]
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600767 yield mount
Alex Klein231d2da2019-07-22 16:44:45 -0600768
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600769 self.PatchObject(image_lib, 'LoopbackPartitions', MockLoopbackPartitions)
770
Alex Klein231d2da2019-07-22 16:44:45 -0600771 def testValidateOnly(self):
772 """Sanity check that a validate only call does not execute any logic."""
773 test_controller.MoblabVmTest(self._Input(), self._Output(),
774 self.validate_only_config)
775 self.mock_create_moblab_vms.assert_not_called()
776
Michael Mortensen7a7646d2019-12-12 15:36:14 -0700777 def testMockCall(self):
778 """Test mock call does not execute any logic."""
779 patch = self.PatchObject(key_value_store, 'LoadFile')
780
781 # MoblabVmTest does not return a value, checking mocked value is flagged by
782 # lint.
783 test_controller.MoblabVmTest(self._Input(), self._Output(),
784 self.mock_call_config)
785 patch.assert_not_called()
786
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600787 def testImageContainsBuilder(self):
788 """MoblabVmTest calls service with correct args."""
789 request = self._Input()
790 response = self._Output()
791
792 self.PatchObject(
Mike Frysingere652ba12019-09-08 00:57:43 -0400793 key_value_store, 'LoadFile',
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600794 return_value={cros_set_lsb_release.LSB_KEY_BUILDER_PATH: self.builder})
795
Alex Klein231d2da2019-07-22 16:44:45 -0600796 test_controller.MoblabVmTest(request, response, self.api_config)
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600797
798 self.assertEqual(
799 self.mock_create_moblab_vms.call_args_list,
Evan Hernandeze1e05d32019-07-19 12:32:18 -0600800 [mock.call(mock.ANY, self.chroot_dir, self.image_payload_dir)])
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600801 self.assertEqual(
802 self.mock_prepare_moblab_vm_image_cache.call_args_list,
803 [mock.call(mock.ANY, self.builder, [self.autotest_payload_dir])])
804 self.assertEqual(
805 self.mock_run_moblab_vm_tests.call_args_list,
Evan Hernandez655e8042019-06-13 12:50:44 -0600806 [mock.call(mock.ANY, mock.ANY, self.builder, self.image_cache_dir,
807 mock.ANY)])
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600808 self.assertEqual(
809 self.mock_validate_moblab_vm_tests.call_args_list,
810 [mock.call(mock.ANY)])
811
812 def testImageMissingBuilder(self):
813 """MoblabVmTest dies when builder path not found in lsb-release."""
814 request = self._Input()
815 response = self._Output()
816
Mike Frysingere652ba12019-09-08 00:57:43 -0400817 self.PatchObject(key_value_store, 'LoadFile', return_value={})
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600818
819 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600820 test_controller.MoblabVmTest(request, response, self.api_config)
David Wellingc1433c22021-06-25 16:29:48 +0000821
822
823class GetArtifactsTest(cros_test_lib.MockTempDirTestCase):
824 """Test GetArtifacts."""
825
826 CODE_COVERAGE_LLVM_ARTIFACT_TYPE = (
827 common_pb2.ArtifactsByService.Test.ArtifactType.CODE_COVERAGE_LLVM_JSON
828 )
George Engelbrecht764b1cd2021-06-18 17:01:07 -0600829 UNIT_TEST_ARTIFACT_TYPE = (
830 common_pb2.ArtifactsByService.Test.ArtifactType.UNIT_TESTS
831 )
David Wellingc1433c22021-06-25 16:29:48 +0000832
833 def setUp(self):
834 """Set up the class for tests."""
835 chroot_dir = os.path.join(self.tempdir, 'chroot')
836 osutils.SafeMakedirs(chroot_dir)
837 osutils.SafeMakedirs(os.path.join(chroot_dir, 'tmp'))
838 self.chroot = chroot_lib.Chroot(chroot_dir)
839
840 sysroot_path = os.path.join(chroot_dir, 'build', 'board')
841 osutils.SafeMakedirs(sysroot_path)
842 self.sysroot = sysroot_lib.Sysroot(sysroot_path)
843
Jack Neusc9707c32021-07-23 21:48:54 +0000844 self.build_target = build_target_lib.BuildTarget('board')
845
David Wellingc1433c22021-06-25 16:29:48 +0000846 def testReturnsEmptyListWhenNoOutputArtifactsProvided(self):
847 """Test empty list is returned when there are no output_artifacts."""
848 result = test_controller.GetArtifacts(
849 common_pb2.ArtifactsByService.Test(output_artifacts=[]),
Jack Neusc9707c32021-07-23 21:48:54 +0000850 self.chroot, self.sysroot, self.build_target, self.tempdir)
David Wellingc1433c22021-06-25 16:29:48 +0000851
852 self.assertEqual(len(result), 0)
853
854 def testShouldCallBundleCodeCoverageLlvmJsonForEachValidArtifact(self):
855 """Test BundleCodeCoverageLlvmJson is called on each valid artifact."""
Sean McAllister17eed8d2021-09-21 10:41:16 -0600856 BundleCodeCoverageLlvmJson_mock = (
857 self.PatchObject(
858 test_service,
859 'BundleCodeCoverageLlvmJson',
860 return_value='test'))
David Wellingc1433c22021-06-25 16:29:48 +0000861
862 test_controller.GetArtifacts(
863 common_pb2.ArtifactsByService.Test(output_artifacts=[
864 # Valid
865 common_pb2.ArtifactsByService.Test.ArtifactInfo(
866 artifact_types=[
867 self.CODE_COVERAGE_LLVM_ARTIFACT_TYPE
868 ]
869 ),
870
871 # Invalid
872 common_pb2.ArtifactsByService.Test.ArtifactInfo(
873 artifact_types=[
874 common_pb2.ArtifactsByService.Test.ArtifactType.UNIT_TESTS
875 ]
876 ),
877 ]),
Jack Neusc9707c32021-07-23 21:48:54 +0000878 self.chroot, self.sysroot, self.build_target, self.tempdir)
David Wellingc1433c22021-06-25 16:29:48 +0000879
880 BundleCodeCoverageLlvmJson_mock.assert_called_once()
881
882 def testShouldReturnValidResult(self):
883 """Test result contains paths and code_coverage_llvm_json type."""
884 self.PatchObject(test_service, 'BundleCodeCoverageLlvmJson',
Sean McAllister17eed8d2021-09-21 10:41:16 -0600885 return_value='test')
George Engelbrecht764b1cd2021-06-18 17:01:07 -0600886 self.PatchObject(test_service, 'BuildTargetUnitTestTarball',
Sean McAllister17eed8d2021-09-21 10:41:16 -0600887 return_value='unit_tests.tar')
David Wellingc1433c22021-06-25 16:29:48 +0000888
889 result = test_controller.GetArtifacts(
890 common_pb2.ArtifactsByService.Test(output_artifacts=[
891 # Valid
892 common_pb2.ArtifactsByService.Test.ArtifactInfo(
893 artifact_types=[
George Engelbrecht764b1cd2021-06-18 17:01:07 -0600894 self.UNIT_TEST_ARTIFACT_TYPE
895 ]
896 ),
897 common_pb2.ArtifactsByService.Test.ArtifactInfo(
898 artifact_types=[
David Wellingc1433c22021-06-25 16:29:48 +0000899 self.CODE_COVERAGE_LLVM_ARTIFACT_TYPE
900 ]
901 ),
902 ]),
Jack Neusc9707c32021-07-23 21:48:54 +0000903 self.chroot, self.sysroot, self.build_target, self.tempdir)
David Wellingc1433c22021-06-25 16:29:48 +0000904
George Engelbrecht764b1cd2021-06-18 17:01:07 -0600905 self.assertEqual(result[0]['paths'], ['unit_tests.tar'])
906 self.assertEqual(result[0]['type'], self.UNIT_TEST_ARTIFACT_TYPE)
907 self.assertEqual(result[1]['paths'], ['test'])
908 self.assertEqual(result[1]['type'], self.CODE_COVERAGE_LLVM_ARTIFACT_TYPE)