blob: 56de3c3d7e966a92300d9bfd3bb95fe9f8545304 [file] [log] [blame]
Alex Klein2966e302019-01-17 13:29:38 -07001# -*- coding: utf-8 -*-
2# Copyright 2019 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Image service tests."""
7
8from __future__ import print_function
9
10import os
11
Mike Frysinger6db648e2018-07-24 19:57:58 -040012import mock
13
Alex Klein231d2da2019-07-22 16:44:45 -060014from chromite.api import api_config
Alex Klein8cb365a2019-05-15 16:24:53 -060015from chromite.api import controller
16from chromite.api.controller import image as image_controller
Alex Klein7107bdd2019-03-14 17:14:31 -060017from chromite.api.gen.chromite.api import image_pb2
David Burger13e06be2019-05-13 20:33:16 -060018from chromite.api.gen.chromiumos import common_pb2
Alex Klein56355682019-02-07 10:36:54 -070019from chromite.lib import constants
Alex Klein4f0eb432019-05-02 13:56:04 -060020from chromite.lib import cros_build_lib
Alex Klein2966e302019-01-17 13:29:38 -070021from chromite.lib import cros_test_lib
Michael Mortensenc83c9952019-08-05 12:15:12 -060022from chromite.lib import image_lib
Alex Klein2966e302019-01-17 13:29:38 -070023from chromite.lib import osutils
Alex Kleinb7cdbe62019-02-22 11:41:32 -070024from chromite.service import image as image_service
Alex Klein2966e302019-01-17 13:29:38 -070025
26
Alex Klein231d2da2019-07-22 16:44:45 -060027class CreateTest(cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin):
Alex Klein56355682019-02-07 10:36:54 -070028 """Create image tests."""
29
Alex Klein231d2da2019-07-22 16:44:45 -060030 def setUp(self):
31 self.response = image_pb2.CreateImageResult()
32
Alex Klein21b95022019-05-09 14:14:46 -060033 def _GetRequest(self, board=None, types=None, version=None, builder_path=None,
34 disable_rootfs_verification=False):
35 """Helper to build a request instance."""
36 return image_pb2.CreateImageRequest(
37 build_target={'name': board},
38 image_types=types,
39 disable_rootfs_verification=disable_rootfs_verification,
40 version=version,
41 builder_path=builder_path,
42 )
43
Alex Klein231d2da2019-07-22 16:44:45 -060044 def testValidateOnly(self):
45 """Sanity check that a validate only call does not execute any logic."""
46 patch = self.PatchObject(image_service, 'Build')
Alex Klein21b95022019-05-09 14:14:46 -060047
Alex Klein231d2da2019-07-22 16:44:45 -060048 request = self._GetRequest(board='board')
49 image_controller.Create(request, self.response, self.validate_only_config)
50 patch.assert_not_called()
51
Michael Mortensen10146cf2019-11-19 19:59:22 -070052 def testMockCall(self):
53 """Test that mock call does not execute any logic, returns mocked value."""
54 patch = self.PatchObject(image_service, 'Build')
55
56 request = self._GetRequest(board='board')
57 image_controller.Create(request, self.response, self.mock_call_config)
58 patch.assert_not_called()
59 self.assertEqual(self.response.success, True)
60
Michael Mortensen85d38402019-12-12 09:50:29 -070061 def testMockError(self):
62 """Test that mock call does not execute any logic, returns error."""
63 patch = self.PatchObject(image_service, 'Build')
64
65 request = self._GetRequest(board='board')
66 rc = image_controller.Create(request, self.response, self.mock_error_config)
67 patch.assert_not_called()
68 self.assertEqual(controller.RETURN_CODE_COMPLETED_UNSUCCESSFULLY, rc)
69
Alex Klein231d2da2019-07-22 16:44:45 -060070 def testNoBoard(self):
71 """Test no board given fails."""
72 request = self._GetRequest()
Alex Klein56355682019-02-07 10:36:54 -070073
74 # No board should cause it to fail.
Alex Klein4f0eb432019-05-02 13:56:04 -060075 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -060076 image_controller.Create(request, self.response, self.api_config)
Alex Klein56355682019-02-07 10:36:54 -070077
Alex Klein21b95022019-05-09 14:14:46 -060078 def testNoTypeSpecified(self):
79 """Test the image type default."""
80 request = self._GetRequest(board='board')
Alex Klein21b95022019-05-09 14:14:46 -060081
Alex Klein1bcd9882019-03-19 13:25:24 -060082 # Failed result to avoid the success handling logic.
83 result = image_service.BuildResult(1, [])
84 build_patch = self.PatchObject(image_service, 'Build', return_value=result)
Alex Klein56355682019-02-07 10:36:54 -070085
Alex Klein231d2da2019-07-22 16:44:45 -060086 image_controller.Create(request, self.response, self.api_config)
Alex Klein56355682019-02-07 10:36:54 -070087 build_patch.assert_called_with(images=[constants.IMAGE_TYPE_BASE],
Alex Klein21b95022019-05-09 14:14:46 -060088 board='board', config=mock.ANY)
Alex Klein56355682019-02-07 10:36:54 -070089
Alex Klein21b95022019-05-09 14:14:46 -060090 def testSingleTypeSpecified(self):
91 """Test it's properly using a specified type."""
92 request = self._GetRequest(board='board', types=[common_pb2.DEV])
Alex Klein21b95022019-05-09 14:14:46 -060093
94 # Failed result to avoid the success handling logic.
95 result = image_service.BuildResult(1, [])
96 build_patch = self.PatchObject(image_service, 'Build', return_value=result)
97
Alex Klein231d2da2019-07-22 16:44:45 -060098 image_controller.Create(request, self.response, self.api_config)
Alex Klein56355682019-02-07 10:36:54 -070099 build_patch.assert_called_with(images=[constants.IMAGE_TYPE_DEV],
Alex Klein21b95022019-05-09 14:14:46 -0600100 board='board', config=mock.ANY)
Alex Klein56355682019-02-07 10:36:54 -0700101
Alex Klein21b95022019-05-09 14:14:46 -0600102 def testMultipleAndImpliedTypes(self):
103 """Test multiple types and implied type handling."""
104 # The TEST_VM type should force it to build the test image.
105 types = [common_pb2.BASE, common_pb2.TEST_VM]
106 expected_images = [constants.IMAGE_TYPE_BASE, constants.IMAGE_TYPE_TEST]
107
108 request = self._GetRequest(board='board', types=types)
Alex Klein21b95022019-05-09 14:14:46 -0600109
110 # Failed result to avoid the success handling logic.
111 result = image_service.BuildResult(1, [])
112 build_patch = self.PatchObject(image_service, 'Build', return_value=result)
113
Alex Klein231d2da2019-07-22 16:44:45 -0600114 image_controller.Create(request, self.response, self.api_config)
Alex Klein21b95022019-05-09 14:14:46 -0600115 build_patch.assert_called_with(images=expected_images, board='board',
Alex Klein56355682019-02-07 10:36:54 -0700116 config=mock.ANY)
117
Alex Klein1bcd9882019-03-19 13:25:24 -0600118 def testFailedPackageHandling(self):
119 """Test failed packages are populated correctly."""
120 result = image_service.BuildResult(1, ['foo/bar', 'cat/pkg'])
121 expected_packages = [('foo', 'bar'), ('cat', 'pkg')]
122 self.PatchObject(image_service, 'Build', return_value=result)
123
Alex Klein231d2da2019-07-22 16:44:45 -0600124 input_proto = self._GetRequest(board='board')
Alex Klein1bcd9882019-03-19 13:25:24 -0600125
Alex Klein231d2da2019-07-22 16:44:45 -0600126 rc = image_controller.Create(input_proto, self.response, self.api_config)
127
Alex Klein8cb365a2019-05-15 16:24:53 -0600128 self.assertEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
Alex Klein231d2da2019-07-22 16:44:45 -0600129 for package in self.response.failed_packages:
Alex Klein1bcd9882019-03-19 13:25:24 -0600130 self.assertIn((package.category, package.package_name), expected_packages)
131
Alex Klein2557b4f2019-07-11 14:34:00 -0600132 def testNoPackagesFailureHandling(self):
133 """Test failed packages are populated correctly."""
134 result = image_service.BuildResult(1, [])
135 self.PatchObject(image_service, 'Build', return_value=result)
Alex Kleinb7cdbe62019-02-22 11:41:32 -0700136
Alex Klein2557b4f2019-07-11 14:34:00 -0600137 input_proto = image_pb2.CreateImageRequest()
138 input_proto.build_target.name = 'board'
Alex Klein2557b4f2019-07-11 14:34:00 -0600139
Alex Klein231d2da2019-07-22 16:44:45 -0600140 rc = image_controller.Create(input_proto, self.response, self.api_config)
Alex Klein2557b4f2019-07-11 14:34:00 -0600141 self.assertTrue(rc)
142 self.assertNotEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE,
143 rc)
Alex Klein231d2da2019-07-22 16:44:45 -0600144 self.assertFalse(self.response.failed_packages)
Alex Klein2557b4f2019-07-11 14:34:00 -0600145
146
Alex Klein231d2da2019-07-22 16:44:45 -0600147class ImageSignerTestTest(cros_test_lib.MockTempDirTestCase,
148 api_config.ApiConfigMixin):
Michael Mortensenc83c9952019-08-05 12:15:12 -0600149 """Image signer test tests."""
150
151 def setUp(self):
152 self.image_path = os.path.join(self.tempdir, 'image.bin')
Michael Mortensenc83c9952019-08-05 12:15:12 -0600153 self.result_directory = os.path.join(self.tempdir, 'results')
154
155 osutils.SafeMakedirs(self.result_directory)
156 osutils.Touch(self.image_path)
157
Alex Klein231d2da2019-07-22 16:44:45 -0600158 def testValidateOnly(self):
159 """Sanity check that validate-only calls don't execute any logic."""
160 patch = self.PatchObject(image_lib, 'SecurityTest', return_value=True)
161 input_proto = image_pb2.TestImageRequest()
162 input_proto.image.path = self.image_path
163 output_proto = image_pb2.TestImageResult()
164
165 image_controller.SignerTest(input_proto, output_proto,
166 self.validate_only_config)
167
168 patch.assert_not_called()
169
Michael Mortensen10146cf2019-11-19 19:59:22 -0700170 def testMockCall(self):
171 """Test that mock call does not execute any logic, returns mocked value."""
172 patch = self.PatchObject(image_lib, 'SecurityTest', return_value=True)
173 input_proto = image_pb2.TestImageRequest()
174 input_proto.image.path = self.image_path
175 output_proto = image_pb2.TestImageResult()
176
177 image_controller.SignerTest(input_proto, output_proto,
178 self.mock_call_config)
179
180 patch.assert_not_called()
181 self.assertEqual(output_proto.success, True)
182
Michael Mortensen85d38402019-12-12 09:50:29 -0700183 def testMockError(self):
184 """Test that mock call does not execute any logic, returns error."""
185 patch = self.PatchObject(image_lib, 'SecurityTest', return_value=True)
186 input_proto = image_pb2.TestImageRequest()
187 input_proto.image.path = self.image_path
188 output_proto = image_pb2.TestImageResult()
189
190 rc = image_controller.SignerTest(input_proto, output_proto,
191 self.mock_error_config)
192
193 patch.assert_not_called()
194 self.assertEqual(controller.RETURN_CODE_COMPLETED_UNSUCCESSFULLY, rc)
195
Alex Klein231d2da2019-07-22 16:44:45 -0600196 def testSignerTestNoImage(self):
197 """Test function argument validation."""
Michael Mortensenc83c9952019-08-05 12:15:12 -0600198 input_proto = image_pb2.TestImageRequest()
199 output_proto = image_pb2.TestImageResult()
200
201 # Nothing provided.
202 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600203 image_controller.SignerTest(input_proto, output_proto, self.api_config)
Michael Mortensenc83c9952019-08-05 12:15:12 -0600204
Alex Klein231d2da2019-07-22 16:44:45 -0600205 def testSignerTestSuccess(self):
206 """Test successful call handling."""
207 self.PatchObject(image_lib, 'SecurityTest', return_value=True)
208 input_proto = image_pb2.TestImageRequest()
Michael Mortensenc83c9952019-08-05 12:15:12 -0600209 input_proto.image.path = self.image_path
Alex Klein231d2da2019-07-22 16:44:45 -0600210 output_proto = image_pb2.TestImageResult()
Michael Mortensenc83c9952019-08-05 12:15:12 -0600211
Alex Klein231d2da2019-07-22 16:44:45 -0600212 image_controller.SignerTest(input_proto, output_proto, self.api_config)
213
214 def testSignerTestFailure(self):
Michael Mortensenc83c9952019-08-05 12:15:12 -0600215 """Test function output tests."""
216 input_proto = image_pb2.TestImageRequest()
217 input_proto.image.path = self.image_path
Michael Mortensenc83c9952019-08-05 12:15:12 -0600218 output_proto = image_pb2.TestImageResult()
219
Michael Mortensenc83c9952019-08-05 12:15:12 -0600220 self.PatchObject(image_lib, 'SecurityTest', return_value=False)
Alex Klein231d2da2019-07-22 16:44:45 -0600221 image_controller.SignerTest(input_proto, output_proto, self.api_config)
Michael Mortensenc83c9952019-08-05 12:15:12 -0600222 self.assertFalse(output_proto.success)
223
Michael Mortensenc83c9952019-08-05 12:15:12 -0600224
Alex Klein231d2da2019-07-22 16:44:45 -0600225class ImageTestTest(cros_test_lib.MockTempDirTestCase,
226 api_config.ApiConfigMixin):
Alex Klein2557b4f2019-07-11 14:34:00 -0600227 """Image test tests."""
Alex Klein2966e302019-01-17 13:29:38 -0700228
229 def setUp(self):
230 self.image_path = os.path.join(self.tempdir, 'image.bin')
231 self.board = 'board'
232 self.result_directory = os.path.join(self.tempdir, 'results')
233
234 osutils.SafeMakedirs(self.result_directory)
235 osutils.Touch(self.image_path)
236
Alex Klein231d2da2019-07-22 16:44:45 -0600237 def testValidateOnly(self):
238 """Sanity check that a validate only call does not execute any logic."""
239 patch = self.PatchObject(image_service, 'Test')
240
241 input_proto = image_pb2.TestImageRequest()
242 input_proto.image.path = self.image_path
243 input_proto.build_target.name = self.board
244 input_proto.result.directory = self.result_directory
245 output_proto = image_pb2.TestImageResult()
246
247 image_controller.Test(input_proto, output_proto, self.validate_only_config)
248 patch.assert_not_called()
249
Michael Mortensen10146cf2019-11-19 19:59:22 -0700250 def testMockCall(self):
251 """Test that mock call does not execute any logic, returns mocked value."""
252 patch = self.PatchObject(image_service, 'Test')
253
254 input_proto = image_pb2.TestImageRequest()
255 input_proto.image.path = self.image_path
256 input_proto.build_target.name = self.board
257 input_proto.result.directory = self.result_directory
258 output_proto = image_pb2.TestImageResult()
259
260 image_controller.Test(input_proto, output_proto, self.mock_call_config)
261 patch.assert_not_called()
262 self.assertEqual(output_proto.success, True)
263
Michael Mortensen85d38402019-12-12 09:50:29 -0700264 def testMockError(self):
265 """Test that mock call does not execute any logic, returns error."""
266 patch = self.PatchObject(image_service, 'Test')
267
268 input_proto = image_pb2.TestImageRequest()
269 input_proto.image.path = self.image_path
270 input_proto.build_target.name = self.board
271 input_proto.result.directory = self.result_directory
272 output_proto = image_pb2.TestImageResult()
273
274 rc = image_controller.Test(input_proto, output_proto,
275 self.mock_error_config)
276 patch.assert_not_called()
277 self.assertEqual(controller.RETURN_CODE_COMPLETED_UNSUCCESSFULLY, rc)
278
Alex Klein2966e302019-01-17 13:29:38 -0700279 def testTestArgumentValidation(self):
280 """Test function argument validation tests."""
Alex Kleinb7cdbe62019-02-22 11:41:32 -0700281 self.PatchObject(image_service, 'Test', return_value=True)
Alex Klein2966e302019-01-17 13:29:38 -0700282 input_proto = image_pb2.TestImageRequest()
283 output_proto = image_pb2.TestImageResult()
284
285 # Nothing provided.
Alex Klein4f0eb432019-05-02 13:56:04 -0600286 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600287 image_controller.Test(input_proto, output_proto, self.api_config)
Alex Klein2966e302019-01-17 13:29:38 -0700288
289 # Just one argument.
290 input_proto.build_target.name = self.board
Alex Klein4f0eb432019-05-02 13:56:04 -0600291 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600292 image_controller.Test(input_proto, output_proto, self.api_config)
Alex Klein2966e302019-01-17 13:29:38 -0700293
294 # Two arguments provided.
295 input_proto.result.directory = self.result_directory
Alex Klein4f0eb432019-05-02 13:56:04 -0600296 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600297 image_controller.Test(input_proto, output_proto, self.api_config)
Alex Klein2966e302019-01-17 13:29:38 -0700298
299 # Invalid image path.
300 input_proto.image.path = '/invalid/image/path'
Alex Klein4f0eb432019-05-02 13:56:04 -0600301 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600302 image_controller.Test(input_proto, output_proto, self.api_config)
Alex Klein2966e302019-01-17 13:29:38 -0700303
304 # All valid arguments.
305 input_proto.image.path = self.image_path
Alex Klein231d2da2019-07-22 16:44:45 -0600306 image_controller.Test(input_proto, output_proto, self.api_config)
Alex Klein2966e302019-01-17 13:29:38 -0700307
308 def testTestOutputHandling(self):
309 """Test function output tests."""
310 input_proto = image_pb2.TestImageRequest()
311 input_proto.image.path = self.image_path
312 input_proto.build_target.name = self.board
313 input_proto.result.directory = self.result_directory
314 output_proto = image_pb2.TestImageResult()
315
Alex Kleinb7cdbe62019-02-22 11:41:32 -0700316 self.PatchObject(image_service, 'Test', return_value=True)
Alex Klein231d2da2019-07-22 16:44:45 -0600317 image_controller.Test(input_proto, output_proto, self.api_config)
Alex Klein2966e302019-01-17 13:29:38 -0700318 self.assertTrue(output_proto.success)
319
Alex Kleinb7cdbe62019-02-22 11:41:32 -0700320 self.PatchObject(image_service, 'Test', return_value=False)
Alex Klein231d2da2019-07-22 16:44:45 -0600321 image_controller.Test(input_proto, output_proto, self.api_config)
Alex Klein2966e302019-01-17 13:29:38 -0700322 self.assertFalse(output_proto.success)