blob: 5c5255c597eeb8a0820e64b696b6f409ceef4a7f [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
Greg Edelstondc941072021-08-11 12:32:30 -06008import pathlib
Varun Somani04dccd72021-10-09 01:06:11 +00009from typing import Optional
Mike Frysinger166fea02021-02-12 05:30:33 -050010from unittest import mock
Evan Hernandezf388cbf2019-04-01 11:15:23 -060011
Alex Klein231d2da2019-07-22 16:44:45 -060012from chromite.api import api_config
Evan Hernandezf388cbf2019-04-01 11:15:23 -060013from chromite.api.controller import artifacts
Greg Edelstondc941072021-08-11 12:32:30 -060014from chromite.api.controller import controller_util
Evan Hernandezf388cbf2019-04-01 11:15:23 -060015from chromite.api.gen.chromite.api import artifacts_pb2
Greg Edelstondc941072021-08-11 12:32:30 -060016from chromite.api.gen.chromiumos import common_pb2
Evan Hernandezf388cbf2019-04-01 11:15:23 -060017from chromite.cbuildbot import commands
Alex Kleinb9d810b2019-07-01 12:38:02 -060018from chromite.lib import chroot_lib
Evan Hernandezf388cbf2019-04-01 11:15:23 -060019from chromite.lib import constants
20from chromite.lib import cros_build_lib
21from chromite.lib import cros_test_lib
22from chromite.lib import osutils
Alex Klein238d8862019-05-07 11:32:46 -060023from chromite.lib import sysroot_lib
Alex Klein2275d692019-04-23 16:04:12 -060024from chromite.service import artifacts as artifacts_svc
Evan Hernandezf388cbf2019-04-01 11:15:23 -060025
26
Alex Kleind91e95a2019-09-17 10:39:02 -060027class BundleRequestMixin(object):
28 """Mixin to provide bundle request methods."""
29
30 def EmptyRequest(self):
31 return artifacts_pb2.BundleRequest()
32
33 def BuildTargetRequest(self, build_target=None, output_dir=None, chroot=None):
34 """Get a build target format request instance."""
35 request = self.EmptyRequest()
36 if build_target:
37 request.build_target.name = build_target
38 if output_dir:
39 request.output_dir = output_dir
40 if chroot:
41 request.chroot.path = chroot
42
43 return request
44
45 def SysrootRequest(self,
46 sysroot=None,
47 build_target=None,
48 output_dir=None,
49 chroot=None):
50 """Get a sysroot format request instance."""
51 request = self.EmptyRequest()
52 if sysroot:
53 request.sysroot.path = sysroot
54 if build_target:
55 request.sysroot.build_target.name = build_target
56 if output_dir:
57 request.output_dir = output_dir
58 if chroot:
59 request.chroot.path = chroot
60
61 return request
62
63
Alex Klein231d2da2019-07-22 16:44:45 -060064class BundleTestCase(cros_test_lib.MockTempDirTestCase,
Alex Kleind91e95a2019-09-17 10:39:02 -060065 api_config.ApiConfigMixin, BundleRequestMixin):
Evan Hernandezf388cbf2019-04-01 11:15:23 -060066 """Basic setup for all artifacts unittests."""
67
68 def setUp(self):
Gilberto Contrerasf9fd1f42022-02-26 09:31:30 -080069 self.PatchObject(cros_build_lib, 'IsInsideChroot', return_value=False)
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):
Greg Edelstondc941072021-08-11 12:32:30 -0600103 """Quick check that a validate only call does not execute any logic."""
Alex Kleind91e95a2019-09-17 10:39:02 -0600104 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."""
Mike Frysinger3bb61cb2022-04-14 16:07:44 -0400123 request = self.BuildTargetRequest(output_dir=str(self.tempdir))
Alex Kleind91e95a2019-09-17 10:39:02 -0600124 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):
Greg Edelstondc941072021-08-11 12:32:30 -0600156 """Quick check that a validate only call does not execute any logic."""
Alex Klein231d2da2019-07-22 16:44:45 -0600157 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):
Greg Edelstondc941072021-08-11 12:32:30 -0600200 """Quick check that a validate only call does not execute any logic."""
Alex Klein231d2da2019-07-22 16:44:45 -0600201 patch = self.PatchObject(artifacts_svc, 'BundleAutotestFiles')
Alex Klein036833d2022-06-01 13:05:01 -0600202 artifacts.BundleAutotestFiles(self.sysroot_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')
Alex Klein036833d2022-06-01 13:05:01 -0600209 artifacts.BundleAutotestFiles(self.sysroot_request, self.response,
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700210 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 testBundleAutotestFiles(self):
217 """BundleAutotestFiles calls service correctly."""
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.sysroot_request, self.response,
226 self.api_config)
Alex Klein238d8862019-05-07 11:32:46 -0600227
228 # 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.
232 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 testInvalidOutputDir(self):
237 """Test invalid output directory argument."""
Alex Klein68c8fdf2019-09-25 15:09:11 -0600238 request = self.SysrootRequest(chroot=self.chroot_path,
239 sysroot=self.sysroot_path)
Alex Klein238d8862019-05-07 11:32:46 -0600240
241 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600242 artifacts.BundleAutotestFiles(request, self.response, self.api_config)
Alex Klein238d8862019-05-07 11:32:46 -0600243
244 def testInvalidSysroot(self):
245 """Test no sysroot directory."""
Alex Klein68c8fdf2019-09-25 15:09:11 -0600246 request = self.SysrootRequest(chroot=self.chroot_path,
247 output_dir=self.output_dir)
Alex Klein238d8862019-05-07 11:32:46 -0600248
249 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600250 artifacts.BundleAutotestFiles(request, self.response, self.api_config)
Alex Klein238d8862019-05-07 11:32:46 -0600251
252 def testSysrootDoesNotExist(self):
253 """Test dies when no sysroot does not exist."""
Alex Klein68c8fdf2019-09-25 15:09:11 -0600254 request = self.SysrootRequest(chroot=self.chroot_path,
255 sysroot='/does/not/exist',
256 output_dir=self.output_dir)
Alex Klein238d8862019-05-07 11:32:46 -0600257
Alex Klein036833d2022-06-01 13:05:01 -0600258 artifacts.BundleAutotestFiles(request, self.response, self.api_config)
259 self.assertFalse(self.response.artifacts)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600260
261
262class BundleTastFilesTest(BundleTestCase):
263 """Unittests for BundleTastFiles."""
264
Alex Klein231d2da2019-07-22 16:44:45 -0600265 def testValidateOnly(self):
Greg Edelstondc941072021-08-11 12:32:30 -0600266 """Quick check that a validate only call does not execute any logic."""
Alex Klein231d2da2019-07-22 16:44:45 -0600267 patch = self.PatchObject(artifacts_svc, 'BundleTastFiles')
Alex Klein036833d2022-06-01 13:05:01 -0600268 artifacts.BundleTastFiles(self.sysroot_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600269 self.validate_only_config)
270 patch.assert_not_called()
271
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700272 def testMockCall(self):
273 """Test that a mock call does not execute logic, returns mocked value."""
274 patch = self.PatchObject(artifacts_svc, 'BundleTastFiles')
Alex Klein036833d2022-06-01 13:05:01 -0600275 artifacts.BundleTastFiles(self.sysroot_request, self.response,
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700276 self.mock_call_config)
277 patch.assert_not_called()
278 self.assertEqual(len(self.response.artifacts), 1)
279 self.assertEqual(self.response.artifacts[0].path,
280 os.path.join(self.output_dir, 'tast_bundles.tar.gz'))
281
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600282 def testBundleTastFilesNoLogs(self):
LaMont Jonesb9793cd2020-06-11 08:14:46 -0600283 """BundleTasteFiles succeeds when no tast files found."""
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600284 self.PatchObject(commands, 'BuildTastBundleTarball',
285 return_value=None)
Alex Klein036833d2022-06-01 13:05:01 -0600286 artifacts.BundleTastFiles(self.sysroot_request, self.response,
LaMont Jonesb9793cd2020-06-11 08:14:46 -0600287 self.api_config)
Alex Klein036833d2022-06-01 13:05:01 -0600288 self.assertFalse(self.response.artifacts)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600289
290 def testBundleTastFiles(self):
291 """BundleTastFiles calls service correctly."""
Alex Kleinb49be8a2019-12-20 10:23:03 -0700292 chroot = chroot_lib.Chroot(self.chroot_path)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600293
Alex Klein68c8fdf2019-09-25 15:09:11 -0600294 expected_archive = os.path.join(self.output_dir,
295 artifacts_svc.TAST_BUNDLE_NAME)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600296 # Patch the service being called.
297 bundle_patch = self.PatchObject(artifacts_svc, 'BundleTastFiles',
298 return_value=expected_archive)
299
Alex Klein68c8fdf2019-09-25 15:09:11 -0600300 artifacts.BundleTastFiles(self.sysroot_request, self.response,
301 self.api_config)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600302
303 # Make sure the artifact got recorded successfully.
Alex Klein68c8fdf2019-09-25 15:09:11 -0600304 self.assertTrue(self.response.artifacts)
305 self.assertEqual(expected_archive, self.response.artifacts[0].path)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600306 # Make sure the service got called correctly.
Alex Klein68c8fdf2019-09-25 15:09:11 -0600307 bundle_patch.assert_called_once_with(chroot, self.sysroot, self.output_dir)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600308
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600309
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600310class BundleFirmwareTest(BundleTestCase):
311 """Unittests for BundleFirmware."""
312
Alex Klein231d2da2019-07-22 16:44:45 -0600313 def testValidateOnly(self):
Greg Edelstondc941072021-08-11 12:32:30 -0600314 """Quick check that a validate only call does not execute any logic."""
Alex Klein231d2da2019-07-22 16:44:45 -0600315 patch = self.PatchObject(artifacts_svc, 'BundleTastFiles')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600316 artifacts.BundleFirmware(self.sysroot_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600317 self.validate_only_config)
318 patch.assert_not_called()
Michael Mortensen38675192019-06-28 16:52:55 +0000319
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700320 def testMockCall(self):
321 """Test that a mock call does not execute logic, returns mocked value."""
322 patch = self.PatchObject(artifacts_svc, 'BundleTastFiles')
323 artifacts.BundleFirmware(self.sysroot_request, self.response,
324 self.mock_call_config)
325 patch.assert_not_called()
326 self.assertEqual(len(self.response.artifacts), 1)
327 self.assertEqual(self.response.artifacts[0].path,
328 os.path.join(self.output_dir, 'firmware.tar.gz'))
329
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600330 def testBundleFirmware(self):
331 """BundleFirmware calls cbuildbot/commands with correct args."""
Alex Klein231d2da2019-07-22 16:44:45 -0600332 self.PatchObject(
333 artifacts_svc,
334 'BuildFirmwareArchive',
335 return_value=os.path.join(self.output_dir, 'firmware.tar.gz'))
336
Alex Klein68c8fdf2019-09-25 15:09:11 -0600337 artifacts.BundleFirmware(self.sysroot_request, self.response,
338 self.api_config)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600339 self.assertEqual(
Alex Klein231d2da2019-07-22 16:44:45 -0600340 [artifact.path for artifact in self.response.artifacts],
341 [os.path.join(self.output_dir, 'firmware.tar.gz')])
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600342
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600343 def testBundleFirmwareNoLogs(self):
344 """BundleFirmware dies when no firmware found."""
345 self.PatchObject(commands, 'BuildFirmwareArchive', return_value=None)
George Engelbrecht9e41e172021-11-18 17:04:22 -0700346 artifacts.BundleFirmware(self.sysroot_request, self.response,
347 self.api_config)
348 self.assertEqual(len(self.response.artifacts), 0)
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600349
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600350
Yicheng Liea1181f2020-09-22 11:51:10 -0700351class BundleFpmcuUnittestsTest(BundleTestCase):
352 """Unittests for BundleFpmcuUnittests."""
353
354 def testValidateOnly(self):
Greg Edelstondc941072021-08-11 12:32:30 -0600355 """Quick check that a validate only call does not execute any logic."""
Yicheng Liea1181f2020-09-22 11:51:10 -0700356 patch = self.PatchObject(artifacts_svc, 'BundleFpmcuUnittests')
357 artifacts.BundleFpmcuUnittests(self.sysroot_request, self.response,
358 self.validate_only_config)
359 patch.assert_not_called()
360
361 def testMockCall(self):
362 """Test that a mock call does not execute logic, returns mocked value."""
363 patch = self.PatchObject(artifacts_svc, 'BundleFpmcuUnittests')
364 artifacts.BundleFpmcuUnittests(self.sysroot_request, self.response,
365 self.mock_call_config)
366 patch.assert_not_called()
367 self.assertEqual(len(self.response.artifacts), 1)
368 self.assertEqual(self.response.artifacts[0].path,
369 os.path.join(self.output_dir,
370 'fpmcu_unittests.tar.gz'))
371
372 def testBundleFpmcuUnittests(self):
373 """BundleFpmcuUnittests calls cbuildbot/commands with correct args."""
374 self.PatchObject(
375 artifacts_svc,
376 'BundleFpmcuUnittests',
377 return_value=os.path.join(self.output_dir, 'fpmcu_unittests.tar.gz'))
378 artifacts.BundleFpmcuUnittests(self.sysroot_request, self.response,
379 self.api_config)
380 self.assertEqual(
381 [artifact.path for artifact in self.response.artifacts],
382 [os.path.join(self.output_dir, 'fpmcu_unittests.tar.gz')])
383
384 def testBundleFpmcuUnittestsNoLogs(self):
385 """BundleFpmcuUnittests does not die when no fpmcu unittests found."""
386 self.PatchObject(artifacts_svc, 'BundleFpmcuUnittests',
387 return_value=None)
388 artifacts.BundleFpmcuUnittests(self.sysroot_request, self.response,
389 self.api_config)
390 self.assertFalse(self.response.artifacts)
391
392
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600393class BundleEbuildLogsTest(BundleTestCase):
394 """Unittests for BundleEbuildLogs."""
395
Alex Klein231d2da2019-07-22 16:44:45 -0600396 def testValidateOnly(self):
Greg Edelstondc941072021-08-11 12:32:30 -0600397 """Quick check that a validate only call does not execute any logic."""
Alex Klein231d2da2019-07-22 16:44:45 -0600398 patch = self.PatchObject(commands, 'BuildEbuildLogsTarball')
Alex Klein036833d2022-06-01 13:05:01 -0600399 artifacts.BundleEbuildLogs(self.sysroot_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600400 self.validate_only_config)
401 patch.assert_not_called()
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600402
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700403 def testMockCall(self):
404 """Test that a mock call does not execute logic, returns mocked value."""
405 patch = self.PatchObject(commands, 'BuildEbuildLogsTarball')
Alex Klein036833d2022-06-01 13:05:01 -0600406 artifacts.BundleEbuildLogs(self.sysroot_request, self.response,
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700407 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, 'ebuild-logs.tar.gz'))
412
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600413 def testBundleEbuildLogs(self):
414 """BundleEbuildLogs calls cbuildbot/commands with correct args."""
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600415 bundle_ebuild_logs_tarball = self.PatchObject(
416 artifacts_svc, 'BundleEBuildLogsTarball',
417 return_value='ebuild-logs.tar.gz')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600418 artifacts.BundleEbuildLogs(self.sysroot_request, self.response,
419 self.api_config)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600420 self.assertEqual(
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600421 [artifact.path for artifact in self.response.artifacts],
Alex Klein68c8fdf2019-09-25 15:09:11 -0600422 [os.path.join(self.output_dir, 'ebuild-logs.tar.gz')])
Evan Hernandeza478d802019-04-08 15:08:24 -0600423 self.assertEqual(
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600424 bundle_ebuild_logs_tarball.call_args_list,
Alex Klein68c8fdf2019-09-25 15:09:11 -0600425 [mock.call(mock.ANY, self.sysroot, self.output_dir)])
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600426
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600427 def testBundleEbuildLogsNoLogs(self):
428 """BundleEbuildLogs dies when no logs found."""
429 self.PatchObject(commands, 'BuildEbuildLogsTarball', return_value=None)
Alex Klein036833d2022-06-01 13:05:01 -0600430 artifacts.BundleEbuildLogs(self.sysroot_request, self.response,
431 self.api_config)
432
433 self.assertFalse(self.response.artifacts)
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600434
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600435
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600436class BundleChromeOSConfigTest(BundleTestCase):
437 """Unittests for BundleChromeOSConfig"""
438
439 def testValidateOnly(self):
Greg Edelstondc941072021-08-11 12:32:30 -0600440 """Quick check that a validate only call does not execute any logic."""
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600441 patch = self.PatchObject(artifacts_svc, 'BundleChromeOSConfig')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600442 artifacts.BundleChromeOSConfig(self.target_request, self.response,
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600443 self.validate_only_config)
444 patch.assert_not_called()
445
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700446 def testMockCall(self):
447 """Test that a mock call does not execute logic, returns mocked value."""
448 patch = self.PatchObject(artifacts_svc, 'BundleChromeOSConfig')
449 artifacts.BundleChromeOSConfig(self.target_request, self.response,
450 self.mock_call_config)
451 patch.assert_not_called()
452 self.assertEqual(len(self.response.artifacts), 1)
453 self.assertEqual(self.response.artifacts[0].path,
454 os.path.join(self.output_dir, 'config.yaml'))
455
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600456 def testBundleChromeOSConfigCallWithSysroot(self):
457 """Call with a request that sets sysroot."""
458 bundle_chromeos_config = self.PatchObject(
459 artifacts_svc, 'BundleChromeOSConfig', return_value='config.yaml')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600460 artifacts.BundleChromeOSConfig(self.sysroot_request, self.response,
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600461 self.api_config)
462 self.assertEqual(
Alex Klein68c8fdf2019-09-25 15:09:11 -0600463 [artifact.path for artifact in self.response.artifacts],
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600464 [os.path.join(self.output_dir, 'config.yaml')])
465
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600466 self.assertEqual(bundle_chromeos_config.call_args_list,
Alex Klein68c8fdf2019-09-25 15:09:11 -0600467 [mock.call(mock.ANY, self.sysroot, self.output_dir)])
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600468
469 def testBundleChromeOSConfigCallWithBuildTarget(self):
470 """Call with a request that sets build_target."""
471 bundle_chromeos_config = self.PatchObject(
472 artifacts_svc, 'BundleChromeOSConfig', return_value='config.yaml')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600473 artifacts.BundleChromeOSConfig(self.target_request, self.response,
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600474 self.api_config)
475
476 self.assertEqual(
Alex Klein68c8fdf2019-09-25 15:09:11 -0600477 [artifact.path for artifact in self.response.artifacts],
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600478 [os.path.join(self.output_dir, 'config.yaml')])
479
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600480 self.assertEqual(bundle_chromeos_config.call_args_list,
Alex Klein68c8fdf2019-09-25 15:09:11 -0600481 [mock.call(mock.ANY, self.sysroot, self.output_dir)])
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600482
483 def testBundleChromeOSConfigNoConfigFound(self):
Alex Klein383a7a32021-12-07 16:01:19 -0700484 """Empty results when the config payload isn't found."""
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600485 self.PatchObject(artifacts_svc, 'BundleChromeOSConfig', return_value=None)
486
Alex Klein383a7a32021-12-07 16:01:19 -0700487 artifacts.BundleChromeOSConfig(self.sysroot_request, self.response,
488 self.api_config)
489 self.assertFalse(self.response.artifacts)
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600490
491
Alex Klein231d2da2019-07-22 16:44:45 -0600492class BundleTestUpdatePayloadsTest(cros_test_lib.MockTempDirTestCase,
493 api_config.ApiConfigMixin):
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600494 """Unittests for BundleTestUpdatePayloads."""
495
496 def setUp(self):
497 self.source_root = os.path.join(self.tempdir, 'cros')
498 osutils.SafeMakedirs(self.source_root)
499
500 self.archive_root = os.path.join(self.tempdir, 'output')
501 osutils.SafeMakedirs(self.archive_root)
502
503 self.target = 'target'
Evan Hernandez59690b72019-04-08 16:24:45 -0600504 self.image_root = os.path.join(self.source_root,
505 'src/build/images/target/latest')
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600506
507 self.input_proto = artifacts_pb2.BundleRequest()
508 self.input_proto.build_target.name = self.target
509 self.input_proto.output_dir = self.archive_root
510 self.output_proto = artifacts_pb2.BundleResponse()
511
512 self.PatchObject(constants, 'SOURCE_ROOT', new=self.source_root)
513
Alex Kleincb541e82019-06-26 15:06:11 -0600514 def MockPayloads(image_path, archive_dir):
515 osutils.WriteFile(os.path.join(archive_dir, 'payload1.bin'), image_path)
516 osutils.WriteFile(os.path.join(archive_dir, 'payload2.bin'), image_path)
517 return [os.path.join(archive_dir, 'payload1.bin'),
518 os.path.join(archive_dir, 'payload2.bin')]
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600519
Alex Kleincb541e82019-06-26 15:06:11 -0600520 self.bundle_patch = self.PatchObject(
521 artifacts_svc, 'BundleTestUpdatePayloads', side_effect=MockPayloads)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600522
Alex Klein231d2da2019-07-22 16:44:45 -0600523 def testValidateOnly(self):
Greg Edelstondc941072021-08-11 12:32:30 -0600524 """Quick check that a validate only call does not execute any logic."""
Alex Klein231d2da2019-07-22 16:44:45 -0600525 patch = self.PatchObject(artifacts_svc, 'BundleTestUpdatePayloads')
526 artifacts.BundleTestUpdatePayloads(self.input_proto, self.output_proto,
527 self.validate_only_config)
528 patch.assert_not_called()
529
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700530 def testMockCall(self):
531 """Test that a mock call does not execute logic, returns mocked value."""
532 patch = self.PatchObject(artifacts_svc, 'BundleTestUpdatePayloads')
533 artifacts.BundleTestUpdatePayloads(self.input_proto, self.output_proto,
534 self.mock_call_config)
535 patch.assert_not_called()
George Engelbrechtf0239d52022-04-06 13:09:33 -0600536 self.assertEqual(len(self.output_proto.artifacts), 3)
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700537 self.assertEqual(self.output_proto.artifacts[0].path,
538 os.path.join(self.archive_root, 'payload1.bin'))
George Engelbrechtf0239d52022-04-06 13:09:33 -0600539 self.assertEqual(self.output_proto.artifacts[1].path,
540 os.path.join(self.archive_root, 'payload1.json'))
541 self.assertEqual(self.output_proto.artifacts[2].path,
542 os.path.join(self.archive_root, 'payload1.log'))
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700543
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600544 def testBundleTestUpdatePayloads(self):
545 """BundleTestUpdatePayloads calls cbuildbot/commands with correct args."""
546 image_path = os.path.join(self.image_root, constants.BASE_IMAGE_BIN)
547 osutils.WriteFile(image_path, 'image!', makedirs=True)
548
Alex Klein231d2da2019-07-22 16:44:45 -0600549 artifacts.BundleTestUpdatePayloads(self.input_proto, self.output_proto,
550 self.api_config)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600551
552 actual = [
553 os.path.relpath(artifact.path, self.archive_root)
554 for artifact in self.output_proto.artifacts
555 ]
Alex Kleincb541e82019-06-26 15:06:11 -0600556 expected = ['payload1.bin', 'payload2.bin']
Mike Frysinger678735c2019-09-28 18:23:28 -0400557 self.assertCountEqual(actual, expected)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600558
559 actual = [
560 os.path.relpath(path, self.archive_root)
561 for path in osutils.DirectoryIterator(self.archive_root)
562 ]
Mike Frysinger678735c2019-09-28 18:23:28 -0400563 self.assertCountEqual(actual, expected)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600564
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600565 def testBundleTestUpdatePayloadsNoImageDir(self):
566 """BundleTestUpdatePayloads dies if no image dir is found."""
567 # Intentionally do not write image directory.
Alex Kleind2bf1462019-10-24 16:37:04 -0600568 artifacts.BundleTestUpdatePayloads(self.input_proto, self.output_proto,
569 self.api_config)
570 self.assertFalse(self.output_proto.artifacts)
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600571
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600572 def testBundleTestUpdatePayloadsNoImage(self):
573 """BundleTestUpdatePayloads dies if no usable image is found for target."""
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600574 # Intentionally do not write image, but create the directory.
575 osutils.SafeMakedirs(self.image_root)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600576 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600577 artifacts.BundleTestUpdatePayloads(self.input_proto, self.output_proto,
578 self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600579
580
Alex Klein231d2da2019-07-22 16:44:45 -0600581class BundleSimpleChromeArtifactsTest(cros_test_lib.MockTempDirTestCase,
582 api_config.ApiConfigMixin):
Alex Klein2275d692019-04-23 16:04:12 -0600583 """BundleSimpleChromeArtifacts tests."""
584
585 def setUp(self):
586 self.chroot_dir = os.path.join(self.tempdir, 'chroot_dir')
587 self.sysroot_path = '/sysroot'
588 self.sysroot_dir = os.path.join(self.chroot_dir, 'sysroot')
589 osutils.SafeMakedirs(self.sysroot_dir)
590 self.output_dir = os.path.join(self.tempdir, 'output_dir')
591 osutils.SafeMakedirs(self.output_dir)
592
593 self.does_not_exist = os.path.join(self.tempdir, 'does_not_exist')
594
Alex Klein231d2da2019-07-22 16:44:45 -0600595 self.response = artifacts_pb2.BundleResponse()
596
Varun Somani04dccd72021-10-09 01:06:11 +0000597 def _GetRequest(
598 self,
599 chroot: Optional[str] = None,
600 sysroot: Optional[str] = None,
601 build_target: Optional[str] = None,
602 output_dir: Optional[str] = None) -> artifacts_pb2.BundleRequest:
Alex Klein2275d692019-04-23 16:04:12 -0600603 """Helper to create a request message instance.
604
605 Args:
Varun Somani04dccd72021-10-09 01:06:11 +0000606 chroot: The chroot path.
607 sysroot: The sysroot path.
608 build_target: The build target name.
609 output_dir: The output directory.
Alex Klein2275d692019-04-23 16:04:12 -0600610 """
611 return artifacts_pb2.BundleRequest(
612 sysroot={'path': sysroot, 'build_target': {'name': build_target}},
613 chroot={'path': chroot}, output_dir=output_dir)
614
Alex Klein231d2da2019-07-22 16:44:45 -0600615 def testValidateOnly(self):
Greg Edelstondc941072021-08-11 12:32:30 -0600616 """Quick check that a validate only call does not execute any logic."""
Alex Klein231d2da2019-07-22 16:44:45 -0600617 patch = self.PatchObject(artifacts_svc, 'BundleSimpleChromeArtifacts')
618 request = self._GetRequest(chroot=self.chroot_dir,
619 sysroot=self.sysroot_path,
620 build_target='board', output_dir=self.output_dir)
621 artifacts.BundleSimpleChromeArtifacts(request, self.response,
622 self.validate_only_config)
623 patch.assert_not_called()
Alex Klein2275d692019-04-23 16:04:12 -0600624
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700625 def testMockCall(self):
626 """Test that a mock call does not execute logic, returns mocked value."""
627 patch = self.PatchObject(artifacts_svc, 'BundleSimpleChromeArtifacts')
628 request = self._GetRequest(chroot=self.chroot_dir,
629 sysroot=self.sysroot_path,
630 build_target='board', output_dir=self.output_dir)
631 artifacts.BundleSimpleChromeArtifacts(request, self.response,
632 self.mock_call_config)
633 patch.assert_not_called()
634 self.assertEqual(len(self.response.artifacts), 1)
635 self.assertEqual(self.response.artifacts[0].path,
636 os.path.join(self.output_dir, 'simple_chrome.txt'))
637
Alex Klein2275d692019-04-23 16:04:12 -0600638 def testNoBuildTarget(self):
639 """Test no build target fails."""
640 request = self._GetRequest(chroot=self.chroot_dir,
641 sysroot=self.sysroot_path,
642 output_dir=self.output_dir)
Alex Klein231d2da2019-07-22 16:44:45 -0600643 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600644 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600645 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600646
647 def testNoSysroot(self):
648 """Test no sysroot fails."""
649 request = self._GetRequest(build_target='board', output_dir=self.output_dir)
Alex Klein231d2da2019-07-22 16:44:45 -0600650 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600651 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600652 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600653
654 def testSysrootDoesNotExist(self):
655 """Test no sysroot fails."""
656 request = self._GetRequest(build_target='board', output_dir=self.output_dir,
657 sysroot=self.does_not_exist)
Alex Klein231d2da2019-07-22 16:44:45 -0600658 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600659 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600660 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600661
662 def testNoOutputDir(self):
663 """Test no output dir fails."""
664 request = self._GetRequest(chroot=self.chroot_dir,
665 sysroot=self.sysroot_path,
666 build_target='board')
Alex Klein231d2da2019-07-22 16:44:45 -0600667 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600668 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600669 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600670
671 def testOutputDirDoesNotExist(self):
672 """Test no output dir fails."""
673 request = self._GetRequest(chroot=self.chroot_dir,
674 sysroot=self.sysroot_path,
675 build_target='board',
676 output_dir=self.does_not_exist)
Alex Klein231d2da2019-07-22 16:44:45 -0600677 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600678 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600679 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600680
681 def testOutputHandling(self):
682 """Test response output."""
683 files = ['file1', 'file2', 'file3']
684 expected_files = [os.path.join(self.output_dir, f) for f in files]
685 self.PatchObject(artifacts_svc, 'BundleSimpleChromeArtifacts',
686 return_value=expected_files)
687 request = self._GetRequest(chroot=self.chroot_dir,
688 sysroot=self.sysroot_path,
689 build_target='board', output_dir=self.output_dir)
Alex Klein231d2da2019-07-22 16:44:45 -0600690 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600691
Alex Klein231d2da2019-07-22 16:44:45 -0600692 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600693
694 self.assertTrue(response.artifacts)
Mike Frysinger678735c2019-09-28 18:23:28 -0400695 self.assertCountEqual(expected_files, [a.path for a in response.artifacts])
Alex Klein2275d692019-04-23 16:04:12 -0600696
697
Alex Klein231d2da2019-07-22 16:44:45 -0600698class BundleVmFilesTest(cros_test_lib.MockTempDirTestCase,
699 api_config.ApiConfigMixin):
Alex Klein6504eca2019-04-18 15:37:56 -0600700 """BuildVmFiles tests."""
701
Alex Klein231d2da2019-07-22 16:44:45 -0600702 def setUp(self):
703 self.output_dir = os.path.join(self.tempdir, 'output')
704 osutils.SafeMakedirs(self.output_dir)
705
706 self.response = artifacts_pb2.BundleResponse()
707
Varun Somani04dccd72021-10-09 01:06:11 +0000708 def _GetInput(
709 self,
710 chroot: Optional[str] = None,
711 sysroot: Optional[str] = None,
712 test_results_dir: Optional[str] = None,
713 output_dir: Optional[str] = None) -> artifacts_pb2.BundleVmFilesRequest:
Alex Klein6504eca2019-04-18 15:37:56 -0600714 """Helper to build out an input message instance.
715
716 Args:
Varun Somani04dccd72021-10-09 01:06:11 +0000717 chroot: The chroot path.
718 sysroot: The sysroot path relative to the chroot.
719 test_results_dir: The test results directory relative to the sysroot.
720 output_dir: The directory where the results tarball should be saved.
Alex Klein6504eca2019-04-18 15:37:56 -0600721 """
722 return artifacts_pb2.BundleVmFilesRequest(
723 chroot={'path': chroot}, sysroot={'path': sysroot},
724 test_results_dir=test_results_dir, output_dir=output_dir,
725 )
726
Alex Klein231d2da2019-07-22 16:44:45 -0600727 def testValidateOnly(self):
Greg Edelstondc941072021-08-11 12:32:30 -0600728 """Quick check that a validate only call does not execute any logic."""
Alex Klein231d2da2019-07-22 16:44:45 -0600729 patch = self.PatchObject(artifacts_svc, 'BundleVmFiles')
730 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
731 test_results_dir='/test/results',
732 output_dir=self.output_dir)
733 artifacts.BundleVmFiles(in_proto, self.response, self.validate_only_config)
734 patch.assert_not_called()
Alex Klein6504eca2019-04-18 15:37:56 -0600735
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700736 def testMockCall(self):
737 """Test that a mock call does not execute logic, returns mocked value."""
738 patch = self.PatchObject(artifacts_svc, 'BundleVmFiles')
739 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
740 test_results_dir='/test/results',
741 output_dir=self.output_dir)
742 artifacts.BundleVmFiles(in_proto, self.response, self.mock_call_config)
743 patch.assert_not_called()
744 self.assertEqual(len(self.response.artifacts), 1)
745 self.assertEqual(self.response.artifacts[0].path,
746 os.path.join(self.output_dir, 'f1.tar'))
747
Alex Klein6504eca2019-04-18 15:37:56 -0600748 def testChrootMissing(self):
749 """Test error handling for missing chroot."""
750 in_proto = self._GetInput(sysroot='/build/board',
751 test_results_dir='/test/results',
Alex Klein231d2da2019-07-22 16:44:45 -0600752 output_dir=self.output_dir)
Alex Klein6504eca2019-04-18 15:37:56 -0600753
754 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600755 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600756
Alex Klein6504eca2019-04-18 15:37:56 -0600757 def testTestResultsDirMissing(self):
758 """Test error handling for missing test results directory."""
759 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
Alex Klein231d2da2019-07-22 16:44:45 -0600760 output_dir=self.output_dir)
Alex Klein6504eca2019-04-18 15:37:56 -0600761
762 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600763 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600764
765 def testOutputDirMissing(self):
766 """Test error handling for missing output directory."""
767 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
768 test_results_dir='/test/results')
Alex Klein6504eca2019-04-18 15:37:56 -0600769
770 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600771 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
772
773 def testOutputDirDoesNotExist(self):
774 """Test error handling for output directory that does not exist."""
775 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
776 output_dir=os.path.join(self.tempdir, 'dne'),
777 test_results_dir='/test/results')
778
779 with self.assertRaises(cros_build_lib.DieSystemExit):
780 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600781
782 def testValidCall(self):
783 """Test image dir building."""
784 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
785 test_results_dir='/test/results',
Alex Klein231d2da2019-07-22 16:44:45 -0600786 output_dir=self.output_dir)
787
Alex Klein6504eca2019-04-18 15:37:56 -0600788 expected_files = ['/tmp/output/f1.tar', '/tmp/output/f2.tar']
Michael Mortensen51f06722019-07-18 09:55:50 -0600789 patch = self.PatchObject(artifacts_svc, 'BundleVmFiles',
Alex Klein6504eca2019-04-18 15:37:56 -0600790 return_value=expected_files)
791
Alex Klein231d2da2019-07-22 16:44:45 -0600792 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600793
Alex Klein231d2da2019-07-22 16:44:45 -0600794 patch.assert_called_with(mock.ANY, '/test/results', self.output_dir)
Alex Klein6504eca2019-04-18 15:37:56 -0600795
796 # Make sure we have artifacts, and that every artifact is an expected file.
Alex Klein231d2da2019-07-22 16:44:45 -0600797 self.assertTrue(self.response.artifacts)
798 for artifact in self.response.artifacts:
Alex Klein6504eca2019-04-18 15:37:56 -0600799 self.assertIn(artifact.path, expected_files)
800 expected_files.remove(artifact.path)
801
802 # Make sure we've seen all of the expected files.
803 self.assertFalse(expected_files)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700804
Alex Kleinb9d810b2019-07-01 12:38:02 -0600805
Tiancong Wang50b80a92019-08-01 14:46:15 -0700806
Alex Klein036833d2022-06-01 13:05:01 -0600807class ExportCpeReportTest(BundleTestCase):
Alex Klein0b1cbfc2019-08-14 10:09:58 -0600808 """ExportCpeReport tests."""
809
Alex Klein0b1cbfc2019-08-14 10:09:58 -0600810 def testValidateOnly(self):
Greg Edelstondc941072021-08-11 12:32:30 -0600811 """Quick check validate only calls don't execute."""
Alex Klein0b1cbfc2019-08-14 10:09:58 -0600812 patch = self.PatchObject(artifacts_svc, 'GenerateCpeReport')
813
Alex Klein036833d2022-06-01 13:05:01 -0600814 artifacts.ExportCpeReport(self.sysroot_request, self.response,
815 self.validate_only_config)
Alex Klein0b1cbfc2019-08-14 10:09:58 -0600816
817 patch.assert_not_called()
818
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700819 def testMockCall(self):
820 """Test that a mock call does not execute logic, returns mocked value."""
821 patch = self.PatchObject(artifacts_svc, 'GenerateCpeReport')
822
Alex Klein036833d2022-06-01 13:05:01 -0600823 artifacts.ExportCpeReport(self.sysroot_request, self.response,
824 self.mock_call_config)
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700825
826 patch.assert_not_called()
827 self.assertEqual(len(self.response.artifacts), 2)
828 self.assertEqual(self.response.artifacts[0].path,
Alex Klein036833d2022-06-01 13:05:01 -0600829 os.path.join(self.output_dir, 'cpe_report.txt'))
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700830 self.assertEqual(self.response.artifacts[1].path,
Alex Klein036833d2022-06-01 13:05:01 -0600831 os.path.join(self.output_dir, 'cpe_warnings.txt'))
Alex Klein0b1cbfc2019-08-14 10:09:58 -0600832
833 def testSuccess(self):
834 """Test success case."""
835 expected = artifacts_svc.CpeResult(
836 report='/output/report.json', warnings='/output/warnings.json')
837 self.PatchObject(artifacts_svc, 'GenerateCpeReport', return_value=expected)
838
Alex Klein036833d2022-06-01 13:05:01 -0600839 artifacts.ExportCpeReport(self.sysroot_request, self.response,
840 self.api_config)
Alex Klein0b1cbfc2019-08-14 10:09:58 -0600841
842 for artifact in self.response.artifacts:
843 self.assertIn(artifact.path, [expected.report, expected.warnings])
Shao-Chuan Leea44dddc2020-10-30 17:16:55 +0900844
845
846class BundleGceTarballTest(BundleTestCase):
847 """Unittests for BundleGceTarball."""
848
849 def testValidateOnly(self):
850 """Check that a validate only call does not execute any logic."""
851 patch = self.PatchObject(artifacts_svc, 'BundleGceTarball')
852 artifacts.BundleGceTarball(self.target_request, self.response,
853 self.validate_only_config)
854 patch.assert_not_called()
855
856 def testMockCall(self):
857 """Test that a mock call does not execute logic, returns mocked value."""
858 patch = self.PatchObject(artifacts_svc, 'BundleGceTarball')
859 artifacts.BundleGceTarball(self.target_request, self.response,
860 self.mock_call_config)
861 patch.assert_not_called()
862 self.assertEqual(len(self.response.artifacts), 1)
863 self.assertEqual(self.response.artifacts[0].path,
864 os.path.join(self.output_dir,
865 constants.TEST_IMAGE_GCE_TAR))
866
867 def testBundleGceTarball(self):
868 """BundleGceTarball calls cbuildbot/commands with correct args."""
869 bundle_gce_tarball = self.PatchObject(
870 artifacts_svc, 'BundleGceTarball',
871 return_value=os.path.join(self.output_dir,
872 constants.TEST_IMAGE_GCE_TAR))
873 self.PatchObject(os.path, 'exists', return_value=True)
874 artifacts.BundleGceTarball(self.target_request, self.response,
875 self.api_config)
876 self.assertEqual(
877 [artifact.path for artifact in self.response.artifacts],
878 [os.path.join(self.output_dir, constants.TEST_IMAGE_GCE_TAR)])
879
880 latest = os.path.join(self.source_root, 'src/build/images/target/latest')
881 self.assertEqual(
882 bundle_gce_tarball.call_args_list,
883 [mock.call(self.output_dir, latest)])
884
885 def testBundleGceTarballNoImageDir(self):
886 """BundleGceTarball dies when image dir does not exist."""
887 self.PatchObject(os.path, 'exists', return_value=False)
888 with self.assertRaises(cros_build_lib.DieSystemExit):
889 artifacts.BundleGceTarball(self.target_request, self.response,
890 self.api_config)
Greg Edelstondc941072021-08-11 12:32:30 -0600891
892class FetchMetadataTestCase(cros_test_lib.MockTempDirTestCase,
893 api_config.ApiConfigMixin):
894 """Unittests for FetchMetadata."""
895
896 sysroot_path = '/build/coral'
897 chroot_name = 'chroot'
898
899 def setUp(self):
Gilberto Contrerasf9fd1f42022-02-26 09:31:30 -0800900 self.PatchObject(cros_build_lib, 'IsInsideChroot', return_value=False)
Greg Edelstondc941072021-08-11 12:32:30 -0600901 self.chroot_path = os.path.join(self.tempdir, 'chroot')
902 pathlib.Path(self.chroot_path).touch()
903 self.expected_filepaths = [os.path.join(self.chroot_path, fp) for fp in (
904 'build/coral/usr/local/build/autotest/autotest_metadata.pb',
905 'build/coral/usr/share/tast/metadata/local/cros.pb',
906 'build/coral/build/share/tast/metadata/local/crosint.pb',
907 'usr/share/tast/metadata/remote/cros.pb',
908 )]
909 self.PatchObject(cros_build_lib, 'AssertOutsideChroot')
910
911 def createFetchMetadataRequest(self, use_sysroot_path=True, use_chroot=True):
912 """Construct a FetchMetadataRequest for use in test cases."""
913 request = artifacts_pb2.FetchMetadataRequest()
914 if use_sysroot_path:
915 request.sysroot.path = self.sysroot_path
916 if use_chroot:
917 request.chroot.path = self.chroot_path
918 return request
919
920 def testValidateOnly(self):
921 """Check that a validate only call does not execute any logic."""
922 patch = self.PatchObject(controller_util, 'ParseSysroot')
923 request = self.createFetchMetadataRequest()
924 response = artifacts_pb2.FetchMetadataResponse()
925 artifacts.FetchMetadata(request, response, self.validate_only_config)
926 patch.assert_not_called()
927
928 def testMockCall(self):
929 """Test that a mock call does not execute logic, returns mocked value."""
930 patch = self.PatchObject(controller_util, 'ParseSysroot')
931 request = self.createFetchMetadataRequest()
932 response = artifacts_pb2.FetchMetadataResponse()
933 artifacts.FetchMetadata(request, response, self.mock_call_config)
934 patch.assert_not_called()
935 self.assertGreater(len(response.filepaths), 0)
936
937 def testNoSysrootPath(self):
938 """Check that a request with no sysroot.path results in failure."""
939 request = self.createFetchMetadataRequest(use_sysroot_path=False)
940 response = artifacts_pb2.FetchMetadataResponse()
941 with self.assertRaises(cros_build_lib.DieSystemExit):
942 artifacts.FetchMetadata(request, response, self.api_config)
943
944 def testNoChroot(self):
945 """Check that a request with no chroot results in failure."""
946 request = self.createFetchMetadataRequest(use_chroot=False)
947 response = artifacts_pb2.FetchMetadataResponse()
948 with self.assertRaises(cros_build_lib.DieSystemExit):
949 artifacts.FetchMetadata(request, response, self.api_config)
950
951 def testSuccess(self):
952 """Check that a well-formed request yields the expected results."""
953 request = self.createFetchMetadataRequest(use_chroot=True)
954 response = artifacts_pb2.FetchMetadataResponse()
955 artifacts.FetchMetadata(request, response, self.api_config)
956 actual_filepaths = [fp.path.path for fp in response.filepaths]
957 self.assertEqual(sorted(actual_filepaths), sorted(self.expected_filepaths))
Mike Frysinger80ff4542022-05-06 23:52:04 -0400958 self.assertTrue(all(fp.path.location == common_pb2.Path.OUTSIDE
959 for fp in response.filepaths))