Mike Frysinger | f1ba7ad | 2022-09-12 05:42:57 -0400 | [diff] [blame] | 1 | # Copyright 2019 The ChromiumOS Authors |
George Engelbrecht | fe63c8c | 2019-08-31 22:51:29 -0600 | [diff] [blame] | 2 | # 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 Engelbrecht | fe63c8c | 2019-08-31 22:51:29 -0600 | [diff] [blame] | 7 | from chromite.api import api_config |
| 8 | from chromite.api import controller |
| 9 | from chromite.api.controller import payload |
| 10 | from chromite.api.gen.chromite.api import payload_pb2 |
| 11 | from chromite.api.gen.chromiumos import common_pb2 |
Jack Neus | aeb58a4 | 2023-09-26 21:05:20 +0000 | [diff] [blame^] | 12 | from chromite.lib import cros_build_lib |
George Engelbrecht | fe63c8c | 2019-08-31 22:51:29 -0600 | [diff] [blame] | 13 | from chromite.lib import cros_test_lib |
| 14 | from chromite.lib.paygen import paygen_payload_lib |
| 15 | |
| 16 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 17 | class PayloadApiTests( |
| 18 | cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin |
| 19 | ): |
| 20 | """Unittests for PayloadApi.""" |
George Engelbrecht | fe63c8c | 2019-08-31 22:51:29 -0600 | [diff] [blame] | 21 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 22 | def setUp(self): |
| 23 | self.response = payload_pb2.GenerationResponse() |
George Engelbrecht | fe63c8c | 2019-08-31 22:51:29 -0600 | [diff] [blame] | 24 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 25 | 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 Engelbrecht | fe63c8c | 2019-08-31 22:51:29 -0600 | [diff] [blame] | 31 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 32 | src_image = payload_pb2.UnsignedImage( |
| 33 | build=src_build, image_type=6, milestone="R70" |
| 34 | ) |
George Engelbrecht | fe63c8c | 2019-08-31 22:51:29 -0600 | [diff] [blame] | 35 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 36 | 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 Engelbrecht | fe63c8c | 2019-08-31 22:51:29 -0600 | [diff] [blame] | 42 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 43 | tgt_image = payload_pb2.UnsignedImage( |
| 44 | build=tgt_build, image_type=6, milestone="R70" |
| 45 | ) |
George Engelbrecht | fe63c8c | 2019-08-31 22:51:29 -0600 | [diff] [blame] | 46 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 47 | 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 Norris | 351745f | 2023-08-25 15:23:38 -0700 | [diff] [blame] | 54 | 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 Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 60 | ) |
George Engelbrecht | fe63c8c | 2019-08-31 22:51:29 -0600 | [diff] [blame] | 61 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 62 | 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 Norris | 351745f | 2023-08-25 15:23:38 -0700 | [diff] [blame] | 70 | 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 Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 76 | ) |
Greg Edelston | 629468c | 2022-02-11 14:54:56 -0700 | [diff] [blame] | 77 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 78 | self.result = payload_pb2.GenerationResponse( |
Benjamin Shai | 3c1a232 | 2023-02-10 17:29:46 +0000 | [diff] [blame] | 79 | versioned_artifacts=[ |
| 80 | payload_pb2.GenerationResponse.VersionedArtifact( |
| 81 | version=1, |
Brian Norris | 351745f | 2023-08-25 15:23:38 -0700 | [diff] [blame] | 82 | file_path=common_pb2.Path( |
| 83 | path="/tmp/aohiwdadoi/delta.bin", |
| 84 | location=common_pb2.Path.INSIDE, |
| 85 | ), |
Benjamin Shai | 3c1a232 | 2023-02-10 17:29:46 +0000 | [diff] [blame] | 86 | remote_uri="gs://something", |
| 87 | ) |
| 88 | ] |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 89 | ) |
George Engelbrecht | fe63c8c | 2019-08-31 22:51:29 -0600 | [diff] [blame] | 90 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 91 | self.PatchObject( |
| 92 | payload, "_DEFAULT_PAYGEN_CACHE_DIR", new=str(self.tempdir) |
| 93 | ) |
Alex Klein | c07a48b | 2022-08-26 15:58:44 -0600 | [diff] [blame] | 94 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 95 | def testValidateOnly(self): |
| 96 | """Basic check that a validate only call does not execute any logic.""" |
George Engelbrecht | fe63c8c | 2019-08-31 22:51:29 -0600 | [diff] [blame] | 97 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 98 | res = payload.GeneratePayload( |
| 99 | self.req, self.result, self.validate_only_config |
| 100 | ) |
| 101 | self.assertEqual(res, controller.RETURN_CODE_VALID_INPUT) |
George Engelbrecht | fe63c8c | 2019-08-31 22:51:29 -0600 | [diff] [blame] | 102 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 103 | 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 Kim | e70c603 | 2023-02-10 02:56:36 +0000 | [diff] [blame] | 107 | patch_obj.return_value.Run.return_value = { |
Benjamin Shai | 3c1a232 | 2023-02-10 17:29:46 +0000 | [diff] [blame] | 108 | 1: ("/tmp/aohiwdadoi/delta.bin", "gs://something") |
Jae Hoon Kim | e70c603 | 2023-02-10 02:56:36 +0000 | [diff] [blame] | 109 | } |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 110 | res = payload.GeneratePayload(self.req, self.result, self.api_config) |
| 111 | self.assertEqual(res, controller.RETURN_CODE_SUCCESS) |
Michael Mortensen | 85d3840 | 2019-12-12 09:50:29 -0700 | [diff] [blame] | 112 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 113 | def testMockError(self): |
| 114 | """Test mock error call does not execute any logic, returns error.""" |
| 115 | patch = self.PatchObject(paygen_payload_lib, "PaygenPayload") |
Michael Mortensen | 85d3840 | 2019-12-12 09:50:29 -0700 | [diff] [blame] | 116 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 117 | 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 Mortensen | 85d3840 | 2019-12-12 09:50:29 -0700 | [diff] [blame] | 122 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 123 | def testMockCall(self): |
| 124 | """Test mock call does not execute any logic, returns success.""" |
| 125 | patch = self.PatchObject(paygen_payload_lib, "PaygenPayload") |
Michael Mortensen | 85d3840 | 2019-12-12 09:50:29 -0700 | [diff] [blame] | 126 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 127 | 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 Edelston | 629468c | 2022-02-11 14:54:56 -0700 | [diff] [blame] | 132 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 133 | def testMiniOSSuccess(self): |
| 134 | """Test a miniOS paygen request.""" |
| 135 | patch = self.PatchObject(paygen_payload_lib, "PaygenPayload") |
Jae Hoon Kim | e70c603 | 2023-02-10 02:56:36 +0000 | [diff] [blame] | 136 | patch.return_value.Run.return_value = { |
Benjamin Shai | 3c1a232 | 2023-02-10 17:29:46 +0000 | [diff] [blame] | 137 | 1: ("/tmp/aohiwdadoi/delta.bin", "gs://minios/something") |
Jae Hoon Kim | e70c603 | 2023-02-10 02:56:36 +0000 | [diff] [blame] | 138 | } |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 139 | res = payload.GeneratePayload( |
| 140 | self.minios_req, self.result, self.api_config |
| 141 | ) |
| 142 | self.assertEqual(res, controller.RETURN_CODE_SUCCESS) |
Greg Edelston | 629468c | 2022-02-11 14:54:56 -0700 | [diff] [blame] | 143 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 144 | 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 Neus | 2577e2d | 2023-04-06 16:14:01 +0000 | [diff] [blame] | 159 | |
| 160 | def testNoMiniOSPartitionMismatch(self): |
| 161 | """Test a miniOS paygen request with a partition count mismatch.""" |
| 162 | patch = self.PatchObject(paygen_payload_lib, "PaygenPayload") |
Greg Edelston | bccc22f | 2023-08-14 10:01:34 -0600 | [diff] [blame] | 163 | patch.side_effect = paygen_payload_lib.MiniOSPartitionMismatchException |
Jack Neus | 2577e2d | 2023-04-06 16:14:01 +0000 | [diff] [blame] | 164 | 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 Neus | aeb58a4 | 2023-09-26 21:05:20 +0000 | [diff] [blame^] | 175 | |
| 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) |