blob: 433e2254c39b69181a346800b2e7b7abc0f26516 [file] [log] [blame]
Evan Hernandezf388cbf2019-04-01 11:15:23 -06001# -*- 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"""Unittests for Artifacts operations."""
7
8from __future__ import print_function
9
10import mock
11import os
12
Alex Klein231d2da2019-07-22 16:44:45 -060013from chromite.api import api_config
Evan Hernandezf388cbf2019-04-01 11:15:23 -060014from chromite.api.controller import artifacts
15from chromite.api.gen.chromite.api import artifacts_pb2
16from chromite.cbuildbot import commands
Alex Kleinb9d810b2019-07-01 12:38:02 -060017from chromite.lib import chroot_lib
Evan Hernandezf388cbf2019-04-01 11:15:23 -060018from chromite.lib import constants
19from chromite.lib import cros_build_lib
20from chromite.lib import cros_test_lib
21from chromite.lib import osutils
Alex Klein238d8862019-05-07 11:32:46 -060022from chromite.lib import sysroot_lib
Alex Klein2275d692019-04-23 16:04:12 -060023from chromite.service import artifacts as artifacts_svc
Evan Hernandezf388cbf2019-04-01 11:15:23 -060024
25
Alex Klein231d2da2019-07-22 16:44:45 -060026class BundleTestCase(cros_test_lib.MockTempDirTestCase,
27 api_config.ApiConfigMixin):
Evan Hernandezf388cbf2019-04-01 11:15:23 -060028 """Basic setup for all artifacts unittests."""
29
30 def setUp(self):
Alex Klein231d2da2019-07-22 16:44:45 -060031 self.output_dir = os.path.join(self.tempdir, 'artifacts')
32 osutils.SafeMakedirs(self.output_dir)
33 self.sysroot_path = '/build/target'
34 self.chroot_path = os.path.join(self.tempdir, 'chroot')
35 full_sysroot_path = os.path.join(self.chroot_path,
36 self.sysroot_path.lstrip(os.sep))
37 osutils.SafeMakedirs(full_sysroot_path)
38
39 # Legacy call.
Evan Hernandezf388cbf2019-04-01 11:15:23 -060040 self.input_proto = artifacts_pb2.BundleRequest()
41 self.input_proto.build_target.name = 'target'
Alex Klein231d2da2019-07-22 16:44:45 -060042 self.input_proto.output_dir = self.output_dir
Evan Hernandezf388cbf2019-04-01 11:15:23 -060043 self.output_proto = artifacts_pb2.BundleResponse()
44
Alex Klein231d2da2019-07-22 16:44:45 -060045 # New call format.
46 self.request = artifacts_pb2.BundleRequest()
47 self.request.chroot.path = self.chroot_path
48 self.request.sysroot.path = self.sysroot_path
49 self.request.output_dir = self.output_dir
50 self.response = artifacts_pb2.BundleResponse()
51
52 self.source_root = self.tempdir
53 self.PatchObject(constants, 'SOURCE_ROOT', new=self.tempdir)
Evan Hernandezf388cbf2019-04-01 11:15:23 -060054
55
Alex Klein231d2da2019-07-22 16:44:45 -060056class BundleTempDirTestCase(cros_test_lib.MockTempDirTestCase,
57 api_config.ApiConfigMixin):
Alex Klein238d8862019-05-07 11:32:46 -060058 """Basic setup for artifacts unittests that need a tempdir."""
59
60 def _GetRequest(self, chroot=None, sysroot=None, build_target=None,
61 output_dir=None):
62 """Helper to create a request message instance.
63
64 Args:
65 chroot (str): The chroot path.
66 sysroot (str): The sysroot path.
67 build_target (str): The build target name.
68 output_dir (str): The output directory.
69 """
70 return artifacts_pb2.BundleRequest(
71 sysroot={'path': sysroot, 'build_target': {'name': build_target}},
72 chroot={'path': chroot}, output_dir=output_dir)
73
Alex Klein238d8862019-05-07 11:32:46 -060074 def setUp(self):
75 self.output_dir = os.path.join(self.tempdir, 'artifacts')
76 osutils.SafeMakedirs(self.output_dir)
77
78 # Old style paths.
79 self.old_sysroot_path = os.path.join(self.tempdir, 'cros', 'chroot',
80 'build', 'target')
81 self.old_sysroot = sysroot_lib.Sysroot(self.old_sysroot_path)
82 osutils.SafeMakedirs(self.old_sysroot_path)
83
84 # Old style proto.
85 self.input_proto = artifacts_pb2.BundleRequest()
86 self.input_proto.build_target.name = 'target'
87 self.input_proto.output_dir = self.output_dir
88 self.output_proto = artifacts_pb2.BundleResponse()
89
90 source_root = os.path.join(self.tempdir, 'cros')
91 self.PatchObject(constants, 'SOURCE_ROOT', new=source_root)
92
93 # New style paths.
94 self.chroot_path = os.path.join(self.tempdir, 'cros', 'chroot')
95 self.sysroot_path = '/build/target'
96 self.full_sysroot_path = os.path.join(self.chroot_path,
97 self.sysroot_path.lstrip(os.sep))
98 self.sysroot = sysroot_lib.Sysroot(self.full_sysroot_path)
99 osutils.SafeMakedirs(self.full_sysroot_path)
100
101 # New style proto.
102 self.request = artifacts_pb2.BundleRequest()
103 self.request.output_dir = self.output_dir
104 self.request.chroot.path = self.chroot_path
105 self.request.sysroot.path = self.sysroot_path
106 self.response = artifacts_pb2.BundleResponse()
107
108
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600109class BundleImageZipTest(BundleTestCase):
110 """Unittests for BundleImageZip."""
111
Alex Klein231d2da2019-07-22 16:44:45 -0600112 def testValidateOnly(self):
113 """Sanity check that a validate only call does not execute any logic."""
114 patch = self.PatchObject(commands, 'BuildImageZip')
115 artifacts.BundleImageZip(self.input_proto, self.output_proto,
116 self.validate_only_config)
117 patch.assert_not_called()
118
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600119 def testBundleImageZip(self):
120 """BundleImageZip calls cbuildbot/commands with correct args."""
Michael Mortensen01910922019-07-24 14:48:10 -0600121 bundle_image_zip = self.PatchObject(
122 artifacts_svc, 'BundleImageZip', return_value='image.zip')
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600123 self.PatchObject(os.path, 'exists', return_value=True)
Alex Klein231d2da2019-07-22 16:44:45 -0600124 artifacts.BundleImageZip(self.input_proto, self.output_proto,
125 self.api_config)
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600126 self.assertEqual(
127 [artifact.path for artifact in self.output_proto.artifacts],
Alex Klein231d2da2019-07-22 16:44:45 -0600128 [os.path.join(self.output_dir, 'image.zip')])
129
130 latest = os.path.join(self.source_root, 'src/build/images/target/latest')
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600131 self.assertEqual(
Michael Mortensen01910922019-07-24 14:48:10 -0600132 bundle_image_zip.call_args_list,
Alex Klein231d2da2019-07-22 16:44:45 -0600133 [mock.call(self.output_dir, latest)])
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600134
135 def testBundleImageZipNoImageDir(self):
136 """BundleImageZip dies when image dir does not exist."""
137 self.PatchObject(os.path, 'exists', return_value=False)
138 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600139 artifacts.BundleImageZip(self.input_proto, self.output_proto,
140 self.api_config)
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600141
142
Alex Klein238d8862019-05-07 11:32:46 -0600143class BundleAutotestFilesTest(BundleTempDirTestCase):
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600144 """Unittests for BundleAutotestFiles."""
145
Alex Klein231d2da2019-07-22 16:44:45 -0600146 def testValidateOnly(self):
147 """Sanity check that a validate only call does not execute any logic."""
148 patch = self.PatchObject(artifacts_svc, 'BundleAutotestFiles')
149 artifacts.BundleAutotestFiles(self.input_proto, self.output_proto,
150 self.validate_only_config)
151 patch.assert_not_called()
152
Alex Klein238d8862019-05-07 11:32:46 -0600153 def testBundleAutotestFilesLegacy(self):
154 """BundleAutotestFiles calls service correctly with legacy args."""
155 files = {
156 artifacts_svc.ARCHIVE_CONTROL_FILES: '/tmp/artifacts/autotest-a.tar.gz',
157 artifacts_svc.ARCHIVE_PACKAGES: '/tmp/artifacts/autotest-b.tar.gz',
158 }
159 patch = self.PatchObject(artifacts_svc, 'BundleAutotestFiles',
160 return_value=files)
161
162 sysroot_patch = self.PatchObject(sysroot_lib, 'Sysroot',
163 return_value=self.old_sysroot)
Alex Klein231d2da2019-07-22 16:44:45 -0600164 artifacts.BundleAutotestFiles(self.input_proto, self.output_proto,
165 self.api_config)
Alex Klein238d8862019-05-07 11:32:46 -0600166
167 # Verify the sysroot is being built out correctly.
168 sysroot_patch.assert_called_with(self.old_sysroot_path)
169
170 # Verify the arguments are being passed through.
171 patch.assert_called_with(self.old_sysroot, self.output_dir)
172
173 # Verify the output proto is being populated correctly.
174 self.assertTrue(self.output_proto.artifacts)
175 paths = [artifact.path for artifact in self.output_proto.artifacts]
176 self.assertItemsEqual(files.values(), paths)
177
178 def testBundleAutotestFiles(self):
179 """BundleAutotestFiles calls service correctly."""
180 files = {
181 artifacts_svc.ARCHIVE_CONTROL_FILES: '/tmp/artifacts/autotest-a.tar.gz',
182 artifacts_svc.ARCHIVE_PACKAGES: '/tmp/artifacts/autotest-b.tar.gz',
183 }
184 patch = self.PatchObject(artifacts_svc, 'BundleAutotestFiles',
185 return_value=files)
186
187 sysroot_patch = self.PatchObject(sysroot_lib, 'Sysroot',
188 return_value=self.sysroot)
Alex Klein231d2da2019-07-22 16:44:45 -0600189 artifacts.BundleAutotestFiles(self.request, self.response, self.api_config)
Alex Klein238d8862019-05-07 11:32:46 -0600190
191 # Verify the sysroot is being built out correctly.
192 sysroot_patch.assert_called_with(self.full_sysroot_path)
193
194 # Verify the arguments are being passed through.
195 patch.assert_called_with(self.sysroot, self.output_dir)
196
197 # Verify the output proto is being populated correctly.
198 self.assertTrue(self.response.artifacts)
199 paths = [artifact.path for artifact in self.response.artifacts]
200 self.assertItemsEqual(files.values(), paths)
201
202 def testInvalidOutputDir(self):
203 """Test invalid output directory argument."""
204 request = self._GetRequest(chroot=self.chroot_path,
205 sysroot=self.sysroot_path)
Alex Klein238d8862019-05-07 11:32:46 -0600206
207 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600208 artifacts.BundleAutotestFiles(request, self.response, self.api_config)
Alex Klein238d8862019-05-07 11:32:46 -0600209
210 def testInvalidSysroot(self):
211 """Test no sysroot directory."""
212 request = self._GetRequest(chroot=self.chroot_path,
213 output_dir=self.output_dir)
Alex Klein238d8862019-05-07 11:32:46 -0600214
215 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600216 artifacts.BundleAutotestFiles(request, self.response, self.api_config)
Alex Klein238d8862019-05-07 11:32:46 -0600217
218 def testSysrootDoesNotExist(self):
219 """Test dies when no sysroot does not exist."""
220 request = self._GetRequest(chroot=self.chroot_path,
221 sysroot='/does/not/exist',
222 output_dir=self.output_dir)
Alex Klein238d8862019-05-07 11:32:46 -0600223
224 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600225 artifacts.BundleAutotestFiles(request, self.response, self.api_config)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600226
227
228class BundleTastFilesTest(BundleTestCase):
229 """Unittests for BundleTastFiles."""
230
Alex Klein231d2da2019-07-22 16:44:45 -0600231 def testValidateOnly(self):
232 """Sanity check that a validate only call does not execute any logic."""
233 patch = self.PatchObject(artifacts_svc, 'BundleTastFiles')
234 artifacts.BundleTastFiles(self.input_proto, self.output_proto,
235 self.validate_only_config)
236 patch.assert_not_called()
237
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600238 def testBundleTastFilesNoLogs(self):
239 """BundleTasteFiles dies when no tast files found."""
240 self.PatchObject(commands, 'BuildTastBundleTarball',
241 return_value=None)
242 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600243 artifacts.BundleTastFiles(self.input_proto, self.output_proto,
244 self.api_config)
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600245
Alex Kleinb9d810b2019-07-01 12:38:02 -0600246 def testBundleTastFilesLegacy(self):
247 """BundleTastFiles handles legacy args correctly."""
248 buildroot = self.tempdir
249 chroot_dir = os.path.join(buildroot, 'chroot')
250 sysroot_path = os.path.join(chroot_dir, 'build', 'board')
251 output_dir = os.path.join(self.tempdir, 'results')
252 osutils.SafeMakedirs(sysroot_path)
253 osutils.SafeMakedirs(output_dir)
254
Alex Klein171da612019-08-06 14:00:42 -0600255 chroot = chroot_lib.Chroot(chroot_dir)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600256 sysroot = sysroot_lib.Sysroot('/build/board')
257
258 expected_archive = os.path.join(output_dir, artifacts_svc.TAST_BUNDLE_NAME)
259 # Patch the service being called.
260 bundle_patch = self.PatchObject(artifacts_svc, 'BundleTastFiles',
261 return_value=expected_archive)
262 self.PatchObject(constants, 'SOURCE_ROOT', new=buildroot)
263
264 request = artifacts_pb2.BundleRequest(build_target={'name': 'board'},
265 output_dir=output_dir)
Alex Klein231d2da2019-07-22 16:44:45 -0600266 artifacts.BundleTastFiles(request, self.output_proto, self.api_config)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600267 self.assertEqual(
268 [artifact.path for artifact in self.output_proto.artifacts],
269 [expected_archive])
270 bundle_patch.assert_called_once_with(chroot, sysroot, output_dir)
271
272 def testBundleTastFiles(self):
273 """BundleTastFiles calls service correctly."""
274 # Setup.
275 sysroot_path = os.path.join(self.tempdir, 'sysroot')
276 output_dir = os.path.join(self.tempdir, 'results')
277 osutils.SafeMakedirs(sysroot_path)
278 osutils.SafeMakedirs(output_dir)
279
280 chroot = chroot_lib.Chroot(self.tempdir, env={'FEATURES': 'separatedebug'})
281 sysroot = sysroot_lib.Sysroot('/sysroot')
282
283 expected_archive = os.path.join(output_dir, artifacts_svc.TAST_BUNDLE_NAME)
284 # Patch the service being called.
285 bundle_patch = self.PatchObject(artifacts_svc, 'BundleTastFiles',
286 return_value=expected_archive)
287
288 # Request and response building.
289 request = artifacts_pb2.BundleRequest(chroot={'path': self.tempdir},
290 sysroot={'path': '/sysroot'},
291 output_dir=output_dir)
292 response = artifacts_pb2.BundleResponse()
293
Alex Klein231d2da2019-07-22 16:44:45 -0600294 artifacts.BundleTastFiles(request, response, self.api_config)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600295
296 # Make sure the artifact got recorded successfully.
297 self.assertTrue(response.artifacts)
298 self.assertEqual(expected_archive, response.artifacts[0].path)
299 # Make sure the service got called correctly.
300 bundle_patch.assert_called_once_with(chroot, sysroot, output_dir)
301
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600302
303class BundlePinnedGuestImagesTest(BundleTestCase):
304 """Unittests for BundlePinnedGuestImages."""
305
Alex Klein231d2da2019-07-22 16:44:45 -0600306 def testValidateOnly(self):
307 """Sanity check that a validate only call does not execute any logic."""
308 patch = self.PatchObject(commands, 'BuildPinnedGuestImagesTarball')
309 artifacts.BundlePinnedGuestImages(self.input_proto, self.output_proto,
310 self.validate_only_config)
311 patch.assert_not_called()
312
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600313 def testBundlePinnedGuestImages(self):
314 """BundlePinnedGuestImages calls cbuildbot/commands with correct args."""
315 build_pinned_guest_images_tarball = self.PatchObject(
316 commands,
317 'BuildPinnedGuestImagesTarball',
318 return_value='pinned-guest-images.tar.gz')
Alex Klein231d2da2019-07-22 16:44:45 -0600319 artifacts.BundlePinnedGuestImages(self.input_proto, self.output_proto,
320 self.api_config)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600321 self.assertEqual(
322 [artifact.path for artifact in self.output_proto.artifacts],
Alex Klein231d2da2019-07-22 16:44:45 -0600323 [os.path.join(self.output_dir, 'pinned-guest-images.tar.gz')])
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600324 self.assertEqual(build_pinned_guest_images_tarball.call_args_list,
Alex Klein231d2da2019-07-22 16:44:45 -0600325 [mock.call(self.source_root, 'target', self.output_dir)])
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600326
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600327 def testBundlePinnedGuestImagesNoLogs(self):
Evan Hernandezde445982019-04-22 13:42:34 -0600328 """BundlePinnedGuestImages does not die when no pinned images found."""
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600329 self.PatchObject(commands, 'BuildPinnedGuestImagesTarball',
330 return_value=None)
Alex Klein231d2da2019-07-22 16:44:45 -0600331 artifacts.BundlePinnedGuestImages(self.input_proto, self.output_proto,
332 self.api_config)
Evan Hernandezde445982019-04-22 13:42:34 -0600333 self.assertFalse(self.output_proto.artifacts)
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600334
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600335
336class BundleFirmwareTest(BundleTestCase):
337 """Unittests for BundleFirmware."""
338
Alex Klein231d2da2019-07-22 16:44:45 -0600339 def testValidateOnly(self):
340 """Sanity check that a validate only call does not execute any logic."""
341 patch = self.PatchObject(artifacts_svc, 'BundleTastFiles')
342 artifacts.BundleFirmware(self.request, self.response,
343 self.validate_only_config)
344 patch.assert_not_called()
Michael Mortensen38675192019-06-28 16:52:55 +0000345
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600346 def testBundleFirmware(self):
347 """BundleFirmware calls cbuildbot/commands with correct args."""
Alex Klein231d2da2019-07-22 16:44:45 -0600348 self.PatchObject(
349 artifacts_svc,
350 'BuildFirmwareArchive',
351 return_value=os.path.join(self.output_dir, 'firmware.tar.gz'))
352
353 artifacts.BundleFirmware(self.request, self.response, self.api_config)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600354 self.assertEqual(
Alex Klein231d2da2019-07-22 16:44:45 -0600355 [artifact.path for artifact in self.response.artifacts],
356 [os.path.join(self.output_dir, 'firmware.tar.gz')])
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600357
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600358 def testBundleFirmwareNoLogs(self):
359 """BundleFirmware dies when no firmware found."""
360 self.PatchObject(commands, 'BuildFirmwareArchive', return_value=None)
361 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600362 artifacts.BundleFirmware(self.input_proto, self.output_proto,
363 self.api_config)
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600364
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600365
366class BundleEbuildLogsTest(BundleTestCase):
367 """Unittests for BundleEbuildLogs."""
368
Alex Klein231d2da2019-07-22 16:44:45 -0600369 def testValidateOnly(self):
370 """Sanity check that a validate only call does not execute any logic."""
371 patch = self.PatchObject(commands, 'BuildEbuildLogsTarball')
372 artifacts.BundleEbuildLogs(self.input_proto, self.output_proto,
373 self.validate_only_config)
374 patch.assert_not_called()
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600375
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600376 def testBundleEbuildLogs(self):
377 """BundleEbuildLogs calls cbuildbot/commands with correct args."""
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600378 bundle_ebuild_logs_tarball = self.PatchObject(
379 artifacts_svc, 'BundleEBuildLogsTarball',
380 return_value='ebuild-logs.tar.gz')
Alex Klein231d2da2019-07-22 16:44:45 -0600381 artifacts.BundleEbuildLogs(self.request, self.response, self.api_config)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600382 self.assertEqual(
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600383 [artifact.path for artifact in self.response.artifacts],
384 [os.path.join(self.request.output_dir, 'ebuild-logs.tar.gz')])
385 sysroot = sysroot_lib.Sysroot(self.sysroot_path)
Evan Hernandeza478d802019-04-08 15:08:24 -0600386 self.assertEqual(
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600387 bundle_ebuild_logs_tarball.call_args_list,
388 [mock.call(mock.ANY, sysroot, self.output_dir)])
389
390 def testBundleEBuildLogsOldProto(self):
391 bundle_ebuild_logs_tarball = self.PatchObject(
392 artifacts_svc, 'BundleEBuildLogsTarball',
393 return_value='ebuild-logs.tar.gz')
Alex Klein231d2da2019-07-22 16:44:45 -0600394
395 artifacts.BundleEbuildLogs(self.input_proto, self.output_proto,
396 self.api_config)
397
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600398 sysroot = sysroot_lib.Sysroot(self.sysroot_path)
399 self.assertEqual(
400 bundle_ebuild_logs_tarball.call_args_list,
401 [mock.call(mock.ANY, sysroot, self.output_dir)])
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600402
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600403 def testBundleEbuildLogsNoLogs(self):
404 """BundleEbuildLogs dies when no logs found."""
405 self.PatchObject(commands, 'BuildEbuildLogsTarball', return_value=None)
406 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600407 artifacts.BundleEbuildLogs(self.request, self.response, self.api_config)
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600408
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600409
Alex Klein231d2da2019-07-22 16:44:45 -0600410class BundleTestUpdatePayloadsTest(cros_test_lib.MockTempDirTestCase,
411 api_config.ApiConfigMixin):
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600412 """Unittests for BundleTestUpdatePayloads."""
413
414 def setUp(self):
415 self.source_root = os.path.join(self.tempdir, 'cros')
416 osutils.SafeMakedirs(self.source_root)
417
418 self.archive_root = os.path.join(self.tempdir, 'output')
419 osutils.SafeMakedirs(self.archive_root)
420
421 self.target = 'target'
Evan Hernandez59690b72019-04-08 16:24:45 -0600422 self.image_root = os.path.join(self.source_root,
423 'src/build/images/target/latest')
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600424
425 self.input_proto = artifacts_pb2.BundleRequest()
426 self.input_proto.build_target.name = self.target
427 self.input_proto.output_dir = self.archive_root
428 self.output_proto = artifacts_pb2.BundleResponse()
429
430 self.PatchObject(constants, 'SOURCE_ROOT', new=self.source_root)
431
Alex Kleincb541e82019-06-26 15:06:11 -0600432 def MockPayloads(image_path, archive_dir):
433 osutils.WriteFile(os.path.join(archive_dir, 'payload1.bin'), image_path)
434 osutils.WriteFile(os.path.join(archive_dir, 'payload2.bin'), image_path)
435 return [os.path.join(archive_dir, 'payload1.bin'),
436 os.path.join(archive_dir, 'payload2.bin')]
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600437
Alex Kleincb541e82019-06-26 15:06:11 -0600438 self.bundle_patch = self.PatchObject(
439 artifacts_svc, 'BundleTestUpdatePayloads', side_effect=MockPayloads)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600440
Alex Klein231d2da2019-07-22 16:44:45 -0600441 def testValidateOnly(self):
442 """Sanity check that a validate only call does not execute any logic."""
443 patch = self.PatchObject(artifacts_svc, 'BundleTestUpdatePayloads')
444 artifacts.BundleTestUpdatePayloads(self.input_proto, self.output_proto,
445 self.validate_only_config)
446 patch.assert_not_called()
447
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600448 def testBundleTestUpdatePayloads(self):
449 """BundleTestUpdatePayloads calls cbuildbot/commands with correct args."""
450 image_path = os.path.join(self.image_root, constants.BASE_IMAGE_BIN)
451 osutils.WriteFile(image_path, 'image!', makedirs=True)
452
Alex Klein231d2da2019-07-22 16:44:45 -0600453 artifacts.BundleTestUpdatePayloads(self.input_proto, self.output_proto,
454 self.api_config)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600455
456 actual = [
457 os.path.relpath(artifact.path, self.archive_root)
458 for artifact in self.output_proto.artifacts
459 ]
Alex Kleincb541e82019-06-26 15:06:11 -0600460 expected = ['payload1.bin', 'payload2.bin']
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600461 self.assertItemsEqual(actual, expected)
462
463 actual = [
464 os.path.relpath(path, self.archive_root)
465 for path in osutils.DirectoryIterator(self.archive_root)
466 ]
467 self.assertItemsEqual(actual, expected)
468
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600469 def testBundleTestUpdatePayloadsNoImageDir(self):
470 """BundleTestUpdatePayloads dies if no image dir is found."""
471 # Intentionally do not write image directory.
472 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600473 artifacts.BundleTestUpdatePayloads(self.input_proto, self.output_proto,
474 self.api_config)
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600475
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600476 def testBundleTestUpdatePayloadsNoImage(self):
477 """BundleTestUpdatePayloads dies if no usable image is found for target."""
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600478 # Intentionally do not write image, but create the directory.
479 osutils.SafeMakedirs(self.image_root)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600480 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600481 artifacts.BundleTestUpdatePayloads(self.input_proto, self.output_proto,
482 self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600483
484
Alex Klein231d2da2019-07-22 16:44:45 -0600485class BundleSimpleChromeArtifactsTest(cros_test_lib.MockTempDirTestCase,
486 api_config.ApiConfigMixin):
Alex Klein2275d692019-04-23 16:04:12 -0600487 """BundleSimpleChromeArtifacts tests."""
488
489 def setUp(self):
490 self.chroot_dir = os.path.join(self.tempdir, 'chroot_dir')
491 self.sysroot_path = '/sysroot'
492 self.sysroot_dir = os.path.join(self.chroot_dir, 'sysroot')
493 osutils.SafeMakedirs(self.sysroot_dir)
494 self.output_dir = os.path.join(self.tempdir, 'output_dir')
495 osutils.SafeMakedirs(self.output_dir)
496
497 self.does_not_exist = os.path.join(self.tempdir, 'does_not_exist')
498
Alex Klein231d2da2019-07-22 16:44:45 -0600499 self.response = artifacts_pb2.BundleResponse()
500
Alex Klein2275d692019-04-23 16:04:12 -0600501 def _GetRequest(self, chroot=None, sysroot=None, build_target=None,
502 output_dir=None):
503 """Helper to create a request message instance.
504
505 Args:
506 chroot (str): The chroot path.
507 sysroot (str): The sysroot path.
508 build_target (str): The build target name.
509 output_dir (str): The output directory.
510 """
511 return artifacts_pb2.BundleRequest(
512 sysroot={'path': sysroot, 'build_target': {'name': build_target}},
513 chroot={'path': chroot}, output_dir=output_dir)
514
Alex Klein231d2da2019-07-22 16:44:45 -0600515 def testValidateOnly(self):
516 """Sanity check that a validate only call does not execute any logic."""
517 patch = self.PatchObject(artifacts_svc, 'BundleSimpleChromeArtifacts')
518 request = self._GetRequest(chroot=self.chroot_dir,
519 sysroot=self.sysroot_path,
520 build_target='board', output_dir=self.output_dir)
521 artifacts.BundleSimpleChromeArtifacts(request, self.response,
522 self.validate_only_config)
523 patch.assert_not_called()
Alex Klein2275d692019-04-23 16:04:12 -0600524
525 def testNoBuildTarget(self):
526 """Test no build target fails."""
527 request = self._GetRequest(chroot=self.chroot_dir,
528 sysroot=self.sysroot_path,
529 output_dir=self.output_dir)
Alex Klein231d2da2019-07-22 16:44:45 -0600530 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600531 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600532 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600533
534 def testNoSysroot(self):
535 """Test no sysroot fails."""
536 request = self._GetRequest(build_target='board', output_dir=self.output_dir)
Alex Klein231d2da2019-07-22 16:44:45 -0600537 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600538 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600539 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600540
541 def testSysrootDoesNotExist(self):
542 """Test no sysroot fails."""
543 request = self._GetRequest(build_target='board', output_dir=self.output_dir,
544 sysroot=self.does_not_exist)
Alex Klein231d2da2019-07-22 16:44:45 -0600545 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600546 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600547 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600548
549 def testNoOutputDir(self):
550 """Test no output dir fails."""
551 request = self._GetRequest(chroot=self.chroot_dir,
552 sysroot=self.sysroot_path,
553 build_target='board')
Alex Klein231d2da2019-07-22 16:44:45 -0600554 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600555 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600556 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600557
558 def testOutputDirDoesNotExist(self):
559 """Test no output dir fails."""
560 request = self._GetRequest(chroot=self.chroot_dir,
561 sysroot=self.sysroot_path,
562 build_target='board',
563 output_dir=self.does_not_exist)
Alex Klein231d2da2019-07-22 16:44:45 -0600564 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600565 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600566 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600567
568 def testOutputHandling(self):
569 """Test response output."""
570 files = ['file1', 'file2', 'file3']
571 expected_files = [os.path.join(self.output_dir, f) for f in files]
572 self.PatchObject(artifacts_svc, 'BundleSimpleChromeArtifacts',
573 return_value=expected_files)
574 request = self._GetRequest(chroot=self.chroot_dir,
575 sysroot=self.sysroot_path,
576 build_target='board', output_dir=self.output_dir)
Alex Klein231d2da2019-07-22 16:44:45 -0600577 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600578
Alex Klein231d2da2019-07-22 16:44:45 -0600579 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600580
581 self.assertTrue(response.artifacts)
582 self.assertItemsEqual(expected_files, [a.path for a in response.artifacts])
583
584
Alex Klein231d2da2019-07-22 16:44:45 -0600585class BundleVmFilesTest(cros_test_lib.MockTempDirTestCase,
586 api_config.ApiConfigMixin):
Alex Klein6504eca2019-04-18 15:37:56 -0600587 """BuildVmFiles tests."""
588
Alex Klein231d2da2019-07-22 16:44:45 -0600589 def setUp(self):
590 self.output_dir = os.path.join(self.tempdir, 'output')
591 osutils.SafeMakedirs(self.output_dir)
592
593 self.response = artifacts_pb2.BundleResponse()
594
Alex Klein6504eca2019-04-18 15:37:56 -0600595 def _GetInput(self, chroot=None, sysroot=None, test_results_dir=None,
596 output_dir=None):
597 """Helper to build out an input message instance.
598
599 Args:
600 chroot (str|None): The chroot path.
601 sysroot (str|None): The sysroot path relative to the chroot.
602 test_results_dir (str|None): The test results directory relative to the
603 sysroot.
604 output_dir (str|None): The directory where the results tarball should be
605 saved.
606 """
607 return artifacts_pb2.BundleVmFilesRequest(
608 chroot={'path': chroot}, sysroot={'path': sysroot},
609 test_results_dir=test_results_dir, output_dir=output_dir,
610 )
611
Alex Klein231d2da2019-07-22 16:44:45 -0600612 def testValidateOnly(self):
613 """Sanity check that a validate only call does not execute any logic."""
614 patch = self.PatchObject(artifacts_svc, 'BundleVmFiles')
615 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
616 test_results_dir='/test/results',
617 output_dir=self.output_dir)
618 artifacts.BundleVmFiles(in_proto, self.response, self.validate_only_config)
619 patch.assert_not_called()
Alex Klein6504eca2019-04-18 15:37:56 -0600620
621 def testChrootMissing(self):
622 """Test error handling for missing chroot."""
623 in_proto = self._GetInput(sysroot='/build/board',
624 test_results_dir='/test/results',
Alex Klein231d2da2019-07-22 16:44:45 -0600625 output_dir=self.output_dir)
Alex Klein6504eca2019-04-18 15:37:56 -0600626
627 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600628 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600629
Alex Klein6504eca2019-04-18 15:37:56 -0600630 def testTestResultsDirMissing(self):
631 """Test error handling for missing test results directory."""
632 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
Alex Klein231d2da2019-07-22 16:44:45 -0600633 output_dir=self.output_dir)
Alex Klein6504eca2019-04-18 15:37:56 -0600634
635 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600636 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600637
638 def testOutputDirMissing(self):
639 """Test error handling for missing output directory."""
640 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
641 test_results_dir='/test/results')
Alex Klein6504eca2019-04-18 15:37:56 -0600642
643 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600644 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
645
646 def testOutputDirDoesNotExist(self):
647 """Test error handling for output directory that does not exist."""
648 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
649 output_dir=os.path.join(self.tempdir, 'dne'),
650 test_results_dir='/test/results')
651
652 with self.assertRaises(cros_build_lib.DieSystemExit):
653 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600654
655 def testValidCall(self):
656 """Test image dir building."""
657 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
658 test_results_dir='/test/results',
Alex Klein231d2da2019-07-22 16:44:45 -0600659 output_dir=self.output_dir)
660
Alex Klein6504eca2019-04-18 15:37:56 -0600661 expected_files = ['/tmp/output/f1.tar', '/tmp/output/f2.tar']
Michael Mortensen51f06722019-07-18 09:55:50 -0600662 patch = self.PatchObject(artifacts_svc, 'BundleVmFiles',
Alex Klein6504eca2019-04-18 15:37:56 -0600663 return_value=expected_files)
664
Alex Klein231d2da2019-07-22 16:44:45 -0600665 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600666
Alex Klein231d2da2019-07-22 16:44:45 -0600667 patch.assert_called_with(mock.ANY, '/test/results', self.output_dir)
Alex Klein6504eca2019-04-18 15:37:56 -0600668
669 # Make sure we have artifacts, and that every artifact is an expected file.
Alex Klein231d2da2019-07-22 16:44:45 -0600670 self.assertTrue(self.response.artifacts)
671 for artifact in self.response.artifacts:
Alex Klein6504eca2019-04-18 15:37:56 -0600672 self.assertIn(artifact.path, expected_files)
673 expected_files.remove(artifact.path)
674
675 # Make sure we've seen all of the expected files.
676 self.assertFalse(expected_files)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700677
Alex Kleinb9d810b2019-07-01 12:38:02 -0600678
Tiancong Wang78b685d2019-07-29 13:57:23 -0700679class BundleOrderfileGenerationArtifactsTestCase(
Alex Klein231d2da2019-07-22 16:44:45 -0600680 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin):
Tiancong Wangc4805b72019-06-11 12:12:03 -0700681 """Unittests for BundleOrderfileGenerationArtifacts."""
682
683 def setUp(self):
684 self.chroot_dir = os.path.join(self.tempdir, 'chroot_dir')
685 osutils.SafeMakedirs(self.chroot_dir)
686 temp_dir = os.path.join(self.chroot_dir, 'tmp')
687 osutils.SafeMakedirs(temp_dir)
688 self.output_dir = os.path.join(self.tempdir, 'output_dir')
689 osutils.SafeMakedirs(self.output_dir)
690 self.build_target = 'board'
Tiancong Wang78b685d2019-07-29 13:57:23 -0700691 self.orderfile_name = 'chromeos-chrome-1.0'
Tiancong Wangc4805b72019-06-11 12:12:03 -0700692
693 self.does_not_exist = os.path.join(self.tempdir, 'does_not_exist')
694
Alex Klein231d2da2019-07-22 16:44:45 -0600695 self.response = artifacts_pb2.BundleResponse()
696
Tiancong Wang78b685d2019-07-29 13:57:23 -0700697 def _GetRequest(self, chroot=None, build_target=None, output_dir=None):
Tiancong Wangc4805b72019-06-11 12:12:03 -0700698 """Helper to create a request message instance.
699
700 Args:
701 chroot (str): The chroot path.
702 build_target (str): The build target name.
703 output_dir (str): The output directory.
Tiancong Wangc4805b72019-06-11 12:12:03 -0700704 """
705 return artifacts_pb2.BundleChromeOrderfileRequest(
706 build_target={'name': build_target},
707 chroot={'path': chroot},
Tiancong Wang78b685d2019-07-29 13:57:23 -0700708 output_dir=output_dir
Tiancong Wangc4805b72019-06-11 12:12:03 -0700709 )
710
Alex Klein231d2da2019-07-22 16:44:45 -0600711 def testValidateOnly(self):
712 """Sanity check that a validate only call does not execute any logic."""
713 patch = self.PatchObject(artifacts_svc,
714 'BundleOrderfileGenerationArtifacts')
715 request = self._GetRequest(chroot=self.chroot_dir,
716 build_target=self.build_target,
717 output_dir=self.output_dir)
718 artifacts.BundleOrderfileGenerationArtifacts(request, self.response,
719 self.validate_only_config)
720 patch.assert_not_called()
Tiancong Wangc4805b72019-06-11 12:12:03 -0700721
722 def testNoBuildTarget(self):
723 """Test no build target fails."""
724 request = self._GetRequest(chroot=self.chroot_dir,
Tiancong Wang78b685d2019-07-29 13:57:23 -0700725 output_dir=self.output_dir)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700726 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600727 artifacts.BundleOrderfileGenerationArtifacts(request, self.response,
728 self.api_config)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700729
730 def testNoOutputDir(self):
731 """Test no output dir fails."""
732 request = self._GetRequest(chroot=self.chroot_dir,
Tiancong Wangc4805b72019-06-11 12:12:03 -0700733 build_target=self.build_target)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700734 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600735 artifacts.BundleOrderfileGenerationArtifacts(request, self.response,
736 self.api_config)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700737
738 def testOutputDirDoesNotExist(self):
739 """Test output directory not existing fails."""
740 request = self._GetRequest(chroot=self.chroot_dir,
Tiancong Wangc4805b72019-06-11 12:12:03 -0700741 build_target=self.build_target,
742 output_dir=self.does_not_exist)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700743 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600744 artifacts.BundleOrderfileGenerationArtifacts(request, self.response,
745 self.api_config)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700746
747 def testOutputHandling(self):
748 """Test response output."""
Tiancong Wang78b685d2019-07-29 13:57:23 -0700749 files = [self.orderfile_name + '.orderfile.tar.xz',
750 self.orderfile_name + '.nm.tar.xz']
Tiancong Wangc4805b72019-06-11 12:12:03 -0700751 expected_files = [os.path.join(self.output_dir, f) for f in files]
752 self.PatchObject(artifacts_svc, 'BundleOrderfileGenerationArtifacts',
753 return_value=expected_files)
Alex Klein231d2da2019-07-22 16:44:45 -0600754
Tiancong Wangc4805b72019-06-11 12:12:03 -0700755 request = self._GetRequest(chroot=self.chroot_dir,
Tiancong Wangc4805b72019-06-11 12:12:03 -0700756 build_target=self.build_target,
757 output_dir=self.output_dir)
Alex Klein231d2da2019-07-22 16:44:45 -0600758 response = self.response
Tiancong Wangc4805b72019-06-11 12:12:03 -0700759
Alex Klein231d2da2019-07-22 16:44:45 -0600760 artifacts.BundleOrderfileGenerationArtifacts(request, response,
761 self.api_config)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700762
763 self.assertTrue(response.artifacts)
764 self.assertItemsEqual(expected_files, [a.path for a in response.artifacts])