blob: ef58e9c93e6cb67f9a3aaec5cb7e9eb92c81c3f2 [file] [log] [blame]
Mike Frysingerf1ba7ad2022-09-12 05:42:57 -04001# Copyright 2019 The ChromiumOS Authors
George Engelbrechtfe63c8c2019-08-31 22:51:29 -06002# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Payload operations."""
6
George Engelbrechtfe63c8c2019-08-31 22:51:29 -06007from chromite.api import api_config
8from chromite.api import controller
9from chromite.api.controller import payload
10from chromite.api.gen.chromite.api import payload_pb2
11from chromite.api.gen.chromiumos import common_pb2
Jack Neusaeb58a42023-09-26 21:05:20 +000012from chromite.lib import cros_build_lib
George Engelbrechtfe63c8c2019-08-31 22:51:29 -060013from chromite.lib import cros_test_lib
14from chromite.lib.paygen import paygen_payload_lib
15
16
Alex Klein1699fab2022-09-08 08:46:06 -060017class PayloadApiTests(
18 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin
19):
20 """Unittests for PayloadApi."""
George Engelbrechtfe63c8c2019-08-31 22:51:29 -060021
Alex Klein1699fab2022-09-08 08:46:06 -060022 def setUp(self):
23 self.response = payload_pb2.GenerationResponse()
George Engelbrechtfe63c8c2019-08-31 22:51:29 -060024
Alex Klein1699fab2022-09-08 08:46:06 -060025 src_build = payload_pb2.Build(
26 version="1.0.0",
27 bucket="test",
28 channel="test-channel",
29 build_target=common_pb2.BuildTarget(name="cave"),
30 )
George Engelbrechtfe63c8c2019-08-31 22:51:29 -060031
Alex Klein1699fab2022-09-08 08:46:06 -060032 src_image = payload_pb2.UnsignedImage(
33 build=src_build, image_type=6, milestone="R70"
34 )
George Engelbrechtfe63c8c2019-08-31 22:51:29 -060035
Alex Klein1699fab2022-09-08 08:46:06 -060036 tgt_build = payload_pb2.Build(
37 version="2.0.0",
38 bucket="test",
39 channel="test-channel",
40 build_target=common_pb2.BuildTarget(name="cave"),
41 )
George Engelbrechtfe63c8c2019-08-31 22:51:29 -060042
Alex Klein1699fab2022-09-08 08:46:06 -060043 tgt_image = payload_pb2.UnsignedImage(
44 build=tgt_build, image_type=6, milestone="R70"
45 )
George Engelbrechtfe63c8c2019-08-31 22:51:29 -060046
Alex Klein1699fab2022-09-08 08:46:06 -060047 self.req = payload_pb2.GenerationRequest(
48 tgt_unsigned_image=tgt_image,
49 src_unsigned_image=src_image,
50 bucket="test-destination-bucket",
51 verify=True,
52 keyset="update_signer",
53 dryrun=False,
Brian Norris351745f2023-08-25 15:23:38 -070054 result_path=common_pb2.ResultPath(
55 path=common_pb2.Path(
56 path=str(self.tempdir / "results"),
57 location=common_pb2.Path.OUTSIDE,
58 )
59 ),
Alex Klein1699fab2022-09-08 08:46:06 -060060 )
George Engelbrechtfe63c8c2019-08-31 22:51:29 -060061
Alex Klein1699fab2022-09-08 08:46:06 -060062 self.minios_req = payload_pb2.GenerationRequest(
63 tgt_unsigned_image=tgt_image,
64 src_unsigned_image=src_image,
65 bucket="test-destination-bucket",
66 minios=True,
67 verify=True,
68 keyset="update_signer",
69 dryrun=False,
Brian Norris351745f2023-08-25 15:23:38 -070070 result_path=common_pb2.ResultPath(
71 path=common_pb2.Path(
72 path=str(self.tempdir / "results"),
73 location=common_pb2.Path.OUTSIDE,
74 )
75 ),
Alex Klein1699fab2022-09-08 08:46:06 -060076 )
Greg Edelston629468c2022-02-11 14:54:56 -070077
Alex Klein1699fab2022-09-08 08:46:06 -060078 self.result = payload_pb2.GenerationResponse(
Benjamin Shai3c1a2322023-02-10 17:29:46 +000079 versioned_artifacts=[
80 payload_pb2.GenerationResponse.VersionedArtifact(
81 version=1,
Brian Norris351745f2023-08-25 15:23:38 -070082 file_path=common_pb2.Path(
83 path="/tmp/aohiwdadoi/delta.bin",
84 location=common_pb2.Path.INSIDE,
85 ),
Benjamin Shai3c1a2322023-02-10 17:29:46 +000086 remote_uri="gs://something",
87 )
88 ]
Alex Klein1699fab2022-09-08 08:46:06 -060089 )
George Engelbrechtfe63c8c2019-08-31 22:51:29 -060090
Alex Klein1699fab2022-09-08 08:46:06 -060091 self.PatchObject(
92 payload, "_DEFAULT_PAYGEN_CACHE_DIR", new=str(self.tempdir)
93 )
Alex Kleinc07a48b2022-08-26 15:58:44 -060094
Alex Klein1699fab2022-09-08 08:46:06 -060095 def testValidateOnly(self):
96 """Basic check that a validate only call does not execute any logic."""
George Engelbrechtfe63c8c2019-08-31 22:51:29 -060097
Alex Klein1699fab2022-09-08 08:46:06 -060098 res = payload.GeneratePayload(
99 self.req, self.result, self.validate_only_config
100 )
101 self.assertEqual(res, controller.RETURN_CODE_VALID_INPUT)
George Engelbrechtfe63c8c2019-08-31 22:51:29 -0600102
Alex Klein1699fab2022-09-08 08:46:06 -0600103 def testCallSucceeds(self):
104 """Check that a call is made successfully."""
105 # Deep patch the paygen lib, this is a full run through service as well.
106 patch_obj = self.PatchObject(paygen_payload_lib, "PaygenPayload")
Jae Hoon Kime70c6032023-02-10 02:56:36 +0000107 patch_obj.return_value.Run.return_value = {
Benjamin Shai3c1a2322023-02-10 17:29:46 +0000108 1: ("/tmp/aohiwdadoi/delta.bin", "gs://something")
Jae Hoon Kime70c6032023-02-10 02:56:36 +0000109 }
Alex Klein1699fab2022-09-08 08:46:06 -0600110 res = payload.GeneratePayload(self.req, self.result, self.api_config)
111 self.assertEqual(res, controller.RETURN_CODE_SUCCESS)
Michael Mortensen85d38402019-12-12 09:50:29 -0700112
Alex Klein1699fab2022-09-08 08:46:06 -0600113 def testMockError(self):
114 """Test mock error call does not execute any logic, returns error."""
115 patch = self.PatchObject(paygen_payload_lib, "PaygenPayload")
Michael Mortensen85d38402019-12-12 09:50:29 -0700116
Alex Klein1699fab2022-09-08 08:46:06 -0600117 res = payload.GeneratePayload(
118 self.req, self.result, self.mock_error_config
119 )
120 patch.assert_not_called()
121 self.assertEqual(controller.RETURN_CODE_COMPLETED_UNSUCCESSFULLY, res)
Michael Mortensen85d38402019-12-12 09:50:29 -0700122
Alex Klein1699fab2022-09-08 08:46:06 -0600123 def testMockCall(self):
124 """Test mock call does not execute any logic, returns success."""
125 patch = self.PatchObject(paygen_payload_lib, "PaygenPayload")
Michael Mortensen85d38402019-12-12 09:50:29 -0700126
Alex Klein1699fab2022-09-08 08:46:06 -0600127 res = payload.GeneratePayload(
128 self.req, self.result, self.mock_call_config
129 )
130 patch.assert_not_called()
131 self.assertEqual(controller.RETURN_CODE_SUCCESS, res)
Greg Edelston629468c2022-02-11 14:54:56 -0700132
Alex Klein1699fab2022-09-08 08:46:06 -0600133 def testMiniOSSuccess(self):
134 """Test a miniOS paygen request."""
135 patch = self.PatchObject(paygen_payload_lib, "PaygenPayload")
Jae Hoon Kime70c6032023-02-10 02:56:36 +0000136 patch.return_value.Run.return_value = {
Benjamin Shai3c1a2322023-02-10 17:29:46 +0000137 1: ("/tmp/aohiwdadoi/delta.bin", "gs://minios/something")
Jae Hoon Kime70c6032023-02-10 02:56:36 +0000138 }
Alex Klein1699fab2022-09-08 08:46:06 -0600139 res = payload.GeneratePayload(
140 self.minios_req, self.result, self.api_config
141 )
142 self.assertEqual(res, controller.RETURN_CODE_SUCCESS)
Greg Edelston629468c2022-02-11 14:54:56 -0700143
Alex Klein1699fab2022-09-08 08:46:06 -0600144 def testNoMiniOSPartition(self):
145 """Test a miniOS paygen request on an image with no miniOS part."""
146 patch = self.PatchObject(paygen_payload_lib, "PaygenPayload")
147 patch.side_effect = paygen_payload_lib.NoMiniOSPartitionException
148 response_code = payload.GeneratePayload(
149 self.minios_req, self.result, self.api_config
150 )
151 self.assertEqual(
152 self.result.failure_reason,
153 payload_pb2.GenerationResponse.NOT_MINIOS_COMPATIBLE,
154 )
155 self.assertEqual(
156 response_code,
157 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE,
158 )
Jack Neus2577e2d2023-04-06 16:14:01 +0000159
160 def testNoMiniOSPartitionMismatch(self):
161 """Test a miniOS paygen request with a partition count mismatch."""
162 patch = self.PatchObject(paygen_payload_lib, "PaygenPayload")
Greg Edelstonbccc22f2023-08-14 10:01:34 -0600163 patch.side_effect = paygen_payload_lib.MiniOSPartitionMismatchException
Jack Neus2577e2d2023-04-06 16:14:01 +0000164 response_code = payload.GeneratePayload(
165 self.minios_req, self.result, self.api_config
166 )
167 self.assertEqual(
168 self.result.failure_reason,
169 payload_pb2.GenerationResponse.MINIOS_COUNT_MISMATCH,
170 )
171 self.assertEqual(
172 response_code,
173 controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE,
174 )
Jack Neusaeb58a42023-09-26 21:05:20 +0000175
176 def testLocalSigningSuccess(self):
177 """Test a local signing paygen request."""
178 patch = self.PatchObject(paygen_payload_lib, "PaygenPayload")
179 patch.return_value.Run.return_value = {
180 1: ("/tmp/aohiwdadoi/delta.bin", "gs://minios/something")
181 }
182
183 req = self.req
184 req.use_local_signing = True
185 req.docker_image = (
186 "us-docker.pkg.dev/chromeos-bot/signing/signing:16963491"
187 )
188
189 res = payload.GeneratePayload(self.req, self.result, self.api_config)
190 self.assertEqual(res, controller.RETURN_CODE_SUCCESS)
191
192 def testLocalSigningFailure(self):
193 """Test a local signing paygen request."""
194 patch = self.PatchObject(paygen_payload_lib, "PaygenPayload")
195 patch.return_value.Run.return_value = {
196 1: ("/tmp/aohiwdadoi/delta.bin", "gs://minios/something")
197 }
198
199 req = self.req
200 req.use_local_signing = True
201
202 # No docker image, will fail.
203 with self.assertRaises(cros_build_lib.DieSystemExit):
204 payload.GeneratePayload(self.req, self.result, self.api_config)