blob: 6f1fc233bcbe2e8ecc29a387f1136a0d712bcf33 [file] [log] [blame]
Mike Frysingerf1ba7ad2022-09-12 05:42:57 -04001# Copyright 2019 The ChromiumOS Authors
Evan Hernandezf388cbf2019-04-01 11:15:23 -06002# 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):
Alex Klein1699fab2022-09-08 08:46:06 -060028 """Mixin to provide bundle request methods."""
Alex Kleind91e95a2019-09-17 10:39:02 -060029
Alex Klein1699fab2022-09-08 08:46:06 -060030 def EmptyRequest(self):
31 return artifacts_pb2.BundleRequest()
Alex Kleind91e95a2019-09-17 10:39:02 -060032
Alex Klein1699fab2022-09-08 08:46:06 -060033 def BuildTargetRequest(
34 self, build_target=None, output_dir=None, chroot=None
35 ):
36 """Get a build target format request instance."""
37 request = self.EmptyRequest()
38 if build_target:
39 request.build_target.name = build_target
40 if output_dir:
41 request.output_dir = output_dir
42 if chroot:
43 request.chroot.path = chroot
Alex Kleind91e95a2019-09-17 10:39:02 -060044
Alex Klein1699fab2022-09-08 08:46:06 -060045 return request
Alex Kleind91e95a2019-09-17 10:39:02 -060046
Alex Klein1699fab2022-09-08 08:46:06 -060047 def SysrootRequest(
48 self, sysroot=None, build_target=None, output_dir=None, chroot=None
49 ):
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
Alex Kleind91e95a2019-09-17 10:39:02 -060060
Alex Klein1699fab2022-09-08 08:46:06 -060061 return request
Alex Kleind91e95a2019-09-17 10:39:02 -060062
63
Alex Klein1699fab2022-09-08 08:46:06 -060064class BundleTestCase(
65 cros_test_lib.MockTempDirTestCase,
66 api_config.ApiConfigMixin,
67 BundleRequestMixin,
68):
69 """Basic setup for all artifacts unittests."""
Evan Hernandezf388cbf2019-04-01 11:15:23 -060070
Alex Klein1699fab2022-09-08 08:46:06 -060071 def setUp(self):
72 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=False)
73 self.output_dir = os.path.join(self.tempdir, "artifacts")
74 osutils.SafeMakedirs(self.output_dir)
75 self.sysroot_path = "/build/target"
76 self.sysroot = sysroot_lib.Sysroot(self.sysroot_path)
77 self.chroot_path = os.path.join(self.tempdir, "chroot")
78 full_sysroot_path = os.path.join(
79 self.chroot_path, self.sysroot_path.lstrip(os.sep)
80 )
81 osutils.SafeMakedirs(full_sysroot_path)
Alex Klein231d2da2019-07-22 16:44:45 -060082
Alex Klein1699fab2022-09-08 08:46:06 -060083 # All requests use same response type.
84 self.response = artifacts_pb2.BundleResponse()
Alex Klein231d2da2019-07-22 16:44:45 -060085
Alex Klein1699fab2022-09-08 08:46:06 -060086 # Build target request.
87 self.target_request = self.BuildTargetRequest(
88 build_target="target",
89 output_dir=self.output_dir,
90 chroot=self.chroot_path,
91 )
Alex Klein68c8fdf2019-09-25 15:09:11 -060092
Alex Klein1699fab2022-09-08 08:46:06 -060093 # Sysroot request.
94 self.sysroot_request = self.SysrootRequest(
95 sysroot=self.sysroot_path,
96 build_target="target",
97 output_dir=self.output_dir,
98 chroot=self.chroot_path,
99 )
Alex Klein68c8fdf2019-09-25 15:09:11 -0600100
Alex Klein1699fab2022-09-08 08:46:06 -0600101 self.source_root = self.tempdir
102 self.PatchObject(constants, "SOURCE_ROOT", new=self.tempdir)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600103
104
Alex Kleind91e95a2019-09-17 10:39:02 -0600105class BundleImageArchivesTest(BundleTestCase):
Alex Klein1699fab2022-09-08 08:46:06 -0600106 """BundleImageArchives tests."""
Alex Kleind91e95a2019-09-17 10:39:02 -0600107
Alex Klein1699fab2022-09-08 08:46:06 -0600108 def testValidateOnly(self):
109 """Quick check that a validate only call does not execute any logic."""
110 patch = self.PatchObject(artifacts_svc, "ArchiveImages")
111 artifacts.BundleImageArchives(
112 self.target_request, self.response, self.validate_only_config
113 )
114 patch.assert_not_called()
Alex Kleind91e95a2019-09-17 10:39:02 -0600115
Alex Klein1699fab2022-09-08 08:46:06 -0600116 def testMockCall(self):
117 """Test that a mock call does not execute logic, returns mocked value."""
118 patch = self.PatchObject(artifacts_svc, "ArchiveImages")
119 artifacts.BundleImageArchives(
120 self.target_request, self.response, self.mock_call_config
121 )
122 patch.assert_not_called()
123 self.assertEqual(len(self.response.artifacts), 2)
124 self.assertEqual(
125 self.response.artifacts[0].path,
126 os.path.join(self.output_dir, "path0.tar.xz"),
127 )
128 self.assertEqual(
129 self.response.artifacts[1].path,
130 os.path.join(self.output_dir, "path1.tar.xz"),
131 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700132
Alex Klein1699fab2022-09-08 08:46:06 -0600133 def testNoBuildTarget(self):
134 """Test that no build target fails."""
135 request = self.BuildTargetRequest(output_dir=str(self.tempdir))
136 with self.assertRaises(cros_build_lib.DieSystemExit):
137 artifacts.BundleImageArchives(
138 request, self.response, self.api_config
139 )
Alex Kleind91e95a2019-09-17 10:39:02 -0600140
Alex Klein1699fab2022-09-08 08:46:06 -0600141 def testNoOutputDir(self):
142 """Test no output dir fails."""
143 request = self.BuildTargetRequest(build_target="board")
144 with self.assertRaises(cros_build_lib.DieSystemExit):
145 artifacts.BundleImageArchives(
146 request, self.response, self.api_config
147 )
Alex Kleind91e95a2019-09-17 10:39:02 -0600148
Alex Klein1699fab2022-09-08 08:46:06 -0600149 def testInvalidOutputDir(self):
150 """Test invalid output dir fails."""
151 request = self.BuildTargetRequest(
152 build_target="board", output_dir=os.path.join(self.tempdir, "DNE")
153 )
154 with self.assertRaises(cros_build_lib.DieSystemExit):
155 artifacts.BundleImageArchives(
156 request, self.response, self.api_config
157 )
Alex Kleind91e95a2019-09-17 10:39:02 -0600158
Alex Klein1699fab2022-09-08 08:46:06 -0600159 def testOutputHandling(self):
160 """Test the artifact output handling."""
161 expected = [os.path.join(self.output_dir, f) for f in ("a", "b", "c")]
162 self.PatchObject(artifacts_svc, "ArchiveImages", return_value=expected)
163 self.PatchObject(os.path, "exists", return_value=True)
Alex Kleind91e95a2019-09-17 10:39:02 -0600164
Alex Klein1699fab2022-09-08 08:46:06 -0600165 artifacts.BundleImageArchives(
166 self.target_request, self.response, self.api_config
167 )
Alex Kleind91e95a2019-09-17 10:39:02 -0600168
Alex Klein1699fab2022-09-08 08:46:06 -0600169 self.assertCountEqual(
170 expected, [a.path for a in self.response.artifacts]
171 )
Alex Kleind91e95a2019-09-17 10:39:02 -0600172
173
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600174class BundleImageZipTest(BundleTestCase):
Alex Klein1699fab2022-09-08 08:46:06 -0600175 """Unittests for BundleImageZip."""
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600176
Alex Klein1699fab2022-09-08 08:46:06 -0600177 def testValidateOnly(self):
178 """Quick check that a validate only call does not execute any logic."""
179 patch = self.PatchObject(commands, "BuildImageZip")
180 artifacts.BundleImageZip(
181 self.target_request, self.response, self.validate_only_config
182 )
183 patch.assert_not_called()
Alex Klein231d2da2019-07-22 16:44:45 -0600184
Alex Klein1699fab2022-09-08 08:46:06 -0600185 def testMockCall(self):
186 """Test that a mock call does not execute logic, returns mocked value."""
187 patch = self.PatchObject(commands, "BuildImageZip")
188 artifacts.BundleImageZip(
189 self.target_request, self.response, self.mock_call_config
190 )
191 patch.assert_not_called()
192 self.assertEqual(len(self.response.artifacts), 1)
193 self.assertEqual(
194 self.response.artifacts[0].path,
195 os.path.join(self.output_dir, "image.zip"),
196 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700197
Alex Klein1699fab2022-09-08 08:46:06 -0600198 def testBundleImageZip(self):
199 """BundleImageZip calls cbuildbot/commands with correct args."""
200 bundle_image_zip = self.PatchObject(
201 artifacts_svc, "BundleImageZip", return_value="image.zip"
202 )
203 self.PatchObject(os.path, "exists", return_value=True)
204 artifacts.BundleImageZip(
205 self.target_request, self.response, self.api_config
206 )
207 self.assertEqual(
208 [artifact.path for artifact in self.response.artifacts],
209 [os.path.join(self.output_dir, "image.zip")],
210 )
Alex Klein231d2da2019-07-22 16:44:45 -0600211
Alex Klein1699fab2022-09-08 08:46:06 -0600212 latest = os.path.join(
213 self.source_root, "src/build/images/target/latest"
214 )
215 self.assertEqual(
216 bundle_image_zip.call_args_list,
217 [mock.call(self.output_dir, latest)],
218 )
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600219
Alex Klein1699fab2022-09-08 08:46:06 -0600220 def testBundleImageZipNoImageDir(self):
221 """BundleImageZip dies when image dir does not exist."""
222 self.PatchObject(os.path, "exists", return_value=False)
223 with self.assertRaises(cros_build_lib.DieSystemExit):
224 artifacts.BundleImageZip(
225 self.target_request, self.response, self.api_config
226 )
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600227
228
Alex Klein68c8fdf2019-09-25 15:09:11 -0600229class BundleAutotestFilesTest(BundleTestCase):
Alex Klein1699fab2022-09-08 08:46:06 -0600230 """Unittests for BundleAutotestFiles."""
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600231
Alex Klein1699fab2022-09-08 08:46:06 -0600232 def testValidateOnly(self):
233 """Quick check that a validate only call does not execute any logic."""
234 patch = self.PatchObject(artifacts_svc, "BundleAutotestFiles")
235 artifacts.BundleAutotestFiles(
236 self.sysroot_request, self.response, self.validate_only_config
237 )
238 patch.assert_not_called()
Alex Klein231d2da2019-07-22 16:44:45 -0600239
Alex Klein1699fab2022-09-08 08:46:06 -0600240 def testMockCall(self):
241 """Test that a mock call does not execute logic, returns mocked value."""
242 patch = self.PatchObject(artifacts_svc, "BundleAutotestFiles")
243 artifacts.BundleAutotestFiles(
244 self.sysroot_request, self.response, self.mock_call_config
245 )
246 patch.assert_not_called()
247 self.assertEqual(len(self.response.artifacts), 1)
248 self.assertEqual(
249 self.response.artifacts[0].path,
250 os.path.join(self.output_dir, "autotest-a.tar.gz"),
251 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700252
Alex Klein1699fab2022-09-08 08:46:06 -0600253 def testBundleAutotestFiles(self):
254 """BundleAutotestFiles calls service correctly."""
255 files = {
256 artifacts_svc.ARCHIVE_CONTROL_FILES: "/tmp/artifacts/autotest-a.tar.gz",
257 artifacts_svc.ARCHIVE_PACKAGES: "/tmp/artifacts/autotest-b.tar.gz",
258 }
259 patch = self.PatchObject(
260 artifacts_svc, "BundleAutotestFiles", return_value=files
261 )
Alex Klein238d8862019-05-07 11:32:46 -0600262
Alex Klein1699fab2022-09-08 08:46:06 -0600263 artifacts.BundleAutotestFiles(
264 self.sysroot_request, self.response, self.api_config
265 )
Alex Klein238d8862019-05-07 11:32:46 -0600266
Alex Klein1699fab2022-09-08 08:46:06 -0600267 # Verify the arguments are being passed through.
268 patch.assert_called_with(mock.ANY, self.sysroot, self.output_dir)
Alex Klein238d8862019-05-07 11:32:46 -0600269
Alex Klein1699fab2022-09-08 08:46:06 -0600270 # Verify the output proto is being populated correctly.
271 self.assertTrue(self.response.artifacts)
272 paths = [artifact.path for artifact in self.response.artifacts]
273 self.assertCountEqual(list(files.values()), paths)
Alex Klein238d8862019-05-07 11:32:46 -0600274
Alex Klein1699fab2022-09-08 08:46:06 -0600275 def testInvalidOutputDir(self):
276 """Test invalid output directory argument."""
277 request = self.SysrootRequest(
278 chroot=self.chroot_path, sysroot=self.sysroot_path
279 )
Alex Klein238d8862019-05-07 11:32:46 -0600280
Alex Klein1699fab2022-09-08 08:46:06 -0600281 with self.assertRaises(cros_build_lib.DieSystemExit):
282 artifacts.BundleAutotestFiles(
283 request, self.response, self.api_config
284 )
Alex Klein238d8862019-05-07 11:32:46 -0600285
Alex Klein1699fab2022-09-08 08:46:06 -0600286 def testInvalidSysroot(self):
287 """Test no sysroot directory."""
288 request = self.SysrootRequest(
289 chroot=self.chroot_path, output_dir=self.output_dir
290 )
Alex Klein238d8862019-05-07 11:32:46 -0600291
Alex Klein1699fab2022-09-08 08:46:06 -0600292 with self.assertRaises(cros_build_lib.DieSystemExit):
293 artifacts.BundleAutotestFiles(
294 request, self.response, self.api_config
295 )
Alex Klein238d8862019-05-07 11:32:46 -0600296
Alex Klein1699fab2022-09-08 08:46:06 -0600297 def testSysrootDoesNotExist(self):
298 """Test dies when no sysroot does not exist."""
299 request = self.SysrootRequest(
300 chroot=self.chroot_path,
301 sysroot="/does/not/exist",
302 output_dir=self.output_dir,
303 )
Alex Klein238d8862019-05-07 11:32:46 -0600304
Alex Klein1699fab2022-09-08 08:46:06 -0600305 artifacts.BundleAutotestFiles(request, self.response, self.api_config)
306 self.assertFalse(self.response.artifacts)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600307
308
309class BundleTastFilesTest(BundleTestCase):
Alex Klein1699fab2022-09-08 08:46:06 -0600310 """Unittests for BundleTastFiles."""
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600311
Alex Klein1699fab2022-09-08 08:46:06 -0600312 def testValidateOnly(self):
313 """Quick check that a validate only call does not execute any logic."""
314 patch = self.PatchObject(artifacts_svc, "BundleTastFiles")
315 artifacts.BundleTastFiles(
316 self.sysroot_request, self.response, self.validate_only_config
317 )
318 patch.assert_not_called()
Alex Klein231d2da2019-07-22 16:44:45 -0600319
Alex Klein1699fab2022-09-08 08:46:06 -0600320 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.BundleTastFiles(
324 self.sysroot_request, self.response, self.mock_call_config
325 )
326 patch.assert_not_called()
327 self.assertEqual(len(self.response.artifacts), 1)
328 self.assertEqual(
329 self.response.artifacts[0].path,
330 os.path.join(self.output_dir, "tast_bundles.tar.gz"),
331 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700332
Alex Klein1699fab2022-09-08 08:46:06 -0600333 def testBundleTastFilesNoLogs(self):
334 """BundleTasteFiles succeeds when no tast files found."""
335 self.PatchObject(commands, "BuildTastBundleTarball", return_value=None)
336 artifacts.BundleTastFiles(
337 self.sysroot_request, self.response, self.api_config
338 )
339 self.assertFalse(self.response.artifacts)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600340
Alex Klein1699fab2022-09-08 08:46:06 -0600341 def testBundleTastFiles(self):
342 """BundleTastFiles calls service correctly."""
343 chroot = chroot_lib.Chroot(self.chroot_path)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600344
Alex Klein1699fab2022-09-08 08:46:06 -0600345 expected_archive = os.path.join(
346 self.output_dir, artifacts_svc.TAST_BUNDLE_NAME
347 )
348 # Patch the service being called.
349 bundle_patch = self.PatchObject(
350 artifacts_svc, "BundleTastFiles", return_value=expected_archive
351 )
Alex Kleinb9d810b2019-07-01 12:38:02 -0600352
Alex Klein1699fab2022-09-08 08:46:06 -0600353 artifacts.BundleTastFiles(
354 self.sysroot_request, self.response, self.api_config
355 )
Alex Kleinb9d810b2019-07-01 12:38:02 -0600356
Alex Klein1699fab2022-09-08 08:46:06 -0600357 # Make sure the artifact got recorded successfully.
358 self.assertTrue(self.response.artifacts)
359 self.assertEqual(expected_archive, self.response.artifacts[0].path)
360 # Make sure the service got called correctly.
361 bundle_patch.assert_called_once_with(
362 chroot, self.sysroot, self.output_dir
363 )
Alex Kleinb9d810b2019-07-01 12:38:02 -0600364
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600365
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600366class BundleFirmwareTest(BundleTestCase):
Alex Klein1699fab2022-09-08 08:46:06 -0600367 """Unittests for BundleFirmware."""
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600368
Alex Klein1699fab2022-09-08 08:46:06 -0600369 def testValidateOnly(self):
370 """Quick check that a validate only call does not execute any logic."""
371 patch = self.PatchObject(artifacts_svc, "BundleTastFiles")
372 artifacts.BundleFirmware(
373 self.sysroot_request, self.response, self.validate_only_config
374 )
375 patch.assert_not_called()
Michael Mortensen38675192019-06-28 16:52:55 +0000376
Alex Klein1699fab2022-09-08 08:46:06 -0600377 def testMockCall(self):
378 """Test that a mock call does not execute logic, returns mocked value."""
379 patch = self.PatchObject(artifacts_svc, "BundleTastFiles")
380 artifacts.BundleFirmware(
381 self.sysroot_request, self.response, self.mock_call_config
382 )
383 patch.assert_not_called()
384 self.assertEqual(len(self.response.artifacts), 1)
385 self.assertEqual(
386 self.response.artifacts[0].path,
387 os.path.join(self.output_dir, "firmware.tar.gz"),
388 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700389
Alex Klein1699fab2022-09-08 08:46:06 -0600390 def testBundleFirmware(self):
391 """BundleFirmware calls cbuildbot/commands with correct args."""
392 self.PatchObject(
393 artifacts_svc,
394 "BuildFirmwareArchive",
395 return_value=os.path.join(self.output_dir, "firmware.tar.gz"),
396 )
Alex Klein231d2da2019-07-22 16:44:45 -0600397
Alex Klein1699fab2022-09-08 08:46:06 -0600398 artifacts.BundleFirmware(
399 self.sysroot_request, self.response, self.api_config
400 )
401 self.assertEqual(
402 [artifact.path for artifact in self.response.artifacts],
403 [os.path.join(self.output_dir, "firmware.tar.gz")],
404 )
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600405
Alex Klein1699fab2022-09-08 08:46:06 -0600406 def testBundleFirmwareNoLogs(self):
407 """BundleFirmware dies when no firmware found."""
408 self.PatchObject(commands, "BuildFirmwareArchive", return_value=None)
409 artifacts.BundleFirmware(
410 self.sysroot_request, self.response, self.api_config
411 )
412 self.assertEqual(len(self.response.artifacts), 0)
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600413
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600414
Yicheng Liea1181f2020-09-22 11:51:10 -0700415class BundleFpmcuUnittestsTest(BundleTestCase):
Alex Klein1699fab2022-09-08 08:46:06 -0600416 """Unittests for BundleFpmcuUnittests."""
Yicheng Liea1181f2020-09-22 11:51:10 -0700417
Alex Klein1699fab2022-09-08 08:46:06 -0600418 def testValidateOnly(self):
419 """Quick check that a validate only call does not execute any logic."""
420 patch = self.PatchObject(artifacts_svc, "BundleFpmcuUnittests")
421 artifacts.BundleFpmcuUnittests(
422 self.sysroot_request, self.response, self.validate_only_config
423 )
424 patch.assert_not_called()
Yicheng Liea1181f2020-09-22 11:51:10 -0700425
Alex Klein1699fab2022-09-08 08:46:06 -0600426 def testMockCall(self):
427 """Test that a mock call does not execute logic, returns mocked value."""
428 patch = self.PatchObject(artifacts_svc, "BundleFpmcuUnittests")
429 artifacts.BundleFpmcuUnittests(
430 self.sysroot_request, self.response, self.mock_call_config
431 )
432 patch.assert_not_called()
433 self.assertEqual(len(self.response.artifacts), 1)
434 self.assertEqual(
435 self.response.artifacts[0].path,
436 os.path.join(self.output_dir, "fpmcu_unittests.tar.gz"),
437 )
Yicheng Liea1181f2020-09-22 11:51:10 -0700438
Alex Klein1699fab2022-09-08 08:46:06 -0600439 def testBundleFpmcuUnittests(self):
440 """BundleFpmcuUnittests calls cbuildbot/commands with correct args."""
441 self.PatchObject(
442 artifacts_svc,
443 "BundleFpmcuUnittests",
444 return_value=os.path.join(
445 self.output_dir, "fpmcu_unittests.tar.gz"
446 ),
447 )
448 artifacts.BundleFpmcuUnittests(
449 self.sysroot_request, self.response, self.api_config
450 )
451 self.assertEqual(
452 [artifact.path for artifact in self.response.artifacts],
453 [os.path.join(self.output_dir, "fpmcu_unittests.tar.gz")],
454 )
Yicheng Liea1181f2020-09-22 11:51:10 -0700455
Alex Klein1699fab2022-09-08 08:46:06 -0600456 def testBundleFpmcuUnittestsNoLogs(self):
457 """BundleFpmcuUnittests does not die when no fpmcu unittests found."""
458 self.PatchObject(
459 artifacts_svc, "BundleFpmcuUnittests", return_value=None
460 )
461 artifacts.BundleFpmcuUnittests(
462 self.sysroot_request, self.response, self.api_config
463 )
464 self.assertFalse(self.response.artifacts)
Yicheng Liea1181f2020-09-22 11:51:10 -0700465
466
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600467class BundleEbuildLogsTest(BundleTestCase):
Alex Klein1699fab2022-09-08 08:46:06 -0600468 """Unittests for BundleEbuildLogs."""
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600469
Alex Klein1699fab2022-09-08 08:46:06 -0600470 def testValidateOnly(self):
471 """Quick check that a validate only call does not execute any logic."""
472 patch = self.PatchObject(commands, "BuildEbuildLogsTarball")
473 artifacts.BundleEbuildLogs(
474 self.sysroot_request, self.response, self.validate_only_config
475 )
476 patch.assert_not_called()
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600477
Alex Klein1699fab2022-09-08 08:46:06 -0600478 def testMockCall(self):
479 """Test that a mock call does not execute logic, returns mocked value."""
480 patch = self.PatchObject(commands, "BuildEbuildLogsTarball")
481 artifacts.BundleEbuildLogs(
482 self.sysroot_request, self.response, self.mock_call_config
483 )
484 patch.assert_not_called()
485 self.assertEqual(len(self.response.artifacts), 1)
486 self.assertEqual(
487 self.response.artifacts[0].path,
488 os.path.join(self.output_dir, "ebuild-logs.tar.gz"),
489 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700490
Alex Klein1699fab2022-09-08 08:46:06 -0600491 def testBundleEbuildLogs(self):
492 """BundleEbuildLogs calls cbuildbot/commands with correct args."""
493 bundle_ebuild_logs_tarball = self.PatchObject(
494 artifacts_svc,
495 "BundleEBuildLogsTarball",
496 return_value="ebuild-logs.tar.gz",
497 )
498 artifacts.BundleEbuildLogs(
499 self.sysroot_request, self.response, self.api_config
500 )
501 self.assertEqual(
502 [artifact.path for artifact in self.response.artifacts],
503 [os.path.join(self.output_dir, "ebuild-logs.tar.gz")],
504 )
505 self.assertEqual(
506 bundle_ebuild_logs_tarball.call_args_list,
507 [mock.call(mock.ANY, self.sysroot, self.output_dir)],
508 )
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600509
Alex Klein1699fab2022-09-08 08:46:06 -0600510 def testBundleEbuildLogsNoLogs(self):
511 """BundleEbuildLogs dies when no logs found."""
512 self.PatchObject(commands, "BuildEbuildLogsTarball", return_value=None)
513 artifacts.BundleEbuildLogs(
514 self.sysroot_request, self.response, self.api_config
515 )
Alex Klein036833d2022-06-01 13:05:01 -0600516
Alex Klein1699fab2022-09-08 08:46:06 -0600517 self.assertFalse(self.response.artifacts)
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600518
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600519
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600520class BundleChromeOSConfigTest(BundleTestCase):
Alex Klein1699fab2022-09-08 08:46:06 -0600521 """Unittests for BundleChromeOSConfig"""
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600522
Alex Klein1699fab2022-09-08 08:46:06 -0600523 def testValidateOnly(self):
524 """Quick check that a validate only call does not execute any logic."""
525 patch = self.PatchObject(artifacts_svc, "BundleChromeOSConfig")
526 artifacts.BundleChromeOSConfig(
527 self.sysroot_request, self.response, self.validate_only_config
528 )
529 patch.assert_not_called()
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600530
Alex Klein1699fab2022-09-08 08:46:06 -0600531 def testMockCall(self):
532 """Test that a mock call does not execute logic, returns mocked value."""
533 patch = self.PatchObject(artifacts_svc, "BundleChromeOSConfig")
534 artifacts.BundleChromeOSConfig(
535 self.sysroot_request, self.response, self.mock_call_config
536 )
537 patch.assert_not_called()
538 self.assertEqual(len(self.response.artifacts), 1)
539 self.assertEqual(
540 self.response.artifacts[0].path,
541 os.path.join(self.output_dir, "config.yaml"),
542 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700543
Alex Klein1699fab2022-09-08 08:46:06 -0600544 def testBundleChromeOSConfigSuccess(self):
545 """Test standard success case."""
546 bundle_chromeos_config = self.PatchObject(
547 artifacts_svc, "BundleChromeOSConfig", return_value="config.yaml"
548 )
549 artifacts.BundleChromeOSConfig(
550 self.sysroot_request, self.response, self.api_config
551 )
552 self.assertEqual(
553 [artifact.path for artifact in self.response.artifacts],
554 [os.path.join(self.output_dir, "config.yaml")],
555 )
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600556
Alex Klein1699fab2022-09-08 08:46:06 -0600557 self.assertEqual(
558 bundle_chromeos_config.call_args_list,
559 [mock.call(mock.ANY, self.sysroot, self.output_dir)],
560 )
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600561
Alex Klein1699fab2022-09-08 08:46:06 -0600562 def testBundleChromeOSConfigNoConfigFound(self):
563 """Empty results when the config payload isn't found."""
564 self.PatchObject(
565 artifacts_svc, "BundleChromeOSConfig", return_value=None
566 )
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600567
Alex Klein1699fab2022-09-08 08:46:06 -0600568 artifacts.BundleChromeOSConfig(
569 self.sysroot_request, self.response, self.api_config
570 )
571 self.assertFalse(self.response.artifacts)
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600572
573
Alex Klein1699fab2022-09-08 08:46:06 -0600574class BundleTestUpdatePayloadsTest(
575 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin
576):
577 """Unittests for BundleTestUpdatePayloads."""
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600578
Alex Klein1699fab2022-09-08 08:46:06 -0600579 def setUp(self):
580 self.source_root = os.path.join(self.tempdir, "cros")
581 osutils.SafeMakedirs(self.source_root)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600582
Alex Klein1699fab2022-09-08 08:46:06 -0600583 self.archive_root = os.path.join(self.tempdir, "output")
584 osutils.SafeMakedirs(self.archive_root)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600585
Alex Klein1699fab2022-09-08 08:46:06 -0600586 self.target = "target"
587 self.image_root = os.path.join(
588 self.source_root, "src/build/images/target/latest"
589 )
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600590
Alex Klein1699fab2022-09-08 08:46:06 -0600591 self.input_proto = artifacts_pb2.BundleRequest()
592 self.input_proto.build_target.name = self.target
593 self.input_proto.output_dir = self.archive_root
594 self.output_proto = artifacts_pb2.BundleResponse()
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600595
Alex Klein1699fab2022-09-08 08:46:06 -0600596 self.PatchObject(constants, "SOURCE_ROOT", new=self.source_root)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600597
Alex Klein1699fab2022-09-08 08:46:06 -0600598 def MockPayloads(image_path, archive_dir):
599 osutils.WriteFile(
600 os.path.join(archive_dir, "payload1.bin"), image_path
601 )
602 osutils.WriteFile(
603 os.path.join(archive_dir, "payload2.bin"), image_path
604 )
605 return [
606 os.path.join(archive_dir, "payload1.bin"),
607 os.path.join(archive_dir, "payload2.bin"),
608 ]
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600609
Alex Klein1699fab2022-09-08 08:46:06 -0600610 self.bundle_patch = self.PatchObject(
611 artifacts_svc, "BundleTestUpdatePayloads", side_effect=MockPayloads
612 )
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600613
Alex Klein1699fab2022-09-08 08:46:06 -0600614 def testValidateOnly(self):
615 """Quick check that a validate only call does not execute any logic."""
616 patch = self.PatchObject(artifacts_svc, "BundleTestUpdatePayloads")
617 artifacts.BundleTestUpdatePayloads(
618 self.input_proto, self.output_proto, self.validate_only_config
619 )
620 patch.assert_not_called()
Alex Klein231d2da2019-07-22 16:44:45 -0600621
Alex Klein1699fab2022-09-08 08:46:06 -0600622 def testMockCall(self):
623 """Test that a mock call does not execute logic, returns mocked value."""
624 patch = self.PatchObject(artifacts_svc, "BundleTestUpdatePayloads")
625 artifacts.BundleTestUpdatePayloads(
626 self.input_proto, self.output_proto, self.mock_call_config
627 )
628 patch.assert_not_called()
629 self.assertEqual(len(self.output_proto.artifacts), 3)
630 self.assertEqual(
631 self.output_proto.artifacts[0].path,
632 os.path.join(self.archive_root, "payload1.bin"),
633 )
634 self.assertEqual(
635 self.output_proto.artifacts[1].path,
636 os.path.join(self.archive_root, "payload1.json"),
637 )
638 self.assertEqual(
639 self.output_proto.artifacts[2].path,
640 os.path.join(self.archive_root, "payload1.log"),
641 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700642
Alex Klein1699fab2022-09-08 08:46:06 -0600643 def testBundleTestUpdatePayloads(self):
644 """BundleTestUpdatePayloads calls cbuildbot/commands with correct args."""
645 image_path = os.path.join(self.image_root, constants.BASE_IMAGE_BIN)
646 osutils.WriteFile(image_path, "image!", makedirs=True)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600647
Alex Klein1699fab2022-09-08 08:46:06 -0600648 artifacts.BundleTestUpdatePayloads(
649 self.input_proto, self.output_proto, self.api_config
650 )
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600651
Alex Klein1699fab2022-09-08 08:46:06 -0600652 actual = [
653 os.path.relpath(artifact.path, self.archive_root)
654 for artifact in self.output_proto.artifacts
655 ]
656 expected = ["payload1.bin", "payload2.bin"]
657 self.assertCountEqual(actual, expected)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600658
Alex Klein1699fab2022-09-08 08:46:06 -0600659 actual = [
660 os.path.relpath(path, self.archive_root)
661 for path in osutils.DirectoryIterator(self.archive_root)
662 ]
663 self.assertCountEqual(actual, expected)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600664
Alex Klein1699fab2022-09-08 08:46:06 -0600665 def testBundleTestUpdatePayloadsNoImageDir(self):
666 """BundleTestUpdatePayloads dies if no image dir is found."""
667 # Intentionally do not write image directory.
668 artifacts.BundleTestUpdatePayloads(
669 self.input_proto, self.output_proto, self.api_config
670 )
671 self.assertFalse(self.output_proto.artifacts)
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600672
Alex Klein1699fab2022-09-08 08:46:06 -0600673 def testBundleTestUpdatePayloadsNoImage(self):
674 """BundleTestUpdatePayloads dies if no usable image is found for target."""
675 # Intentionally do not write image, but create the directory.
676 osutils.SafeMakedirs(self.image_root)
677 with self.assertRaises(cros_build_lib.DieSystemExit):
678 artifacts.BundleTestUpdatePayloads(
679 self.input_proto, self.output_proto, self.api_config
680 )
Alex Klein6504eca2019-04-18 15:37:56 -0600681
682
Alex Klein1699fab2022-09-08 08:46:06 -0600683class BundleSimpleChromeArtifactsTest(
684 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin
685):
686 """BundleSimpleChromeArtifacts tests."""
Alex Klein2275d692019-04-23 16:04:12 -0600687
Alex Klein1699fab2022-09-08 08:46:06 -0600688 def setUp(self):
689 self.chroot_dir = os.path.join(self.tempdir, "chroot_dir")
690 self.sysroot_path = "/sysroot"
691 self.sysroot_dir = os.path.join(self.chroot_dir, "sysroot")
692 osutils.SafeMakedirs(self.sysroot_dir)
693 self.output_dir = os.path.join(self.tempdir, "output_dir")
694 osutils.SafeMakedirs(self.output_dir)
Alex Klein2275d692019-04-23 16:04:12 -0600695
Alex Klein1699fab2022-09-08 08:46:06 -0600696 self.does_not_exist = os.path.join(self.tempdir, "does_not_exist")
Alex Klein2275d692019-04-23 16:04:12 -0600697
Alex Klein1699fab2022-09-08 08:46:06 -0600698 self.response = artifacts_pb2.BundleResponse()
Alex Klein231d2da2019-07-22 16:44:45 -0600699
Alex Klein1699fab2022-09-08 08:46:06 -0600700 def _GetRequest(
701 self,
702 chroot: Optional[str] = None,
703 sysroot: Optional[str] = None,
704 build_target: Optional[str] = None,
705 output_dir: Optional[str] = None,
706 ) -> artifacts_pb2.BundleRequest:
707 """Helper to create a request message instance.
Alex Klein2275d692019-04-23 16:04:12 -0600708
Alex Klein1699fab2022-09-08 08:46:06 -0600709 Args:
710 chroot: The chroot path.
711 sysroot: The sysroot path.
712 build_target: The build target name.
713 output_dir: The output directory.
714 """
715 return artifacts_pb2.BundleRequest(
716 sysroot={"path": sysroot, "build_target": {"name": build_target}},
717 chroot={"path": chroot},
718 output_dir=output_dir,
719 )
Alex Klein2275d692019-04-23 16:04:12 -0600720
Alex Klein1699fab2022-09-08 08:46:06 -0600721 def testValidateOnly(self):
722 """Quick check that a validate only call does not execute any logic."""
723 patch = self.PatchObject(artifacts_svc, "BundleSimpleChromeArtifacts")
724 request = self._GetRequest(
725 chroot=self.chroot_dir,
726 sysroot=self.sysroot_path,
727 build_target="board",
728 output_dir=self.output_dir,
729 )
730 artifacts.BundleSimpleChromeArtifacts(
731 request, self.response, self.validate_only_config
732 )
733 patch.assert_not_called()
Alex Klein2275d692019-04-23 16:04:12 -0600734
Alex Klein1699fab2022-09-08 08:46:06 -0600735 def testMockCall(self):
736 """Test that a mock call does not execute logic, returns mocked value."""
737 patch = self.PatchObject(artifacts_svc, "BundleSimpleChromeArtifacts")
738 request = self._GetRequest(
739 chroot=self.chroot_dir,
740 sysroot=self.sysroot_path,
741 build_target="board",
742 output_dir=self.output_dir,
743 )
744 artifacts.BundleSimpleChromeArtifacts(
745 request, self.response, self.mock_call_config
746 )
747 patch.assert_not_called()
748 self.assertEqual(len(self.response.artifacts), 1)
749 self.assertEqual(
750 self.response.artifacts[0].path,
751 os.path.join(self.output_dir, "simple_chrome.txt"),
752 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700753
Alex Klein1699fab2022-09-08 08:46:06 -0600754 def testNoBuildTarget(self):
755 """Test no build target fails."""
756 request = self._GetRequest(
757 chroot=self.chroot_dir,
758 sysroot=self.sysroot_path,
759 output_dir=self.output_dir,
760 )
761 response = self.response
762 with self.assertRaises(cros_build_lib.DieSystemExit):
763 artifacts.BundleSimpleChromeArtifacts(
764 request, response, self.api_config
765 )
Alex Klein2275d692019-04-23 16:04:12 -0600766
Alex Klein1699fab2022-09-08 08:46:06 -0600767 def testNoSysroot(self):
768 """Test no sysroot fails."""
769 request = self._GetRequest(
770 build_target="board", output_dir=self.output_dir
771 )
772 response = self.response
773 with self.assertRaises(cros_build_lib.DieSystemExit):
774 artifacts.BundleSimpleChromeArtifacts(
775 request, response, self.api_config
776 )
Alex Klein2275d692019-04-23 16:04:12 -0600777
Alex Klein1699fab2022-09-08 08:46:06 -0600778 def testSysrootDoesNotExist(self):
779 """Test no sysroot fails."""
780 request = self._GetRequest(
781 build_target="board",
782 output_dir=self.output_dir,
783 sysroot=self.does_not_exist,
784 )
785 response = self.response
786 with self.assertRaises(cros_build_lib.DieSystemExit):
787 artifacts.BundleSimpleChromeArtifacts(
788 request, response, self.api_config
789 )
Alex Klein2275d692019-04-23 16:04:12 -0600790
Alex Klein1699fab2022-09-08 08:46:06 -0600791 def testNoOutputDir(self):
792 """Test no output dir fails."""
793 request = self._GetRequest(
794 chroot=self.chroot_dir,
795 sysroot=self.sysroot_path,
796 build_target="board",
797 )
798 response = self.response
799 with self.assertRaises(cros_build_lib.DieSystemExit):
800 artifacts.BundleSimpleChromeArtifacts(
801 request, response, self.api_config
802 )
Alex Klein2275d692019-04-23 16:04:12 -0600803
Alex Klein1699fab2022-09-08 08:46:06 -0600804 def testOutputDirDoesNotExist(self):
805 """Test no output dir fails."""
806 request = self._GetRequest(
807 chroot=self.chroot_dir,
808 sysroot=self.sysroot_path,
809 build_target="board",
810 output_dir=self.does_not_exist,
811 )
812 response = self.response
813 with self.assertRaises(cros_build_lib.DieSystemExit):
814 artifacts.BundleSimpleChromeArtifacts(
815 request, response, self.api_config
816 )
Alex Klein2275d692019-04-23 16:04:12 -0600817
Alex Klein1699fab2022-09-08 08:46:06 -0600818 def testOutputHandling(self):
819 """Test response output."""
820 files = ["file1", "file2", "file3"]
821 expected_files = [os.path.join(self.output_dir, f) for f in files]
822 self.PatchObject(
823 artifacts_svc,
824 "BundleSimpleChromeArtifacts",
825 return_value=expected_files,
826 )
827 request = self._GetRequest(
828 chroot=self.chroot_dir,
829 sysroot=self.sysroot_path,
830 build_target="board",
831 output_dir=self.output_dir,
832 )
833 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600834
Alex Klein1699fab2022-09-08 08:46:06 -0600835 artifacts.BundleSimpleChromeArtifacts(
836 request, response, self.api_config
837 )
Alex Klein2275d692019-04-23 16:04:12 -0600838
Alex Klein1699fab2022-09-08 08:46:06 -0600839 self.assertTrue(response.artifacts)
840 self.assertCountEqual(
841 expected_files, [a.path for a in response.artifacts]
842 )
Alex Klein2275d692019-04-23 16:04:12 -0600843
844
Alex Klein1699fab2022-09-08 08:46:06 -0600845class BundleVmFilesTest(
846 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin
847):
848 """BuildVmFiles tests."""
Alex Klein6504eca2019-04-18 15:37:56 -0600849
Alex Klein1699fab2022-09-08 08:46:06 -0600850 def setUp(self):
851 self.output_dir = os.path.join(self.tempdir, "output")
852 osutils.SafeMakedirs(self.output_dir)
Alex Klein231d2da2019-07-22 16:44:45 -0600853
Alex Klein1699fab2022-09-08 08:46:06 -0600854 self.response = artifacts_pb2.BundleResponse()
Alex Klein231d2da2019-07-22 16:44:45 -0600855
Alex Klein1699fab2022-09-08 08:46:06 -0600856 def _GetInput(
857 self,
858 chroot: Optional[str] = None,
859 sysroot: Optional[str] = None,
860 test_results_dir: Optional[str] = None,
861 output_dir: Optional[str] = None,
862 ) -> artifacts_pb2.BundleVmFilesRequest:
863 """Helper to build out an input message instance.
Alex Klein6504eca2019-04-18 15:37:56 -0600864
Alex Klein1699fab2022-09-08 08:46:06 -0600865 Args:
866 chroot: The chroot path.
867 sysroot: The sysroot path relative to the chroot.
868 test_results_dir: The test results directory relative to the sysroot.
869 output_dir: The directory where the results tarball should be saved.
870 """
871 return artifacts_pb2.BundleVmFilesRequest(
872 chroot={"path": chroot},
873 sysroot={"path": sysroot},
874 test_results_dir=test_results_dir,
875 output_dir=output_dir,
876 )
Alex Klein6504eca2019-04-18 15:37:56 -0600877
Alex Klein1699fab2022-09-08 08:46:06 -0600878 def testValidateOnly(self):
879 """Quick check that a validate only call does not execute any logic."""
880 patch = self.PatchObject(artifacts_svc, "BundleVmFiles")
881 in_proto = self._GetInput(
882 chroot="/chroot/dir",
883 sysroot="/build/board",
884 test_results_dir="/test/results",
885 output_dir=self.output_dir,
886 )
887 artifacts.BundleVmFiles(
888 in_proto, self.response, self.validate_only_config
889 )
890 patch.assert_not_called()
Alex Klein6504eca2019-04-18 15:37:56 -0600891
Alex Klein1699fab2022-09-08 08:46:06 -0600892 def testMockCall(self):
893 """Test that a mock call does not execute logic, returns mocked value."""
894 patch = self.PatchObject(artifacts_svc, "BundleVmFiles")
895 in_proto = self._GetInput(
896 chroot="/chroot/dir",
897 sysroot="/build/board",
898 test_results_dir="/test/results",
899 output_dir=self.output_dir,
900 )
901 artifacts.BundleVmFiles(in_proto, self.response, self.mock_call_config)
902 patch.assert_not_called()
903 self.assertEqual(len(self.response.artifacts), 1)
904 self.assertEqual(
905 self.response.artifacts[0].path,
906 os.path.join(self.output_dir, "f1.tar"),
907 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700908
Alex Klein1699fab2022-09-08 08:46:06 -0600909 def testChrootMissing(self):
910 """Test error handling for missing chroot."""
911 in_proto = self._GetInput(
912 sysroot="/build/board",
913 test_results_dir="/test/results",
914 output_dir=self.output_dir,
915 )
Alex Klein6504eca2019-04-18 15:37:56 -0600916
Alex Klein1699fab2022-09-08 08:46:06 -0600917 with self.assertRaises(cros_build_lib.DieSystemExit):
918 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600919
Alex Klein1699fab2022-09-08 08:46:06 -0600920 def testTestResultsDirMissing(self):
921 """Test error handling for missing test results directory."""
922 in_proto = self._GetInput(
923 chroot="/chroot/dir",
924 sysroot="/build/board",
925 output_dir=self.output_dir,
926 )
Alex Klein6504eca2019-04-18 15:37:56 -0600927
Alex Klein1699fab2022-09-08 08:46:06 -0600928 with self.assertRaises(cros_build_lib.DieSystemExit):
929 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600930
Alex Klein1699fab2022-09-08 08:46:06 -0600931 def testOutputDirMissing(self):
932 """Test error handling for missing output directory."""
933 in_proto = self._GetInput(
934 chroot="/chroot/dir",
935 sysroot="/build/board",
936 test_results_dir="/test/results",
937 )
Alex Klein6504eca2019-04-18 15:37:56 -0600938
Alex Klein1699fab2022-09-08 08:46:06 -0600939 with self.assertRaises(cros_build_lib.DieSystemExit):
940 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
Alex Klein231d2da2019-07-22 16:44:45 -0600941
Alex Klein1699fab2022-09-08 08:46:06 -0600942 def testOutputDirDoesNotExist(self):
943 """Test error handling for output directory that does not exist."""
944 in_proto = self._GetInput(
945 chroot="/chroot/dir",
946 sysroot="/build/board",
947 output_dir=os.path.join(self.tempdir, "dne"),
948 test_results_dir="/test/results",
949 )
Alex Klein231d2da2019-07-22 16:44:45 -0600950
Alex Klein1699fab2022-09-08 08:46:06 -0600951 with self.assertRaises(cros_build_lib.DieSystemExit):
952 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600953
Alex Klein1699fab2022-09-08 08:46:06 -0600954 def testValidCall(self):
955 """Test image dir building."""
956 in_proto = self._GetInput(
957 chroot="/chroot/dir",
958 sysroot="/build/board",
959 test_results_dir="/test/results",
960 output_dir=self.output_dir,
961 )
Alex Klein231d2da2019-07-22 16:44:45 -0600962
Alex Klein1699fab2022-09-08 08:46:06 -0600963 expected_files = ["/tmp/output/f1.tar", "/tmp/output/f2.tar"]
964 patch = self.PatchObject(
965 artifacts_svc, "BundleVmFiles", return_value=expected_files
966 )
Alex Klein6504eca2019-04-18 15:37:56 -0600967
Alex Klein1699fab2022-09-08 08:46:06 -0600968 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600969
Alex Klein1699fab2022-09-08 08:46:06 -0600970 patch.assert_called_with(mock.ANY, "/test/results", self.output_dir)
Alex Klein6504eca2019-04-18 15:37:56 -0600971
Alex Klein1699fab2022-09-08 08:46:06 -0600972 # Make sure we have artifacts, and that every artifact is an expected file.
973 self.assertTrue(self.response.artifacts)
974 for artifact in self.response.artifacts:
975 self.assertIn(artifact.path, expected_files)
976 expected_files.remove(artifact.path)
Alex Klein6504eca2019-04-18 15:37:56 -0600977
Alex Klein1699fab2022-09-08 08:46:06 -0600978 # Make sure we've seen all of the expected files.
979 self.assertFalse(expected_files)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600980
Tiancong Wang50b80a92019-08-01 14:46:15 -0700981
Alex Klein036833d2022-06-01 13:05:01 -0600982class ExportCpeReportTest(BundleTestCase):
Alex Klein1699fab2022-09-08 08:46:06 -0600983 """ExportCpeReport tests."""
Alex Klein0b1cbfc2019-08-14 10:09:58 -0600984
Alex Klein1699fab2022-09-08 08:46:06 -0600985 def testValidateOnly(self):
986 """Quick check validate only calls don't execute."""
987 patch = self.PatchObject(artifacts_svc, "GenerateCpeReport")
Alex Klein0b1cbfc2019-08-14 10:09:58 -0600988
Alex Klein1699fab2022-09-08 08:46:06 -0600989 artifacts.ExportCpeReport(
990 self.sysroot_request, self.response, self.validate_only_config
991 )
Alex Klein0b1cbfc2019-08-14 10:09:58 -0600992
Alex Klein1699fab2022-09-08 08:46:06 -0600993 patch.assert_not_called()
Alex Klein0b1cbfc2019-08-14 10:09:58 -0600994
Alex Klein1699fab2022-09-08 08:46:06 -0600995 def testMockCall(self):
996 """Test that a mock call does not execute logic, returns mocked value."""
997 patch = self.PatchObject(artifacts_svc, "GenerateCpeReport")
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700998
Alex Klein1699fab2022-09-08 08:46:06 -0600999 artifacts.ExportCpeReport(
1000 self.sysroot_request, self.response, self.mock_call_config
1001 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -07001002
Alex Klein1699fab2022-09-08 08:46:06 -06001003 patch.assert_not_called()
1004 self.assertEqual(len(self.response.artifacts), 2)
1005 self.assertEqual(
1006 self.response.artifacts[0].path,
1007 os.path.join(self.output_dir, "cpe_report.txt"),
1008 )
1009 self.assertEqual(
1010 self.response.artifacts[1].path,
1011 os.path.join(self.output_dir, "cpe_warnings.txt"),
1012 )
Alex Klein0b1cbfc2019-08-14 10:09:58 -06001013
Alex Klein1699fab2022-09-08 08:46:06 -06001014 def testSuccess(self):
1015 """Test success case."""
1016 expected = artifacts_svc.CpeResult(
1017 report="/output/report.json", warnings="/output/warnings.json"
1018 )
1019 self.PatchObject(
1020 artifacts_svc, "GenerateCpeReport", return_value=expected
1021 )
Alex Klein0b1cbfc2019-08-14 10:09:58 -06001022
Alex Klein1699fab2022-09-08 08:46:06 -06001023 artifacts.ExportCpeReport(
1024 self.sysroot_request, self.response, self.api_config
1025 )
Alex Klein0b1cbfc2019-08-14 10:09:58 -06001026
Alex Klein1699fab2022-09-08 08:46:06 -06001027 for artifact in self.response.artifacts:
1028 self.assertIn(artifact.path, [expected.report, expected.warnings])
Shao-Chuan Leea44dddc2020-10-30 17:16:55 +09001029
1030
1031class BundleGceTarballTest(BundleTestCase):
Alex Klein1699fab2022-09-08 08:46:06 -06001032 """Unittests for BundleGceTarball."""
Shao-Chuan Leea44dddc2020-10-30 17:16:55 +09001033
Alex Klein1699fab2022-09-08 08:46:06 -06001034 def testValidateOnly(self):
1035 """Check that a validate only call does not execute any logic."""
1036 patch = self.PatchObject(artifacts_svc, "BundleGceTarball")
1037 artifacts.BundleGceTarball(
1038 self.target_request, self.response, self.validate_only_config
1039 )
1040 patch.assert_not_called()
Shao-Chuan Leea44dddc2020-10-30 17:16:55 +09001041
Alex Klein1699fab2022-09-08 08:46:06 -06001042 def testMockCall(self):
1043 """Test that a mock call does not execute logic, returns mocked value."""
1044 patch = self.PatchObject(artifacts_svc, "BundleGceTarball")
1045 artifacts.BundleGceTarball(
1046 self.target_request, self.response, self.mock_call_config
1047 )
1048 patch.assert_not_called()
1049 self.assertEqual(len(self.response.artifacts), 1)
1050 self.assertEqual(
1051 self.response.artifacts[0].path,
1052 os.path.join(self.output_dir, constants.TEST_IMAGE_GCE_TAR),
1053 )
Shao-Chuan Leea44dddc2020-10-30 17:16:55 +09001054
Alex Klein1699fab2022-09-08 08:46:06 -06001055 def testBundleGceTarball(self):
1056 """BundleGceTarball calls cbuildbot/commands with correct args."""
1057 bundle_gce_tarball = self.PatchObject(
1058 artifacts_svc,
1059 "BundleGceTarball",
1060 return_value=os.path.join(
1061 self.output_dir, constants.TEST_IMAGE_GCE_TAR
1062 ),
1063 )
1064 self.PatchObject(os.path, "exists", return_value=True)
1065 artifacts.BundleGceTarball(
1066 self.target_request, self.response, self.api_config
1067 )
1068 self.assertEqual(
1069 [artifact.path for artifact in self.response.artifacts],
1070 [os.path.join(self.output_dir, constants.TEST_IMAGE_GCE_TAR)],
1071 )
Shao-Chuan Leea44dddc2020-10-30 17:16:55 +09001072
Alex Klein1699fab2022-09-08 08:46:06 -06001073 latest = os.path.join(
1074 self.source_root, "src/build/images/target/latest"
1075 )
1076 self.assertEqual(
1077 bundle_gce_tarball.call_args_list,
1078 [mock.call(self.output_dir, latest)],
1079 )
Shao-Chuan Leea44dddc2020-10-30 17:16:55 +09001080
Alex Klein1699fab2022-09-08 08:46:06 -06001081 def testBundleGceTarballNoImageDir(self):
1082 """BundleGceTarball dies when image dir does not exist."""
1083 self.PatchObject(os.path, "exists", return_value=False)
1084 with self.assertRaises(cros_build_lib.DieSystemExit):
1085 artifacts.BundleGceTarball(
1086 self.target_request, self.response, self.api_config
1087 )
Greg Edelstondc941072021-08-11 12:32:30 -06001088
Greg Edelstondc941072021-08-11 12:32:30 -06001089
Alex Klein1699fab2022-09-08 08:46:06 -06001090class FetchMetadataTestCase(
1091 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin
1092):
1093 """Unittests for FetchMetadata."""
Greg Edelstondc941072021-08-11 12:32:30 -06001094
Alex Klein1699fab2022-09-08 08:46:06 -06001095 sysroot_path = "/build/coral"
1096 chroot_name = "chroot"
Greg Edelstondc941072021-08-11 12:32:30 -06001097
Alex Klein1699fab2022-09-08 08:46:06 -06001098 def setUp(self):
1099 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=False)
1100 self.chroot_path = os.path.join(self.tempdir, "chroot")
1101 pathlib.Path(self.chroot_path).touch()
1102 self.expected_filepaths = [
1103 os.path.join(self.chroot_path, fp)
1104 for fp in (
1105 "build/coral/usr/local/build/autotest/autotest_metadata.pb",
1106 "build/coral/usr/share/tast/metadata/local/cros.pb",
1107 "build/coral/build/share/tast/metadata/local/crosint.pb",
1108 "usr/share/tast/metadata/remote/cros.pb",
1109 )
1110 ]
1111 self.PatchObject(cros_build_lib, "AssertOutsideChroot")
Greg Edelstondc941072021-08-11 12:32:30 -06001112
Alex Klein1699fab2022-09-08 08:46:06 -06001113 def createFetchMetadataRequest(
1114 self, use_sysroot_path=True, use_chroot=True
1115 ):
1116 """Construct a FetchMetadataRequest for use in test cases."""
1117 request = artifacts_pb2.FetchMetadataRequest()
1118 if use_sysroot_path:
1119 request.sysroot.path = self.sysroot_path
1120 if use_chroot:
1121 request.chroot.path = self.chroot_path
1122 return request
Greg Edelstondc941072021-08-11 12:32:30 -06001123
Alex Klein1699fab2022-09-08 08:46:06 -06001124 def testValidateOnly(self):
1125 """Check that a validate only call does not execute any logic."""
1126 patch = self.PatchObject(controller_util, "ParseSysroot")
1127 request = self.createFetchMetadataRequest()
1128 response = artifacts_pb2.FetchMetadataResponse()
1129 artifacts.FetchMetadata(request, response, self.validate_only_config)
1130 patch.assert_not_called()
Greg Edelstondc941072021-08-11 12:32:30 -06001131
Alex Klein1699fab2022-09-08 08:46:06 -06001132 def testMockCall(self):
1133 """Test that a mock call does not execute logic, returns mocked value."""
1134 patch = self.PatchObject(controller_util, "ParseSysroot")
1135 request = self.createFetchMetadataRequest()
1136 response = artifacts_pb2.FetchMetadataResponse()
1137 artifacts.FetchMetadata(request, response, self.mock_call_config)
1138 patch.assert_not_called()
1139 self.assertGreater(len(response.filepaths), 0)
Greg Edelstondc941072021-08-11 12:32:30 -06001140
Alex Klein1699fab2022-09-08 08:46:06 -06001141 def testNoSysrootPath(self):
1142 """Check that a request with no sysroot.path results in failure."""
1143 request = self.createFetchMetadataRequest(use_sysroot_path=False)
1144 response = artifacts_pb2.FetchMetadataResponse()
1145 with self.assertRaises(cros_build_lib.DieSystemExit):
1146 artifacts.FetchMetadata(request, response, self.api_config)
Greg Edelstondc941072021-08-11 12:32:30 -06001147
Alex Klein1699fab2022-09-08 08:46:06 -06001148 def testNoChroot(self):
1149 """Check that a request with no chroot results in failure."""
1150 request = self.createFetchMetadataRequest(use_chroot=False)
1151 response = artifacts_pb2.FetchMetadataResponse()
1152 with self.assertRaises(cros_build_lib.DieSystemExit):
1153 artifacts.FetchMetadata(request, response, self.api_config)
1154
1155 def testSuccess(self):
1156 """Check that a well-formed request yields the expected results."""
1157 request = self.createFetchMetadataRequest(use_chroot=True)
1158 response = artifacts_pb2.FetchMetadataResponse()
1159 artifacts.FetchMetadata(request, response, self.api_config)
1160 actual_filepaths = [fp.path.path for fp in response.filepaths]
1161 self.assertEqual(
1162 sorted(actual_filepaths), sorted(self.expected_filepaths)
1163 )
1164 self.assertTrue(
1165 all(
1166 fp.path.location == common_pb2.Path.OUTSIDE
1167 for fp in response.filepaths
1168 )
1169 )