blob: 862340a6d7cb20411d51047f4ff908b1c273ffff [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'
Alex Klein68c8fdf2019-09-25 15:09:11 -060073 self.sysroot = sysroot_lib.Sysroot(self.sysroot_path)
Alex Klein231d2da2019-07-22 16:44:45 -060074 self.chroot_path = os.path.join(self.tempdir, 'chroot')
75 full_sysroot_path = os.path.join(self.chroot_path,
76 self.sysroot_path.lstrip(os.sep))
77 osutils.SafeMakedirs(full_sysroot_path)
78
Alex Klein68c8fdf2019-09-25 15:09:11 -060079 # All requests use same response type.
Alex Klein231d2da2019-07-22 16:44:45 -060080 self.response = artifacts_pb2.BundleResponse()
81
Alex Klein68c8fdf2019-09-25 15:09:11 -060082 # Build target request.
83 self.target_request = self.BuildTargetRequest(
84 build_target='target',
85 output_dir=self.output_dir,
86 chroot=self.chroot_path)
87
88 # Sysroot request.
89 self.sysroot_request = self.SysrootRequest(
90 sysroot=self.sysroot_path,
91 build_target='target',
92 output_dir=self.output_dir,
93 chroot=self.chroot_path)
94
Alex Klein231d2da2019-07-22 16:44:45 -060095 self.source_root = self.tempdir
96 self.PatchObject(constants, 'SOURCE_ROOT', new=self.tempdir)
Evan Hernandezf388cbf2019-04-01 11:15:23 -060097
98
Alex Kleind91e95a2019-09-17 10:39:02 -060099class BundleImageArchivesTest(BundleTestCase):
100 """BundleImageArchives tests."""
101
102 def testValidateOnly(self):
103 """Sanity check that a validate only call does not execute any logic."""
104 patch = self.PatchObject(artifacts_svc, 'ArchiveImages')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600105 artifacts.BundleImageArchives(self.target_request, self.response,
Alex Kleind91e95a2019-09-17 10:39:02 -0600106 self.validate_only_config)
107 patch.assert_not_called()
108
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700109 def testMockCall(self):
110 """Test that a mock call does not execute logic, returns mocked value."""
111 patch = self.PatchObject(artifacts_svc, 'ArchiveImages')
112 artifacts.BundleImageArchives(self.target_request, self.response,
113 self.mock_call_config)
114 patch.assert_not_called()
115 self.assertEqual(len(self.response.artifacts), 2)
116 self.assertEqual(self.response.artifacts[0].path,
117 os.path.join(self.output_dir, 'path0.tar.xz'))
118 self.assertEqual(self.response.artifacts[1].path,
119 os.path.join(self.output_dir, 'path1.tar.xz'))
120
Alex Kleind91e95a2019-09-17 10:39:02 -0600121 def testNoBuildTarget(self):
122 """Test that no build target fails."""
123 request = self.BuildTargetRequest(output_dir=self.tempdir)
124 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein68c8fdf2019-09-25 15:09:11 -0600125 artifacts.BundleImageArchives(request, self.response, self.api_config)
Alex Kleind91e95a2019-09-17 10:39:02 -0600126
127 def testNoOutputDir(self):
128 """Test no output dir fails."""
129 request = self.BuildTargetRequest(build_target='board')
130 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein68c8fdf2019-09-25 15:09:11 -0600131 artifacts.BundleImageArchives(request, self.response, self.api_config)
Alex Kleind91e95a2019-09-17 10:39:02 -0600132
133 def testInvalidOutputDir(self):
134 """Test invalid output dir fails."""
135 request = self.BuildTargetRequest(
136 build_target='board', output_dir=os.path.join(self.tempdir, 'DNE'))
137 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein68c8fdf2019-09-25 15:09:11 -0600138 artifacts.BundleImageArchives(request, self.response, self.api_config)
Alex Kleind91e95a2019-09-17 10:39:02 -0600139
140 def testOutputHandling(self):
141 """Test the artifact output handling."""
142 expected = [os.path.join(self.output_dir, f) for f in ('a', 'b', 'c')]
143 self.PatchObject(artifacts_svc, 'ArchiveImages', return_value=expected)
144 self.PatchObject(os.path, 'exists', return_value=True)
145
Alex Klein68c8fdf2019-09-25 15:09:11 -0600146 artifacts.BundleImageArchives(self.target_request, self.response,
Alex Kleind91e95a2019-09-17 10:39:02 -0600147 self.api_config)
148
Mike Frysinger678735c2019-09-28 18:23:28 -0400149 self.assertCountEqual(expected, [a.path for a in self.response.artifacts])
Alex Kleind91e95a2019-09-17 10:39:02 -0600150
151
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600152class BundleImageZipTest(BundleTestCase):
153 """Unittests for BundleImageZip."""
154
Alex Klein231d2da2019-07-22 16:44:45 -0600155 def testValidateOnly(self):
156 """Sanity check that a validate only call does not execute any logic."""
157 patch = self.PatchObject(commands, 'BuildImageZip')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600158 artifacts.BundleImageZip(self.target_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600159 self.validate_only_config)
160 patch.assert_not_called()
161
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700162 def testMockCall(self):
163 """Test that a mock call does not execute logic, returns mocked value."""
164 patch = self.PatchObject(commands, 'BuildImageZip')
165 artifacts.BundleImageZip(self.target_request, self.response,
166 self.mock_call_config)
167 patch.assert_not_called()
168 self.assertEqual(len(self.response.artifacts), 1)
169 self.assertEqual(self.response.artifacts[0].path,
170 os.path.join(self.output_dir, 'image.zip'))
171
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600172 def testBundleImageZip(self):
173 """BundleImageZip calls cbuildbot/commands with correct args."""
Michael Mortensen01910922019-07-24 14:48:10 -0600174 bundle_image_zip = self.PatchObject(
175 artifacts_svc, 'BundleImageZip', return_value='image.zip')
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600176 self.PatchObject(os.path, 'exists', return_value=True)
Alex Klein68c8fdf2019-09-25 15:09:11 -0600177 artifacts.BundleImageZip(self.target_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600178 self.api_config)
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600179 self.assertEqual(
Alex Klein68c8fdf2019-09-25 15:09:11 -0600180 [artifact.path for artifact in self.response.artifacts],
Alex Klein231d2da2019-07-22 16:44:45 -0600181 [os.path.join(self.output_dir, 'image.zip')])
182
183 latest = os.path.join(self.source_root, 'src/build/images/target/latest')
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600184 self.assertEqual(
Michael Mortensen01910922019-07-24 14:48:10 -0600185 bundle_image_zip.call_args_list,
Alex Klein231d2da2019-07-22 16:44:45 -0600186 [mock.call(self.output_dir, latest)])
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600187
188 def testBundleImageZipNoImageDir(self):
189 """BundleImageZip dies when image dir does not exist."""
190 self.PatchObject(os.path, 'exists', return_value=False)
191 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein68c8fdf2019-09-25 15:09:11 -0600192 artifacts.BundleImageZip(self.target_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600193 self.api_config)
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600194
195
Alex Klein68c8fdf2019-09-25 15:09:11 -0600196class BundleAutotestFilesTest(BundleTestCase):
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600197 """Unittests for BundleAutotestFiles."""
198
Alex Klein231d2da2019-07-22 16:44:45 -0600199 def testValidateOnly(self):
200 """Sanity check that a validate only call does not execute any logic."""
201 patch = self.PatchObject(artifacts_svc, 'BundleAutotestFiles')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600202 artifacts.BundleAutotestFiles(self.target_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600203 self.validate_only_config)
204 patch.assert_not_called()
205
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700206 def testMockCall(self):
207 """Test that a mock call does not execute logic, returns mocked value."""
208 patch = self.PatchObject(artifacts_svc, 'BundleAutotestFiles')
209 artifacts.BundleAutotestFiles(self.target_request, self.response,
210 self.mock_call_config)
211 patch.assert_not_called()
212 self.assertEqual(len(self.response.artifacts), 1)
213 self.assertEqual(self.response.artifacts[0].path,
214 os.path.join(self.output_dir, 'autotest-a.tar.gz'))
215
Alex Klein238d8862019-05-07 11:32:46 -0600216 def testBundleAutotestFilesLegacy(self):
217 """BundleAutotestFiles calls service correctly with legacy args."""
218 files = {
219 artifacts_svc.ARCHIVE_CONTROL_FILES: '/tmp/artifacts/autotest-a.tar.gz',
220 artifacts_svc.ARCHIVE_PACKAGES: '/tmp/artifacts/autotest-b.tar.gz',
221 }
222 patch = self.PatchObject(artifacts_svc, 'BundleAutotestFiles',
223 return_value=files)
224
Alex Klein68c8fdf2019-09-25 15:09:11 -0600225 artifacts.BundleAutotestFiles(self.target_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600226 self.api_config)
Alex Klein238d8862019-05-07 11:32:46 -0600227
Alex Klein238d8862019-05-07 11:32:46 -0600228 # Verify the arguments are being passed through.
Alex Kleine21a0952019-08-23 16:08:16 -0600229 patch.assert_called_with(mock.ANY, self.sysroot, self.output_dir)
Alex Klein238d8862019-05-07 11:32:46 -0600230
231 # Verify the output proto is being populated correctly.
Alex Klein68c8fdf2019-09-25 15:09:11 -0600232 self.assertTrue(self.response.artifacts)
233 paths = [artifact.path for artifact in self.response.artifacts]
Mike Frysinger1f4478c2019-10-20 18:33:17 -0400234 self.assertCountEqual(list(files.values()), paths)
Alex Klein238d8862019-05-07 11:32:46 -0600235
236 def testBundleAutotestFiles(self):
237 """BundleAutotestFiles calls service correctly."""
238 files = {
239 artifacts_svc.ARCHIVE_CONTROL_FILES: '/tmp/artifacts/autotest-a.tar.gz',
240 artifacts_svc.ARCHIVE_PACKAGES: '/tmp/artifacts/autotest-b.tar.gz',
241 }
242 patch = self.PatchObject(artifacts_svc, 'BundleAutotestFiles',
243 return_value=files)
244
Alex Klein68c8fdf2019-09-25 15:09:11 -0600245 artifacts.BundleAutotestFiles(self.sysroot_request, self.response,
246 self.api_config)
Alex Klein238d8862019-05-07 11:32:46 -0600247
248 # Verify the arguments are being passed through.
Alex Kleine21a0952019-08-23 16:08:16 -0600249 patch.assert_called_with(mock.ANY, self.sysroot, self.output_dir)
Alex Klein238d8862019-05-07 11:32:46 -0600250
251 # Verify the output proto is being populated correctly.
252 self.assertTrue(self.response.artifacts)
253 paths = [artifact.path for artifact in self.response.artifacts]
Mike Frysinger1f4478c2019-10-20 18:33:17 -0400254 self.assertCountEqual(list(files.values()), paths)
Alex Klein238d8862019-05-07 11:32:46 -0600255
256 def testInvalidOutputDir(self):
257 """Test invalid output directory argument."""
Alex Klein68c8fdf2019-09-25 15:09:11 -0600258 request = self.SysrootRequest(chroot=self.chroot_path,
259 sysroot=self.sysroot_path)
Alex Klein238d8862019-05-07 11:32:46 -0600260
261 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600262 artifacts.BundleAutotestFiles(request, self.response, self.api_config)
Alex Klein238d8862019-05-07 11:32:46 -0600263
264 def testInvalidSysroot(self):
265 """Test no sysroot directory."""
Alex Klein68c8fdf2019-09-25 15:09:11 -0600266 request = self.SysrootRequest(chroot=self.chroot_path,
267 output_dir=self.output_dir)
Alex Klein238d8862019-05-07 11:32:46 -0600268
269 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600270 artifacts.BundleAutotestFiles(request, self.response, self.api_config)
Alex Klein238d8862019-05-07 11:32:46 -0600271
272 def testSysrootDoesNotExist(self):
273 """Test dies when no sysroot does not exist."""
Alex Klein68c8fdf2019-09-25 15:09:11 -0600274 request = self.SysrootRequest(chroot=self.chroot_path,
275 sysroot='/does/not/exist',
276 output_dir=self.output_dir)
Alex Klein238d8862019-05-07 11:32:46 -0600277
278 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600279 artifacts.BundleAutotestFiles(request, self.response, self.api_config)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600280
281
282class BundleTastFilesTest(BundleTestCase):
283 """Unittests for BundleTastFiles."""
284
Alex Klein231d2da2019-07-22 16:44:45 -0600285 def testValidateOnly(self):
286 """Sanity check that a validate only call does not execute any logic."""
287 patch = self.PatchObject(artifacts_svc, 'BundleTastFiles')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600288 artifacts.BundleTastFiles(self.target_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600289 self.validate_only_config)
290 patch.assert_not_called()
291
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700292 def testMockCall(self):
293 """Test that a mock call does not execute logic, returns mocked value."""
294 patch = self.PatchObject(artifacts_svc, 'BundleTastFiles')
295 artifacts.BundleTastFiles(self.target_request, self.response,
296 self.mock_call_config)
297 patch.assert_not_called()
298 self.assertEqual(len(self.response.artifacts), 1)
299 self.assertEqual(self.response.artifacts[0].path,
300 os.path.join(self.output_dir, 'tast_bundles.tar.gz'))
301
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600302 def testBundleTastFilesNoLogs(self):
LaMont Jonesb9793cd2020-06-11 08:14:46 -0600303 """BundleTasteFiles succeeds when no tast files found."""
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600304 self.PatchObject(commands, 'BuildTastBundleTarball',
305 return_value=None)
LaMont Jonesb9793cd2020-06-11 08:14:46 -0600306 artifacts.BundleTastFiles(self.target_request, self.response,
307 self.api_config)
308 self.assertEqual(list(self.response.artifacts), [])
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600309
Alex Kleinb9d810b2019-07-01 12:38:02 -0600310 def testBundleTastFilesLegacy(self):
311 """BundleTastFiles handles legacy args correctly."""
312 buildroot = self.tempdir
313 chroot_dir = os.path.join(buildroot, 'chroot')
314 sysroot_path = os.path.join(chroot_dir, 'build', 'board')
315 output_dir = os.path.join(self.tempdir, 'results')
316 osutils.SafeMakedirs(sysroot_path)
317 osutils.SafeMakedirs(output_dir)
318
Alex Klein171da612019-08-06 14:00:42 -0600319 chroot = chroot_lib.Chroot(chroot_dir)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600320 sysroot = sysroot_lib.Sysroot('/build/board')
321
322 expected_archive = os.path.join(output_dir, artifacts_svc.TAST_BUNDLE_NAME)
323 # Patch the service being called.
324 bundle_patch = self.PatchObject(artifacts_svc, 'BundleTastFiles',
325 return_value=expected_archive)
326 self.PatchObject(constants, 'SOURCE_ROOT', new=buildroot)
327
328 request = artifacts_pb2.BundleRequest(build_target={'name': 'board'},
329 output_dir=output_dir)
Alex Klein68c8fdf2019-09-25 15:09:11 -0600330 artifacts.BundleTastFiles(request, self.response, self.api_config)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600331 self.assertEqual(
Alex Klein68c8fdf2019-09-25 15:09:11 -0600332 [artifact.path for artifact in self.response.artifacts],
Alex Kleinb9d810b2019-07-01 12:38:02 -0600333 [expected_archive])
334 bundle_patch.assert_called_once_with(chroot, sysroot, output_dir)
335
336 def testBundleTastFiles(self):
337 """BundleTastFiles calls service correctly."""
Alex Kleinb49be8a2019-12-20 10:23:03 -0700338 chroot = chroot_lib.Chroot(self.chroot_path)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600339
Alex Klein68c8fdf2019-09-25 15:09:11 -0600340 expected_archive = os.path.join(self.output_dir,
341 artifacts_svc.TAST_BUNDLE_NAME)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600342 # Patch the service being called.
343 bundle_patch = self.PatchObject(artifacts_svc, 'BundleTastFiles',
344 return_value=expected_archive)
345
Alex Klein68c8fdf2019-09-25 15:09:11 -0600346 artifacts.BundleTastFiles(self.sysroot_request, self.response,
347 self.api_config)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600348
349 # Make sure the artifact got recorded successfully.
Alex Klein68c8fdf2019-09-25 15:09:11 -0600350 self.assertTrue(self.response.artifacts)
351 self.assertEqual(expected_archive, self.response.artifacts[0].path)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600352 # Make sure the service got called correctly.
Alex Klein68c8fdf2019-09-25 15:09:11 -0600353 bundle_patch.assert_called_once_with(chroot, self.sysroot, self.output_dir)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600354
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600355
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600356class BundleFirmwareTest(BundleTestCase):
357 """Unittests for BundleFirmware."""
358
Alex Klein231d2da2019-07-22 16:44:45 -0600359 def testValidateOnly(self):
360 """Sanity check that a validate only call does not execute any logic."""
361 patch = self.PatchObject(artifacts_svc, 'BundleTastFiles')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600362 artifacts.BundleFirmware(self.sysroot_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600363 self.validate_only_config)
364 patch.assert_not_called()
Michael Mortensen38675192019-06-28 16:52:55 +0000365
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700366 def testMockCall(self):
367 """Test that a mock call does not execute logic, returns mocked value."""
368 patch = self.PatchObject(artifacts_svc, 'BundleTastFiles')
369 artifacts.BundleFirmware(self.sysroot_request, self.response,
370 self.mock_call_config)
371 patch.assert_not_called()
372 self.assertEqual(len(self.response.artifacts), 1)
373 self.assertEqual(self.response.artifacts[0].path,
374 os.path.join(self.output_dir, 'firmware.tar.gz'))
375
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600376 def testBundleFirmware(self):
377 """BundleFirmware calls cbuildbot/commands with correct args."""
Alex Klein231d2da2019-07-22 16:44:45 -0600378 self.PatchObject(
379 artifacts_svc,
380 'BuildFirmwareArchive',
381 return_value=os.path.join(self.output_dir, 'firmware.tar.gz'))
382
Alex Klein68c8fdf2019-09-25 15:09:11 -0600383 artifacts.BundleFirmware(self.sysroot_request, self.response,
384 self.api_config)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600385 self.assertEqual(
Alex Klein231d2da2019-07-22 16:44:45 -0600386 [artifact.path for artifact in self.response.artifacts],
387 [os.path.join(self.output_dir, 'firmware.tar.gz')])
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600388
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600389 def testBundleFirmwareNoLogs(self):
390 """BundleFirmware dies when no firmware found."""
391 self.PatchObject(commands, 'BuildFirmwareArchive', return_value=None)
392 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein68c8fdf2019-09-25 15:09:11 -0600393 artifacts.BundleFirmware(self.sysroot_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600394 self.api_config)
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600395
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600396
Yicheng Liea1181f2020-09-22 11:51:10 -0700397class BundleFpmcuUnittestsTest(BundleTestCase):
398 """Unittests for BundleFpmcuUnittests."""
399
400 def testValidateOnly(self):
401 """Sanity check that a validate only call does not execute any logic."""
402 patch = self.PatchObject(artifacts_svc, 'BundleFpmcuUnittests')
403 artifacts.BundleFpmcuUnittests(self.sysroot_request, self.response,
404 self.validate_only_config)
405 patch.assert_not_called()
406
407 def testMockCall(self):
408 """Test that a mock call does not execute logic, returns mocked value."""
409 patch = self.PatchObject(artifacts_svc, 'BundleFpmcuUnittests')
410 artifacts.BundleFpmcuUnittests(self.sysroot_request, self.response,
411 self.mock_call_config)
412 patch.assert_not_called()
413 self.assertEqual(len(self.response.artifacts), 1)
414 self.assertEqual(self.response.artifacts[0].path,
415 os.path.join(self.output_dir,
416 'fpmcu_unittests.tar.gz'))
417
418 def testBundleFpmcuUnittests(self):
419 """BundleFpmcuUnittests calls cbuildbot/commands with correct args."""
420 self.PatchObject(
421 artifacts_svc,
422 'BundleFpmcuUnittests',
423 return_value=os.path.join(self.output_dir, 'fpmcu_unittests.tar.gz'))
424 artifacts.BundleFpmcuUnittests(self.sysroot_request, self.response,
425 self.api_config)
426 self.assertEqual(
427 [artifact.path for artifact in self.response.artifacts],
428 [os.path.join(self.output_dir, 'fpmcu_unittests.tar.gz')])
429
430 def testBundleFpmcuUnittestsNoLogs(self):
431 """BundleFpmcuUnittests does not die when no fpmcu unittests found."""
432 self.PatchObject(artifacts_svc, 'BundleFpmcuUnittests',
433 return_value=None)
434 artifacts.BundleFpmcuUnittests(self.sysroot_request, self.response,
435 self.api_config)
436 self.assertFalse(self.response.artifacts)
437
438
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600439class BundleEbuildLogsTest(BundleTestCase):
440 """Unittests for BundleEbuildLogs."""
441
Alex Klein231d2da2019-07-22 16:44:45 -0600442 def testValidateOnly(self):
443 """Sanity check that a validate only call does not execute any logic."""
444 patch = self.PatchObject(commands, 'BuildEbuildLogsTarball')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600445 artifacts.BundleEbuildLogs(self.target_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600446 self.validate_only_config)
447 patch.assert_not_called()
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600448
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700449 def testMockCall(self):
450 """Test that a mock call does not execute logic, returns mocked value."""
451 patch = self.PatchObject(commands, 'BuildEbuildLogsTarball')
452 artifacts.BundleEbuildLogs(self.target_request, self.response,
453 self.mock_call_config)
454 patch.assert_not_called()
455 self.assertEqual(len(self.response.artifacts), 1)
456 self.assertEqual(self.response.artifacts[0].path,
457 os.path.join(self.output_dir, 'ebuild-logs.tar.gz'))
458
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600459 def testBundleEbuildLogs(self):
460 """BundleEbuildLogs calls cbuildbot/commands with correct args."""
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600461 bundle_ebuild_logs_tarball = self.PatchObject(
462 artifacts_svc, 'BundleEBuildLogsTarball',
463 return_value='ebuild-logs.tar.gz')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600464 artifacts.BundleEbuildLogs(self.sysroot_request, self.response,
465 self.api_config)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600466 self.assertEqual(
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600467 [artifact.path for artifact in self.response.artifacts],
Alex Klein68c8fdf2019-09-25 15:09:11 -0600468 [os.path.join(self.output_dir, 'ebuild-logs.tar.gz')])
Evan Hernandeza478d802019-04-08 15:08:24 -0600469 self.assertEqual(
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600470 bundle_ebuild_logs_tarball.call_args_list,
Alex Klein68c8fdf2019-09-25 15:09:11 -0600471 [mock.call(mock.ANY, self.sysroot, self.output_dir)])
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600472
473 def testBundleEBuildLogsOldProto(self):
474 bundle_ebuild_logs_tarball = self.PatchObject(
475 artifacts_svc, 'BundleEBuildLogsTarball',
476 return_value='ebuild-logs.tar.gz')
Alex Klein231d2da2019-07-22 16:44:45 -0600477
Alex Klein68c8fdf2019-09-25 15:09:11 -0600478 artifacts.BundleEbuildLogs(self.target_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600479 self.api_config)
480
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600481 self.assertEqual(
482 bundle_ebuild_logs_tarball.call_args_list,
Alex Klein68c8fdf2019-09-25 15:09:11 -0600483 [mock.call(mock.ANY, self.sysroot, self.output_dir)])
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600484
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600485 def testBundleEbuildLogsNoLogs(self):
486 """BundleEbuildLogs dies when no logs found."""
487 self.PatchObject(commands, 'BuildEbuildLogsTarball', return_value=None)
488 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein68c8fdf2019-09-25 15:09:11 -0600489 artifacts.BundleEbuildLogs(self.sysroot_request, self.response,
490 self.api_config)
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600491
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600492
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600493class BundleChromeOSConfigTest(BundleTestCase):
494 """Unittests for BundleChromeOSConfig"""
495
496 def testValidateOnly(self):
497 """Sanity check that a validate only call does not execute any logic."""
498 patch = self.PatchObject(artifacts_svc, 'BundleChromeOSConfig')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600499 artifacts.BundleChromeOSConfig(self.target_request, self.response,
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600500 self.validate_only_config)
501 patch.assert_not_called()
502
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700503 def testMockCall(self):
504 """Test that a mock call does not execute logic, returns mocked value."""
505 patch = self.PatchObject(artifacts_svc, 'BundleChromeOSConfig')
506 artifacts.BundleChromeOSConfig(self.target_request, self.response,
507 self.mock_call_config)
508 patch.assert_not_called()
509 self.assertEqual(len(self.response.artifacts), 1)
510 self.assertEqual(self.response.artifacts[0].path,
511 os.path.join(self.output_dir, 'config.yaml'))
512
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600513 def testBundleChromeOSConfigCallWithSysroot(self):
514 """Call with a request that sets sysroot."""
515 bundle_chromeos_config = self.PatchObject(
516 artifacts_svc, 'BundleChromeOSConfig', return_value='config.yaml')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600517 artifacts.BundleChromeOSConfig(self.sysroot_request, self.response,
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600518 self.api_config)
519 self.assertEqual(
Alex Klein68c8fdf2019-09-25 15:09:11 -0600520 [artifact.path for artifact in self.response.artifacts],
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600521 [os.path.join(self.output_dir, 'config.yaml')])
522
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600523 self.assertEqual(bundle_chromeos_config.call_args_list,
Alex Klein68c8fdf2019-09-25 15:09:11 -0600524 [mock.call(mock.ANY, self.sysroot, self.output_dir)])
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600525
526 def testBundleChromeOSConfigCallWithBuildTarget(self):
527 """Call with a request that sets build_target."""
528 bundle_chromeos_config = self.PatchObject(
529 artifacts_svc, 'BundleChromeOSConfig', return_value='config.yaml')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600530 artifacts.BundleChromeOSConfig(self.target_request, self.response,
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600531 self.api_config)
532
533 self.assertEqual(
Alex Klein68c8fdf2019-09-25 15:09:11 -0600534 [artifact.path for artifact in self.response.artifacts],
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600535 [os.path.join(self.output_dir, 'config.yaml')])
536
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600537 self.assertEqual(bundle_chromeos_config.call_args_list,
Alex Klein68c8fdf2019-09-25 15:09:11 -0600538 [mock.call(mock.ANY, self.sysroot, self.output_dir)])
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600539
540 def testBundleChromeOSConfigNoConfigFound(self):
541 """An error is raised if the config payload isn't found."""
542 self.PatchObject(artifacts_svc, 'BundleChromeOSConfig', return_value=None)
543
544 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein68c8fdf2019-09-25 15:09:11 -0600545 artifacts.BundleChromeOSConfig(self.sysroot_request, self.response,
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600546 self.api_config)
547
548
Alex Klein231d2da2019-07-22 16:44:45 -0600549class BundleTestUpdatePayloadsTest(cros_test_lib.MockTempDirTestCase,
550 api_config.ApiConfigMixin):
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600551 """Unittests for BundleTestUpdatePayloads."""
552
553 def setUp(self):
554 self.source_root = os.path.join(self.tempdir, 'cros')
555 osutils.SafeMakedirs(self.source_root)
556
557 self.archive_root = os.path.join(self.tempdir, 'output')
558 osutils.SafeMakedirs(self.archive_root)
559
560 self.target = 'target'
Evan Hernandez59690b72019-04-08 16:24:45 -0600561 self.image_root = os.path.join(self.source_root,
562 'src/build/images/target/latest')
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600563
564 self.input_proto = artifacts_pb2.BundleRequest()
565 self.input_proto.build_target.name = self.target
566 self.input_proto.output_dir = self.archive_root
567 self.output_proto = artifacts_pb2.BundleResponse()
568
569 self.PatchObject(constants, 'SOURCE_ROOT', new=self.source_root)
570
Alex Kleincb541e82019-06-26 15:06:11 -0600571 def MockPayloads(image_path, archive_dir):
572 osutils.WriteFile(os.path.join(archive_dir, 'payload1.bin'), image_path)
573 osutils.WriteFile(os.path.join(archive_dir, 'payload2.bin'), image_path)
574 return [os.path.join(archive_dir, 'payload1.bin'),
575 os.path.join(archive_dir, 'payload2.bin')]
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600576
Alex Kleincb541e82019-06-26 15:06:11 -0600577 self.bundle_patch = self.PatchObject(
578 artifacts_svc, 'BundleTestUpdatePayloads', side_effect=MockPayloads)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600579
Alex Klein231d2da2019-07-22 16:44:45 -0600580 def testValidateOnly(self):
581 """Sanity check that a validate only call does not execute any logic."""
582 patch = self.PatchObject(artifacts_svc, 'BundleTestUpdatePayloads')
583 artifacts.BundleTestUpdatePayloads(self.input_proto, self.output_proto,
584 self.validate_only_config)
585 patch.assert_not_called()
586
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700587 def testMockCall(self):
588 """Test that a mock call does not execute logic, returns mocked value."""
589 patch = self.PatchObject(artifacts_svc, 'BundleTestUpdatePayloads')
590 artifacts.BundleTestUpdatePayloads(self.input_proto, self.output_proto,
591 self.mock_call_config)
592 patch.assert_not_called()
593 self.assertEqual(len(self.output_proto.artifacts), 1)
594 self.assertEqual(self.output_proto.artifacts[0].path,
595 os.path.join(self.archive_root, 'payload1.bin'))
596
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600597 def testBundleTestUpdatePayloads(self):
598 """BundleTestUpdatePayloads calls cbuildbot/commands with correct args."""
599 image_path = os.path.join(self.image_root, constants.BASE_IMAGE_BIN)
600 osutils.WriteFile(image_path, 'image!', makedirs=True)
601
Alex Klein231d2da2019-07-22 16:44:45 -0600602 artifacts.BundleTestUpdatePayloads(self.input_proto, self.output_proto,
603 self.api_config)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600604
605 actual = [
606 os.path.relpath(artifact.path, self.archive_root)
607 for artifact in self.output_proto.artifacts
608 ]
Alex Kleincb541e82019-06-26 15:06:11 -0600609 expected = ['payload1.bin', 'payload2.bin']
Mike Frysinger678735c2019-09-28 18:23:28 -0400610 self.assertCountEqual(actual, expected)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600611
612 actual = [
613 os.path.relpath(path, self.archive_root)
614 for path in osutils.DirectoryIterator(self.archive_root)
615 ]
Mike Frysinger678735c2019-09-28 18:23:28 -0400616 self.assertCountEqual(actual, expected)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600617
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600618 def testBundleTestUpdatePayloadsNoImageDir(self):
619 """BundleTestUpdatePayloads dies if no image dir is found."""
620 # Intentionally do not write image directory.
Alex Kleind2bf1462019-10-24 16:37:04 -0600621 artifacts.BundleTestUpdatePayloads(self.input_proto, self.output_proto,
622 self.api_config)
623 self.assertFalse(self.output_proto.artifacts)
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600624
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600625 def testBundleTestUpdatePayloadsNoImage(self):
626 """BundleTestUpdatePayloads dies if no usable image is found for target."""
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600627 # Intentionally do not write image, but create the directory.
628 osutils.SafeMakedirs(self.image_root)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600629 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600630 artifacts.BundleTestUpdatePayloads(self.input_proto, self.output_proto,
631 self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600632
633
Alex Klein231d2da2019-07-22 16:44:45 -0600634class BundleSimpleChromeArtifactsTest(cros_test_lib.MockTempDirTestCase,
635 api_config.ApiConfigMixin):
Alex Klein2275d692019-04-23 16:04:12 -0600636 """BundleSimpleChromeArtifacts tests."""
637
638 def setUp(self):
639 self.chroot_dir = os.path.join(self.tempdir, 'chroot_dir')
640 self.sysroot_path = '/sysroot'
641 self.sysroot_dir = os.path.join(self.chroot_dir, 'sysroot')
642 osutils.SafeMakedirs(self.sysroot_dir)
643 self.output_dir = os.path.join(self.tempdir, 'output_dir')
644 osutils.SafeMakedirs(self.output_dir)
645
646 self.does_not_exist = os.path.join(self.tempdir, 'does_not_exist')
647
Alex Klein231d2da2019-07-22 16:44:45 -0600648 self.response = artifacts_pb2.BundleResponse()
649
Alex Klein2275d692019-04-23 16:04:12 -0600650 def _GetRequest(self, chroot=None, sysroot=None, build_target=None,
651 output_dir=None):
652 """Helper to create a request message instance.
653
654 Args:
655 chroot (str): The chroot path.
656 sysroot (str): The sysroot path.
657 build_target (str): The build target name.
658 output_dir (str): The output directory.
659 """
660 return artifacts_pb2.BundleRequest(
661 sysroot={'path': sysroot, 'build_target': {'name': build_target}},
662 chroot={'path': chroot}, output_dir=output_dir)
663
Alex Klein231d2da2019-07-22 16:44:45 -0600664 def testValidateOnly(self):
665 """Sanity check that a validate only call does not execute any logic."""
666 patch = self.PatchObject(artifacts_svc, 'BundleSimpleChromeArtifacts')
667 request = self._GetRequest(chroot=self.chroot_dir,
668 sysroot=self.sysroot_path,
669 build_target='board', output_dir=self.output_dir)
670 artifacts.BundleSimpleChromeArtifacts(request, self.response,
671 self.validate_only_config)
672 patch.assert_not_called()
Alex Klein2275d692019-04-23 16:04:12 -0600673
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700674 def testMockCall(self):
675 """Test that a mock call does not execute logic, returns mocked value."""
676 patch = self.PatchObject(artifacts_svc, 'BundleSimpleChromeArtifacts')
677 request = self._GetRequest(chroot=self.chroot_dir,
678 sysroot=self.sysroot_path,
679 build_target='board', output_dir=self.output_dir)
680 artifacts.BundleSimpleChromeArtifacts(request, self.response,
681 self.mock_call_config)
682 patch.assert_not_called()
683 self.assertEqual(len(self.response.artifacts), 1)
684 self.assertEqual(self.response.artifacts[0].path,
685 os.path.join(self.output_dir, 'simple_chrome.txt'))
686
Alex Klein2275d692019-04-23 16:04:12 -0600687 def testNoBuildTarget(self):
688 """Test no build target fails."""
689 request = self._GetRequest(chroot=self.chroot_dir,
690 sysroot=self.sysroot_path,
691 output_dir=self.output_dir)
Alex Klein231d2da2019-07-22 16:44:45 -0600692 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600693 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600694 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600695
696 def testNoSysroot(self):
697 """Test no sysroot fails."""
698 request = self._GetRequest(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 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600701 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600702
703 def testSysrootDoesNotExist(self):
704 """Test no sysroot fails."""
705 request = self._GetRequest(build_target='board', output_dir=self.output_dir,
706 sysroot=self.does_not_exist)
Alex Klein231d2da2019-07-22 16:44:45 -0600707 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600708 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600709 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600710
711 def testNoOutputDir(self):
712 """Test no output dir fails."""
713 request = self._GetRequest(chroot=self.chroot_dir,
714 sysroot=self.sysroot_path,
715 build_target='board')
Alex Klein231d2da2019-07-22 16:44:45 -0600716 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600717 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600718 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600719
720 def testOutputDirDoesNotExist(self):
721 """Test no output dir fails."""
722 request = self._GetRequest(chroot=self.chroot_dir,
723 sysroot=self.sysroot_path,
724 build_target='board',
725 output_dir=self.does_not_exist)
Alex Klein231d2da2019-07-22 16:44:45 -0600726 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600727 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600728 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600729
730 def testOutputHandling(self):
731 """Test response output."""
732 files = ['file1', 'file2', 'file3']
733 expected_files = [os.path.join(self.output_dir, f) for f in files]
734 self.PatchObject(artifacts_svc, 'BundleSimpleChromeArtifacts',
735 return_value=expected_files)
736 request = self._GetRequest(chroot=self.chroot_dir,
737 sysroot=self.sysroot_path,
738 build_target='board', output_dir=self.output_dir)
Alex Klein231d2da2019-07-22 16:44:45 -0600739 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600740
Alex Klein231d2da2019-07-22 16:44:45 -0600741 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600742
743 self.assertTrue(response.artifacts)
Mike Frysinger678735c2019-09-28 18:23:28 -0400744 self.assertCountEqual(expected_files, [a.path for a in response.artifacts])
Alex Klein2275d692019-04-23 16:04:12 -0600745
746
Alex Klein231d2da2019-07-22 16:44:45 -0600747class BundleVmFilesTest(cros_test_lib.MockTempDirTestCase,
748 api_config.ApiConfigMixin):
Alex Klein6504eca2019-04-18 15:37:56 -0600749 """BuildVmFiles tests."""
750
Alex Klein231d2da2019-07-22 16:44:45 -0600751 def setUp(self):
752 self.output_dir = os.path.join(self.tempdir, 'output')
753 osutils.SafeMakedirs(self.output_dir)
754
755 self.response = artifacts_pb2.BundleResponse()
756
Alex Klein6504eca2019-04-18 15:37:56 -0600757 def _GetInput(self, chroot=None, sysroot=None, test_results_dir=None,
758 output_dir=None):
759 """Helper to build out an input message instance.
760
761 Args:
762 chroot (str|None): The chroot path.
763 sysroot (str|None): The sysroot path relative to the chroot.
764 test_results_dir (str|None): The test results directory relative to the
765 sysroot.
766 output_dir (str|None): The directory where the results tarball should be
767 saved.
768 """
769 return artifacts_pb2.BundleVmFilesRequest(
770 chroot={'path': chroot}, sysroot={'path': sysroot},
771 test_results_dir=test_results_dir, output_dir=output_dir,
772 )
773
Alex Klein231d2da2019-07-22 16:44:45 -0600774 def testValidateOnly(self):
775 """Sanity check that a validate only call does not execute any logic."""
776 patch = self.PatchObject(artifacts_svc, 'BundleVmFiles')
777 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
778 test_results_dir='/test/results',
779 output_dir=self.output_dir)
780 artifacts.BundleVmFiles(in_proto, self.response, self.validate_only_config)
781 patch.assert_not_called()
Alex Klein6504eca2019-04-18 15:37:56 -0600782
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700783 def testMockCall(self):
784 """Test that a mock call does not execute logic, returns mocked value."""
785 patch = self.PatchObject(artifacts_svc, 'BundleVmFiles')
786 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
787 test_results_dir='/test/results',
788 output_dir=self.output_dir)
789 artifacts.BundleVmFiles(in_proto, self.response, self.mock_call_config)
790 patch.assert_not_called()
791 self.assertEqual(len(self.response.artifacts), 1)
792 self.assertEqual(self.response.artifacts[0].path,
793 os.path.join(self.output_dir, 'f1.tar'))
794
Alex Klein6504eca2019-04-18 15:37:56 -0600795 def testChrootMissing(self):
796 """Test error handling for missing chroot."""
797 in_proto = self._GetInput(sysroot='/build/board',
798 test_results_dir='/test/results',
Alex Klein231d2da2019-07-22 16:44:45 -0600799 output_dir=self.output_dir)
Alex Klein6504eca2019-04-18 15:37:56 -0600800
801 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600802 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600803
Alex Klein6504eca2019-04-18 15:37:56 -0600804 def testTestResultsDirMissing(self):
805 """Test error handling for missing test results directory."""
806 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
Alex Klein231d2da2019-07-22 16:44:45 -0600807 output_dir=self.output_dir)
Alex Klein6504eca2019-04-18 15:37:56 -0600808
809 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600810 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600811
812 def testOutputDirMissing(self):
813 """Test error handling for missing output directory."""
814 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
815 test_results_dir='/test/results')
Alex Klein6504eca2019-04-18 15:37:56 -0600816
817 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600818 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
819
820 def testOutputDirDoesNotExist(self):
821 """Test error handling for output directory that does not exist."""
822 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
823 output_dir=os.path.join(self.tempdir, 'dne'),
824 test_results_dir='/test/results')
825
826 with self.assertRaises(cros_build_lib.DieSystemExit):
827 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600828
829 def testValidCall(self):
830 """Test image dir building."""
831 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
832 test_results_dir='/test/results',
Alex Klein231d2da2019-07-22 16:44:45 -0600833 output_dir=self.output_dir)
834
Alex Klein6504eca2019-04-18 15:37:56 -0600835 expected_files = ['/tmp/output/f1.tar', '/tmp/output/f2.tar']
Michael Mortensen51f06722019-07-18 09:55:50 -0600836 patch = self.PatchObject(artifacts_svc, 'BundleVmFiles',
Alex Klein6504eca2019-04-18 15:37:56 -0600837 return_value=expected_files)
838
Alex Klein231d2da2019-07-22 16:44:45 -0600839 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600840
Alex Klein231d2da2019-07-22 16:44:45 -0600841 patch.assert_called_with(mock.ANY, '/test/results', self.output_dir)
Alex Klein6504eca2019-04-18 15:37:56 -0600842
843 # Make sure we have artifacts, and that every artifact is an expected file.
Alex Klein231d2da2019-07-22 16:44:45 -0600844 self.assertTrue(self.response.artifacts)
845 for artifact in self.response.artifacts:
Alex Klein6504eca2019-04-18 15:37:56 -0600846 self.assertIn(artifact.path, expected_files)
847 expected_files.remove(artifact.path)
848
849 # Make sure we've seen all of the expected files.
850 self.assertFalse(expected_files)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700851
Alex Kleinb9d810b2019-07-01 12:38:02 -0600852
Tiancong Wang50b80a92019-08-01 14:46:15 -0700853
854class BundleAFDOGenerationArtifactsTestCase(
Alex Klein231d2da2019-07-22 16:44:45 -0600855 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin):
Tiancong Wang50b80a92019-08-01 14:46:15 -0700856 """Unittests for BundleAFDOGenerationArtifacts."""
857
858 @staticmethod
859 def mock_die(message, *args):
860 raise cros_build_lib.DieSystemExit(message % args)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700861
862 def setUp(self):
863 self.chroot_dir = os.path.join(self.tempdir, 'chroot_dir')
864 osutils.SafeMakedirs(self.chroot_dir)
865 temp_dir = os.path.join(self.chroot_dir, 'tmp')
866 osutils.SafeMakedirs(temp_dir)
867 self.output_dir = os.path.join(self.tempdir, 'output_dir')
868 osutils.SafeMakedirs(self.output_dir)
Tiancong Wang2ade7932019-09-27 14:15:40 -0700869 self.chrome_root = os.path.join(self.tempdir, 'chrome_root')
870 osutils.SafeMakedirs(self.chrome_root)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700871 self.build_target = 'board'
Tiancong Wang24a3df72019-08-20 15:48:51 -0700872 self.valid_artifact_type = toolchain_pb2.ORDERFILE
873 self.invalid_artifact_type = toolchain_pb2.NONE_TYPE
Tiancong Wangc4805b72019-06-11 12:12:03 -0700874 self.does_not_exist = os.path.join(self.tempdir, 'does_not_exist')
Tiancong Wang50b80a92019-08-01 14:46:15 -0700875 self.PatchObject(cros_build_lib, 'Die', new=self.mock_die)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700876
Alex Klein231d2da2019-07-22 16:44:45 -0600877 self.response = artifacts_pb2.BundleResponse()
878
Tiancong Wang2ade7932019-09-27 14:15:40 -0700879 def _GetRequest(self, chroot=None, build_target=None, chrome_root=None,
880 output_dir=None, artifact_type=None):
Tiancong Wangc4805b72019-06-11 12:12:03 -0700881 """Helper to create a request message instance.
882
883 Args:
884 chroot (str): The chroot path.
885 build_target (str): The build target name.
Tiancong Wang2ade7932019-09-27 14:15:40 -0700886 chrome_root (str): The path to Chrome root.
Tiancong Wangc4805b72019-06-11 12:12:03 -0700887 output_dir (str): The output directory.
Tiancong Wang50b80a92019-08-01 14:46:15 -0700888 artifact_type (artifacts_pb2.AFDOArtifactType):
889 The type of the artifact.
Tiancong Wangc4805b72019-06-11 12:12:03 -0700890 """
Tiancong Wang50b80a92019-08-01 14:46:15 -0700891 return artifacts_pb2.BundleChromeAFDORequest(
Tiancong Wang2ade7932019-09-27 14:15:40 -0700892 chroot={'path': chroot, 'chrome_dir': chrome_root},
Tiancong Wang50b80a92019-08-01 14:46:15 -0700893 build_target={'name': build_target},
894 output_dir=output_dir,
895 artifact_type=artifact_type,
Tiancong Wangc4805b72019-06-11 12:12:03 -0700896 )
897
Alex Klein231d2da2019-07-22 16:44:45 -0600898 def testValidateOnly(self):
899 """Sanity check that a validate only call does not execute any logic."""
900 patch = self.PatchObject(artifacts_svc,
Tiancong Wang50b80a92019-08-01 14:46:15 -0700901 'BundleAFDOGenerationArtifacts')
Alex Klein231d2da2019-07-22 16:44:45 -0600902 request = self._GetRequest(chroot=self.chroot_dir,
903 build_target=self.build_target,
Tiancong Wang2ade7932019-09-27 14:15:40 -0700904 chrome_root=self.chrome_root,
Tiancong Wang50b80a92019-08-01 14:46:15 -0700905 output_dir=self.output_dir,
906 artifact_type=self.valid_artifact_type)
907 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
908 self.validate_only_config)
Alex Klein231d2da2019-07-22 16:44:45 -0600909 patch.assert_not_called()
Tiancong Wangc4805b72019-06-11 12:12:03 -0700910
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700911 def testMockCall(self):
912 """Test that a mock call does not execute logic, returns mocked value."""
913 patch = self.PatchObject(artifacts_svc,
914 'BundleAFDOGenerationArtifacts')
915 request = self._GetRequest(chroot=self.chroot_dir,
916 build_target=self.build_target,
917 chrome_root=self.chrome_root,
918 output_dir=self.output_dir,
919 artifact_type=self.valid_artifact_type)
920 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
921 self.mock_call_config)
922 patch.assert_not_called()
923 self.assertEqual(len(self.response.artifacts), 1)
924 self.assertEqual(self.response.artifacts[0].path,
925 os.path.join(self.output_dir, 'artifact1'))
926
Tiancong Wangc4805b72019-06-11 12:12:03 -0700927 def testNoBuildTarget(self):
928 """Test no build target fails."""
929 request = self._GetRequest(chroot=self.chroot_dir,
Tiancong Wang2ade7932019-09-27 14:15:40 -0700930 chrome_root=self.chrome_root,
Tiancong Wang50b80a92019-08-01 14:46:15 -0700931 output_dir=self.output_dir,
932 artifact_type=self.valid_artifact_type)
933 with self.assertRaises(cros_build_lib.DieSystemExit) as context:
934 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
935 self.api_config)
936 self.assertEqual('build_target.name is required.',
937 str(context.exception))
Tiancong Wangc4805b72019-06-11 12:12:03 -0700938
Tiancong Wang2ade7932019-09-27 14:15:40 -0700939 def testNoChromeRoot(self):
940 """Test no chrome root fails."""
941 request = self._GetRequest(chroot=self.chroot_dir,
942 build_target=self.build_target,
943 output_dir=self.output_dir,
944 artifact_type=self.valid_artifact_type)
945 with self.assertRaises(cros_build_lib.DieSystemExit) as context:
946 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
947 self.api_config)
948 self.assertEqual('chroot.chrome_dir path does not exist: ',
949 str(context.exception))
950
Tiancong Wangc4805b72019-06-11 12:12:03 -0700951 def testNoOutputDir(self):
952 """Test no output dir fails."""
953 request = self._GetRequest(chroot=self.chroot_dir,
Tiancong Wang50b80a92019-08-01 14:46:15 -0700954 build_target=self.build_target,
Tiancong Wang2ade7932019-09-27 14:15:40 -0700955 chrome_root=self.chrome_root,
Tiancong Wang50b80a92019-08-01 14:46:15 -0700956 artifact_type=self.valid_artifact_type)
957 with self.assertRaises(cros_build_lib.DieSystemExit) as context:
958 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
959 self.api_config)
960 self.assertEqual('output_dir is required.',
961 str(context.exception))
Tiancong Wangc4805b72019-06-11 12:12:03 -0700962
963 def testOutputDirDoesNotExist(self):
964 """Test output directory not existing fails."""
965 request = self._GetRequest(chroot=self.chroot_dir,
Tiancong Wangc4805b72019-06-11 12:12:03 -0700966 build_target=self.build_target,
Tiancong Wang2ade7932019-09-27 14:15:40 -0700967 chrome_root=self.chrome_root,
Tiancong Wang50b80a92019-08-01 14:46:15 -0700968 output_dir=self.does_not_exist,
969 artifact_type=self.valid_artifact_type)
970 with self.assertRaises(cros_build_lib.DieSystemExit) as context:
971 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
972 self.api_config)
973 self.assertEqual(
974 'output_dir path does not exist: %s' % self.does_not_exist,
975 str(context.exception))
Tiancong Wangc4805b72019-06-11 12:12:03 -0700976
Tiancong Wang50b80a92019-08-01 14:46:15 -0700977 def testNoArtifactType(self):
978 """Test no artifact type."""
979 request = self._GetRequest(chroot=self.chroot_dir,
980 build_target=self.build_target,
Tiancong Wang2ade7932019-09-27 14:15:40 -0700981 chrome_root=self.chrome_root,
Tiancong Wang50b80a92019-08-01 14:46:15 -0700982 output_dir=self.output_dir)
983 with self.assertRaises(cros_build_lib.DieSystemExit) as context:
984 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
985 self.api_config)
986 self.assertIn('artifact_type (0) must be in',
987 str(context.exception))
988
989 def testWrongArtifactType(self):
990 """Test passing wrong artifact type."""
991 request = self._GetRequest(chroot=self.chroot_dir,
992 build_target=self.build_target,
Tiancong Wang2ade7932019-09-27 14:15:40 -0700993 chrome_root=self.chrome_root,
Tiancong Wang50b80a92019-08-01 14:46:15 -0700994 output_dir=self.output_dir,
995 artifact_type=self.invalid_artifact_type)
996 with self.assertRaises(cros_build_lib.DieSystemExit) as context:
997 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
998 self.api_config)
Tiancong Wang24a3df72019-08-20 15:48:51 -0700999 self.assertIn('artifact_type (%d) must be in' % self.invalid_artifact_type,
Tiancong Wang50b80a92019-08-01 14:46:15 -07001000 str(context.exception))
1001
1002 def testOutputHandlingOnOrderfile(self,
Tiancong Wang24a3df72019-08-20 15:48:51 -07001003 artifact_type=toolchain_pb2.ORDERFILE):
Tiancong Wang50b80a92019-08-01 14:46:15 -07001004 """Test response output for orderfile."""
1005 files = ['artifact1', 'artifact2', 'artifact3']
Tiancong Wangc4805b72019-06-11 12:12:03 -07001006 expected_files = [os.path.join(self.output_dir, f) for f in files]
Tiancong Wang50b80a92019-08-01 14:46:15 -07001007 self.PatchObject(artifacts_svc, 'BundleAFDOGenerationArtifacts',
Tiancong Wangc4805b72019-06-11 12:12:03 -07001008 return_value=expected_files)
Alex Klein231d2da2019-07-22 16:44:45 -06001009
Tiancong Wangc4805b72019-06-11 12:12:03 -07001010 request = self._GetRequest(chroot=self.chroot_dir,
Tiancong Wangc4805b72019-06-11 12:12:03 -07001011 build_target=self.build_target,
Tiancong Wang2ade7932019-09-27 14:15:40 -07001012 chrome_root=self.chrome_root,
Tiancong Wang50b80a92019-08-01 14:46:15 -07001013 output_dir=self.output_dir,
1014 artifact_type=artifact_type)
Tiancong Wangc4805b72019-06-11 12:12:03 -07001015
Tiancong Wang50b80a92019-08-01 14:46:15 -07001016 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
1017 self.api_config)
Tiancong Wangc4805b72019-06-11 12:12:03 -07001018
Tiancong Wang50b80a92019-08-01 14:46:15 -07001019 self.assertTrue(self.response.artifacts)
Mike Frysinger678735c2019-09-28 18:23:28 -04001020 self.assertCountEqual(expected_files,
Tiancong Wang50b80a92019-08-01 14:46:15 -07001021 [a.path for a in self.response.artifacts])
1022
1023 def testOutputHandlingOnAFDO(self):
1024 """Test response output for AFDO."""
1025 self.testOutputHandlingOnOrderfile(
Tiancong Wang24a3df72019-08-20 15:48:51 -07001026 artifact_type=toolchain_pb2.BENCHMARK_AFDO)
Alex Klein0b1cbfc2019-08-14 10:09:58 -06001027
1028
1029class ExportCpeReportTest(cros_test_lib.MockTempDirTestCase,
1030 api_config.ApiConfigMixin):
1031 """ExportCpeReport tests."""
1032
1033 def setUp(self):
1034 self.response = artifacts_pb2.BundleResponse()
1035
1036 def testValidateOnly(self):
1037 """Sanity check validate only calls don't execute."""
1038 patch = self.PatchObject(artifacts_svc, 'GenerateCpeReport')
1039
1040 request = artifacts_pb2.BundleRequest()
1041 request.build_target.name = 'board'
1042 request.output_dir = self.tempdir
1043
1044 artifacts.ExportCpeReport(request, self.response, self.validate_only_config)
1045
1046 patch.assert_not_called()
1047
Michael Mortensen2d6a2402019-11-26 13:40:40 -07001048 def testMockCall(self):
1049 """Test that a mock call does not execute logic, returns mocked value."""
1050 patch = self.PatchObject(artifacts_svc, 'GenerateCpeReport')
1051
1052 request = artifacts_pb2.BundleRequest()
1053 request.build_target.name = 'board'
1054 request.output_dir = self.tempdir
1055
1056 artifacts.ExportCpeReport(request, self.response, self.mock_call_config)
1057
1058 patch.assert_not_called()
1059 self.assertEqual(len(self.response.artifacts), 2)
1060 self.assertEqual(self.response.artifacts[0].path,
1061 os.path.join(self.tempdir, 'cpe_report.txt'))
1062 self.assertEqual(self.response.artifacts[1].path,
1063 os.path.join(self.tempdir, 'cpe_warnings.txt'))
1064
Alex Klein0b1cbfc2019-08-14 10:09:58 -06001065 def testNoBuildTarget(self):
1066 request = artifacts_pb2.BundleRequest()
1067 request.output_dir = self.tempdir
1068
1069 with self.assertRaises(cros_build_lib.DieSystemExit):
1070 artifacts.ExportCpeReport(request, self.response, self.api_config)
1071
1072 def testSuccess(self):
1073 """Test success case."""
1074 expected = artifacts_svc.CpeResult(
1075 report='/output/report.json', warnings='/output/warnings.json')
1076 self.PatchObject(artifacts_svc, 'GenerateCpeReport', return_value=expected)
1077
1078 request = artifacts_pb2.BundleRequest()
1079 request.build_target.name = 'board'
1080 request.output_dir = self.tempdir
1081
1082 artifacts.ExportCpeReport(request, self.response, self.api_config)
1083
1084 for artifact in self.response.artifacts:
1085 self.assertIn(artifact.path, [expected.report, expected.warnings])
Shao-Chuan Leea44dddc2020-10-30 17:16:55 +09001086
1087
1088class BundleGceTarballTest(BundleTestCase):
1089 """Unittests for BundleGceTarball."""
1090
1091 def testValidateOnly(self):
1092 """Check that a validate only call does not execute any logic."""
1093 patch = self.PatchObject(artifacts_svc, 'BundleGceTarball')
1094 artifacts.BundleGceTarball(self.target_request, self.response,
1095 self.validate_only_config)
1096 patch.assert_not_called()
1097
1098 def testMockCall(self):
1099 """Test that a mock call does not execute logic, returns mocked value."""
1100 patch = self.PatchObject(artifacts_svc, 'BundleGceTarball')
1101 artifacts.BundleGceTarball(self.target_request, self.response,
1102 self.mock_call_config)
1103 patch.assert_not_called()
1104 self.assertEqual(len(self.response.artifacts), 1)
1105 self.assertEqual(self.response.artifacts[0].path,
1106 os.path.join(self.output_dir,
1107 constants.TEST_IMAGE_GCE_TAR))
1108
1109 def testBundleGceTarball(self):
1110 """BundleGceTarball calls cbuildbot/commands with correct args."""
1111 bundle_gce_tarball = self.PatchObject(
1112 artifacts_svc, 'BundleGceTarball',
1113 return_value=os.path.join(self.output_dir,
1114 constants.TEST_IMAGE_GCE_TAR))
1115 self.PatchObject(os.path, 'exists', return_value=True)
1116 artifacts.BundleGceTarball(self.target_request, self.response,
1117 self.api_config)
1118 self.assertEqual(
1119 [artifact.path for artifact in self.response.artifacts],
1120 [os.path.join(self.output_dir, constants.TEST_IMAGE_GCE_TAR)])
1121
1122 latest = os.path.join(self.source_root, 'src/build/images/target/latest')
1123 self.assertEqual(
1124 bundle_gce_tarball.call_args_list,
1125 [mock.call(self.output_dir, latest)])
1126
1127 def testBundleGceTarballNoImageDir(self):
1128 """BundleGceTarball dies when image dir does not exist."""
1129 self.PatchObject(os.path, 'exists', return_value=False)
1130 with self.assertRaises(cros_build_lib.DieSystemExit):
1131 artifacts.BundleGceTarball(self.target_request, self.response,
1132 self.api_config)
Michael Mortensen6667b542020-12-12 11:09:55 -07001133
1134
1135class BundleDebugSymbolsTest(BundleTestCase):
1136 """Unittests for BundleDebugSymbols."""
1137
1138 def setUp(self):
1139 # Create a chroot_path that also includes a chroot tmp dir.
1140 self.chroot_path = os.path.join(self.tempdir, 'chroot_dir')
1141 osutils.SafeMakedirs(self.chroot_path)
1142 osutils.SafeMakedirs(os.path.join(self.chroot_path, 'tmp'))
1143 # Create output dir.
1144 output_dir = os.path.join(self.tempdir, 'output_dir')
1145 osutils.SafeMakedirs(output_dir)
1146 # Build target request.
1147 self.target_request = self.BuildTargetRequest(
1148 build_target='target',
1149 output_dir=self.output_dir,
1150 chroot=self.chroot_path)
1151
1152 def testValidateOnly(self):
1153 """Check that a validate only call does not execute any logic."""
1154 patch = self.PatchObject(artifacts_svc, 'GenerateBreakpadSymbols')
1155 artifacts.BundleDebugSymbols(self.target_request, self.response,
1156 self.validate_only_config)
1157 patch.assert_not_called()
1158
1159 def testMockCall(self):
1160 """Test that a mock call does not execute logic, returns mocked value."""
1161 patch = self.PatchObject(artifacts_svc, 'GenerateBreakpadSymbols')
1162 artifacts.BundleDebugSymbols(self.target_request, self.response,
1163 self.mock_call_config)
1164 patch.assert_not_called()
1165 self.assertEqual(len(self.response.artifacts), 1)
1166 self.assertEqual(self.response.artifacts[0].path,
1167 os.path.join(self.output_dir,
1168 constants.DEBUG_SYMBOLS_TAR))
1169
1170 def testBundleDebugSymbols(self):
1171 """BundleDebugSymbols calls cbuildbot/commands with correct args."""
1172 # Patch service layer functions.
1173 generate_breakpad_symbols_patch = self.PatchObject(
1174 artifacts_svc, 'GenerateBreakpadSymbols',
1175 return_value=cros_build_lib.CommandResult(returncode=0, output=''))
1176 gather_symbol_files_patch = self.PatchObject(
1177 artifacts_svc, 'GatherSymbolFiles',
1178 return_value=[artifacts_svc.SymbolFileTuple(
1179 source_file_name='path/to/source/file1.sym',
1180 relative_path='file1.sym')])
1181
1182 artifacts.BundleDebugSymbols(self.target_request, self.response,
1183 self.api_config)
1184 # Verify mock objects were called.
1185 generate_breakpad_symbols_patch.assert_called()
1186 gather_symbol_files_patch.assert_called()
1187
1188 # Verify response proto contents and output directory contents.
1189 self.assertEqual(
1190 [artifact.path for artifact in self.response.artifacts],
1191 [os.path.join(self.output_dir, constants.DEBUG_SYMBOLS_TAR)])
1192 files = os.listdir(self.output_dir)
1193 self.assertEqual(files, [constants.DEBUG_SYMBOLS_TAR])
1194
1195 def testBundleGceTarballNoImageDir(self):
1196 """BundleDebugSymbols dies when image dir does not exist."""
1197 self.PatchObject(os.path, 'exists', return_value=False)
1198 with self.assertRaises(cros_build_lib.DieSystemExit):
1199 artifacts.BundleDebugSymbols(self.target_request, self.response,
1200 self.api_config)