blob: a738f5e83b198fc53a8d9d450d6f634a388e7392 [file] [log] [blame]
Mike Frysingerf1ba7ad2022-09-12 05:42:57 -04001# Copyright 2019 The ChromiumOS Authors
Alex Kleina2e42c42019-04-17 16:13:19 -06002# 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
Lizzy Presland4feb2372022-01-20 05:16:30 +00007import datetime
Mike Frysingeref94e4c2020-02-10 23:59:54 -05008import os
Mike Frysinger40443592022-05-05 13:03:40 -04009from typing import Union
Mike Frysingeref94e4c2020-02-10 23:59:54 -050010
Mike Frysinger1cc8f1f2022-04-28 22:40:40 -040011from chromite.third_party.google.protobuf import json_format
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
Lizzy Presland4feb2372022-01-20 05:16:30 +000015from chromite.api.controller import controller_util
Alex Kleina2e42c42019-04-17 16:13:19 -060016from chromite.api.controller import test as test_controller
17from chromite.api.gen.chromite.api import test_pb2
Mike Frysinger1cc8f1f2022-04-28 22:40:40 -040018from chromite.api.gen.chromiumos import common_pb2
Sean McAllister3834fef2021-10-08 15:45:18 -060019from chromite.api.gen.chromiumos.build.api import container_metadata_pb2
Jack Neusc9707c32021-07-23 21:48:54 +000020from chromite.lib import build_target_lib
Evan Hernandeze1e05d32019-07-19 12:32:18 -060021from chromite.lib import chroot_lib
Alex Kleina2e42c42019-04-17 16:13:19 -060022from chromite.lib import cros_build_lib
23from chromite.lib import cros_test_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.service import test as test_service
Alex Kleina2e42c42019-04-17 16:13:19 -060028
29
Alex Klein1699fab2022-09-08 08:46:06 -060030class DebugInfoTestTest(
31 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin
32):
33 """Tests for the DebugInfoTest function."""
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -070034
Alex Klein1699fab2022-09-08 08:46:06 -060035 def setUp(self):
36 self.board = "board"
37 self.chroot_path = os.path.join(self.tempdir, "chroot")
38 self.sysroot_path = "/build/board"
39 self.full_sysroot_path = os.path.join(
40 self.chroot_path, self.sysroot_path.lstrip(os.sep)
41 )
42 osutils.SafeMakedirs(self.full_sysroot_path)
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -070043
Alex Klein1699fab2022-09-08 08:46:06 -060044 def _GetInput(self, sysroot_path=None, build_target=None):
45 """Helper to build an input message instance."""
46 proto = test_pb2.DebugInfoTestRequest()
47 if sysroot_path:
48 proto.sysroot.path = sysroot_path
49 if build_target:
50 proto.sysroot.build_target.name = build_target
51 return proto
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -070052
Alex Klein1699fab2022-09-08 08:46:06 -060053 def _GetOutput(self):
54 """Helper to get an empty output message instance."""
55 return test_pb2.DebugInfoTestResponse()
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -070056
Alex Klein1699fab2022-09-08 08:46:06 -060057 def testValidateOnly(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -070058 """Verify a validate-only call does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -060059 patch = self.PatchObject(test_service, "DebugInfoTest")
60 input_msg = self._GetInput(sysroot_path=self.full_sysroot_path)
61 test_controller.DebugInfoTest(
62 input_msg, self._GetOutput(), self.validate_only_config
63 )
64 patch.assert_not_called()
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -070065
Alex Klein1699fab2022-09-08 08:46:06 -060066 def testMockError(self):
67 """Test mock error call does not execute any logic, returns error."""
68 patch = self.PatchObject(test_service, "DebugInfoTest")
Michael Mortensen85d38402019-12-12 09:50:29 -070069
Alex Klein1699fab2022-09-08 08:46:06 -060070 input_msg = self._GetInput(sysroot_path=self.full_sysroot_path)
71 rc = test_controller.DebugInfoTest(
72 input_msg, self._GetOutput(), self.mock_error_config
73 )
74 patch.assert_not_called()
75 self.assertEqual(controller.RETURN_CODE_COMPLETED_UNSUCCESSFULLY, rc)
Michael Mortensen85d38402019-12-12 09:50:29 -070076
Alex Klein1699fab2022-09-08 08:46:06 -060077 def testMockCall(self):
78 """Test mock call does not execute any logic, returns success."""
79 patch = self.PatchObject(test_service, "DebugInfoTest")
Michael Mortensen85d38402019-12-12 09:50:29 -070080
Alex Klein1699fab2022-09-08 08:46:06 -060081 input_msg = self._GetInput(sysroot_path=self.full_sysroot_path)
82 rc = test_controller.DebugInfoTest(
83 input_msg, self._GetOutput(), self.mock_call_config
84 )
85 patch.assert_not_called()
86 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
Michael Mortensen85d38402019-12-12 09:50:29 -070087
Alex Klein1699fab2022-09-08 08:46:06 -060088 def testNoBuildTargetNoSysrootFails(self):
89 """Test missing build target name and sysroot path fails."""
90 input_msg = self._GetInput()
91 output_msg = self._GetOutput()
92 with self.assertRaises(cros_build_lib.DieSystemExit):
93 test_controller.DebugInfoTest(
94 input_msg, output_msg, self.api_config
95 )
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -070096
Alex Klein1699fab2022-09-08 08:46:06 -060097 def testDebugInfoTest(self):
98 """Call DebugInfoTest with valid sysroot_path."""
99 request = self._GetInput(sysroot_path=self.full_sysroot_path)
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -0700100
Alex Klein1699fab2022-09-08 08:46:06 -0600101 test_controller.DebugInfoTest(
102 request, self._GetOutput(), self.api_config
103 )
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -0700104
105
Alex Klein1699fab2022-09-08 08:46:06 -0600106class BuildTargetUnitTestTest(
107 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin
108):
109 """Tests for the UnitTest function."""
Alex Kleina2e42c42019-04-17 16:13:19 -0600110
Alex Klein1699fab2022-09-08 08:46:06 -0600111 def setUp(self):
112 # Set up portage log directory.
113 self.sysroot = os.path.join(self.tempdir, "build", "board")
114 osutils.SafeMakedirs(self.sysroot)
115 self.target_sysroot = sysroot_lib.Sysroot(self.sysroot)
116 self.portage_dir = os.path.join(self.tempdir, "portage_logdir")
117 self.PatchObject(
118 sysroot_lib.Sysroot, "portage_logdir", new=self.portage_dir
119 )
120 osutils.SafeMakedirs(self.portage_dir)
Lizzy Presland4feb2372022-01-20 05:16:30 +0000121
Alex Klein1699fab2022-09-08 08:46:06 -0600122 def _GetInput(
123 self,
124 board=None,
125 chroot_path=None,
126 cache_dir=None,
127 empty_sysroot=None,
128 packages=None,
129 blocklist=None,
130 ):
131 """Helper to build an input message instance."""
132 formatted_packages = []
133 for pkg in packages or []:
134 formatted_packages.append(
135 {"category": pkg.category, "package_name": pkg.package}
136 )
137 formatted_blocklist = []
138 for pkg in blocklist or []:
139 formatted_blocklist.append(
140 {"category": pkg.category, "package_name": pkg.package}
141 )
Alex Kleinf2674462019-05-16 16:47:24 -0600142
Alex Klein1699fab2022-09-08 08:46:06 -0600143 return test_pb2.BuildTargetUnitTestRequest(
144 build_target={"name": board},
145 chroot={"path": chroot_path, "cache_dir": cache_dir},
146 flags={"empty_sysroot": empty_sysroot},
147 packages=formatted_packages,
148 package_blocklist=formatted_blocklist,
149 )
Alex Kleina2e42c42019-04-17 16:13:19 -0600150
Alex Klein1699fab2022-09-08 08:46:06 -0600151 def _GetOutput(self):
152 """Helper to get an empty output message instance."""
153 return test_pb2.BuildTargetUnitTestResponse()
Alex Kleina2e42c42019-04-17 16:13:19 -0600154
Alex Klein1699fab2022-09-08 08:46:06 -0600155 def _CreatePortageLogFile(
156 self,
157 log_path: Union[str, os.PathLike],
158 pkg_info: package_info.PackageInfo,
159 timestamp: datetime.datetime,
160 ) -> str:
Alex Kleinab87ceb2023-01-24 12:00:51 -0700161 """Creates a log file to test for individual packages built by Portage.
Lizzy Presland4feb2372022-01-20 05:16:30 +0000162
Alex Klein1699fab2022-09-08 08:46:06 -0600163 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600164 log_path: The PORTAGE_LOGDIR path.
165 pkg_info: name components for log file.
166 timestamp: Timestamp used to name the file.
Alex Klein1699fab2022-09-08 08:46:06 -0600167 """
168 path = os.path.join(
169 log_path,
170 f"{pkg_info.category}:{pkg_info.pvr}:"
171 f'{timestamp.strftime("%Y%m%d-%H%M%S")}.log',
172 )
173 osutils.WriteFile(
174 path,
175 f"Test log file for package {pkg_info.category}/"
176 f"{pkg_info.package} written to {path}",
177 )
178 return path
Lizzy Presland4feb2372022-01-20 05:16:30 +0000179
Alex Klein1699fab2022-09-08 08:46:06 -0600180 def testValidateOnly(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700181 """Verify a validate-only call does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -0600182 patch = self.PatchObject(test_service, "BuildTargetUnitTest")
Alex Klein231d2da2019-07-22 16:44:45 -0600183
Alex Klein1699fab2022-09-08 08:46:06 -0600184 input_msg = self._GetInput(board="board")
185 test_controller.BuildTargetUnitTest(
186 input_msg, self._GetOutput(), self.validate_only_config
187 )
188 patch.assert_not_called()
Alex Klein231d2da2019-07-22 16:44:45 -0600189
Alex Klein1699fab2022-09-08 08:46:06 -0600190 def testMockCall(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700191 """Test a mock call does not execute logic, returns mocked value."""
Alex Klein1699fab2022-09-08 08:46:06 -0600192 patch = self.PatchObject(test_service, "BuildTargetUnitTest")
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700193
Alex Klein1699fab2022-09-08 08:46:06 -0600194 input_msg = self._GetInput(board="board")
195 response = self._GetOutput()
196 test_controller.BuildTargetUnitTest(
197 input_msg, response, self.mock_call_config
198 )
199 patch.assert_not_called()
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700200
Alex Klein1699fab2022-09-08 08:46:06 -0600201 def testMockError(self):
202 """Test that a mock error does not execute logic, returns error."""
203 patch = self.PatchObject(test_service, "BuildTargetUnitTest")
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700204
Alex Klein1699fab2022-09-08 08:46:06 -0600205 input_msg = self._GetInput(board="board")
206 response = self._GetOutput()
207 rc = test_controller.BuildTargetUnitTest(
208 input_msg, response, self.mock_error_config
209 )
210 patch.assert_not_called()
211 self.assertEqual(
212 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
213 )
214 self.assertTrue(response.failed_package_data)
215 self.assertEqual(response.failed_package_data[0].name.category, "foo")
216 self.assertEqual(
217 response.failed_package_data[0].name.package_name, "bar"
218 )
219 self.assertEqual(response.failed_package_data[1].name.category, "cat")
220 self.assertEqual(
221 response.failed_package_data[1].name.package_name, "pkg"
222 )
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700223
Alex Klein1699fab2022-09-08 08:46:06 -0600224 def testInvalidPackageFails(self):
225 """Test missing result path fails."""
226 # Missing result_path.
227 pkg = package_info.PackageInfo(package="bar")
228 input_msg = self._GetInput(board="board", packages=[pkg])
229 output_msg = self._GetOutput()
230 with self.assertRaises(cros_build_lib.DieSystemExit):
231 test_controller.BuildTargetUnitTest(
232 input_msg, output_msg, self.api_config
233 )
Alex Klein64ac34c2020-09-23 10:21:33 -0600234
Alex Klein1699fab2022-09-08 08:46:06 -0600235 def testPackageBuildFailure(self):
236 """Test handling of raised BuildPackageFailure."""
237 tempdir = osutils.TempDir(base_dir=self.tempdir)
238 self.PatchObject(osutils, "TempDir", return_value=tempdir)
Alex Kleina2e42c42019-04-17 16:13:19 -0600239
Alex Klein1699fab2022-09-08 08:46:06 -0600240 pkgs = ["cat/pkg-1.0-r1", "foo/bar-2.0-r1"]
241 cpvrs = [package_info.parse(pkg) for pkg in pkgs]
242 expected = [("cat", "pkg"), ("foo", "bar")]
243 new_logs = {}
244 for i, pkg in enumerate(pkgs):
245 self._CreatePortageLogFile(
246 self.portage_dir,
247 cpvrs[i],
248 datetime.datetime(2021, 6, 9, 13, 37, 0),
249 )
250 new_logs[pkg] = self._CreatePortageLogFile(
251 self.portage_dir,
252 cpvrs[i],
253 datetime.datetime(2021, 6, 9, 16, 20, 0),
254 )
Alex Kleina2e42c42019-04-17 16:13:19 -0600255
Alex Klein1699fab2022-09-08 08:46:06 -0600256 result = test_service.BuildTargetUnitTestResult(1, None)
257 result.failed_pkgs = [package_info.parse(p) for p in pkgs]
258 self.PatchObject(
259 test_service, "BuildTargetUnitTest", return_value=result
260 )
Alex Kleina2e42c42019-04-17 16:13:19 -0600261
Alex Klein1699fab2022-09-08 08:46:06 -0600262 input_msg = self._GetInput(board="board")
263 output_msg = self._GetOutput()
Alex Kleina2e42c42019-04-17 16:13:19 -0600264
Alex Klein1699fab2022-09-08 08:46:06 -0600265 rc = test_controller.BuildTargetUnitTest(
266 input_msg, output_msg, self.api_config
267 )
Alex Kleina2e42c42019-04-17 16:13:19 -0600268
Alex Klein1699fab2022-09-08 08:46:06 -0600269 self.assertEqual(
270 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc
271 )
272 self.assertTrue(output_msg.failed_package_data)
Alex Kleina2e42c42019-04-17 16:13:19 -0600273
Alex Klein1699fab2022-09-08 08:46:06 -0600274 failed_with_logs = []
275 for data in output_msg.failed_package_data:
276 failed_with_logs.append(
277 (data.name.category, data.name.package_name)
278 )
279 package = controller_util.deserialize_package_info(data.name)
280 self.assertEqual(data.log_path.path, new_logs[package.cpvr])
281 self.assertCountEqual(expected, failed_with_logs)
Lizzy Presland4feb2372022-01-20 05:16:30 +0000282
Alex Klein1699fab2022-09-08 08:46:06 -0600283 def testOtherBuildScriptFailure(self):
284 """Test build script failure due to non-package emerge error."""
285 tempdir = osutils.TempDir(base_dir=self.tempdir)
286 self.PatchObject(osutils, "TempDir", return_value=tempdir)
Alex Kleina2e42c42019-04-17 16:13:19 -0600287
Alex Klein1699fab2022-09-08 08:46:06 -0600288 result = test_service.BuildTargetUnitTestResult(1, None)
289 self.PatchObject(
290 test_service, "BuildTargetUnitTest", return_value=result
291 )
Alex Kleina2e42c42019-04-17 16:13:19 -0600292
Alex Klein1699fab2022-09-08 08:46:06 -0600293 pkgs = ["foo/bar", "cat/pkg"]
Alex Kleind3b84042023-05-19 14:43:59 -0600294 blocklist = [package_info.parse(p) for p in pkgs]
Alex Klein1699fab2022-09-08 08:46:06 -0600295 input_msg = self._GetInput(
296 board="board", empty_sysroot=True, blocklist=blocklist
297 )
298 output_msg = self._GetOutput()
Alex Kleina2e42c42019-04-17 16:13:19 -0600299
Alex Klein1699fab2022-09-08 08:46:06 -0600300 rc = test_controller.BuildTargetUnitTest(
301 input_msg, output_msg, self.api_config
302 )
Alex Kleina2e42c42019-04-17 16:13:19 -0600303
Alex Klein1699fab2022-09-08 08:46:06 -0600304 self.assertEqual(controller.RETURN_CODE_COMPLETED_UNSUCCESSFULLY, rc)
305 self.assertFalse(output_msg.failed_package_data)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600306
Alex Klein1699fab2022-09-08 08:46:06 -0600307 def testBuildTargetUnitTest(self):
308 """Test BuildTargetUnitTest successful call."""
309 pkgs = ["foo/bar", "cat/pkg"]
310 packages = [package_info.SplitCPV(p, strict=False) for p in pkgs]
311 input_msg = self._GetInput(board="board", packages=packages)
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700312
Alex Klein1699fab2022-09-08 08:46:06 -0600313 result = test_service.BuildTargetUnitTestResult(0, None)
314 self.PatchObject(
315 test_service, "BuildTargetUnitTest", return_value=result
316 )
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700317
Alex Klein1699fab2022-09-08 08:46:06 -0600318 response = self._GetOutput()
319 test_controller.BuildTargetUnitTest(
320 input_msg, response, self.api_config
321 )
322 self.assertFalse(response.failed_package_data)
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700323
Evan Hernandez4e388a52019-05-01 12:16:33 -0600324
Sean McAllister17eed8d2021-09-21 10:41:16 -0600325class DockerConstraintsTest(cros_test_lib.MockTestCase):
Alex Klein1699fab2022-09-08 08:46:06 -0600326 """Tests for Docker argument constraints."""
Sean McAllister17eed8d2021-09-21 10:41:16 -0600327
Alex Klein1699fab2022-09-08 08:46:06 -0600328 def assertValid(self, output):
329 return output is None
Sean McAllister17eed8d2021-09-21 10:41:16 -0600330
Alex Klein1699fab2022-09-08 08:46:06 -0600331 def assertInvalid(self, output):
332 return not self.assertValid(output)
Sean McAllister17eed8d2021-09-21 10:41:16 -0600333
Alex Klein1699fab2022-09-08 08:46:06 -0600334 def testValidDockerTag(self):
335 """Check logic for validating docker tag format."""
336 # pylint: disable=protected-access
Sean McAllister17eed8d2021-09-21 10:41:16 -0600337
Alex Klein1699fab2022-09-08 08:46:06 -0600338 invalid_tags = [
339 ".invalid-tag",
340 "-invalid-tag",
341 "invalid-tag;",
342 "invalid" * 100,
343 ]
Sean McAllister17eed8d2021-09-21 10:41:16 -0600344
Alex Klein1699fab2022-09-08 08:46:06 -0600345 for tag in invalid_tags:
346 self.assertInvalid(test_controller._ValidDockerTag(tag))
Sean McAllister17eed8d2021-09-21 10:41:16 -0600347
Alex Klein1699fab2022-09-08 08:46:06 -0600348 valid_tags = [
349 "valid-tag",
350 "valid-tag-",
351 "valid.tag.",
352 ]
Sean McAllister17eed8d2021-09-21 10:41:16 -0600353
Alex Klein1699fab2022-09-08 08:46:06 -0600354 for tag in valid_tags:
355 self.assertValid(test_controller._ValidDockerTag(tag))
Sean McAllister17eed8d2021-09-21 10:41:16 -0600356
Alex Klein1699fab2022-09-08 08:46:06 -0600357 def testValidDockerLabelKey(self):
358 """Check logic for validating docker label key format."""
359 # pylint: disable=protected-access
Sean McAllister17eed8d2021-09-21 10:41:16 -0600360
Alex Klein1699fab2022-09-08 08:46:06 -0600361 invalid_keys = [
362 "Invalid-keY",
363 "Invalid-key",
364 "invalid-keY",
365 "iNVALID-KEy",
366 "invalid_key",
367 "invalid-key;",
368 ]
Sean McAllister17eed8d2021-09-21 10:41:16 -0600369
Alex Klein1699fab2022-09-08 08:46:06 -0600370 for key in invalid_keys:
371 self.assertInvalid(test_controller._ValidDockerLabelKey(key))
Sean McAllister17eed8d2021-09-21 10:41:16 -0600372
Alex Klein1699fab2022-09-08 08:46:06 -0600373 valid_keys = [
374 "chromeos.valid-key",
375 "chromeos.valid-key-2",
376 ]
Sean McAllister17eed8d2021-09-21 10:41:16 -0600377
Alex Klein1699fab2022-09-08 08:46:06 -0600378 for key in valid_keys:
379 self.assertValid(test_controller._ValidDockerLabelKey(key))
Sean McAllister17eed8d2021-09-21 10:41:16 -0600380
381
Alex Klein1699fab2022-09-08 08:46:06 -0600382class BuildTestServiceContainers(
383 cros_test_lib.RunCommandTempDirTestCase, api_config.ApiConfigMixin
384):
385 """Tests for the BuildTestServiceContainers function."""
C Shapiro91af1ce2021-06-17 12:42:09 -0500386
Alex Klein1699fab2022-09-08 08:46:06 -0600387 def setUp(self):
388 self.request = test_pb2.BuildTestServiceContainersRequest(
389 chroot={"path": "/path/to/chroot"},
390 build_target={"name": "build_target"},
391 version="R93-14033.0.0",
392 )
C Shapiro91af1ce2021-06-17 12:42:09 -0500393
Alex Klein1699fab2022-09-08 08:46:06 -0600394 def testSuccess(self):
395 """Check passing case with mocked cros_build_lib.run."""
Sean McAllister3834fef2021-10-08 15:45:18 -0600396
Alex Klein1699fab2022-09-08 08:46:06 -0600397 def ContainerMetadata():
398 """Return mocked ContainerImageInfo proto"""
399 metadata = container_metadata_pb2.ContainerImageInfo()
400 metadata.repository.hostname = "gcr.io"
401 metadata.repository.project = "chromeos-bot"
402 metadata.name = "random-container-name"
Alex Kleinab87ceb2023-01-24 12:00:51 -0700403 # pylint: disable=line-too-long
Alex Klein1699fab2022-09-08 08:46:06 -0600404 metadata.digest = "09b730f8b6a862f9c2705cb3acf3554563325f5fca5c784bf5c98beb2e56f6db"
Alex Kleinab87ceb2023-01-24 12:00:51 -0700405 # pylint: enable=line-too-long
Alex Klein1699fab2022-09-08 08:46:06 -0600406 metadata.tags[:] = [
407 "staging-cq-amd64-generic.R96-1.2.3",
408 "8834106026340379089",
409 ]
410 return metadata
Sean McAllister3834fef2021-10-08 15:45:18 -0600411
Alex Klein1699fab2022-09-08 08:46:06 -0600412 def WriteContainerMetadata(path):
413 """Write json formatted metadata to the given file."""
414 osutils.WriteFile(
415 path,
416 json_format.MessageToJson(ContainerMetadata()),
417 )
Sean McAllister3834fef2021-10-08 15:45:18 -0600418
Alex Klein1699fab2022-09-08 08:46:06 -0600419 # Write out mocked container metadata to a temporary file.
420 output_path = os.path.join(self.tempdir, "metadata.jsonpb")
421 self.rc.SetDefaultCmdResult(
422 returncode=0,
423 side_effect=lambda *_, **__: WriteContainerMetadata(output_path),
424 )
Sean McAllister3834fef2021-10-08 15:45:18 -0600425
Alex Klein1699fab2022-09-08 08:46:06 -0600426 # Patch TempDir so that we always use this test's directory.
427 self.PatchObject(
428 osutils.TempDir, "__enter__", return_value=self.tempdir
429 )
C Shapiro91af1ce2021-06-17 12:42:09 -0500430
Alex Klein1699fab2022-09-08 08:46:06 -0600431 response = test_pb2.BuildTestServiceContainersResponse()
432 test_controller.BuildTestServiceContainers(
433 self.request, response, self.api_config
434 )
Sean McAllister3834fef2021-10-08 15:45:18 -0600435
Alex Klein1699fab2022-09-08 08:46:06 -0600436 self.assertTrue(self.rc.called)
437 for result in response.results:
438 self.assertEqual(result.WhichOneof("result"), "success")
439 self.assertEqual(result.success.image_info, ContainerMetadata())
C Shapiro91af1ce2021-06-17 12:42:09 -0500440
Alex Klein1699fab2022-09-08 08:46:06 -0600441 def testFailure(self):
442 """Check failure case with mocked cros_build_lib.run."""
443 patch = self.PatchObject(
444 cros_build_lib,
445 "run",
446 return_value=cros_build_lib.CompletedProcess(returncode=1),
447 )
C Shapiro91af1ce2021-06-17 12:42:09 -0500448
Alex Klein1699fab2022-09-08 08:46:06 -0600449 response = test_pb2.BuildTestServiceContainersResponse()
450 test_controller.BuildTestServiceContainers(
451 self.request, response, self.api_config
452 )
453 patch.assert_called()
454 for result in response.results:
455 self.assertEqual(result.WhichOneof("result"), "failure")
456 self.assertEqual(result.name, "Service Builder")
C Shapiro91af1ce2021-06-17 12:42:09 -0500457
Alex Klein4f215432022-05-23 10:41:14 -0600458
Alex Klein1699fab2022-09-08 08:46:06 -0600459class ChromiteUnitTestTest(
460 cros_test_lib.MockTestCase, api_config.ApiConfigMixin
461):
462 """Tests for the ChromiteInfoTest function."""
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -0700463
Alex Klein1699fab2022-09-08 08:46:06 -0600464 def setUp(self):
465 self.board = "board"
466 self.chroot_path = "/path/to/chroot"
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -0700467
Alex Klein1699fab2022-09-08 08:46:06 -0600468 def _GetInput(self, chroot_path=None):
469 """Helper to build an input message instance."""
470 proto = test_pb2.ChromiteUnitTestRequest(
471 chroot={"path": chroot_path},
472 )
473 return proto
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -0700474
Alex Klein1699fab2022-09-08 08:46:06 -0600475 def _GetOutput(self):
476 """Helper to get an empty output message instance."""
477 return test_pb2.ChromiteUnitTestResponse()
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -0700478
Alex Klein1699fab2022-09-08 08:46:06 -0600479 def testValidateOnly(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700480 """Verify a validate-only call does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -0600481 patch = self.PatchObject(cros_build_lib, "run")
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -0700482
Alex Klein1699fab2022-09-08 08:46:06 -0600483 input_msg = self._GetInput(chroot_path=self.chroot_path)
484 test_controller.ChromiteUnitTest(
485 input_msg, self._GetOutput(), self.validate_only_config
486 )
487 patch.assert_not_called()
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -0700488
Alex Klein1699fab2022-09-08 08:46:06 -0600489 def testMockError(self):
490 """Test mock error call does not execute any logic, returns error."""
491 patch = self.PatchObject(cros_build_lib, "run")
Michael Mortensen7a860eb2019-12-03 20:25:15 -0700492
Alex Klein1699fab2022-09-08 08:46:06 -0600493 input_msg = self._GetInput(chroot_path=self.chroot_path)
494 rc = test_controller.ChromiteUnitTest(
495 input_msg, self._GetOutput(), self.mock_error_config
496 )
497 patch.assert_not_called()
498 self.assertEqual(controller.RETURN_CODE_COMPLETED_UNSUCCESSFULLY, rc)
Michael Mortensen7a860eb2019-12-03 20:25:15 -0700499
Alex Klein1699fab2022-09-08 08:46:06 -0600500 def testMockCall(self):
501 """Test mock call does not execute any logic, returns success."""
502 patch = self.PatchObject(cros_build_lib, "run")
Michael Mortensen7a860eb2019-12-03 20:25:15 -0700503
Alex Klein1699fab2022-09-08 08:46:06 -0600504 input_msg = self._GetInput(chroot_path=self.chroot_path)
505 rc = test_controller.ChromiteUnitTest(
506 input_msg, self._GetOutput(), self.mock_call_config
507 )
508 patch.assert_not_called()
509 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
Michael Mortensen7a860eb2019-12-03 20:25:15 -0700510
Alex Klein1699fab2022-09-08 08:46:06 -0600511 def testChromiteUnitTest(self):
512 """Call ChromiteUnitTest with mocked cros_build_lib.run."""
513 request = self._GetInput(chroot_path=self.chroot_path)
514 patch = self.PatchObject(
515 cros_build_lib,
516 "run",
517 return_value=cros_build_lib.CompletedProcess(returncode=0),
518 )
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -0700519
Alex Klein1699fab2022-09-08 08:46:06 -0600520 test_controller.ChromiteUnitTest(
521 request, self._GetOutput(), self.api_config
522 )
523 patch.assert_called_once()
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -0700524
525
Alex Klein1699fab2022-09-08 08:46:06 -0600526class CrosSigningTestTest(
527 cros_test_lib.RunCommandTestCase, api_config.ApiConfigMixin
528):
529 """CrosSigningTest tests."""
Alex Klein4bc8f4f2019-08-16 14:53:30 -0600530
Alex Klein1699fab2022-09-08 08:46:06 -0600531 def setUp(self):
532 self.chroot_path = "/path/to/chroot"
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700533
Alex Klein1699fab2022-09-08 08:46:06 -0600534 def _GetInput(self, chroot_path=None):
535 """Helper to build an input message instance."""
536 proto = test_pb2.CrosSigningTestRequest(
537 chroot={"path": chroot_path},
538 )
539 return proto
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700540
Alex Klein1699fab2022-09-08 08:46:06 -0600541 def _GetOutput(self):
542 """Helper to get an empty output message instance."""
543 return test_pb2.CrosSigningTestResponse()
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700544
Alex Klein1699fab2022-09-08 08:46:06 -0600545 def testValidateOnly(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700546 """Verify a validate-only call does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -0600547 test_controller.CrosSigningTest(None, None, self.validate_only_config)
548 self.assertFalse(self.rc.call_count)
Alex Klein4bc8f4f2019-08-16 14:53:30 -0600549
Alex Klein1699fab2022-09-08 08:46:06 -0600550 def testMockCall(self):
551 """Test mock call does not execute any logic, returns success."""
552 rc = test_controller.CrosSigningTest(None, None, self.mock_call_config)
553 self.assertFalse(self.rc.call_count)
554 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
Michael Mortensen7a7646d2019-12-12 15:36:14 -0700555
Alex Klein1699fab2022-09-08 08:46:06 -0600556 def testCrosSigningTest(self):
557 """Call CrosSigningTest with mocked cros_build_lib.run."""
558 request = self._GetInput(chroot_path=self.chroot_path)
559 patch = self.PatchObject(
560 cros_build_lib,
561 "run",
562 return_value=cros_build_lib.CompletedProcess(returncode=0),
563 )
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700564
Alex Klein1699fab2022-09-08 08:46:06 -0600565 test_controller.CrosSigningTest(
566 request, self._GetOutput(), self.api_config
567 )
568 patch.assert_called_once()
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700569
Alex Klein4bc8f4f2019-08-16 14:53:30 -0600570
Alex Klein1699fab2022-09-08 08:46:06 -0600571class SimpleChromeWorkflowTestTest(
572 cros_test_lib.MockTestCase, api_config.ApiConfigMixin
573):
574 """Test the SimpleChromeWorkflowTest endpoint."""
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600575
Alex Klein1699fab2022-09-08 08:46:06 -0600576 @staticmethod
577 def _Output():
578 return test_pb2.SimpleChromeWorkflowTestResponse()
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600579
Alex Klein1699fab2022-09-08 08:46:06 -0600580 def _Input(
581 self,
582 sysroot_path=None,
Alex Klein4f215432022-05-23 10:41:14 -0600583 build_target=None,
Alex Klein1699fab2022-09-08 08:46:06 -0600584 chrome_root=None,
585 goma_config=None,
586 ):
587 proto = test_pb2.SimpleChromeWorkflowTestRequest()
588 if sysroot_path:
589 proto.sysroot.path = sysroot_path
590 if build_target:
591 proto.sysroot.build_target.name = build_target
592 if chrome_root:
593 proto.chrome_root = chrome_root
594 if goma_config:
595 proto.goma_config = goma_config
596 return proto
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600597
Alex Klein1699fab2022-09-08 08:46:06 -0600598 def setUp(self):
599 self.chrome_path = "path/to/chrome"
600 self.sysroot_dir = "build/board"
601 self.build_target = "amd64"
602 self.mock_simple_chrome_workflow_test = self.PatchObject(
603 test_service, "SimpleChromeWorkflowTest"
604 )
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600605
Alex Klein1699fab2022-09-08 08:46:06 -0600606 def testMissingBuildTarget(self):
607 """Test SimpleChromeWorkflowTest dies when build_target not set."""
608 input_proto = self._Input(
609 build_target=None,
610 sysroot_path="/sysroot/dir",
611 chrome_root="/chrome/path",
612 )
613 with self.assertRaises(cros_build_lib.DieSystemExit):
614 test_controller.SimpleChromeWorkflowTest(
615 input_proto, None, self.api_config
616 )
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600617
Alex Klein1699fab2022-09-08 08:46:06 -0600618 def testMissingSysrootPath(self):
619 """Test SimpleChromeWorkflowTest dies when build_target not set."""
620 input_proto = self._Input(
621 build_target="board", sysroot_path=None, chrome_root="/chrome/path"
622 )
623 with self.assertRaises(cros_build_lib.DieSystemExit):
624 test_controller.SimpleChromeWorkflowTest(
625 input_proto, None, self.api_config
626 )
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600627
Alex Klein1699fab2022-09-08 08:46:06 -0600628 def testMissingChromeRoot(self):
629 """Test SimpleChromeWorkflowTest dies when build_target not set."""
630 input_proto = self._Input(
631 build_target="board", sysroot_path="/sysroot/dir", chrome_root=None
632 )
633 with self.assertRaises(cros_build_lib.DieSystemExit):
634 test_controller.SimpleChromeWorkflowTest(
635 input_proto, None, self.api_config
636 )
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600637
Alex Klein1699fab2022-09-08 08:46:06 -0600638 def testSimpleChromeWorkflowTest(self):
639 """Call SimpleChromeWorkflowTest with valid args and temp dir."""
640 request = self._Input(
641 sysroot_path="sysroot_path",
642 build_target="board",
643 chrome_root="/path/to/chrome",
644 )
645 response = self._Output()
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600646
Alex Klein1699fab2022-09-08 08:46:06 -0600647 test_controller.SimpleChromeWorkflowTest(
648 request, response, self.api_config
649 )
650 self.mock_simple_chrome_workflow_test.assert_called()
Michael Mortensen7a7646d2019-12-12 15:36:14 -0700651
Alex Klein1699fab2022-09-08 08:46:06 -0600652 def testValidateOnly(self):
653 request = self._Input(
654 sysroot_path="sysroot_path",
655 build_target="board",
656 chrome_root="/path/to/chrome",
657 )
658 test_controller.SimpleChromeWorkflowTest(
659 request, self._Output(), self.validate_only_config
660 )
661 self.mock_simple_chrome_workflow_test.assert_not_called()
662
663 def testMockCall(self):
664 """Test mock call does not execute any logic, returns success."""
665 patch = self.mock_simple_chrome_workflow_test = self.PatchObject(
666 test_service, "SimpleChromeWorkflowTest"
667 )
668
669 request = self._Input(
670 sysroot_path="sysroot_path",
671 build_target="board",
672 chrome_root="/path/to/chrome",
673 )
674 rc = test_controller.SimpleChromeWorkflowTest(
675 request, self._Output(), self.mock_call_config
676 )
677 patch.assert_not_called()
678 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
Michael Mortensen7a7646d2019-12-12 15:36:14 -0700679
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600680
Alex Klein231d2da2019-07-22 16:44:45 -0600681class VmTestTest(cros_test_lib.RunCommandTestCase, api_config.ApiConfigMixin):
Alex Klein1699fab2022-09-08 08:46:06 -0600682 """Test the VmTest endpoint."""
Evan Hernandez4e388a52019-05-01 12:16:33 -0600683
Alex Klein1699fab2022-09-08 08:46:06 -0600684 def _GetInput(self, **kwargs):
685 values = dict(
686 build_target=common_pb2.BuildTarget(name="target"),
687 vm_path=common_pb2.Path(
688 path="/path/to/image.bin", location=common_pb2.Path.INSIDE
689 ),
690 test_harness=test_pb2.VmTestRequest.TAST,
691 vm_tests=[test_pb2.VmTestRequest.VmTest(pattern="suite")],
692 ssh_options=test_pb2.VmTestRequest.SshOptions(
693 port=1234,
694 private_key_path={
695 "path": "/path/to/id_rsa",
696 "location": common_pb2.Path.INSIDE,
697 },
698 ),
699 )
700 values.update(kwargs)
701 return test_pb2.VmTestRequest(**values)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600702
Alex Klein1699fab2022-09-08 08:46:06 -0600703 def _Output(self):
704 return test_pb2.VmTestResponse()
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700705
Alex Klein1699fab2022-09-08 08:46:06 -0600706 def testValidateOnly(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700707 """Verify a validate-only call does not execute any logic."""
Alex Klein1699fab2022-09-08 08:46:06 -0600708 test_controller.VmTest(
709 self._GetInput(), None, self.validate_only_config
710 )
711 self.assertEqual(0, self.rc.call_count)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600712
Alex Klein1699fab2022-09-08 08:46:06 -0600713 def testMockCall(self):
714 """Test mock call does not execute any logic."""
715 patch = self.PatchObject(cros_build_lib, "run")
Michael Mortensen7a7646d2019-12-12 15:36:14 -0700716
Alex Klein1699fab2022-09-08 08:46:06 -0600717 request = self._GetInput()
718 response = self._Output()
Alex Kleinab87ceb2023-01-24 12:00:51 -0700719 # VmTest does not return a value, checking mocked value is flagged by
720 # lint.
Alex Klein1699fab2022-09-08 08:46:06 -0600721 test_controller.VmTest(request, response, self.mock_call_config)
722 patch.assert_not_called()
Michael Mortensen7a7646d2019-12-12 15:36:14 -0700723
Alex Klein1699fab2022-09-08 08:46:06 -0600724 def testTastAllOptions(self):
725 """Test VmTest for Tast with all options set."""
726 test_controller.VmTest(self._GetInput(), None, self.api_config)
727 self.assertCommandContains(
728 [
729 "cros_run_test",
730 "--debug",
731 "--no-display",
732 "--copy-on-write",
733 "--board",
734 "target",
735 "--image-path",
736 "/path/to/image.bin",
737 "--tast",
738 "suite",
739 "--ssh-port",
740 "1234",
741 "--private-key",
742 "/path/to/id_rsa",
743 ]
744 )
Evan Hernandez4e388a52019-05-01 12:16:33 -0600745
Alex Klein1699fab2022-09-08 08:46:06 -0600746 def testAutotestAllOptions(self):
747 """Test VmTest for Autotest with all options set."""
748 input_proto = self._GetInput(
749 test_harness=test_pb2.VmTestRequest.AUTOTEST
750 )
751 test_controller.VmTest(input_proto, None, self.api_config)
752 self.assertCommandContains(
753 [
754 "cros_run_test",
755 "--debug",
756 "--no-display",
757 "--copy-on-write",
758 "--board",
759 "target",
760 "--image-path",
761 "/path/to/image.bin",
762 "--autotest",
763 "suite",
764 "--ssh-port",
765 "1234",
766 "--private-key",
767 "/path/to/id_rsa",
768 "--test_that-args=--allow-chrome-crashes",
769 ]
770 )
Evan Hernandez4e388a52019-05-01 12:16:33 -0600771
Alex Klein1699fab2022-09-08 08:46:06 -0600772 def testMissingBuildTarget(self):
773 """Test VmTest dies when build_target not set."""
774 input_proto = self._GetInput(build_target=None)
775 with self.assertRaises(cros_build_lib.DieSystemExit):
776 test_controller.VmTest(input_proto, None, self.api_config)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600777
Alex Klein1699fab2022-09-08 08:46:06 -0600778 def testMissingVmImage(self):
779 """Test VmTest dies when vm_image not set."""
780 input_proto = self._GetInput(vm_path=None)
781 with self.assertRaises(cros_build_lib.DieSystemExit):
782 test_controller.VmTest(input_proto, None, self.api_config)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600783
Alex Klein1699fab2022-09-08 08:46:06 -0600784 def testMissingTestHarness(self):
785 """Test VmTest dies when test_harness not specified."""
786 input_proto = self._GetInput(
787 test_harness=test_pb2.VmTestRequest.UNSPECIFIED
788 )
789 with self.assertRaises(cros_build_lib.DieSystemExit):
790 test_controller.VmTest(input_proto, None, self.api_config)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600791
Alex Klein1699fab2022-09-08 08:46:06 -0600792 def testMissingVmTests(self):
793 """Test VmTest dies when vm_tests not set."""
794 input_proto = self._GetInput(vm_tests=[])
795 with self.assertRaises(cros_build_lib.DieSystemExit):
796 test_controller.VmTest(input_proto, None, self.api_config)
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600797
Alex Klein1699fab2022-09-08 08:46:06 -0600798 def testVmTest(self):
799 """Call VmTest with valid args and temp dir."""
800 request = self._GetInput()
801 response = self._Output()
802 patch = self.PatchObject(
803 cros_build_lib,
804 "run",
805 return_value=cros_build_lib.CompletedProcess(returncode=0),
806 )
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700807
Alex Klein1699fab2022-09-08 08:46:06 -0600808 test_controller.VmTest(request, response, self.api_config)
809 patch.assert_called()
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700810
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600811
David Wellingc1433c22021-06-25 16:29:48 +0000812class GetArtifactsTest(cros_test_lib.MockTempDirTestCase):
Alex Klein1699fab2022-09-08 08:46:06 -0600813 """Test GetArtifacts."""
David Wellingc1433c22021-06-25 16:29:48 +0000814
Alex Klein1699fab2022-09-08 08:46:06 -0600815 CODE_COVERAGE_LLVM_ARTIFACT_TYPE = (
816 common_pb2.ArtifactsByService.Test.ArtifactType.CODE_COVERAGE_LLVM_JSON
817 )
David Wellingc1433c22021-06-25 16:29:48 +0000818
Alex Kleinab87ceb2023-01-24 12:00:51 -0700819 # pylint: disable=line-too-long
Josiah Hounyode113e52022-11-30 06:30:33 +0000820 _artifact_funcs = {
821 common_pb2.ArtifactsByService.Test.ArtifactType.CODE_COVERAGE_LLVM_JSON: test_service.BundleCodeCoverageLlvmJson,
822 common_pb2.ArtifactsByService.Test.ArtifactType.CODE_COVERAGE_RUST_LLVM_JSON: test_service.BundleCodeCoverageRustLlvmJson,
823 common_pb2.ArtifactsByService.Test.ArtifactType.HWQUAL: test_service.BundleHwqualTarball,
824 common_pb2.ArtifactsByService.Test.ArtifactType.CODE_COVERAGE_GOLANG: test_service.BundleCodeCoverageGolang,
825 }
Alex Kleinab87ceb2023-01-24 12:00:51 -0700826 # pylint: enable=line-too-long
Josiah Hounyode113e52022-11-30 06:30:33 +0000827
Alex Klein1699fab2022-09-08 08:46:06 -0600828 def setUp(self):
829 """Set up the class for tests."""
830 chroot_dir = os.path.join(self.tempdir, "chroot")
831 osutils.SafeMakedirs(chroot_dir)
832 osutils.SafeMakedirs(os.path.join(chroot_dir, "tmp"))
833 self.chroot = chroot_lib.Chroot(chroot_dir)
David Wellingc1433c22021-06-25 16:29:48 +0000834
Alex Klein1699fab2022-09-08 08:46:06 -0600835 sysroot_path = os.path.join(chroot_dir, "build", "board")
836 osutils.SafeMakedirs(sysroot_path)
837 self.sysroot = sysroot_lib.Sysroot(sysroot_path)
David Wellingc1433c22021-06-25 16:29:48 +0000838
Alex Klein1699fab2022-09-08 08:46:06 -0600839 self.build_target = build_target_lib.BuildTarget("board")
Jack Neusc9707c32021-07-23 21:48:54 +0000840
Josiah Hounyode113e52022-11-30 06:30:33 +0000841 self._mocks = {}
842 for artifact, func in self._artifact_funcs.items():
843 self._mocks[artifact] = self.PatchObject(
844 test_service, func.__name__
845 )
846
847 def _InputProto(
848 self,
849 artifact_types=_artifact_funcs.keys(),
850 ):
851 """Helper to build an input proto instance."""
852 return common_pb2.ArtifactsByService.Test(
853 output_artifacts=[
854 common_pb2.ArtifactsByService.Test.ArtifactInfo(
855 artifact_types=artifact_types
856 )
857 ]
858 )
859
Alex Klein1699fab2022-09-08 08:46:06 -0600860 def testReturnsEmptyListWhenNoOutputArtifactsProvided(self):
861 """Test empty list is returned when there are no output_artifacts."""
862 result = test_controller.GetArtifacts(
863 common_pb2.ArtifactsByService.Test(output_artifacts=[]),
864 self.chroot,
865 self.sysroot,
866 self.build_target,
867 self.tempdir,
868 )
David Wellingc1433c22021-06-25 16:29:48 +0000869
Alex Klein1699fab2022-09-08 08:46:06 -0600870 self.assertEqual(len(result), 0)
David Wellingc1433c22021-06-25 16:29:48 +0000871
Alex Klein1699fab2022-09-08 08:46:06 -0600872 def testShouldCallBundleCodeCoverageLlvmJsonForEachValidArtifact(self):
873 """Test BundleCodeCoverageLlvmJson is called on each valid artifact."""
874 BundleCodeCoverageLlvmJson_mock = self.PatchObject(
875 test_service, "BundleCodeCoverageLlvmJson", return_value="test"
876 )
877
Alex Kleinab87ceb2023-01-24 12:00:51 -0700878 # pylint: disable=line-too-long
Alex Klein1699fab2022-09-08 08:46:06 -0600879 test_controller.GetArtifacts(
880 common_pb2.ArtifactsByService.Test(
881 output_artifacts=[
882 # Valid
883 common_pb2.ArtifactsByService.Test.ArtifactInfo(
884 artifact_types=[self.CODE_COVERAGE_LLVM_ARTIFACT_TYPE]
885 ),
886 # Invalid
887 common_pb2.ArtifactsByService.Test.ArtifactInfo(
888 artifact_types=[
889 common_pb2.ArtifactsByService.Test.ArtifactType.UNIT_TESTS
890 ]
891 ),
892 ]
893 ),
894 self.chroot,
895 self.sysroot,
896 self.build_target,
897 self.tempdir,
898 )
Alex Kleinab87ceb2023-01-24 12:00:51 -0700899 # pylint: enable=line-too-long
Alex Klein1699fab2022-09-08 08:46:06 -0600900
901 BundleCodeCoverageLlvmJson_mock.assert_called_once()
902
903 def testShouldReturnValidResult(self):
904 """Test result contains paths and code_coverage_llvm_json type."""
Sean McAllister17eed8d2021-09-21 10:41:16 -0600905 self.PatchObject(
Alex Klein1699fab2022-09-08 08:46:06 -0600906 test_service, "BundleCodeCoverageLlvmJson", return_value="test"
907 )
David Wellingc1433c22021-06-25 16:29:48 +0000908
Alex Klein1699fab2022-09-08 08:46:06 -0600909 result = test_controller.GetArtifacts(
910 common_pb2.ArtifactsByService.Test(
911 output_artifacts=[
912 # Valid
913 common_pb2.ArtifactsByService.Test.ArtifactInfo(
914 artifact_types=[self.CODE_COVERAGE_LLVM_ARTIFACT_TYPE]
915 ),
916 ]
917 ),
918 self.chroot,
919 self.sysroot,
920 self.build_target,
921 self.tempdir,
922 )
David Wellingc1433c22021-06-25 16:29:48 +0000923
Alex Klein1699fab2022-09-08 08:46:06 -0600924 self.assertEqual(result[0]["paths"], ["test"])
925 self.assertEqual(
926 result[0]["type"], self.CODE_COVERAGE_LLVM_ARTIFACT_TYPE
927 )
Josiah Hounyode113e52022-11-30 06:30:33 +0000928
929 def testNoArtifacts(self):
930 """Test GetArtifacts with no artifact types."""
931 in_proto = self._InputProto(artifact_types=[])
932 test_controller.GetArtifacts(
933 in_proto, None, None, self.build_target, ""
934 )
935
936 for _, patch in self._mocks.items():
937 patch.assert_not_called()
938
939 def testArtifactsSuccess(self):
940 """Test GetArtifacts with all artifact types."""
941 test_controller.GetArtifacts(
942 self._InputProto(), None, None, self.build_target, ""
943 )
944
945 for _, patch in self._mocks.items():
946 patch.assert_called_once()
947
948 def testArtifactsException(self):
Alex Kleinab87ceb2023-01-24 12:00:51 -0700949 """Test with all artifact types when one type throws an exception."""
Josiah Hounyode113e52022-11-30 06:30:33 +0000950
951 self._mocks[
952 common_pb2.ArtifactsByService.Test.ArtifactType.CODE_COVERAGE_GOLANG
953 ].side_effect = Exception("foo bar")
954 generated = test_controller.GetArtifacts(
955 self._InputProto(), None, None, self.build_target, ""
956 )
957
958 for _, patch in self._mocks.items():
959 patch.assert_called_once()
960
961 found_artifact = False
962 for data in generated:
963 artifact_type = (
964 common_pb2.ArtifactsByService.Test.ArtifactType.Name(
965 data["type"]
966 )
967 )
968 if artifact_type == "CODE_COVERAGE_GOLANG":
969 found_artifact = True
970 self.assertTrue(data["failed"])
971 self.assertEqual(data["failure_reason"], "foo bar")
972 self.assertTrue(found_artifact)