blob: bf09f11c00e2865bd5fb01ae65ff011d6707fdd4 [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
Evan Hernandezf388cbf2019-04-01 11:15:23 -060010import 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
Evan Hernandezf388cbf2019-04-01 11:15:23 -060015from chromite.api.controller import artifacts
16from chromite.api.gen.chromite.api import artifacts_pb2
Tiancong Wang24a3df72019-08-20 15:48:51 -070017from chromite.api.gen.chromite.api import toolchain_pb2
Evan Hernandezf388cbf2019-04-01 11:15:23 -060018from chromite.cbuildbot import commands
Alex Kleinb9d810b2019-07-01 12:38:02 -060019from chromite.lib import chroot_lib
Evan Hernandezf388cbf2019-04-01 11:15:23 -060020from chromite.lib import constants
21from chromite.lib import cros_build_lib
22from chromite.lib import cros_test_lib
23from chromite.lib import osutils
Alex Klein238d8862019-05-07 11:32:46 -060024from chromite.lib import sysroot_lib
Alex Klein2275d692019-04-23 16:04:12 -060025from chromite.service import artifacts as artifacts_svc
Evan Hernandezf388cbf2019-04-01 11:15:23 -060026
27
Alex Kleind91e95a2019-09-17 10:39:02 -060028class BundleRequestMixin(object):
29 """Mixin to provide bundle request methods."""
30
31 def EmptyRequest(self):
32 return artifacts_pb2.BundleRequest()
33
34 def BuildTargetRequest(self, build_target=None, output_dir=None, chroot=None):
35 """Get a build target format request instance."""
36 request = self.EmptyRequest()
37 if build_target:
38 request.build_target.name = build_target
39 if output_dir:
40 request.output_dir = output_dir
41 if chroot:
42 request.chroot.path = chroot
43
44 return request
45
46 def SysrootRequest(self,
47 sysroot=None,
48 build_target=None,
49 output_dir=None,
50 chroot=None):
51 """Get a sysroot format request instance."""
52 request = self.EmptyRequest()
53 if sysroot:
54 request.sysroot.path = sysroot
55 if build_target:
56 request.sysroot.build_target.name = build_target
57 if output_dir:
58 request.output_dir = output_dir
59 if chroot:
60 request.chroot.path = chroot
61
62 return request
63
64
Alex Klein231d2da2019-07-22 16:44:45 -060065class BundleTestCase(cros_test_lib.MockTempDirTestCase,
Alex Kleind91e95a2019-09-17 10:39:02 -060066 api_config.ApiConfigMixin, BundleRequestMixin):
Evan Hernandezf388cbf2019-04-01 11:15:23 -060067 """Basic setup for all artifacts unittests."""
68
69 def setUp(self):
Alex Klein231d2da2019-07-22 16:44:45 -060070 self.output_dir = os.path.join(self.tempdir, 'artifacts')
71 osutils.SafeMakedirs(self.output_dir)
72 self.sysroot_path = '/build/target'
73 self.chroot_path = os.path.join(self.tempdir, 'chroot')
74 full_sysroot_path = os.path.join(self.chroot_path,
75 self.sysroot_path.lstrip(os.sep))
76 osutils.SafeMakedirs(full_sysroot_path)
77
78 # Legacy call.
Evan Hernandezf388cbf2019-04-01 11:15:23 -060079 self.input_proto = artifacts_pb2.BundleRequest()
80 self.input_proto.build_target.name = 'target'
Alex Klein231d2da2019-07-22 16:44:45 -060081 self.input_proto.output_dir = self.output_dir
Evan Hernandezf388cbf2019-04-01 11:15:23 -060082 self.output_proto = artifacts_pb2.BundleResponse()
83
Alex Klein231d2da2019-07-22 16:44:45 -060084 # New call format.
85 self.request = artifacts_pb2.BundleRequest()
86 self.request.chroot.path = self.chroot_path
87 self.request.sysroot.path = self.sysroot_path
88 self.request.output_dir = self.output_dir
89 self.response = artifacts_pb2.BundleResponse()
90
91 self.source_root = self.tempdir
92 self.PatchObject(constants, 'SOURCE_ROOT', new=self.tempdir)
Evan Hernandezf388cbf2019-04-01 11:15:23 -060093
94
Alex Klein231d2da2019-07-22 16:44:45 -060095class BundleTempDirTestCase(cros_test_lib.MockTempDirTestCase,
96 api_config.ApiConfigMixin):
Alex Klein238d8862019-05-07 11:32:46 -060097 """Basic setup for artifacts unittests that need a tempdir."""
98
99 def _GetRequest(self, chroot=None, sysroot=None, build_target=None,
100 output_dir=None):
101 """Helper to create a request message instance.
102
103 Args:
104 chroot (str): The chroot path.
105 sysroot (str): The sysroot path.
106 build_target (str): The build target name.
107 output_dir (str): The output directory.
108 """
109 return artifacts_pb2.BundleRequest(
110 sysroot={'path': sysroot, 'build_target': {'name': build_target}},
111 chroot={'path': chroot}, output_dir=output_dir)
112
Alex Klein238d8862019-05-07 11:32:46 -0600113 def setUp(self):
114 self.output_dir = os.path.join(self.tempdir, 'artifacts')
115 osutils.SafeMakedirs(self.output_dir)
116
Alex Klein238d8862019-05-07 11:32:46 -0600117 # Old style proto.
118 self.input_proto = artifacts_pb2.BundleRequest()
119 self.input_proto.build_target.name = 'target'
120 self.input_proto.output_dir = self.output_dir
121 self.output_proto = artifacts_pb2.BundleResponse()
122
Alex Kleine21a0952019-08-23 16:08:16 -0600123 self.chroot_path = os.path.join(self.tempdir, 'chroot')
124 self.PatchObject(constants, 'DEFAULT_CHROOT_PATH', new=self.chroot_path)
Alex Klein238d8862019-05-07 11:32:46 -0600125
126 # New style paths.
Alex Klein238d8862019-05-07 11:32:46 -0600127 self.sysroot_path = '/build/target'
Alex Kleine21a0952019-08-23 16:08:16 -0600128 self.sysroot = sysroot_lib.Sysroot(self.sysroot_path)
129 full_sysroot_path = os.path.join(self.chroot_path,
130 self.sysroot_path.lstrip(os.sep))
131 osutils.SafeMakedirs(full_sysroot_path)
Alex Klein238d8862019-05-07 11:32:46 -0600132
133 # New style proto.
134 self.request = artifacts_pb2.BundleRequest()
135 self.request.output_dir = self.output_dir
136 self.request.chroot.path = self.chroot_path
137 self.request.sysroot.path = self.sysroot_path
138 self.response = artifacts_pb2.BundleResponse()
139
140
Alex Kleind91e95a2019-09-17 10:39:02 -0600141class BundleImageArchivesTest(BundleTestCase):
142 """BundleImageArchives tests."""
143
144 def testValidateOnly(self):
145 """Sanity check that a validate only call does not execute any logic."""
146 patch = self.PatchObject(artifacts_svc, 'ArchiveImages')
147 artifacts.BundleImageArchives(self.input_proto, self.output_proto,
148 self.validate_only_config)
149 patch.assert_not_called()
150
151 def testNoBuildTarget(self):
152 """Test that no build target fails."""
153 request = self.BuildTargetRequest(output_dir=self.tempdir)
154 with self.assertRaises(cros_build_lib.DieSystemExit):
155 artifacts.BundleImageArchives(request, self.output_proto, self.api_config)
156
157 def testNoOutputDir(self):
158 """Test no output dir fails."""
159 request = self.BuildTargetRequest(build_target='board')
160 with self.assertRaises(cros_build_lib.DieSystemExit):
161 artifacts.BundleImageArchives(request, self.output_proto, self.api_config)
162
163 def testInvalidOutputDir(self):
164 """Test invalid output dir fails."""
165 request = self.BuildTargetRequest(
166 build_target='board', output_dir=os.path.join(self.tempdir, 'DNE'))
167 with self.assertRaises(cros_build_lib.DieSystemExit):
168 artifacts.BundleImageArchives(request, self.output_proto, self.api_config)
169
170 def testOutputHandling(self):
171 """Test the artifact output handling."""
172 expected = [os.path.join(self.output_dir, f) for f in ('a', 'b', 'c')]
173 self.PatchObject(artifacts_svc, 'ArchiveImages', return_value=expected)
174 self.PatchObject(os.path, 'exists', return_value=True)
175
176 artifacts.BundleImageArchives(self.input_proto, self.output_proto,
177 self.api_config)
178
179 self.assertItemsEqual(expected,
180 [a.path for a in self.output_proto.artifacts])
181
182
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600183class BundleImageZipTest(BundleTestCase):
184 """Unittests for BundleImageZip."""
185
Alex Klein231d2da2019-07-22 16:44:45 -0600186 def testValidateOnly(self):
187 """Sanity check that a validate only call does not execute any logic."""
188 patch = self.PatchObject(commands, 'BuildImageZip')
189 artifacts.BundleImageZip(self.input_proto, self.output_proto,
190 self.validate_only_config)
191 patch.assert_not_called()
192
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600193 def testBundleImageZip(self):
194 """BundleImageZip calls cbuildbot/commands with correct args."""
Michael Mortensen01910922019-07-24 14:48:10 -0600195 bundle_image_zip = self.PatchObject(
196 artifacts_svc, 'BundleImageZip', return_value='image.zip')
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600197 self.PatchObject(os.path, 'exists', return_value=True)
Alex Klein231d2da2019-07-22 16:44:45 -0600198 artifacts.BundleImageZip(self.input_proto, self.output_proto,
199 self.api_config)
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600200 self.assertEqual(
201 [artifact.path for artifact in self.output_proto.artifacts],
Alex Klein231d2da2019-07-22 16:44:45 -0600202 [os.path.join(self.output_dir, 'image.zip')])
203
204 latest = os.path.join(self.source_root, 'src/build/images/target/latest')
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600205 self.assertEqual(
Michael Mortensen01910922019-07-24 14:48:10 -0600206 bundle_image_zip.call_args_list,
Alex Klein231d2da2019-07-22 16:44:45 -0600207 [mock.call(self.output_dir, latest)])
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600208
209 def testBundleImageZipNoImageDir(self):
210 """BundleImageZip dies when image dir does not exist."""
211 self.PatchObject(os.path, 'exists', return_value=False)
212 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600213 artifacts.BundleImageZip(self.input_proto, self.output_proto,
214 self.api_config)
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600215
216
Alex Klein238d8862019-05-07 11:32:46 -0600217class BundleAutotestFilesTest(BundleTempDirTestCase):
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600218 """Unittests for BundleAutotestFiles."""
219
Alex Klein231d2da2019-07-22 16:44:45 -0600220 def testValidateOnly(self):
221 """Sanity check that a validate only call does not execute any logic."""
222 patch = self.PatchObject(artifacts_svc, 'BundleAutotestFiles')
223 artifacts.BundleAutotestFiles(self.input_proto, self.output_proto,
224 self.validate_only_config)
225 patch.assert_not_called()
226
Alex Klein238d8862019-05-07 11:32:46 -0600227 def testBundleAutotestFilesLegacy(self):
228 """BundleAutotestFiles calls service correctly with legacy args."""
229 files = {
230 artifacts_svc.ARCHIVE_CONTROL_FILES: '/tmp/artifacts/autotest-a.tar.gz',
231 artifacts_svc.ARCHIVE_PACKAGES: '/tmp/artifacts/autotest-b.tar.gz',
232 }
233 patch = self.PatchObject(artifacts_svc, 'BundleAutotestFiles',
234 return_value=files)
235
236 sysroot_patch = self.PatchObject(sysroot_lib, 'Sysroot',
Alex Kleine21a0952019-08-23 16:08:16 -0600237 return_value=self.sysroot)
Alex Klein231d2da2019-07-22 16:44:45 -0600238 artifacts.BundleAutotestFiles(self.input_proto, self.output_proto,
239 self.api_config)
Alex Klein238d8862019-05-07 11:32:46 -0600240
241 # Verify the sysroot is being built out correctly.
Alex Kleine21a0952019-08-23 16:08:16 -0600242 sysroot_patch.assert_called_with(self.sysroot_path)
Alex Klein238d8862019-05-07 11:32:46 -0600243
244 # Verify the arguments are being passed through.
Alex Kleine21a0952019-08-23 16:08:16 -0600245 patch.assert_called_with(mock.ANY, self.sysroot, self.output_dir)
Alex Klein238d8862019-05-07 11:32:46 -0600246
247 # Verify the output proto is being populated correctly.
248 self.assertTrue(self.output_proto.artifacts)
249 paths = [artifact.path for artifact in self.output_proto.artifacts]
250 self.assertItemsEqual(files.values(), paths)
251
252 def testBundleAutotestFiles(self):
253 """BundleAutotestFiles calls service correctly."""
254 files = {
255 artifacts_svc.ARCHIVE_CONTROL_FILES: '/tmp/artifacts/autotest-a.tar.gz',
256 artifacts_svc.ARCHIVE_PACKAGES: '/tmp/artifacts/autotest-b.tar.gz',
257 }
258 patch = self.PatchObject(artifacts_svc, 'BundleAutotestFiles',
259 return_value=files)
260
261 sysroot_patch = self.PatchObject(sysroot_lib, 'Sysroot',
262 return_value=self.sysroot)
Alex Klein231d2da2019-07-22 16:44:45 -0600263 artifacts.BundleAutotestFiles(self.request, self.response, self.api_config)
Alex Klein238d8862019-05-07 11:32:46 -0600264
265 # Verify the sysroot is being built out correctly.
Alex Kleine21a0952019-08-23 16:08:16 -0600266 sysroot_patch.assert_called_with(self.sysroot_path)
Alex Klein238d8862019-05-07 11:32:46 -0600267
268 # Verify the arguments are being passed through.
Alex Kleine21a0952019-08-23 16:08:16 -0600269 patch.assert_called_with(mock.ANY, self.sysroot, self.output_dir)
Alex Klein238d8862019-05-07 11:32:46 -0600270
271 # Verify the output proto is being populated correctly.
272 self.assertTrue(self.response.artifacts)
273 paths = [artifact.path for artifact in self.response.artifacts]
274 self.assertItemsEqual(files.values(), paths)
275
276 def testInvalidOutputDir(self):
277 """Test invalid output directory argument."""
278 request = self._GetRequest(chroot=self.chroot_path,
279 sysroot=self.sysroot_path)
Alex Klein238d8862019-05-07 11:32:46 -0600280
281 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600282 artifacts.BundleAutotestFiles(request, self.response, self.api_config)
Alex Klein238d8862019-05-07 11:32:46 -0600283
284 def testInvalidSysroot(self):
285 """Test no sysroot directory."""
286 request = self._GetRequest(chroot=self.chroot_path,
287 output_dir=self.output_dir)
Alex Klein238d8862019-05-07 11:32:46 -0600288
289 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600290 artifacts.BundleAutotestFiles(request, self.response, self.api_config)
Alex Klein238d8862019-05-07 11:32:46 -0600291
292 def testSysrootDoesNotExist(self):
293 """Test dies when no sysroot does not exist."""
294 request = self._GetRequest(chroot=self.chroot_path,
295 sysroot='/does/not/exist',
296 output_dir=self.output_dir)
Alex Klein238d8862019-05-07 11:32:46 -0600297
298 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600299 artifacts.BundleAutotestFiles(request, self.response, self.api_config)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600300
301
302class BundleTastFilesTest(BundleTestCase):
303 """Unittests for BundleTastFiles."""
304
Alex Klein231d2da2019-07-22 16:44:45 -0600305 def testValidateOnly(self):
306 """Sanity check that a validate only call does not execute any logic."""
307 patch = self.PatchObject(artifacts_svc, 'BundleTastFiles')
308 artifacts.BundleTastFiles(self.input_proto, self.output_proto,
309 self.validate_only_config)
310 patch.assert_not_called()
311
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600312 def testBundleTastFilesNoLogs(self):
313 """BundleTasteFiles dies when no tast files found."""
314 self.PatchObject(commands, 'BuildTastBundleTarball',
315 return_value=None)
316 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600317 artifacts.BundleTastFiles(self.input_proto, self.output_proto,
318 self.api_config)
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600319
Alex Kleinb9d810b2019-07-01 12:38:02 -0600320 def testBundleTastFilesLegacy(self):
321 """BundleTastFiles handles legacy args correctly."""
322 buildroot = self.tempdir
323 chroot_dir = os.path.join(buildroot, 'chroot')
324 sysroot_path = os.path.join(chroot_dir, 'build', 'board')
325 output_dir = os.path.join(self.tempdir, 'results')
326 osutils.SafeMakedirs(sysroot_path)
327 osutils.SafeMakedirs(output_dir)
328
Alex Klein171da612019-08-06 14:00:42 -0600329 chroot = chroot_lib.Chroot(chroot_dir)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600330 sysroot = sysroot_lib.Sysroot('/build/board')
331
332 expected_archive = os.path.join(output_dir, artifacts_svc.TAST_BUNDLE_NAME)
333 # Patch the service being called.
334 bundle_patch = self.PatchObject(artifacts_svc, 'BundleTastFiles',
335 return_value=expected_archive)
336 self.PatchObject(constants, 'SOURCE_ROOT', new=buildroot)
337
338 request = artifacts_pb2.BundleRequest(build_target={'name': 'board'},
339 output_dir=output_dir)
Alex Klein231d2da2019-07-22 16:44:45 -0600340 artifacts.BundleTastFiles(request, self.output_proto, self.api_config)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600341 self.assertEqual(
342 [artifact.path for artifact in self.output_proto.artifacts],
343 [expected_archive])
344 bundle_patch.assert_called_once_with(chroot, sysroot, output_dir)
345
346 def testBundleTastFiles(self):
347 """BundleTastFiles calls service correctly."""
348 # Setup.
349 sysroot_path = os.path.join(self.tempdir, 'sysroot')
350 output_dir = os.path.join(self.tempdir, 'results')
351 osutils.SafeMakedirs(sysroot_path)
352 osutils.SafeMakedirs(output_dir)
353
354 chroot = chroot_lib.Chroot(self.tempdir, env={'FEATURES': 'separatedebug'})
355 sysroot = sysroot_lib.Sysroot('/sysroot')
356
357 expected_archive = os.path.join(output_dir, artifacts_svc.TAST_BUNDLE_NAME)
358 # Patch the service being called.
359 bundle_patch = self.PatchObject(artifacts_svc, 'BundleTastFiles',
360 return_value=expected_archive)
361
362 # Request and response building.
363 request = artifacts_pb2.BundleRequest(chroot={'path': self.tempdir},
364 sysroot={'path': '/sysroot'},
365 output_dir=output_dir)
366 response = artifacts_pb2.BundleResponse()
367
Alex Klein231d2da2019-07-22 16:44:45 -0600368 artifacts.BundleTastFiles(request, response, self.api_config)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600369
370 # Make sure the artifact got recorded successfully.
371 self.assertTrue(response.artifacts)
372 self.assertEqual(expected_archive, response.artifacts[0].path)
373 # Make sure the service got called correctly.
374 bundle_patch.assert_called_once_with(chroot, sysroot, output_dir)
375
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600376
377class BundlePinnedGuestImagesTest(BundleTestCase):
378 """Unittests for BundlePinnedGuestImages."""
379
Alex Klein231d2da2019-07-22 16:44:45 -0600380 def testValidateOnly(self):
381 """Sanity check that a validate only call does not execute any logic."""
382 patch = self.PatchObject(commands, 'BuildPinnedGuestImagesTarball')
383 artifacts.BundlePinnedGuestImages(self.input_proto, self.output_proto,
384 self.validate_only_config)
385 patch.assert_not_called()
386
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600387 def testBundlePinnedGuestImages(self):
388 """BundlePinnedGuestImages calls cbuildbot/commands with correct args."""
389 build_pinned_guest_images_tarball = self.PatchObject(
390 commands,
391 'BuildPinnedGuestImagesTarball',
392 return_value='pinned-guest-images.tar.gz')
Alex Klein231d2da2019-07-22 16:44:45 -0600393 artifacts.BundlePinnedGuestImages(self.input_proto, self.output_proto,
394 self.api_config)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600395 self.assertEqual(
396 [artifact.path for artifact in self.output_proto.artifacts],
Alex Klein231d2da2019-07-22 16:44:45 -0600397 [os.path.join(self.output_dir, 'pinned-guest-images.tar.gz')])
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600398 self.assertEqual(build_pinned_guest_images_tarball.call_args_list,
Alex Klein231d2da2019-07-22 16:44:45 -0600399 [mock.call(self.source_root, 'target', self.output_dir)])
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600400
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600401 def testBundlePinnedGuestImagesNoLogs(self):
Evan Hernandezde445982019-04-22 13:42:34 -0600402 """BundlePinnedGuestImages does not die when no pinned images found."""
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600403 self.PatchObject(commands, 'BuildPinnedGuestImagesTarball',
404 return_value=None)
Alex Klein231d2da2019-07-22 16:44:45 -0600405 artifacts.BundlePinnedGuestImages(self.input_proto, self.output_proto,
406 self.api_config)
Evan Hernandezde445982019-04-22 13:42:34 -0600407 self.assertFalse(self.output_proto.artifacts)
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600408
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600409
410class BundleFirmwareTest(BundleTestCase):
411 """Unittests for BundleFirmware."""
412
Alex Klein231d2da2019-07-22 16:44:45 -0600413 def testValidateOnly(self):
414 """Sanity check that a validate only call does not execute any logic."""
415 patch = self.PatchObject(artifacts_svc, 'BundleTastFiles')
416 artifacts.BundleFirmware(self.request, self.response,
417 self.validate_only_config)
418 patch.assert_not_called()
Michael Mortensen38675192019-06-28 16:52:55 +0000419
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600420 def testBundleFirmware(self):
421 """BundleFirmware calls cbuildbot/commands with correct args."""
Alex Klein231d2da2019-07-22 16:44:45 -0600422 self.PatchObject(
423 artifacts_svc,
424 'BuildFirmwareArchive',
425 return_value=os.path.join(self.output_dir, 'firmware.tar.gz'))
426
427 artifacts.BundleFirmware(self.request, self.response, self.api_config)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600428 self.assertEqual(
Alex Klein231d2da2019-07-22 16:44:45 -0600429 [artifact.path for artifact in self.response.artifacts],
430 [os.path.join(self.output_dir, 'firmware.tar.gz')])
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600431
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600432 def testBundleFirmwareNoLogs(self):
433 """BundleFirmware dies when no firmware found."""
434 self.PatchObject(commands, 'BuildFirmwareArchive', return_value=None)
435 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600436 artifacts.BundleFirmware(self.input_proto, self.output_proto,
437 self.api_config)
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600438
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600439
440class BundleEbuildLogsTest(BundleTestCase):
441 """Unittests for BundleEbuildLogs."""
442
Alex Klein231d2da2019-07-22 16:44:45 -0600443 def testValidateOnly(self):
444 """Sanity check that a validate only call does not execute any logic."""
445 patch = self.PatchObject(commands, 'BuildEbuildLogsTarball')
446 artifacts.BundleEbuildLogs(self.input_proto, self.output_proto,
447 self.validate_only_config)
448 patch.assert_not_called()
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600449
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600450 def testBundleEbuildLogs(self):
451 """BundleEbuildLogs calls cbuildbot/commands with correct args."""
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600452 bundle_ebuild_logs_tarball = self.PatchObject(
453 artifacts_svc, 'BundleEBuildLogsTarball',
454 return_value='ebuild-logs.tar.gz')
Alex Klein231d2da2019-07-22 16:44:45 -0600455 artifacts.BundleEbuildLogs(self.request, self.response, self.api_config)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600456 self.assertEqual(
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600457 [artifact.path for artifact in self.response.artifacts],
458 [os.path.join(self.request.output_dir, 'ebuild-logs.tar.gz')])
459 sysroot = sysroot_lib.Sysroot(self.sysroot_path)
Evan Hernandeza478d802019-04-08 15:08:24 -0600460 self.assertEqual(
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600461 bundle_ebuild_logs_tarball.call_args_list,
462 [mock.call(mock.ANY, sysroot, self.output_dir)])
463
464 def testBundleEBuildLogsOldProto(self):
465 bundle_ebuild_logs_tarball = self.PatchObject(
466 artifacts_svc, 'BundleEBuildLogsTarball',
467 return_value='ebuild-logs.tar.gz')
Alex Klein231d2da2019-07-22 16:44:45 -0600468
469 artifacts.BundleEbuildLogs(self.input_proto, self.output_proto,
470 self.api_config)
471
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600472 sysroot = sysroot_lib.Sysroot(self.sysroot_path)
473 self.assertEqual(
474 bundle_ebuild_logs_tarball.call_args_list,
475 [mock.call(mock.ANY, sysroot, self.output_dir)])
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600476
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600477 def testBundleEbuildLogsNoLogs(self):
478 """BundleEbuildLogs dies when no logs found."""
479 self.PatchObject(commands, 'BuildEbuildLogsTarball', return_value=None)
480 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600481 artifacts.BundleEbuildLogs(self.request, self.response, self.api_config)
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600482
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600483
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600484class BundleChromeOSConfigTest(BundleTestCase):
485 """Unittests for BundleChromeOSConfig"""
486
487 def testValidateOnly(self):
488 """Sanity check that a validate only call does not execute any logic."""
489 patch = self.PatchObject(artifacts_svc, 'BundleChromeOSConfig')
490 artifacts.BundleChromeOSConfig(self.input_proto, self.output_proto,
491 self.validate_only_config)
492 patch.assert_not_called()
493
494 def testBundleChromeOSConfigCallWithSysroot(self):
495 """Call with a request that sets sysroot."""
496 bundle_chromeos_config = self.PatchObject(
497 artifacts_svc, 'BundleChromeOSConfig', return_value='config.yaml')
498 artifacts.BundleChromeOSConfig(self.request, self.output_proto,
499 self.api_config)
500 self.assertEqual(
501 [artifact.path for artifact in self.output_proto.artifacts],
502 [os.path.join(self.output_dir, 'config.yaml')])
503
504 sysroot = sysroot_lib.Sysroot(self.sysroot_path)
505 self.assertEqual(bundle_chromeos_config.call_args_list,
506 [mock.call(mock.ANY, sysroot, self.output_dir)])
507
508 def testBundleChromeOSConfigCallWithBuildTarget(self):
509 """Call with a request that sets build_target."""
510 bundle_chromeos_config = self.PatchObject(
511 artifacts_svc, 'BundleChromeOSConfig', return_value='config.yaml')
512 artifacts.BundleChromeOSConfig(self.input_proto, self.output_proto,
513 self.api_config)
514
515 self.assertEqual(
516 [artifact.path for artifact in self.output_proto.artifacts],
517 [os.path.join(self.output_dir, 'config.yaml')])
518
519 sysroot = sysroot_lib.Sysroot(self.sysroot_path)
520 self.assertEqual(bundle_chromeos_config.call_args_list,
521 [mock.call(mock.ANY, sysroot, self.output_dir)])
522
523 def testBundleChromeOSConfigNoConfigFound(self):
524 """An error is raised if the config payload isn't found."""
525 self.PatchObject(artifacts_svc, 'BundleChromeOSConfig', return_value=None)
526
527 with self.assertRaises(cros_build_lib.DieSystemExit):
528 artifacts.BundleChromeOSConfig(self.request, self.output_proto,
529 self.api_config)
530
531
Alex Klein231d2da2019-07-22 16:44:45 -0600532class BundleTestUpdatePayloadsTest(cros_test_lib.MockTempDirTestCase,
533 api_config.ApiConfigMixin):
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600534 """Unittests for BundleTestUpdatePayloads."""
535
536 def setUp(self):
537 self.source_root = os.path.join(self.tempdir, 'cros')
538 osutils.SafeMakedirs(self.source_root)
539
540 self.archive_root = os.path.join(self.tempdir, 'output')
541 osutils.SafeMakedirs(self.archive_root)
542
543 self.target = 'target'
Evan Hernandez59690b72019-04-08 16:24:45 -0600544 self.image_root = os.path.join(self.source_root,
545 'src/build/images/target/latest')
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600546
547 self.input_proto = artifacts_pb2.BundleRequest()
548 self.input_proto.build_target.name = self.target
549 self.input_proto.output_dir = self.archive_root
550 self.output_proto = artifacts_pb2.BundleResponse()
551
552 self.PatchObject(constants, 'SOURCE_ROOT', new=self.source_root)
553
Alex Kleincb541e82019-06-26 15:06:11 -0600554 def MockPayloads(image_path, archive_dir):
555 osutils.WriteFile(os.path.join(archive_dir, 'payload1.bin'), image_path)
556 osutils.WriteFile(os.path.join(archive_dir, 'payload2.bin'), image_path)
557 return [os.path.join(archive_dir, 'payload1.bin'),
558 os.path.join(archive_dir, 'payload2.bin')]
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600559
Alex Kleincb541e82019-06-26 15:06:11 -0600560 self.bundle_patch = self.PatchObject(
561 artifacts_svc, 'BundleTestUpdatePayloads', side_effect=MockPayloads)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600562
Alex Klein231d2da2019-07-22 16:44:45 -0600563 def testValidateOnly(self):
564 """Sanity check that a validate only call does not execute any logic."""
565 patch = self.PatchObject(artifacts_svc, 'BundleTestUpdatePayloads')
566 artifacts.BundleTestUpdatePayloads(self.input_proto, self.output_proto,
567 self.validate_only_config)
568 patch.assert_not_called()
569
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600570 def testBundleTestUpdatePayloads(self):
571 """BundleTestUpdatePayloads calls cbuildbot/commands with correct args."""
572 image_path = os.path.join(self.image_root, constants.BASE_IMAGE_BIN)
573 osutils.WriteFile(image_path, 'image!', makedirs=True)
574
Alex Klein231d2da2019-07-22 16:44:45 -0600575 artifacts.BundleTestUpdatePayloads(self.input_proto, self.output_proto,
576 self.api_config)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600577
578 actual = [
579 os.path.relpath(artifact.path, self.archive_root)
580 for artifact in self.output_proto.artifacts
581 ]
Alex Kleincb541e82019-06-26 15:06:11 -0600582 expected = ['payload1.bin', 'payload2.bin']
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600583 self.assertItemsEqual(actual, expected)
584
585 actual = [
586 os.path.relpath(path, self.archive_root)
587 for path in osutils.DirectoryIterator(self.archive_root)
588 ]
589 self.assertItemsEqual(actual, expected)
590
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600591 def testBundleTestUpdatePayloadsNoImageDir(self):
592 """BundleTestUpdatePayloads dies if no image dir is found."""
593 # Intentionally do not write image directory.
594 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600595 artifacts.BundleTestUpdatePayloads(self.input_proto, self.output_proto,
596 self.api_config)
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600597
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600598 def testBundleTestUpdatePayloadsNoImage(self):
599 """BundleTestUpdatePayloads dies if no usable image is found for target."""
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600600 # Intentionally do not write image, but create the directory.
601 osutils.SafeMakedirs(self.image_root)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600602 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600603 artifacts.BundleTestUpdatePayloads(self.input_proto, self.output_proto,
604 self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600605
606
Alex Klein231d2da2019-07-22 16:44:45 -0600607class BundleSimpleChromeArtifactsTest(cros_test_lib.MockTempDirTestCase,
608 api_config.ApiConfigMixin):
Alex Klein2275d692019-04-23 16:04:12 -0600609 """BundleSimpleChromeArtifacts tests."""
610
611 def setUp(self):
612 self.chroot_dir = os.path.join(self.tempdir, 'chroot_dir')
613 self.sysroot_path = '/sysroot'
614 self.sysroot_dir = os.path.join(self.chroot_dir, 'sysroot')
615 osutils.SafeMakedirs(self.sysroot_dir)
616 self.output_dir = os.path.join(self.tempdir, 'output_dir')
617 osutils.SafeMakedirs(self.output_dir)
618
619 self.does_not_exist = os.path.join(self.tempdir, 'does_not_exist')
620
Alex Klein231d2da2019-07-22 16:44:45 -0600621 self.response = artifacts_pb2.BundleResponse()
622
Alex Klein2275d692019-04-23 16:04:12 -0600623 def _GetRequest(self, chroot=None, sysroot=None, build_target=None,
624 output_dir=None):
625 """Helper to create a request message instance.
626
627 Args:
628 chroot (str): The chroot path.
629 sysroot (str): The sysroot path.
630 build_target (str): The build target name.
631 output_dir (str): The output directory.
632 """
633 return artifacts_pb2.BundleRequest(
634 sysroot={'path': sysroot, 'build_target': {'name': build_target}},
635 chroot={'path': chroot}, output_dir=output_dir)
636
Alex Klein231d2da2019-07-22 16:44:45 -0600637 def testValidateOnly(self):
638 """Sanity check that a validate only call does not execute any logic."""
639 patch = self.PatchObject(artifacts_svc, 'BundleSimpleChromeArtifacts')
640 request = self._GetRequest(chroot=self.chroot_dir,
641 sysroot=self.sysroot_path,
642 build_target='board', output_dir=self.output_dir)
643 artifacts.BundleSimpleChromeArtifacts(request, self.response,
644 self.validate_only_config)
645 patch.assert_not_called()
Alex Klein2275d692019-04-23 16:04:12 -0600646
647 def testNoBuildTarget(self):
648 """Test no build target fails."""
649 request = self._GetRequest(chroot=self.chroot_dir,
650 sysroot=self.sysroot_path,
651 output_dir=self.output_dir)
Alex Klein231d2da2019-07-22 16:44:45 -0600652 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600653 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600654 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600655
656 def testNoSysroot(self):
657 """Test no sysroot fails."""
658 request = self._GetRequest(build_target='board', output_dir=self.output_dir)
Alex Klein231d2da2019-07-22 16:44:45 -0600659 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600660 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600661 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600662
663 def testSysrootDoesNotExist(self):
664 """Test no sysroot fails."""
665 request = self._GetRequest(build_target='board', output_dir=self.output_dir,
666 sysroot=self.does_not_exist)
Alex Klein231d2da2019-07-22 16:44:45 -0600667 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600668 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600669 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600670
671 def testNoOutputDir(self):
672 """Test no output dir fails."""
673 request = self._GetRequest(chroot=self.chroot_dir,
674 sysroot=self.sysroot_path,
675 build_target='board')
Alex Klein231d2da2019-07-22 16:44:45 -0600676 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600677 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600678 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600679
680 def testOutputDirDoesNotExist(self):
681 """Test no output dir fails."""
682 request = self._GetRequest(chroot=self.chroot_dir,
683 sysroot=self.sysroot_path,
684 build_target='board',
685 output_dir=self.does_not_exist)
Alex Klein231d2da2019-07-22 16:44:45 -0600686 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600687 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600688 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600689
690 def testOutputHandling(self):
691 """Test response output."""
692 files = ['file1', 'file2', 'file3']
693 expected_files = [os.path.join(self.output_dir, f) for f in files]
694 self.PatchObject(artifacts_svc, 'BundleSimpleChromeArtifacts',
695 return_value=expected_files)
696 request = self._GetRequest(chroot=self.chroot_dir,
697 sysroot=self.sysroot_path,
698 build_target='board', output_dir=self.output_dir)
Alex Klein231d2da2019-07-22 16:44:45 -0600699 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600700
Alex Klein231d2da2019-07-22 16:44:45 -0600701 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600702
703 self.assertTrue(response.artifacts)
704 self.assertItemsEqual(expected_files, [a.path for a in response.artifacts])
705
706
Alex Klein231d2da2019-07-22 16:44:45 -0600707class BundleVmFilesTest(cros_test_lib.MockTempDirTestCase,
708 api_config.ApiConfigMixin):
Alex Klein6504eca2019-04-18 15:37:56 -0600709 """BuildVmFiles tests."""
710
Alex Klein231d2da2019-07-22 16:44:45 -0600711 def setUp(self):
712 self.output_dir = os.path.join(self.tempdir, 'output')
713 osutils.SafeMakedirs(self.output_dir)
714
715 self.response = artifacts_pb2.BundleResponse()
716
Alex Klein6504eca2019-04-18 15:37:56 -0600717 def _GetInput(self, chroot=None, sysroot=None, test_results_dir=None,
718 output_dir=None):
719 """Helper to build out an input message instance.
720
721 Args:
722 chroot (str|None): The chroot path.
723 sysroot (str|None): The sysroot path relative to the chroot.
724 test_results_dir (str|None): The test results directory relative to the
725 sysroot.
726 output_dir (str|None): The directory where the results tarball should be
727 saved.
728 """
729 return artifacts_pb2.BundleVmFilesRequest(
730 chroot={'path': chroot}, sysroot={'path': sysroot},
731 test_results_dir=test_results_dir, output_dir=output_dir,
732 )
733
Alex Klein231d2da2019-07-22 16:44:45 -0600734 def testValidateOnly(self):
735 """Sanity check that a validate only call does not execute any logic."""
736 patch = self.PatchObject(artifacts_svc, 'BundleVmFiles')
737 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
738 test_results_dir='/test/results',
739 output_dir=self.output_dir)
740 artifacts.BundleVmFiles(in_proto, self.response, self.validate_only_config)
741 patch.assert_not_called()
Alex Klein6504eca2019-04-18 15:37:56 -0600742
743 def testChrootMissing(self):
744 """Test error handling for missing chroot."""
745 in_proto = self._GetInput(sysroot='/build/board',
746 test_results_dir='/test/results',
Alex Klein231d2da2019-07-22 16:44:45 -0600747 output_dir=self.output_dir)
Alex Klein6504eca2019-04-18 15:37:56 -0600748
749 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600750 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600751
Alex Klein6504eca2019-04-18 15:37:56 -0600752 def testTestResultsDirMissing(self):
753 """Test error handling for missing test results directory."""
754 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
Alex Klein231d2da2019-07-22 16:44:45 -0600755 output_dir=self.output_dir)
Alex Klein6504eca2019-04-18 15:37:56 -0600756
757 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600758 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600759
760 def testOutputDirMissing(self):
761 """Test error handling for missing output directory."""
762 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
763 test_results_dir='/test/results')
Alex Klein6504eca2019-04-18 15:37:56 -0600764
765 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600766 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
767
768 def testOutputDirDoesNotExist(self):
769 """Test error handling for output directory that does not exist."""
770 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
771 output_dir=os.path.join(self.tempdir, 'dne'),
772 test_results_dir='/test/results')
773
774 with self.assertRaises(cros_build_lib.DieSystemExit):
775 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600776
777 def testValidCall(self):
778 """Test image dir building."""
779 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
780 test_results_dir='/test/results',
Alex Klein231d2da2019-07-22 16:44:45 -0600781 output_dir=self.output_dir)
782
Alex Klein6504eca2019-04-18 15:37:56 -0600783 expected_files = ['/tmp/output/f1.tar', '/tmp/output/f2.tar']
Michael Mortensen51f06722019-07-18 09:55:50 -0600784 patch = self.PatchObject(artifacts_svc, 'BundleVmFiles',
Alex Klein6504eca2019-04-18 15:37:56 -0600785 return_value=expected_files)
786
Alex Klein231d2da2019-07-22 16:44:45 -0600787 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600788
Alex Klein231d2da2019-07-22 16:44:45 -0600789 patch.assert_called_with(mock.ANY, '/test/results', self.output_dir)
Alex Klein6504eca2019-04-18 15:37:56 -0600790
791 # Make sure we have artifacts, and that every artifact is an expected file.
Alex Klein231d2da2019-07-22 16:44:45 -0600792 self.assertTrue(self.response.artifacts)
793 for artifact in self.response.artifacts:
Alex Klein6504eca2019-04-18 15:37:56 -0600794 self.assertIn(artifact.path, expected_files)
795 expected_files.remove(artifact.path)
796
797 # Make sure we've seen all of the expected files.
798 self.assertFalse(expected_files)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700799
Alex Kleinb9d810b2019-07-01 12:38:02 -0600800
Tiancong Wang50b80a92019-08-01 14:46:15 -0700801
802class BundleAFDOGenerationArtifactsTestCase(
Alex Klein231d2da2019-07-22 16:44:45 -0600803 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin):
Tiancong Wang50b80a92019-08-01 14:46:15 -0700804 """Unittests for BundleAFDOGenerationArtifacts."""
805
806 @staticmethod
807 def mock_die(message, *args):
808 raise cros_build_lib.DieSystemExit(message % args)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700809
810 def setUp(self):
811 self.chroot_dir = os.path.join(self.tempdir, 'chroot_dir')
812 osutils.SafeMakedirs(self.chroot_dir)
813 temp_dir = os.path.join(self.chroot_dir, 'tmp')
814 osutils.SafeMakedirs(temp_dir)
815 self.output_dir = os.path.join(self.tempdir, 'output_dir')
816 osutils.SafeMakedirs(self.output_dir)
817 self.build_target = 'board'
Tiancong Wang24a3df72019-08-20 15:48:51 -0700818 self.valid_artifact_type = toolchain_pb2.ORDERFILE
819 self.invalid_artifact_type = toolchain_pb2.NONE_TYPE
Tiancong Wangc4805b72019-06-11 12:12:03 -0700820 self.does_not_exist = os.path.join(self.tempdir, 'does_not_exist')
Tiancong Wang50b80a92019-08-01 14:46:15 -0700821 self.PatchObject(cros_build_lib, 'Die', new=self.mock_die)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700822
Alex Klein231d2da2019-07-22 16:44:45 -0600823 self.response = artifacts_pb2.BundleResponse()
824
Tiancong Wang50b80a92019-08-01 14:46:15 -0700825 def _GetRequest(self, chroot=None, build_target=None, output_dir=None,
826 artifact_type=None):
Tiancong Wangc4805b72019-06-11 12:12:03 -0700827 """Helper to create a request message instance.
828
829 Args:
830 chroot (str): The chroot path.
831 build_target (str): The build target name.
832 output_dir (str): The output directory.
Tiancong Wang50b80a92019-08-01 14:46:15 -0700833 artifact_type (artifacts_pb2.AFDOArtifactType):
834 The type of the artifact.
Tiancong Wangc4805b72019-06-11 12:12:03 -0700835 """
Tiancong Wang50b80a92019-08-01 14:46:15 -0700836 return artifacts_pb2.BundleChromeAFDORequest(
Tiancong Wangc4805b72019-06-11 12:12:03 -0700837 chroot={'path': chroot},
Tiancong Wang50b80a92019-08-01 14:46:15 -0700838 build_target={'name': build_target},
839 output_dir=output_dir,
840 artifact_type=artifact_type,
Tiancong Wangc4805b72019-06-11 12:12:03 -0700841 )
842
Alex Klein231d2da2019-07-22 16:44:45 -0600843 def testValidateOnly(self):
844 """Sanity check that a validate only call does not execute any logic."""
845 patch = self.PatchObject(artifacts_svc,
Tiancong Wang50b80a92019-08-01 14:46:15 -0700846 'BundleAFDOGenerationArtifacts')
Alex Klein231d2da2019-07-22 16:44:45 -0600847 request = self._GetRequest(chroot=self.chroot_dir,
848 build_target=self.build_target,
Tiancong Wang50b80a92019-08-01 14:46:15 -0700849 output_dir=self.output_dir,
850 artifact_type=self.valid_artifact_type)
851 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
852 self.validate_only_config)
Alex Klein231d2da2019-07-22 16:44:45 -0600853 patch.assert_not_called()
Tiancong Wangc4805b72019-06-11 12:12:03 -0700854
855 def testNoBuildTarget(self):
856 """Test no build target fails."""
857 request = self._GetRequest(chroot=self.chroot_dir,
Tiancong Wang50b80a92019-08-01 14:46:15 -0700858 output_dir=self.output_dir,
859 artifact_type=self.valid_artifact_type)
860 with self.assertRaises(cros_build_lib.DieSystemExit) as context:
861 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
862 self.api_config)
863 self.assertEqual('build_target.name is required.',
864 str(context.exception))
Tiancong Wangc4805b72019-06-11 12:12:03 -0700865
866 def testNoOutputDir(self):
867 """Test no output dir fails."""
868 request = self._GetRequest(chroot=self.chroot_dir,
Tiancong Wang50b80a92019-08-01 14:46:15 -0700869 build_target=self.build_target,
870 artifact_type=self.valid_artifact_type)
871 with self.assertRaises(cros_build_lib.DieSystemExit) as context:
872 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
873 self.api_config)
874 self.assertEqual('output_dir is required.',
875 str(context.exception))
Tiancong Wangc4805b72019-06-11 12:12:03 -0700876
877 def testOutputDirDoesNotExist(self):
878 """Test output directory not existing fails."""
879 request = self._GetRequest(chroot=self.chroot_dir,
Tiancong Wangc4805b72019-06-11 12:12:03 -0700880 build_target=self.build_target,
Tiancong Wang50b80a92019-08-01 14:46:15 -0700881 output_dir=self.does_not_exist,
882 artifact_type=self.valid_artifact_type)
883 with self.assertRaises(cros_build_lib.DieSystemExit) as context:
884 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
885 self.api_config)
886 self.assertEqual(
887 'output_dir path does not exist: %s' % self.does_not_exist,
888 str(context.exception))
Tiancong Wangc4805b72019-06-11 12:12:03 -0700889
Tiancong Wang50b80a92019-08-01 14:46:15 -0700890 def testNoArtifactType(self):
891 """Test no artifact type."""
892 request = self._GetRequest(chroot=self.chroot_dir,
893 build_target=self.build_target,
894 output_dir=self.output_dir)
895 with self.assertRaises(cros_build_lib.DieSystemExit) as context:
896 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
897 self.api_config)
898 self.assertIn('artifact_type (0) must be in',
899 str(context.exception))
900
901 def testWrongArtifactType(self):
902 """Test passing wrong artifact type."""
903 request = self._GetRequest(chroot=self.chroot_dir,
904 build_target=self.build_target,
905 output_dir=self.output_dir,
906 artifact_type=self.invalid_artifact_type)
907 with self.assertRaises(cros_build_lib.DieSystemExit) as context:
908 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
909 self.api_config)
Tiancong Wang24a3df72019-08-20 15:48:51 -0700910 self.assertIn('artifact_type (%d) must be in' % self.invalid_artifact_type,
Tiancong Wang50b80a92019-08-01 14:46:15 -0700911 str(context.exception))
912
913 def testOutputHandlingOnOrderfile(self,
Tiancong Wang24a3df72019-08-20 15:48:51 -0700914 artifact_type=toolchain_pb2.ORDERFILE):
Tiancong Wang50b80a92019-08-01 14:46:15 -0700915 """Test response output for orderfile."""
916 files = ['artifact1', 'artifact2', 'artifact3']
Tiancong Wangc4805b72019-06-11 12:12:03 -0700917 expected_files = [os.path.join(self.output_dir, f) for f in files]
Tiancong Wang50b80a92019-08-01 14:46:15 -0700918 self.PatchObject(artifacts_svc, 'BundleAFDOGenerationArtifacts',
Tiancong Wangc4805b72019-06-11 12:12:03 -0700919 return_value=expected_files)
Alex Klein231d2da2019-07-22 16:44:45 -0600920
Tiancong Wangc4805b72019-06-11 12:12:03 -0700921 request = self._GetRequest(chroot=self.chroot_dir,
Tiancong Wangc4805b72019-06-11 12:12:03 -0700922 build_target=self.build_target,
Tiancong Wang50b80a92019-08-01 14:46:15 -0700923 output_dir=self.output_dir,
924 artifact_type=artifact_type)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700925
Tiancong Wang50b80a92019-08-01 14:46:15 -0700926 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
927 self.api_config)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700928
Tiancong Wang50b80a92019-08-01 14:46:15 -0700929 self.assertTrue(self.response.artifacts)
930 self.assertItemsEqual(expected_files,
931 [a.path for a in self.response.artifacts])
932
933 def testOutputHandlingOnAFDO(self):
934 """Test response output for AFDO."""
935 self.testOutputHandlingOnOrderfile(
Tiancong Wang24a3df72019-08-20 15:48:51 -0700936 artifact_type=toolchain_pb2.BENCHMARK_AFDO)
Alex Klein0b1cbfc2019-08-14 10:09:58 -0600937
938
939class ExportCpeReportTest(cros_test_lib.MockTempDirTestCase,
940 api_config.ApiConfigMixin):
941 """ExportCpeReport tests."""
942
943 def setUp(self):
944 self.response = artifacts_pb2.BundleResponse()
945
946 def testValidateOnly(self):
947 """Sanity check validate only calls don't execute."""
948 patch = self.PatchObject(artifacts_svc, 'GenerateCpeReport')
949
950 request = artifacts_pb2.BundleRequest()
951 request.build_target.name = 'board'
952 request.output_dir = self.tempdir
953
954 artifacts.ExportCpeReport(request, self.response, self.validate_only_config)
955
956 patch.assert_not_called()
957
958 def testNoBuildTarget(self):
959 request = artifacts_pb2.BundleRequest()
960 request.output_dir = self.tempdir
961
962 with self.assertRaises(cros_build_lib.DieSystemExit):
963 artifacts.ExportCpeReport(request, self.response, self.api_config)
964
965 def testSuccess(self):
966 """Test success case."""
967 expected = artifacts_svc.CpeResult(
968 report='/output/report.json', warnings='/output/warnings.json')
969 self.PatchObject(artifacts_svc, 'GenerateCpeReport', return_value=expected)
970
971 request = artifacts_pb2.BundleRequest()
972 request.build_target.name = 'board'
973 request.output_dir = self.tempdir
974
975 artifacts.ExportCpeReport(request, self.response, self.api_config)
976
977 for artifact in self.response.artifacts:
978 self.assertIn(artifact.path, [expected.report, expected.warnings])