blob: 7481e5568a412d4f47ac52fe73ba9d310ac952aa [file] [log] [blame]
Evan Hernandezf388cbf2019-04-01 11:15:23 -06001# Copyright 2019 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Unittests for Artifacts operations."""
6
Evan Hernandezf388cbf2019-04-01 11:15:23 -06007import os
Mike Frysinger166fea02021-02-12 05:30:33 -05008from unittest import mock
Evan Hernandezf388cbf2019-04-01 11:15:23 -06009
Alex Klein231d2da2019-07-22 16:44:45 -060010from chromite.api import api_config
Evan Hernandezf388cbf2019-04-01 11:15:23 -060011from chromite.api.controller import artifacts
12from chromite.api.gen.chromite.api import artifacts_pb2
Tiancong Wang24a3df72019-08-20 15:48:51 -070013from chromite.api.gen.chromite.api import toolchain_pb2
Evan Hernandezf388cbf2019-04-01 11:15:23 -060014from chromite.cbuildbot import commands
Alex Kleinb9d810b2019-07-01 12:38:02 -060015from chromite.lib import chroot_lib
Evan Hernandezf388cbf2019-04-01 11:15:23 -060016from chromite.lib import constants
17from chromite.lib import cros_build_lib
18from chromite.lib import cros_test_lib
19from chromite.lib import osutils
Alex Klein238d8862019-05-07 11:32:46 -060020from chromite.lib import sysroot_lib
Alex Klein2275d692019-04-23 16:04:12 -060021from chromite.service import artifacts as artifacts_svc
Evan Hernandezf388cbf2019-04-01 11:15:23 -060022
23
Alex Kleind91e95a2019-09-17 10:39:02 -060024class BundleRequestMixin(object):
25 """Mixin to provide bundle request methods."""
26
27 def EmptyRequest(self):
28 return artifacts_pb2.BundleRequest()
29
30 def BuildTargetRequest(self, build_target=None, output_dir=None, chroot=None):
31 """Get a build target format request instance."""
32 request = self.EmptyRequest()
33 if build_target:
34 request.build_target.name = build_target
35 if output_dir:
36 request.output_dir = output_dir
37 if chroot:
38 request.chroot.path = chroot
39
40 return request
41
42 def SysrootRequest(self,
43 sysroot=None,
44 build_target=None,
45 output_dir=None,
46 chroot=None):
47 """Get a sysroot format request instance."""
48 request = self.EmptyRequest()
49 if sysroot:
50 request.sysroot.path = sysroot
51 if build_target:
52 request.sysroot.build_target.name = build_target
53 if output_dir:
54 request.output_dir = output_dir
55 if chroot:
56 request.chroot.path = chroot
57
58 return request
59
60
Alex Klein231d2da2019-07-22 16:44:45 -060061class BundleTestCase(cros_test_lib.MockTempDirTestCase,
Alex Kleind91e95a2019-09-17 10:39:02 -060062 api_config.ApiConfigMixin, BundleRequestMixin):
Evan Hernandezf388cbf2019-04-01 11:15:23 -060063 """Basic setup for all artifacts unittests."""
64
65 def setUp(self):
Alex Klein231d2da2019-07-22 16:44:45 -060066 self.output_dir = os.path.join(self.tempdir, 'artifacts')
67 osutils.SafeMakedirs(self.output_dir)
68 self.sysroot_path = '/build/target'
Alex Klein68c8fdf2019-09-25 15:09:11 -060069 self.sysroot = sysroot_lib.Sysroot(self.sysroot_path)
Alex Klein231d2da2019-07-22 16:44:45 -060070 self.chroot_path = os.path.join(self.tempdir, 'chroot')
71 full_sysroot_path = os.path.join(self.chroot_path,
72 self.sysroot_path.lstrip(os.sep))
73 osutils.SafeMakedirs(full_sysroot_path)
74
Alex Klein68c8fdf2019-09-25 15:09:11 -060075 # All requests use same response type.
Alex Klein231d2da2019-07-22 16:44:45 -060076 self.response = artifacts_pb2.BundleResponse()
77
Alex Klein68c8fdf2019-09-25 15:09:11 -060078 # Build target request.
79 self.target_request = self.BuildTargetRequest(
80 build_target='target',
81 output_dir=self.output_dir,
82 chroot=self.chroot_path)
83
84 # Sysroot request.
85 self.sysroot_request = self.SysrootRequest(
86 sysroot=self.sysroot_path,
87 build_target='target',
88 output_dir=self.output_dir,
89 chroot=self.chroot_path)
90
Alex Klein231d2da2019-07-22 16:44:45 -060091 self.source_root = self.tempdir
92 self.PatchObject(constants, 'SOURCE_ROOT', new=self.tempdir)
Evan Hernandezf388cbf2019-04-01 11:15:23 -060093
94
Alex Kleind91e95a2019-09-17 10:39:02 -060095class BundleImageArchivesTest(BundleTestCase):
96 """BundleImageArchives tests."""
97
98 def testValidateOnly(self):
99 """Sanity check that a validate only call does not execute any logic."""
100 patch = self.PatchObject(artifacts_svc, 'ArchiveImages')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600101 artifacts.BundleImageArchives(self.target_request, self.response,
Alex Kleind91e95a2019-09-17 10:39:02 -0600102 self.validate_only_config)
103 patch.assert_not_called()
104
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700105 def testMockCall(self):
106 """Test that a mock call does not execute logic, returns mocked value."""
107 patch = self.PatchObject(artifacts_svc, 'ArchiveImages')
108 artifacts.BundleImageArchives(self.target_request, self.response,
109 self.mock_call_config)
110 patch.assert_not_called()
111 self.assertEqual(len(self.response.artifacts), 2)
112 self.assertEqual(self.response.artifacts[0].path,
113 os.path.join(self.output_dir, 'path0.tar.xz'))
114 self.assertEqual(self.response.artifacts[1].path,
115 os.path.join(self.output_dir, 'path1.tar.xz'))
116
Alex Kleind91e95a2019-09-17 10:39:02 -0600117 def testNoBuildTarget(self):
118 """Test that no build target fails."""
119 request = self.BuildTargetRequest(output_dir=self.tempdir)
120 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein68c8fdf2019-09-25 15:09:11 -0600121 artifacts.BundleImageArchives(request, self.response, self.api_config)
Alex Kleind91e95a2019-09-17 10:39:02 -0600122
123 def testNoOutputDir(self):
124 """Test no output dir fails."""
125 request = self.BuildTargetRequest(build_target='board')
126 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein68c8fdf2019-09-25 15:09:11 -0600127 artifacts.BundleImageArchives(request, self.response, self.api_config)
Alex Kleind91e95a2019-09-17 10:39:02 -0600128
129 def testInvalidOutputDir(self):
130 """Test invalid output dir fails."""
131 request = self.BuildTargetRequest(
132 build_target='board', output_dir=os.path.join(self.tempdir, 'DNE'))
133 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein68c8fdf2019-09-25 15:09:11 -0600134 artifacts.BundleImageArchives(request, self.response, self.api_config)
Alex Kleind91e95a2019-09-17 10:39:02 -0600135
136 def testOutputHandling(self):
137 """Test the artifact output handling."""
138 expected = [os.path.join(self.output_dir, f) for f in ('a', 'b', 'c')]
139 self.PatchObject(artifacts_svc, 'ArchiveImages', return_value=expected)
140 self.PatchObject(os.path, 'exists', return_value=True)
141
Alex Klein68c8fdf2019-09-25 15:09:11 -0600142 artifacts.BundleImageArchives(self.target_request, self.response,
Alex Kleind91e95a2019-09-17 10:39:02 -0600143 self.api_config)
144
Mike Frysinger678735c2019-09-28 18:23:28 -0400145 self.assertCountEqual(expected, [a.path for a in self.response.artifacts])
Alex Kleind91e95a2019-09-17 10:39:02 -0600146
147
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600148class BundleImageZipTest(BundleTestCase):
149 """Unittests for BundleImageZip."""
150
Alex Klein231d2da2019-07-22 16:44:45 -0600151 def testValidateOnly(self):
152 """Sanity check that a validate only call does not execute any logic."""
153 patch = self.PatchObject(commands, 'BuildImageZip')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600154 artifacts.BundleImageZip(self.target_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600155 self.validate_only_config)
156 patch.assert_not_called()
157
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700158 def testMockCall(self):
159 """Test that a mock call does not execute logic, returns mocked value."""
160 patch = self.PatchObject(commands, 'BuildImageZip')
161 artifacts.BundleImageZip(self.target_request, self.response,
162 self.mock_call_config)
163 patch.assert_not_called()
164 self.assertEqual(len(self.response.artifacts), 1)
165 self.assertEqual(self.response.artifacts[0].path,
166 os.path.join(self.output_dir, 'image.zip'))
167
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600168 def testBundleImageZip(self):
169 """BundleImageZip calls cbuildbot/commands with correct args."""
Michael Mortensen01910922019-07-24 14:48:10 -0600170 bundle_image_zip = self.PatchObject(
171 artifacts_svc, 'BundleImageZip', return_value='image.zip')
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600172 self.PatchObject(os.path, 'exists', return_value=True)
Alex Klein68c8fdf2019-09-25 15:09:11 -0600173 artifacts.BundleImageZip(self.target_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600174 self.api_config)
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600175 self.assertEqual(
Alex Klein68c8fdf2019-09-25 15:09:11 -0600176 [artifact.path for artifact in self.response.artifacts],
Alex Klein231d2da2019-07-22 16:44:45 -0600177 [os.path.join(self.output_dir, 'image.zip')])
178
179 latest = os.path.join(self.source_root, 'src/build/images/target/latest')
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600180 self.assertEqual(
Michael Mortensen01910922019-07-24 14:48:10 -0600181 bundle_image_zip.call_args_list,
Alex Klein231d2da2019-07-22 16:44:45 -0600182 [mock.call(self.output_dir, latest)])
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600183
184 def testBundleImageZipNoImageDir(self):
185 """BundleImageZip dies when image dir does not exist."""
186 self.PatchObject(os.path, 'exists', return_value=False)
187 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein68c8fdf2019-09-25 15:09:11 -0600188 artifacts.BundleImageZip(self.target_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600189 self.api_config)
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600190
191
Alex Klein68c8fdf2019-09-25 15:09:11 -0600192class BundleAutotestFilesTest(BundleTestCase):
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600193 """Unittests for BundleAutotestFiles."""
194
Alex Klein231d2da2019-07-22 16:44:45 -0600195 def testValidateOnly(self):
196 """Sanity check that a validate only call does not execute any logic."""
197 patch = self.PatchObject(artifacts_svc, 'BundleAutotestFiles')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600198 artifacts.BundleAutotestFiles(self.target_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600199 self.validate_only_config)
200 patch.assert_not_called()
201
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700202 def testMockCall(self):
203 """Test that a mock call does not execute logic, returns mocked value."""
204 patch = self.PatchObject(artifacts_svc, 'BundleAutotestFiles')
205 artifacts.BundleAutotestFiles(self.target_request, self.response,
206 self.mock_call_config)
207 patch.assert_not_called()
208 self.assertEqual(len(self.response.artifacts), 1)
209 self.assertEqual(self.response.artifacts[0].path,
210 os.path.join(self.output_dir, 'autotest-a.tar.gz'))
211
Alex Klein238d8862019-05-07 11:32:46 -0600212 def testBundleAutotestFilesLegacy(self):
213 """BundleAutotestFiles calls service correctly with legacy args."""
214 files = {
215 artifacts_svc.ARCHIVE_CONTROL_FILES: '/tmp/artifacts/autotest-a.tar.gz',
216 artifacts_svc.ARCHIVE_PACKAGES: '/tmp/artifacts/autotest-b.tar.gz',
217 }
218 patch = self.PatchObject(artifacts_svc, 'BundleAutotestFiles',
219 return_value=files)
220
Alex Klein68c8fdf2019-09-25 15:09:11 -0600221 artifacts.BundleAutotestFiles(self.target_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600222 self.api_config)
Alex Klein238d8862019-05-07 11:32:46 -0600223
Alex Klein238d8862019-05-07 11:32:46 -0600224 # Verify the arguments are being passed through.
Alex Kleine21a0952019-08-23 16:08:16 -0600225 patch.assert_called_with(mock.ANY, self.sysroot, self.output_dir)
Alex Klein238d8862019-05-07 11:32:46 -0600226
227 # Verify the output proto is being populated correctly.
Alex Klein68c8fdf2019-09-25 15:09:11 -0600228 self.assertTrue(self.response.artifacts)
229 paths = [artifact.path for artifact in self.response.artifacts]
Mike Frysinger1f4478c2019-10-20 18:33:17 -0400230 self.assertCountEqual(list(files.values()), paths)
Alex Klein238d8862019-05-07 11:32:46 -0600231
232 def testBundleAutotestFiles(self):
233 """BundleAutotestFiles calls service correctly."""
234 files = {
235 artifacts_svc.ARCHIVE_CONTROL_FILES: '/tmp/artifacts/autotest-a.tar.gz',
236 artifacts_svc.ARCHIVE_PACKAGES: '/tmp/artifacts/autotest-b.tar.gz',
237 }
238 patch = self.PatchObject(artifacts_svc, 'BundleAutotestFiles',
239 return_value=files)
240
Alex Klein68c8fdf2019-09-25 15:09:11 -0600241 artifacts.BundleAutotestFiles(self.sysroot_request, self.response,
242 self.api_config)
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.response.artifacts)
249 paths = [artifact.path for artifact in self.response.artifacts]
Mike Frysinger1f4478c2019-10-20 18:33:17 -0400250 self.assertCountEqual(list(files.values()), paths)
Alex Klein238d8862019-05-07 11:32:46 -0600251
252 def testInvalidOutputDir(self):
253 """Test invalid output directory argument."""
Alex Klein68c8fdf2019-09-25 15:09:11 -0600254 request = self.SysrootRequest(chroot=self.chroot_path,
255 sysroot=self.sysroot_path)
Alex Klein238d8862019-05-07 11:32:46 -0600256
257 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600258 artifacts.BundleAutotestFiles(request, self.response, self.api_config)
Alex Klein238d8862019-05-07 11:32:46 -0600259
260 def testInvalidSysroot(self):
261 """Test no sysroot directory."""
Alex Klein68c8fdf2019-09-25 15:09:11 -0600262 request = self.SysrootRequest(chroot=self.chroot_path,
263 output_dir=self.output_dir)
Alex Klein238d8862019-05-07 11:32:46 -0600264
265 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600266 artifacts.BundleAutotestFiles(request, self.response, self.api_config)
Alex Klein238d8862019-05-07 11:32:46 -0600267
268 def testSysrootDoesNotExist(self):
269 """Test dies when no sysroot does not exist."""
Alex Klein68c8fdf2019-09-25 15:09:11 -0600270 request = self.SysrootRequest(chroot=self.chroot_path,
271 sysroot='/does/not/exist',
272 output_dir=self.output_dir)
Alex Klein238d8862019-05-07 11:32:46 -0600273
274 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600275 artifacts.BundleAutotestFiles(request, self.response, self.api_config)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600276
277
278class BundleTastFilesTest(BundleTestCase):
279 """Unittests for BundleTastFiles."""
280
Alex Klein231d2da2019-07-22 16:44:45 -0600281 def testValidateOnly(self):
282 """Sanity check that a validate only call does not execute any logic."""
283 patch = self.PatchObject(artifacts_svc, 'BundleTastFiles')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600284 artifacts.BundleTastFiles(self.target_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600285 self.validate_only_config)
286 patch.assert_not_called()
287
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700288 def testMockCall(self):
289 """Test that a mock call does not execute logic, returns mocked value."""
290 patch = self.PatchObject(artifacts_svc, 'BundleTastFiles')
291 artifacts.BundleTastFiles(self.target_request, self.response,
292 self.mock_call_config)
293 patch.assert_not_called()
294 self.assertEqual(len(self.response.artifacts), 1)
295 self.assertEqual(self.response.artifacts[0].path,
296 os.path.join(self.output_dir, 'tast_bundles.tar.gz'))
297
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600298 def testBundleTastFilesNoLogs(self):
LaMont Jonesb9793cd2020-06-11 08:14:46 -0600299 """BundleTasteFiles succeeds when no tast files found."""
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600300 self.PatchObject(commands, 'BuildTastBundleTarball',
301 return_value=None)
LaMont Jonesb9793cd2020-06-11 08:14:46 -0600302 artifacts.BundleTastFiles(self.target_request, self.response,
303 self.api_config)
304 self.assertEqual(list(self.response.artifacts), [])
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600305
Alex Kleinb9d810b2019-07-01 12:38:02 -0600306 def testBundleTastFilesLegacy(self):
307 """BundleTastFiles handles legacy args correctly."""
308 buildroot = self.tempdir
309 chroot_dir = os.path.join(buildroot, 'chroot')
310 sysroot_path = os.path.join(chroot_dir, 'build', 'board')
311 output_dir = os.path.join(self.tempdir, 'results')
312 osutils.SafeMakedirs(sysroot_path)
313 osutils.SafeMakedirs(output_dir)
314
Alex Klein171da612019-08-06 14:00:42 -0600315 chroot = chroot_lib.Chroot(chroot_dir)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600316 sysroot = sysroot_lib.Sysroot('/build/board')
317
318 expected_archive = os.path.join(output_dir, artifacts_svc.TAST_BUNDLE_NAME)
319 # Patch the service being called.
320 bundle_patch = self.PatchObject(artifacts_svc, 'BundleTastFiles',
321 return_value=expected_archive)
322 self.PatchObject(constants, 'SOURCE_ROOT', new=buildroot)
323
324 request = artifacts_pb2.BundleRequest(build_target={'name': 'board'},
325 output_dir=output_dir)
Alex Klein68c8fdf2019-09-25 15:09:11 -0600326 artifacts.BundleTastFiles(request, self.response, self.api_config)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600327 self.assertEqual(
Alex Klein68c8fdf2019-09-25 15:09:11 -0600328 [artifact.path for artifact in self.response.artifacts],
Alex Kleinb9d810b2019-07-01 12:38:02 -0600329 [expected_archive])
330 bundle_patch.assert_called_once_with(chroot, sysroot, output_dir)
331
332 def testBundleTastFiles(self):
333 """BundleTastFiles calls service correctly."""
Alex Kleinb49be8a2019-12-20 10:23:03 -0700334 chroot = chroot_lib.Chroot(self.chroot_path)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600335
Alex Klein68c8fdf2019-09-25 15:09:11 -0600336 expected_archive = os.path.join(self.output_dir,
337 artifacts_svc.TAST_BUNDLE_NAME)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600338 # Patch the service being called.
339 bundle_patch = self.PatchObject(artifacts_svc, 'BundleTastFiles',
340 return_value=expected_archive)
341
Alex Klein68c8fdf2019-09-25 15:09:11 -0600342 artifacts.BundleTastFiles(self.sysroot_request, self.response,
343 self.api_config)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600344
345 # Make sure the artifact got recorded successfully.
Alex Klein68c8fdf2019-09-25 15:09:11 -0600346 self.assertTrue(self.response.artifacts)
347 self.assertEqual(expected_archive, self.response.artifacts[0].path)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600348 # Make sure the service got called correctly.
Alex Klein68c8fdf2019-09-25 15:09:11 -0600349 bundle_patch.assert_called_once_with(chroot, self.sysroot, self.output_dir)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600350
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600351
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600352class BundleFirmwareTest(BundleTestCase):
353 """Unittests for BundleFirmware."""
354
Alex Klein231d2da2019-07-22 16:44:45 -0600355 def testValidateOnly(self):
356 """Sanity check that a validate only call does not execute any logic."""
357 patch = self.PatchObject(artifacts_svc, 'BundleTastFiles')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600358 artifacts.BundleFirmware(self.sysroot_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600359 self.validate_only_config)
360 patch.assert_not_called()
Michael Mortensen38675192019-06-28 16:52:55 +0000361
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700362 def testMockCall(self):
363 """Test that a mock call does not execute logic, returns mocked value."""
364 patch = self.PatchObject(artifacts_svc, 'BundleTastFiles')
365 artifacts.BundleFirmware(self.sysroot_request, self.response,
366 self.mock_call_config)
367 patch.assert_not_called()
368 self.assertEqual(len(self.response.artifacts), 1)
369 self.assertEqual(self.response.artifacts[0].path,
370 os.path.join(self.output_dir, 'firmware.tar.gz'))
371
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600372 def testBundleFirmware(self):
373 """BundleFirmware calls cbuildbot/commands with correct args."""
Alex Klein231d2da2019-07-22 16:44:45 -0600374 self.PatchObject(
375 artifacts_svc,
376 'BuildFirmwareArchive',
377 return_value=os.path.join(self.output_dir, 'firmware.tar.gz'))
378
Alex Klein68c8fdf2019-09-25 15:09:11 -0600379 artifacts.BundleFirmware(self.sysroot_request, self.response,
380 self.api_config)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600381 self.assertEqual(
Alex Klein231d2da2019-07-22 16:44:45 -0600382 [artifact.path for artifact in self.response.artifacts],
383 [os.path.join(self.output_dir, 'firmware.tar.gz')])
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600384
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600385 def testBundleFirmwareNoLogs(self):
386 """BundleFirmware dies when no firmware found."""
387 self.PatchObject(commands, 'BuildFirmwareArchive', return_value=None)
388 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein68c8fdf2019-09-25 15:09:11 -0600389 artifacts.BundleFirmware(self.sysroot_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600390 self.api_config)
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600391
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600392
Yicheng Liea1181f2020-09-22 11:51:10 -0700393class BundleFpmcuUnittestsTest(BundleTestCase):
394 """Unittests for BundleFpmcuUnittests."""
395
396 def testValidateOnly(self):
397 """Sanity check that a validate only call does not execute any logic."""
398 patch = self.PatchObject(artifacts_svc, 'BundleFpmcuUnittests')
399 artifacts.BundleFpmcuUnittests(self.sysroot_request, self.response,
400 self.validate_only_config)
401 patch.assert_not_called()
402
403 def testMockCall(self):
404 """Test that a mock call does not execute logic, returns mocked value."""
405 patch = self.PatchObject(artifacts_svc, 'BundleFpmcuUnittests')
406 artifacts.BundleFpmcuUnittests(self.sysroot_request, self.response,
407 self.mock_call_config)
408 patch.assert_not_called()
409 self.assertEqual(len(self.response.artifacts), 1)
410 self.assertEqual(self.response.artifacts[0].path,
411 os.path.join(self.output_dir,
412 'fpmcu_unittests.tar.gz'))
413
414 def testBundleFpmcuUnittests(self):
415 """BundleFpmcuUnittests calls cbuildbot/commands with correct args."""
416 self.PatchObject(
417 artifacts_svc,
418 'BundleFpmcuUnittests',
419 return_value=os.path.join(self.output_dir, 'fpmcu_unittests.tar.gz'))
420 artifacts.BundleFpmcuUnittests(self.sysroot_request, self.response,
421 self.api_config)
422 self.assertEqual(
423 [artifact.path for artifact in self.response.artifacts],
424 [os.path.join(self.output_dir, 'fpmcu_unittests.tar.gz')])
425
426 def testBundleFpmcuUnittestsNoLogs(self):
427 """BundleFpmcuUnittests does not die when no fpmcu unittests found."""
428 self.PatchObject(artifacts_svc, 'BundleFpmcuUnittests',
429 return_value=None)
430 artifacts.BundleFpmcuUnittests(self.sysroot_request, self.response,
431 self.api_config)
432 self.assertFalse(self.response.artifacts)
433
434
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600435class BundleEbuildLogsTest(BundleTestCase):
436 """Unittests for BundleEbuildLogs."""
437
Alex Klein231d2da2019-07-22 16:44:45 -0600438 def testValidateOnly(self):
439 """Sanity check that a validate only call does not execute any logic."""
440 patch = self.PatchObject(commands, 'BuildEbuildLogsTarball')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600441 artifacts.BundleEbuildLogs(self.target_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600442 self.validate_only_config)
443 patch.assert_not_called()
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600444
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700445 def testMockCall(self):
446 """Test that a mock call does not execute logic, returns mocked value."""
447 patch = self.PatchObject(commands, 'BuildEbuildLogsTarball')
448 artifacts.BundleEbuildLogs(self.target_request, self.response,
449 self.mock_call_config)
450 patch.assert_not_called()
451 self.assertEqual(len(self.response.artifacts), 1)
452 self.assertEqual(self.response.artifacts[0].path,
453 os.path.join(self.output_dir, 'ebuild-logs.tar.gz'))
454
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600455 def testBundleEbuildLogs(self):
456 """BundleEbuildLogs calls cbuildbot/commands with correct args."""
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600457 bundle_ebuild_logs_tarball = self.PatchObject(
458 artifacts_svc, 'BundleEBuildLogsTarball',
459 return_value='ebuild-logs.tar.gz')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600460 artifacts.BundleEbuildLogs(self.sysroot_request, self.response,
461 self.api_config)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600462 self.assertEqual(
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600463 [artifact.path for artifact in self.response.artifacts],
Alex Klein68c8fdf2019-09-25 15:09:11 -0600464 [os.path.join(self.output_dir, 'ebuild-logs.tar.gz')])
Evan Hernandeza478d802019-04-08 15:08:24 -0600465 self.assertEqual(
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600466 bundle_ebuild_logs_tarball.call_args_list,
Alex Klein68c8fdf2019-09-25 15:09:11 -0600467 [mock.call(mock.ANY, self.sysroot, self.output_dir)])
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600468
469 def testBundleEBuildLogsOldProto(self):
470 bundle_ebuild_logs_tarball = self.PatchObject(
471 artifacts_svc, 'BundleEBuildLogsTarball',
472 return_value='ebuild-logs.tar.gz')
Alex Klein231d2da2019-07-22 16:44:45 -0600473
Alex Klein68c8fdf2019-09-25 15:09:11 -0600474 artifacts.BundleEbuildLogs(self.target_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600475 self.api_config)
476
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600477 self.assertEqual(
478 bundle_ebuild_logs_tarball.call_args_list,
Alex Klein68c8fdf2019-09-25 15:09:11 -0600479 [mock.call(mock.ANY, self.sysroot, self.output_dir)])
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600480
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600481 def testBundleEbuildLogsNoLogs(self):
482 """BundleEbuildLogs dies when no logs found."""
483 self.PatchObject(commands, 'BuildEbuildLogsTarball', return_value=None)
484 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein68c8fdf2019-09-25 15:09:11 -0600485 artifacts.BundleEbuildLogs(self.sysroot_request, self.response,
486 self.api_config)
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600487
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600488
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600489class BundleChromeOSConfigTest(BundleTestCase):
490 """Unittests for BundleChromeOSConfig"""
491
492 def testValidateOnly(self):
493 """Sanity check that a validate only call does not execute any logic."""
494 patch = self.PatchObject(artifacts_svc, 'BundleChromeOSConfig')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600495 artifacts.BundleChromeOSConfig(self.target_request, self.response,
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600496 self.validate_only_config)
497 patch.assert_not_called()
498
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700499 def testMockCall(self):
500 """Test that a mock call does not execute logic, returns mocked value."""
501 patch = self.PatchObject(artifacts_svc, 'BundleChromeOSConfig')
502 artifacts.BundleChromeOSConfig(self.target_request, self.response,
503 self.mock_call_config)
504 patch.assert_not_called()
505 self.assertEqual(len(self.response.artifacts), 1)
506 self.assertEqual(self.response.artifacts[0].path,
507 os.path.join(self.output_dir, 'config.yaml'))
508
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600509 def testBundleChromeOSConfigCallWithSysroot(self):
510 """Call with a request that sets sysroot."""
511 bundle_chromeos_config = self.PatchObject(
512 artifacts_svc, 'BundleChromeOSConfig', return_value='config.yaml')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600513 artifacts.BundleChromeOSConfig(self.sysroot_request, self.response,
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600514 self.api_config)
515 self.assertEqual(
Alex Klein68c8fdf2019-09-25 15:09:11 -0600516 [artifact.path for artifact in self.response.artifacts],
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600517 [os.path.join(self.output_dir, 'config.yaml')])
518
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600519 self.assertEqual(bundle_chromeos_config.call_args_list,
Alex Klein68c8fdf2019-09-25 15:09:11 -0600520 [mock.call(mock.ANY, self.sysroot, self.output_dir)])
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600521
522 def testBundleChromeOSConfigCallWithBuildTarget(self):
523 """Call with a request that sets build_target."""
524 bundle_chromeos_config = self.PatchObject(
525 artifacts_svc, 'BundleChromeOSConfig', return_value='config.yaml')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600526 artifacts.BundleChromeOSConfig(self.target_request, self.response,
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600527 self.api_config)
528
529 self.assertEqual(
Alex Klein68c8fdf2019-09-25 15:09:11 -0600530 [artifact.path for artifact in self.response.artifacts],
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600531 [os.path.join(self.output_dir, 'config.yaml')])
532
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600533 self.assertEqual(bundle_chromeos_config.call_args_list,
Alex Klein68c8fdf2019-09-25 15:09:11 -0600534 [mock.call(mock.ANY, self.sysroot, self.output_dir)])
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600535
536 def testBundleChromeOSConfigNoConfigFound(self):
537 """An error is raised if the config payload isn't found."""
538 self.PatchObject(artifacts_svc, 'BundleChromeOSConfig', return_value=None)
539
540 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein68c8fdf2019-09-25 15:09:11 -0600541 artifacts.BundleChromeOSConfig(self.sysroot_request, self.response,
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600542 self.api_config)
543
544
Alex Klein231d2da2019-07-22 16:44:45 -0600545class BundleTestUpdatePayloadsTest(cros_test_lib.MockTempDirTestCase,
546 api_config.ApiConfigMixin):
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600547 """Unittests for BundleTestUpdatePayloads."""
548
549 def setUp(self):
550 self.source_root = os.path.join(self.tempdir, 'cros')
551 osutils.SafeMakedirs(self.source_root)
552
553 self.archive_root = os.path.join(self.tempdir, 'output')
554 osutils.SafeMakedirs(self.archive_root)
555
556 self.target = 'target'
Evan Hernandez59690b72019-04-08 16:24:45 -0600557 self.image_root = os.path.join(self.source_root,
558 'src/build/images/target/latest')
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600559
560 self.input_proto = artifacts_pb2.BundleRequest()
561 self.input_proto.build_target.name = self.target
562 self.input_proto.output_dir = self.archive_root
563 self.output_proto = artifacts_pb2.BundleResponse()
564
565 self.PatchObject(constants, 'SOURCE_ROOT', new=self.source_root)
566
Alex Kleincb541e82019-06-26 15:06:11 -0600567 def MockPayloads(image_path, archive_dir):
568 osutils.WriteFile(os.path.join(archive_dir, 'payload1.bin'), image_path)
569 osutils.WriteFile(os.path.join(archive_dir, 'payload2.bin'), image_path)
570 return [os.path.join(archive_dir, 'payload1.bin'),
571 os.path.join(archive_dir, 'payload2.bin')]
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600572
Alex Kleincb541e82019-06-26 15:06:11 -0600573 self.bundle_patch = self.PatchObject(
574 artifacts_svc, 'BundleTestUpdatePayloads', side_effect=MockPayloads)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600575
Alex Klein231d2da2019-07-22 16:44:45 -0600576 def testValidateOnly(self):
577 """Sanity check that a validate only call does not execute any logic."""
578 patch = self.PatchObject(artifacts_svc, 'BundleTestUpdatePayloads')
579 artifacts.BundleTestUpdatePayloads(self.input_proto, self.output_proto,
580 self.validate_only_config)
581 patch.assert_not_called()
582
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700583 def testMockCall(self):
584 """Test that a mock call does not execute logic, returns mocked value."""
585 patch = self.PatchObject(artifacts_svc, 'BundleTestUpdatePayloads')
586 artifacts.BundleTestUpdatePayloads(self.input_proto, self.output_proto,
587 self.mock_call_config)
588 patch.assert_not_called()
589 self.assertEqual(len(self.output_proto.artifacts), 1)
590 self.assertEqual(self.output_proto.artifacts[0].path,
591 os.path.join(self.archive_root, 'payload1.bin'))
592
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600593 def testBundleTestUpdatePayloads(self):
594 """BundleTestUpdatePayloads calls cbuildbot/commands with correct args."""
595 image_path = os.path.join(self.image_root, constants.BASE_IMAGE_BIN)
596 osutils.WriteFile(image_path, 'image!', makedirs=True)
597
Alex Klein231d2da2019-07-22 16:44:45 -0600598 artifacts.BundleTestUpdatePayloads(self.input_proto, self.output_proto,
599 self.api_config)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600600
601 actual = [
602 os.path.relpath(artifact.path, self.archive_root)
603 for artifact in self.output_proto.artifacts
604 ]
Alex Kleincb541e82019-06-26 15:06:11 -0600605 expected = ['payload1.bin', 'payload2.bin']
Mike Frysinger678735c2019-09-28 18:23:28 -0400606 self.assertCountEqual(actual, expected)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600607
608 actual = [
609 os.path.relpath(path, self.archive_root)
610 for path in osutils.DirectoryIterator(self.archive_root)
611 ]
Mike Frysinger678735c2019-09-28 18:23:28 -0400612 self.assertCountEqual(actual, expected)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600613
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600614 def testBundleTestUpdatePayloadsNoImageDir(self):
615 """BundleTestUpdatePayloads dies if no image dir is found."""
616 # Intentionally do not write image directory.
Alex Kleind2bf1462019-10-24 16:37:04 -0600617 artifacts.BundleTestUpdatePayloads(self.input_proto, self.output_proto,
618 self.api_config)
619 self.assertFalse(self.output_proto.artifacts)
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600620
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600621 def testBundleTestUpdatePayloadsNoImage(self):
622 """BundleTestUpdatePayloads dies if no usable image is found for target."""
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600623 # Intentionally do not write image, but create the directory.
624 osutils.SafeMakedirs(self.image_root)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600625 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600626 artifacts.BundleTestUpdatePayloads(self.input_proto, self.output_proto,
627 self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600628
629
Alex Klein231d2da2019-07-22 16:44:45 -0600630class BundleSimpleChromeArtifactsTest(cros_test_lib.MockTempDirTestCase,
631 api_config.ApiConfigMixin):
Alex Klein2275d692019-04-23 16:04:12 -0600632 """BundleSimpleChromeArtifacts tests."""
633
634 def setUp(self):
635 self.chroot_dir = os.path.join(self.tempdir, 'chroot_dir')
636 self.sysroot_path = '/sysroot'
637 self.sysroot_dir = os.path.join(self.chroot_dir, 'sysroot')
638 osutils.SafeMakedirs(self.sysroot_dir)
639 self.output_dir = os.path.join(self.tempdir, 'output_dir')
640 osutils.SafeMakedirs(self.output_dir)
641
642 self.does_not_exist = os.path.join(self.tempdir, 'does_not_exist')
643
Alex Klein231d2da2019-07-22 16:44:45 -0600644 self.response = artifacts_pb2.BundleResponse()
645
Alex Klein2275d692019-04-23 16:04:12 -0600646 def _GetRequest(self, chroot=None, sysroot=None, build_target=None,
647 output_dir=None):
648 """Helper to create a request message instance.
649
650 Args:
651 chroot (str): The chroot path.
652 sysroot (str): The sysroot path.
653 build_target (str): The build target name.
654 output_dir (str): The output directory.
655 """
656 return artifacts_pb2.BundleRequest(
657 sysroot={'path': sysroot, 'build_target': {'name': build_target}},
658 chroot={'path': chroot}, output_dir=output_dir)
659
Alex Klein231d2da2019-07-22 16:44:45 -0600660 def testValidateOnly(self):
661 """Sanity check that a validate only call does not execute any logic."""
662 patch = self.PatchObject(artifacts_svc, 'BundleSimpleChromeArtifacts')
663 request = self._GetRequest(chroot=self.chroot_dir,
664 sysroot=self.sysroot_path,
665 build_target='board', output_dir=self.output_dir)
666 artifacts.BundleSimpleChromeArtifacts(request, self.response,
667 self.validate_only_config)
668 patch.assert_not_called()
Alex Klein2275d692019-04-23 16:04:12 -0600669
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700670 def testMockCall(self):
671 """Test that a mock call does not execute logic, returns mocked value."""
672 patch = self.PatchObject(artifacts_svc, 'BundleSimpleChromeArtifacts')
673 request = self._GetRequest(chroot=self.chroot_dir,
674 sysroot=self.sysroot_path,
675 build_target='board', output_dir=self.output_dir)
676 artifacts.BundleSimpleChromeArtifacts(request, self.response,
677 self.mock_call_config)
678 patch.assert_not_called()
679 self.assertEqual(len(self.response.artifacts), 1)
680 self.assertEqual(self.response.artifacts[0].path,
681 os.path.join(self.output_dir, 'simple_chrome.txt'))
682
Alex Klein2275d692019-04-23 16:04:12 -0600683 def testNoBuildTarget(self):
684 """Test no build target fails."""
685 request = self._GetRequest(chroot=self.chroot_dir,
686 sysroot=self.sysroot_path,
687 output_dir=self.output_dir)
Alex Klein231d2da2019-07-22 16:44:45 -0600688 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600689 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600690 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600691
692 def testNoSysroot(self):
693 """Test no sysroot fails."""
694 request = self._GetRequest(build_target='board', output_dir=self.output_dir)
Alex Klein231d2da2019-07-22 16:44:45 -0600695 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600696 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600697 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600698
699 def testSysrootDoesNotExist(self):
700 """Test no sysroot fails."""
701 request = self._GetRequest(build_target='board', output_dir=self.output_dir,
702 sysroot=self.does_not_exist)
Alex Klein231d2da2019-07-22 16:44:45 -0600703 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600704 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600705 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600706
707 def testNoOutputDir(self):
708 """Test no output dir fails."""
709 request = self._GetRequest(chroot=self.chroot_dir,
710 sysroot=self.sysroot_path,
711 build_target='board')
Alex Klein231d2da2019-07-22 16:44:45 -0600712 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600713 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600714 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600715
716 def testOutputDirDoesNotExist(self):
717 """Test no output dir fails."""
718 request = self._GetRequest(chroot=self.chroot_dir,
719 sysroot=self.sysroot_path,
720 build_target='board',
721 output_dir=self.does_not_exist)
Alex Klein231d2da2019-07-22 16:44:45 -0600722 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600723 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600724 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600725
726 def testOutputHandling(self):
727 """Test response output."""
728 files = ['file1', 'file2', 'file3']
729 expected_files = [os.path.join(self.output_dir, f) for f in files]
730 self.PatchObject(artifacts_svc, 'BundleSimpleChromeArtifacts',
731 return_value=expected_files)
732 request = self._GetRequest(chroot=self.chroot_dir,
733 sysroot=self.sysroot_path,
734 build_target='board', output_dir=self.output_dir)
Alex Klein231d2da2019-07-22 16:44:45 -0600735 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600736
Alex Klein231d2da2019-07-22 16:44:45 -0600737 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600738
739 self.assertTrue(response.artifacts)
Mike Frysinger678735c2019-09-28 18:23:28 -0400740 self.assertCountEqual(expected_files, [a.path for a in response.artifacts])
Alex Klein2275d692019-04-23 16:04:12 -0600741
742
Alex Klein231d2da2019-07-22 16:44:45 -0600743class BundleVmFilesTest(cros_test_lib.MockTempDirTestCase,
744 api_config.ApiConfigMixin):
Alex Klein6504eca2019-04-18 15:37:56 -0600745 """BuildVmFiles tests."""
746
Alex Klein231d2da2019-07-22 16:44:45 -0600747 def setUp(self):
748 self.output_dir = os.path.join(self.tempdir, 'output')
749 osutils.SafeMakedirs(self.output_dir)
750
751 self.response = artifacts_pb2.BundleResponse()
752
Alex Klein6504eca2019-04-18 15:37:56 -0600753 def _GetInput(self, chroot=None, sysroot=None, test_results_dir=None,
754 output_dir=None):
755 """Helper to build out an input message instance.
756
757 Args:
758 chroot (str|None): The chroot path.
759 sysroot (str|None): The sysroot path relative to the chroot.
760 test_results_dir (str|None): The test results directory relative to the
761 sysroot.
762 output_dir (str|None): The directory where the results tarball should be
763 saved.
764 """
765 return artifacts_pb2.BundleVmFilesRequest(
766 chroot={'path': chroot}, sysroot={'path': sysroot},
767 test_results_dir=test_results_dir, output_dir=output_dir,
768 )
769
Alex Klein231d2da2019-07-22 16:44:45 -0600770 def testValidateOnly(self):
771 """Sanity check that a validate only call does not execute any logic."""
772 patch = self.PatchObject(artifacts_svc, 'BundleVmFiles')
773 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
774 test_results_dir='/test/results',
775 output_dir=self.output_dir)
776 artifacts.BundleVmFiles(in_proto, self.response, self.validate_only_config)
777 patch.assert_not_called()
Alex Klein6504eca2019-04-18 15:37:56 -0600778
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700779 def testMockCall(self):
780 """Test that a mock call does not execute logic, returns mocked value."""
781 patch = self.PatchObject(artifacts_svc, 'BundleVmFiles')
782 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
783 test_results_dir='/test/results',
784 output_dir=self.output_dir)
785 artifacts.BundleVmFiles(in_proto, self.response, self.mock_call_config)
786 patch.assert_not_called()
787 self.assertEqual(len(self.response.artifacts), 1)
788 self.assertEqual(self.response.artifacts[0].path,
789 os.path.join(self.output_dir, 'f1.tar'))
790
Alex Klein6504eca2019-04-18 15:37:56 -0600791 def testChrootMissing(self):
792 """Test error handling for missing chroot."""
793 in_proto = self._GetInput(sysroot='/build/board',
794 test_results_dir='/test/results',
Alex Klein231d2da2019-07-22 16:44:45 -0600795 output_dir=self.output_dir)
Alex Klein6504eca2019-04-18 15:37:56 -0600796
797 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600798 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600799
Alex Klein6504eca2019-04-18 15:37:56 -0600800 def testTestResultsDirMissing(self):
801 """Test error handling for missing test results directory."""
802 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
Alex Klein231d2da2019-07-22 16:44:45 -0600803 output_dir=self.output_dir)
Alex Klein6504eca2019-04-18 15:37:56 -0600804
805 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600806 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600807
808 def testOutputDirMissing(self):
809 """Test error handling for missing output directory."""
810 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
811 test_results_dir='/test/results')
Alex Klein6504eca2019-04-18 15:37:56 -0600812
813 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600814 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
815
816 def testOutputDirDoesNotExist(self):
817 """Test error handling for output directory that does not exist."""
818 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
819 output_dir=os.path.join(self.tempdir, 'dne'),
820 test_results_dir='/test/results')
821
822 with self.assertRaises(cros_build_lib.DieSystemExit):
823 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600824
825 def testValidCall(self):
826 """Test image dir building."""
827 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
828 test_results_dir='/test/results',
Alex Klein231d2da2019-07-22 16:44:45 -0600829 output_dir=self.output_dir)
830
Alex Klein6504eca2019-04-18 15:37:56 -0600831 expected_files = ['/tmp/output/f1.tar', '/tmp/output/f2.tar']
Michael Mortensen51f06722019-07-18 09:55:50 -0600832 patch = self.PatchObject(artifacts_svc, 'BundleVmFiles',
Alex Klein6504eca2019-04-18 15:37:56 -0600833 return_value=expected_files)
834
Alex Klein231d2da2019-07-22 16:44:45 -0600835 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600836
Alex Klein231d2da2019-07-22 16:44:45 -0600837 patch.assert_called_with(mock.ANY, '/test/results', self.output_dir)
Alex Klein6504eca2019-04-18 15:37:56 -0600838
839 # Make sure we have artifacts, and that every artifact is an expected file.
Alex Klein231d2da2019-07-22 16:44:45 -0600840 self.assertTrue(self.response.artifacts)
841 for artifact in self.response.artifacts:
Alex Klein6504eca2019-04-18 15:37:56 -0600842 self.assertIn(artifact.path, expected_files)
843 expected_files.remove(artifact.path)
844
845 # Make sure we've seen all of the expected files.
846 self.assertFalse(expected_files)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700847
Alex Kleinb9d810b2019-07-01 12:38:02 -0600848
Tiancong Wang50b80a92019-08-01 14:46:15 -0700849
850class BundleAFDOGenerationArtifactsTestCase(
Alex Klein231d2da2019-07-22 16:44:45 -0600851 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin):
Tiancong Wang50b80a92019-08-01 14:46:15 -0700852 """Unittests for BundleAFDOGenerationArtifacts."""
853
854 @staticmethod
855 def mock_die(message, *args):
856 raise cros_build_lib.DieSystemExit(message % args)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700857
858 def setUp(self):
859 self.chroot_dir = os.path.join(self.tempdir, 'chroot_dir')
860 osutils.SafeMakedirs(self.chroot_dir)
861 temp_dir = os.path.join(self.chroot_dir, 'tmp')
862 osutils.SafeMakedirs(temp_dir)
863 self.output_dir = os.path.join(self.tempdir, 'output_dir')
864 osutils.SafeMakedirs(self.output_dir)
Tiancong Wang2ade7932019-09-27 14:15:40 -0700865 self.chrome_root = os.path.join(self.tempdir, 'chrome_root')
866 osutils.SafeMakedirs(self.chrome_root)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700867 self.build_target = 'board'
Tiancong Wang24a3df72019-08-20 15:48:51 -0700868 self.valid_artifact_type = toolchain_pb2.ORDERFILE
869 self.invalid_artifact_type = toolchain_pb2.NONE_TYPE
Tiancong Wangc4805b72019-06-11 12:12:03 -0700870 self.does_not_exist = os.path.join(self.tempdir, 'does_not_exist')
Tiancong Wang50b80a92019-08-01 14:46:15 -0700871 self.PatchObject(cros_build_lib, 'Die', new=self.mock_die)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700872
Alex Klein231d2da2019-07-22 16:44:45 -0600873 self.response = artifacts_pb2.BundleResponse()
874
Tiancong Wang2ade7932019-09-27 14:15:40 -0700875 def _GetRequest(self, chroot=None, build_target=None, chrome_root=None,
876 output_dir=None, artifact_type=None):
Tiancong Wangc4805b72019-06-11 12:12:03 -0700877 """Helper to create a request message instance.
878
879 Args:
880 chroot (str): The chroot path.
881 build_target (str): The build target name.
Tiancong Wang2ade7932019-09-27 14:15:40 -0700882 chrome_root (str): The path to Chrome root.
Tiancong Wangc4805b72019-06-11 12:12:03 -0700883 output_dir (str): The output directory.
Tiancong Wang50b80a92019-08-01 14:46:15 -0700884 artifact_type (artifacts_pb2.AFDOArtifactType):
885 The type of the artifact.
Tiancong Wangc4805b72019-06-11 12:12:03 -0700886 """
Tiancong Wang50b80a92019-08-01 14:46:15 -0700887 return artifacts_pb2.BundleChromeAFDORequest(
Tiancong Wang2ade7932019-09-27 14:15:40 -0700888 chroot={'path': chroot, 'chrome_dir': chrome_root},
Tiancong Wang50b80a92019-08-01 14:46:15 -0700889 build_target={'name': build_target},
890 output_dir=output_dir,
891 artifact_type=artifact_type,
Tiancong Wangc4805b72019-06-11 12:12:03 -0700892 )
893
Alex Klein231d2da2019-07-22 16:44:45 -0600894 def testValidateOnly(self):
895 """Sanity check that a validate only call does not execute any logic."""
896 patch = self.PatchObject(artifacts_svc,
Tiancong Wang50b80a92019-08-01 14:46:15 -0700897 'BundleAFDOGenerationArtifacts')
Alex Klein231d2da2019-07-22 16:44:45 -0600898 request = self._GetRequest(chroot=self.chroot_dir,
899 build_target=self.build_target,
Tiancong Wang2ade7932019-09-27 14:15:40 -0700900 chrome_root=self.chrome_root,
Tiancong Wang50b80a92019-08-01 14:46:15 -0700901 output_dir=self.output_dir,
902 artifact_type=self.valid_artifact_type)
903 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
904 self.validate_only_config)
Alex Klein231d2da2019-07-22 16:44:45 -0600905 patch.assert_not_called()
Tiancong Wangc4805b72019-06-11 12:12:03 -0700906
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700907 def testMockCall(self):
908 """Test that a mock call does not execute logic, returns mocked value."""
909 patch = self.PatchObject(artifacts_svc,
910 'BundleAFDOGenerationArtifacts')
911 request = self._GetRequest(chroot=self.chroot_dir,
912 build_target=self.build_target,
913 chrome_root=self.chrome_root,
914 output_dir=self.output_dir,
915 artifact_type=self.valid_artifact_type)
916 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
917 self.mock_call_config)
918 patch.assert_not_called()
919 self.assertEqual(len(self.response.artifacts), 1)
920 self.assertEqual(self.response.artifacts[0].path,
921 os.path.join(self.output_dir, 'artifact1'))
922
Tiancong Wangc4805b72019-06-11 12:12:03 -0700923 def testNoBuildTarget(self):
924 """Test no build target fails."""
925 request = self._GetRequest(chroot=self.chroot_dir,
Tiancong Wang2ade7932019-09-27 14:15:40 -0700926 chrome_root=self.chrome_root,
Tiancong Wang50b80a92019-08-01 14:46:15 -0700927 output_dir=self.output_dir,
928 artifact_type=self.valid_artifact_type)
929 with self.assertRaises(cros_build_lib.DieSystemExit) as context:
930 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
931 self.api_config)
932 self.assertEqual('build_target.name is required.',
933 str(context.exception))
Tiancong Wangc4805b72019-06-11 12:12:03 -0700934
Tiancong Wang2ade7932019-09-27 14:15:40 -0700935 def testNoChromeRoot(self):
936 """Test no chrome root fails."""
937 request = self._GetRequest(chroot=self.chroot_dir,
938 build_target=self.build_target,
939 output_dir=self.output_dir,
940 artifact_type=self.valid_artifact_type)
941 with self.assertRaises(cros_build_lib.DieSystemExit) as context:
942 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
943 self.api_config)
944 self.assertEqual('chroot.chrome_dir path does not exist: ',
945 str(context.exception))
946
Tiancong Wangc4805b72019-06-11 12:12:03 -0700947 def testNoOutputDir(self):
948 """Test no output dir fails."""
949 request = self._GetRequest(chroot=self.chroot_dir,
Tiancong Wang50b80a92019-08-01 14:46:15 -0700950 build_target=self.build_target,
Tiancong Wang2ade7932019-09-27 14:15:40 -0700951 chrome_root=self.chrome_root,
Tiancong Wang50b80a92019-08-01 14:46:15 -0700952 artifact_type=self.valid_artifact_type)
953 with self.assertRaises(cros_build_lib.DieSystemExit) as context:
954 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
955 self.api_config)
956 self.assertEqual('output_dir is required.',
957 str(context.exception))
Tiancong Wangc4805b72019-06-11 12:12:03 -0700958
959 def testOutputDirDoesNotExist(self):
960 """Test output directory not existing fails."""
961 request = self._GetRequest(chroot=self.chroot_dir,
Tiancong Wangc4805b72019-06-11 12:12:03 -0700962 build_target=self.build_target,
Tiancong Wang2ade7932019-09-27 14:15:40 -0700963 chrome_root=self.chrome_root,
Tiancong Wang50b80a92019-08-01 14:46:15 -0700964 output_dir=self.does_not_exist,
965 artifact_type=self.valid_artifact_type)
966 with self.assertRaises(cros_build_lib.DieSystemExit) as context:
967 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
968 self.api_config)
969 self.assertEqual(
970 'output_dir path does not exist: %s' % self.does_not_exist,
971 str(context.exception))
Tiancong Wangc4805b72019-06-11 12:12:03 -0700972
Tiancong Wang50b80a92019-08-01 14:46:15 -0700973 def testNoArtifactType(self):
974 """Test no artifact type."""
975 request = self._GetRequest(chroot=self.chroot_dir,
976 build_target=self.build_target,
Tiancong Wang2ade7932019-09-27 14:15:40 -0700977 chrome_root=self.chrome_root,
Tiancong Wang50b80a92019-08-01 14:46:15 -0700978 output_dir=self.output_dir)
979 with self.assertRaises(cros_build_lib.DieSystemExit) as context:
980 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
981 self.api_config)
982 self.assertIn('artifact_type (0) must be in',
983 str(context.exception))
984
985 def testWrongArtifactType(self):
986 """Test passing wrong artifact type."""
987 request = self._GetRequest(chroot=self.chroot_dir,
988 build_target=self.build_target,
Tiancong Wang2ade7932019-09-27 14:15:40 -0700989 chrome_root=self.chrome_root,
Tiancong Wang50b80a92019-08-01 14:46:15 -0700990 output_dir=self.output_dir,
991 artifact_type=self.invalid_artifact_type)
992 with self.assertRaises(cros_build_lib.DieSystemExit) as context:
993 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
994 self.api_config)
Tiancong Wang24a3df72019-08-20 15:48:51 -0700995 self.assertIn('artifact_type (%d) must be in' % self.invalid_artifact_type,
Tiancong Wang50b80a92019-08-01 14:46:15 -0700996 str(context.exception))
997
998 def testOutputHandlingOnOrderfile(self,
Tiancong Wang24a3df72019-08-20 15:48:51 -0700999 artifact_type=toolchain_pb2.ORDERFILE):
Tiancong Wang50b80a92019-08-01 14:46:15 -07001000 """Test response output for orderfile."""
1001 files = ['artifact1', 'artifact2', 'artifact3']
Tiancong Wangc4805b72019-06-11 12:12:03 -07001002 expected_files = [os.path.join(self.output_dir, f) for f in files]
Tiancong Wang50b80a92019-08-01 14:46:15 -07001003 self.PatchObject(artifacts_svc, 'BundleAFDOGenerationArtifacts',
Tiancong Wangc4805b72019-06-11 12:12:03 -07001004 return_value=expected_files)
Alex Klein231d2da2019-07-22 16:44:45 -06001005
Tiancong Wangc4805b72019-06-11 12:12:03 -07001006 request = self._GetRequest(chroot=self.chroot_dir,
Tiancong Wangc4805b72019-06-11 12:12:03 -07001007 build_target=self.build_target,
Tiancong Wang2ade7932019-09-27 14:15:40 -07001008 chrome_root=self.chrome_root,
Tiancong Wang50b80a92019-08-01 14:46:15 -07001009 output_dir=self.output_dir,
1010 artifact_type=artifact_type)
Tiancong Wangc4805b72019-06-11 12:12:03 -07001011
Tiancong Wang50b80a92019-08-01 14:46:15 -07001012 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
1013 self.api_config)
Tiancong Wangc4805b72019-06-11 12:12:03 -07001014
Tiancong Wang50b80a92019-08-01 14:46:15 -07001015 self.assertTrue(self.response.artifacts)
Mike Frysinger678735c2019-09-28 18:23:28 -04001016 self.assertCountEqual(expected_files,
Tiancong Wang50b80a92019-08-01 14:46:15 -07001017 [a.path for a in self.response.artifacts])
1018
1019 def testOutputHandlingOnAFDO(self):
1020 """Test response output for AFDO."""
1021 self.testOutputHandlingOnOrderfile(
Tiancong Wang24a3df72019-08-20 15:48:51 -07001022 artifact_type=toolchain_pb2.BENCHMARK_AFDO)
Alex Klein0b1cbfc2019-08-14 10:09:58 -06001023
1024
1025class ExportCpeReportTest(cros_test_lib.MockTempDirTestCase,
1026 api_config.ApiConfigMixin):
1027 """ExportCpeReport tests."""
1028
1029 def setUp(self):
1030 self.response = artifacts_pb2.BundleResponse()
1031
1032 def testValidateOnly(self):
1033 """Sanity check validate only calls don't execute."""
1034 patch = self.PatchObject(artifacts_svc, 'GenerateCpeReport')
1035
1036 request = artifacts_pb2.BundleRequest()
1037 request.build_target.name = 'board'
1038 request.output_dir = self.tempdir
1039
1040 artifacts.ExportCpeReport(request, self.response, self.validate_only_config)
1041
1042 patch.assert_not_called()
1043
Michael Mortensen2d6a2402019-11-26 13:40:40 -07001044 def testMockCall(self):
1045 """Test that a mock call does not execute logic, returns mocked value."""
1046 patch = self.PatchObject(artifacts_svc, 'GenerateCpeReport')
1047
1048 request = artifacts_pb2.BundleRequest()
1049 request.build_target.name = 'board'
1050 request.output_dir = self.tempdir
1051
1052 artifacts.ExportCpeReport(request, self.response, self.mock_call_config)
1053
1054 patch.assert_not_called()
1055 self.assertEqual(len(self.response.artifacts), 2)
1056 self.assertEqual(self.response.artifacts[0].path,
1057 os.path.join(self.tempdir, 'cpe_report.txt'))
1058 self.assertEqual(self.response.artifacts[1].path,
1059 os.path.join(self.tempdir, 'cpe_warnings.txt'))
1060
Alex Klein0b1cbfc2019-08-14 10:09:58 -06001061 def testNoBuildTarget(self):
1062 request = artifacts_pb2.BundleRequest()
1063 request.output_dir = self.tempdir
1064
1065 with self.assertRaises(cros_build_lib.DieSystemExit):
1066 artifacts.ExportCpeReport(request, self.response, self.api_config)
1067
1068 def testSuccess(self):
1069 """Test success case."""
1070 expected = artifacts_svc.CpeResult(
1071 report='/output/report.json', warnings='/output/warnings.json')
1072 self.PatchObject(artifacts_svc, 'GenerateCpeReport', return_value=expected)
1073
1074 request = artifacts_pb2.BundleRequest()
1075 request.build_target.name = 'board'
1076 request.output_dir = self.tempdir
1077
1078 artifacts.ExportCpeReport(request, self.response, self.api_config)
1079
1080 for artifact in self.response.artifacts:
1081 self.assertIn(artifact.path, [expected.report, expected.warnings])
Shao-Chuan Leea44dddc2020-10-30 17:16:55 +09001082
1083
1084class BundleGceTarballTest(BundleTestCase):
1085 """Unittests for BundleGceTarball."""
1086
1087 def testValidateOnly(self):
1088 """Check that a validate only call does not execute any logic."""
1089 patch = self.PatchObject(artifacts_svc, 'BundleGceTarball')
1090 artifacts.BundleGceTarball(self.target_request, self.response,
1091 self.validate_only_config)
1092 patch.assert_not_called()
1093
1094 def testMockCall(self):
1095 """Test that a mock call does not execute logic, returns mocked value."""
1096 patch = self.PatchObject(artifacts_svc, 'BundleGceTarball')
1097 artifacts.BundleGceTarball(self.target_request, self.response,
1098 self.mock_call_config)
1099 patch.assert_not_called()
1100 self.assertEqual(len(self.response.artifacts), 1)
1101 self.assertEqual(self.response.artifacts[0].path,
1102 os.path.join(self.output_dir,
1103 constants.TEST_IMAGE_GCE_TAR))
1104
1105 def testBundleGceTarball(self):
1106 """BundleGceTarball calls cbuildbot/commands with correct args."""
1107 bundle_gce_tarball = self.PatchObject(
1108 artifacts_svc, 'BundleGceTarball',
1109 return_value=os.path.join(self.output_dir,
1110 constants.TEST_IMAGE_GCE_TAR))
1111 self.PatchObject(os.path, 'exists', return_value=True)
1112 artifacts.BundleGceTarball(self.target_request, self.response,
1113 self.api_config)
1114 self.assertEqual(
1115 [artifact.path for artifact in self.response.artifacts],
1116 [os.path.join(self.output_dir, constants.TEST_IMAGE_GCE_TAR)])
1117
1118 latest = os.path.join(self.source_root, 'src/build/images/target/latest')
1119 self.assertEqual(
1120 bundle_gce_tarball.call_args_list,
1121 [mock.call(self.output_dir, latest)])
1122
1123 def testBundleGceTarballNoImageDir(self):
1124 """BundleGceTarball dies when image dir does not exist."""
1125 self.PatchObject(os.path, 'exists', return_value=False)
1126 with self.assertRaises(cros_build_lib.DieSystemExit):
1127 artifacts.BundleGceTarball(self.target_request, self.response,
1128 self.api_config)