blob: 5f44e132f025e396e59bf88e5dddb113d7397e21 [file] [log] [blame]
Evan Hernandezf388cbf2019-04-01 11:15:23 -06001# -*- coding: utf-8 -*-
2# Copyright 2019 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Unittests for Artifacts operations."""
7
8from __future__ import print_function
9
Michael Mortensen2d6a2402019-11-26 13:40:40 -070010import collections
Evan Hernandezf388cbf2019-04-01 11:15:23 -060011import os
Mike Frysingeref94e4c2020-02-10 23:59:54 -050012import sys
Evan Hernandezf388cbf2019-04-01 11:15:23 -060013
Mike Frysinger6db648e2018-07-24 19:57:58 -040014import mock
15
Alex Klein231d2da2019-07-22 16:44:45 -060016from chromite.api import api_config
Evan Hernandezf388cbf2019-04-01 11:15:23 -060017from chromite.api.controller import artifacts
18from chromite.api.gen.chromite.api import artifacts_pb2
Tiancong Wang24a3df72019-08-20 15:48:51 -070019from chromite.api.gen.chromite.api import toolchain_pb2
Evan Hernandezf388cbf2019-04-01 11:15:23 -060020from chromite.cbuildbot import commands
Alex Kleinb9d810b2019-07-01 12:38:02 -060021from chromite.lib import chroot_lib
Evan Hernandezf388cbf2019-04-01 11:15:23 -060022from chromite.lib import constants
23from chromite.lib import cros_build_lib
24from chromite.lib import cros_test_lib
25from chromite.lib import osutils
Alex Klein238d8862019-05-07 11:32:46 -060026from chromite.lib import sysroot_lib
Alex Klein2275d692019-04-23 16:04:12 -060027from chromite.service import artifacts as artifacts_svc
Evan Hernandezf388cbf2019-04-01 11:15:23 -060028
29
Mike Frysingeref94e4c2020-02-10 23:59:54 -050030assert sys.version_info >= (3, 6), 'This module requires Python 3.6+'
31
32
Michael Mortensen2d6a2402019-11-26 13:40:40 -070033PinnedGuestImage = collections.namedtuple('PinnedGuestImage',
34 ['filename', 'uri'])
35
36
Alex Kleind91e95a2019-09-17 10:39:02 -060037class BundleRequestMixin(object):
38 """Mixin to provide bundle request methods."""
39
40 def EmptyRequest(self):
41 return artifacts_pb2.BundleRequest()
42
43 def BuildTargetRequest(self, build_target=None, output_dir=None, chroot=None):
44 """Get a build target format request instance."""
45 request = self.EmptyRequest()
46 if build_target:
47 request.build_target.name = build_target
48 if output_dir:
49 request.output_dir = output_dir
50 if chroot:
51 request.chroot.path = chroot
52
53 return request
54
55 def SysrootRequest(self,
56 sysroot=None,
57 build_target=None,
58 output_dir=None,
59 chroot=None):
60 """Get a sysroot format request instance."""
61 request = self.EmptyRequest()
62 if sysroot:
63 request.sysroot.path = sysroot
64 if build_target:
65 request.sysroot.build_target.name = build_target
66 if output_dir:
67 request.output_dir = output_dir
68 if chroot:
69 request.chroot.path = chroot
70
71 return request
72
73
Alex Klein231d2da2019-07-22 16:44:45 -060074class BundleTestCase(cros_test_lib.MockTempDirTestCase,
Alex Kleind91e95a2019-09-17 10:39:02 -060075 api_config.ApiConfigMixin, BundleRequestMixin):
Evan Hernandezf388cbf2019-04-01 11:15:23 -060076 """Basic setup for all artifacts unittests."""
77
78 def setUp(self):
Alex Klein231d2da2019-07-22 16:44:45 -060079 self.output_dir = os.path.join(self.tempdir, 'artifacts')
80 osutils.SafeMakedirs(self.output_dir)
81 self.sysroot_path = '/build/target'
Alex Klein68c8fdf2019-09-25 15:09:11 -060082 self.sysroot = sysroot_lib.Sysroot(self.sysroot_path)
Alex Klein231d2da2019-07-22 16:44:45 -060083 self.chroot_path = os.path.join(self.tempdir, 'chroot')
84 full_sysroot_path = os.path.join(self.chroot_path,
85 self.sysroot_path.lstrip(os.sep))
86 osutils.SafeMakedirs(full_sysroot_path)
87
Alex Klein68c8fdf2019-09-25 15:09:11 -060088 # All requests use same response type.
Alex Klein231d2da2019-07-22 16:44:45 -060089 self.response = artifacts_pb2.BundleResponse()
90
Alex Klein68c8fdf2019-09-25 15:09:11 -060091 # Build target request.
92 self.target_request = self.BuildTargetRequest(
93 build_target='target',
94 output_dir=self.output_dir,
95 chroot=self.chroot_path)
96
97 # Sysroot request.
98 self.sysroot_request = self.SysrootRequest(
99 sysroot=self.sysroot_path,
100 build_target='target',
101 output_dir=self.output_dir,
102 chroot=self.chroot_path)
103
Alex Klein231d2da2019-07-22 16:44:45 -0600104 self.source_root = self.tempdir
105 self.PatchObject(constants, 'SOURCE_ROOT', new=self.tempdir)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600106
107
Alex Kleind91e95a2019-09-17 10:39:02 -0600108class BundleImageArchivesTest(BundleTestCase):
109 """BundleImageArchives tests."""
110
111 def testValidateOnly(self):
112 """Sanity check that a validate only call does not execute any logic."""
113 patch = self.PatchObject(artifacts_svc, 'ArchiveImages')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600114 artifacts.BundleImageArchives(self.target_request, self.response,
Alex Kleind91e95a2019-09-17 10:39:02 -0600115 self.validate_only_config)
116 patch.assert_not_called()
117
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700118 def testMockCall(self):
119 """Test that a mock call does not execute logic, returns mocked value."""
120 patch = self.PatchObject(artifacts_svc, 'ArchiveImages')
121 artifacts.BundleImageArchives(self.target_request, self.response,
122 self.mock_call_config)
123 patch.assert_not_called()
124 self.assertEqual(len(self.response.artifacts), 2)
125 self.assertEqual(self.response.artifacts[0].path,
126 os.path.join(self.output_dir, 'path0.tar.xz'))
127 self.assertEqual(self.response.artifacts[1].path,
128 os.path.join(self.output_dir, 'path1.tar.xz'))
129
Alex Kleind91e95a2019-09-17 10:39:02 -0600130 def testNoBuildTarget(self):
131 """Test that no build target fails."""
132 request = self.BuildTargetRequest(output_dir=self.tempdir)
133 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein68c8fdf2019-09-25 15:09:11 -0600134 artifacts.BundleImageArchives(request, self.response, self.api_config)
Alex Kleind91e95a2019-09-17 10:39:02 -0600135
136 def testNoOutputDir(self):
137 """Test no output dir fails."""
138 request = self.BuildTargetRequest(build_target='board')
139 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein68c8fdf2019-09-25 15:09:11 -0600140 artifacts.BundleImageArchives(request, self.response, self.api_config)
Alex Kleind91e95a2019-09-17 10:39:02 -0600141
142 def testInvalidOutputDir(self):
143 """Test invalid output dir fails."""
144 request = self.BuildTargetRequest(
145 build_target='board', output_dir=os.path.join(self.tempdir, 'DNE'))
146 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein68c8fdf2019-09-25 15:09:11 -0600147 artifacts.BundleImageArchives(request, self.response, self.api_config)
Alex Kleind91e95a2019-09-17 10:39:02 -0600148
149 def testOutputHandling(self):
150 """Test the artifact output handling."""
151 expected = [os.path.join(self.output_dir, f) for f in ('a', 'b', 'c')]
152 self.PatchObject(artifacts_svc, 'ArchiveImages', return_value=expected)
153 self.PatchObject(os.path, 'exists', return_value=True)
154
Alex Klein68c8fdf2019-09-25 15:09:11 -0600155 artifacts.BundleImageArchives(self.target_request, self.response,
Alex Kleind91e95a2019-09-17 10:39:02 -0600156 self.api_config)
157
Mike Frysinger678735c2019-09-28 18:23:28 -0400158 self.assertCountEqual(expected, [a.path for a in self.response.artifacts])
Alex Kleind91e95a2019-09-17 10:39:02 -0600159
160
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600161class BundleImageZipTest(BundleTestCase):
162 """Unittests for BundleImageZip."""
163
Alex Klein231d2da2019-07-22 16:44:45 -0600164 def testValidateOnly(self):
165 """Sanity check that a validate only call does not execute any logic."""
166 patch = self.PatchObject(commands, 'BuildImageZip')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600167 artifacts.BundleImageZip(self.target_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600168 self.validate_only_config)
169 patch.assert_not_called()
170
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700171 def testMockCall(self):
172 """Test that a mock call does not execute logic, returns mocked value."""
173 patch = self.PatchObject(commands, 'BuildImageZip')
174 artifacts.BundleImageZip(self.target_request, self.response,
175 self.mock_call_config)
176 patch.assert_not_called()
177 self.assertEqual(len(self.response.artifacts), 1)
178 self.assertEqual(self.response.artifacts[0].path,
179 os.path.join(self.output_dir, 'image.zip'))
180
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600181 def testBundleImageZip(self):
182 """BundleImageZip calls cbuildbot/commands with correct args."""
Michael Mortensen01910922019-07-24 14:48:10 -0600183 bundle_image_zip = self.PatchObject(
184 artifacts_svc, 'BundleImageZip', return_value='image.zip')
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600185 self.PatchObject(os.path, 'exists', return_value=True)
Alex Klein68c8fdf2019-09-25 15:09:11 -0600186 artifacts.BundleImageZip(self.target_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600187 self.api_config)
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600188 self.assertEqual(
Alex Klein68c8fdf2019-09-25 15:09:11 -0600189 [artifact.path for artifact in self.response.artifacts],
Alex Klein231d2da2019-07-22 16:44:45 -0600190 [os.path.join(self.output_dir, 'image.zip')])
191
192 latest = os.path.join(self.source_root, 'src/build/images/target/latest')
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600193 self.assertEqual(
Michael Mortensen01910922019-07-24 14:48:10 -0600194 bundle_image_zip.call_args_list,
Alex Klein231d2da2019-07-22 16:44:45 -0600195 [mock.call(self.output_dir, latest)])
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600196
197 def testBundleImageZipNoImageDir(self):
198 """BundleImageZip dies when image dir does not exist."""
199 self.PatchObject(os.path, 'exists', return_value=False)
200 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein68c8fdf2019-09-25 15:09:11 -0600201 artifacts.BundleImageZip(self.target_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600202 self.api_config)
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600203
204
Alex Klein68c8fdf2019-09-25 15:09:11 -0600205class BundleAutotestFilesTest(BundleTestCase):
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600206 """Unittests for BundleAutotestFiles."""
207
Alex Klein231d2da2019-07-22 16:44:45 -0600208 def testValidateOnly(self):
209 """Sanity check that a validate only call does not execute any logic."""
210 patch = self.PatchObject(artifacts_svc, 'BundleAutotestFiles')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600211 artifacts.BundleAutotestFiles(self.target_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600212 self.validate_only_config)
213 patch.assert_not_called()
214
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700215 def testMockCall(self):
216 """Test that a mock call does not execute logic, returns mocked value."""
217 patch = self.PatchObject(artifacts_svc, 'BundleAutotestFiles')
218 artifacts.BundleAutotestFiles(self.target_request, self.response,
219 self.mock_call_config)
220 patch.assert_not_called()
221 self.assertEqual(len(self.response.artifacts), 1)
222 self.assertEqual(self.response.artifacts[0].path,
223 os.path.join(self.output_dir, 'autotest-a.tar.gz'))
224
Alex Klein238d8862019-05-07 11:32:46 -0600225 def testBundleAutotestFilesLegacy(self):
226 """BundleAutotestFiles calls service correctly with legacy args."""
227 files = {
228 artifacts_svc.ARCHIVE_CONTROL_FILES: '/tmp/artifacts/autotest-a.tar.gz',
229 artifacts_svc.ARCHIVE_PACKAGES: '/tmp/artifacts/autotest-b.tar.gz',
230 }
231 patch = self.PatchObject(artifacts_svc, 'BundleAutotestFiles',
232 return_value=files)
233
Alex Klein68c8fdf2019-09-25 15:09:11 -0600234 artifacts.BundleAutotestFiles(self.target_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600235 self.api_config)
Alex Klein238d8862019-05-07 11:32:46 -0600236
Alex Klein238d8862019-05-07 11:32:46 -0600237 # Verify the arguments are being passed through.
Alex Kleine21a0952019-08-23 16:08:16 -0600238 patch.assert_called_with(mock.ANY, self.sysroot, self.output_dir)
Alex Klein238d8862019-05-07 11:32:46 -0600239
240 # Verify the output proto is being populated correctly.
Alex Klein68c8fdf2019-09-25 15:09:11 -0600241 self.assertTrue(self.response.artifacts)
242 paths = [artifact.path for artifact in self.response.artifacts]
Mike Frysinger1f4478c2019-10-20 18:33:17 -0400243 self.assertCountEqual(list(files.values()), paths)
Alex Klein238d8862019-05-07 11:32:46 -0600244
245 def testBundleAutotestFiles(self):
246 """BundleAutotestFiles calls service correctly."""
247 files = {
248 artifacts_svc.ARCHIVE_CONTROL_FILES: '/tmp/artifacts/autotest-a.tar.gz',
249 artifacts_svc.ARCHIVE_PACKAGES: '/tmp/artifacts/autotest-b.tar.gz',
250 }
251 patch = self.PatchObject(artifacts_svc, 'BundleAutotestFiles',
252 return_value=files)
253
Alex Klein68c8fdf2019-09-25 15:09:11 -0600254 artifacts.BundleAutotestFiles(self.sysroot_request, self.response,
255 self.api_config)
Alex Klein238d8862019-05-07 11:32:46 -0600256
257 # Verify the arguments are being passed through.
Alex Kleine21a0952019-08-23 16:08:16 -0600258 patch.assert_called_with(mock.ANY, self.sysroot, self.output_dir)
Alex Klein238d8862019-05-07 11:32:46 -0600259
260 # Verify the output proto is being populated correctly.
261 self.assertTrue(self.response.artifacts)
262 paths = [artifact.path for artifact in self.response.artifacts]
Mike Frysinger1f4478c2019-10-20 18:33:17 -0400263 self.assertCountEqual(list(files.values()), paths)
Alex Klein238d8862019-05-07 11:32:46 -0600264
265 def testInvalidOutputDir(self):
266 """Test invalid output directory argument."""
Alex Klein68c8fdf2019-09-25 15:09:11 -0600267 request = self.SysrootRequest(chroot=self.chroot_path,
268 sysroot=self.sysroot_path)
Alex Klein238d8862019-05-07 11:32:46 -0600269
270 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600271 artifacts.BundleAutotestFiles(request, self.response, self.api_config)
Alex Klein238d8862019-05-07 11:32:46 -0600272
273 def testInvalidSysroot(self):
274 """Test no sysroot directory."""
Alex Klein68c8fdf2019-09-25 15:09:11 -0600275 request = self.SysrootRequest(chroot=self.chroot_path,
276 output_dir=self.output_dir)
Alex Klein238d8862019-05-07 11:32:46 -0600277
278 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600279 artifacts.BundleAutotestFiles(request, self.response, self.api_config)
Alex Klein238d8862019-05-07 11:32:46 -0600280
281 def testSysrootDoesNotExist(self):
282 """Test dies when no sysroot does not exist."""
Alex Klein68c8fdf2019-09-25 15:09:11 -0600283 request = self.SysrootRequest(chroot=self.chroot_path,
284 sysroot='/does/not/exist',
285 output_dir=self.output_dir)
Alex Klein238d8862019-05-07 11:32:46 -0600286
287 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600288 artifacts.BundleAutotestFiles(request, self.response, self.api_config)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600289
290
291class BundleTastFilesTest(BundleTestCase):
292 """Unittests for BundleTastFiles."""
293
Alex Klein231d2da2019-07-22 16:44:45 -0600294 def testValidateOnly(self):
295 """Sanity check that a validate only call does not execute any logic."""
296 patch = self.PatchObject(artifacts_svc, 'BundleTastFiles')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600297 artifacts.BundleTastFiles(self.target_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600298 self.validate_only_config)
299 patch.assert_not_called()
300
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700301 def testMockCall(self):
302 """Test that a mock call does not execute logic, returns mocked value."""
303 patch = self.PatchObject(artifacts_svc, 'BundleTastFiles')
304 artifacts.BundleTastFiles(self.target_request, self.response,
305 self.mock_call_config)
306 patch.assert_not_called()
307 self.assertEqual(len(self.response.artifacts), 1)
308 self.assertEqual(self.response.artifacts[0].path,
309 os.path.join(self.output_dir, 'tast_bundles.tar.gz'))
310
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600311 def testBundleTastFilesNoLogs(self):
312 """BundleTasteFiles dies when no tast files found."""
313 self.PatchObject(commands, 'BuildTastBundleTarball',
314 return_value=None)
315 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein68c8fdf2019-09-25 15:09:11 -0600316 artifacts.BundleTastFiles(self.target_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600317 self.api_config)
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600318
Alex Kleinb9d810b2019-07-01 12:38:02 -0600319 def testBundleTastFilesLegacy(self):
320 """BundleTastFiles handles legacy args correctly."""
321 buildroot = self.tempdir
322 chroot_dir = os.path.join(buildroot, 'chroot')
323 sysroot_path = os.path.join(chroot_dir, 'build', 'board')
324 output_dir = os.path.join(self.tempdir, 'results')
325 osutils.SafeMakedirs(sysroot_path)
326 osutils.SafeMakedirs(output_dir)
327
Alex Klein171da612019-08-06 14:00:42 -0600328 chroot = chroot_lib.Chroot(chroot_dir)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600329 sysroot = sysroot_lib.Sysroot('/build/board')
330
331 expected_archive = os.path.join(output_dir, artifacts_svc.TAST_BUNDLE_NAME)
332 # Patch the service being called.
333 bundle_patch = self.PatchObject(artifacts_svc, 'BundleTastFiles',
334 return_value=expected_archive)
335 self.PatchObject(constants, 'SOURCE_ROOT', new=buildroot)
336
337 request = artifacts_pb2.BundleRequest(build_target={'name': 'board'},
338 output_dir=output_dir)
Alex Klein68c8fdf2019-09-25 15:09:11 -0600339 artifacts.BundleTastFiles(request, self.response, self.api_config)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600340 self.assertEqual(
Alex Klein68c8fdf2019-09-25 15:09:11 -0600341 [artifact.path for artifact in self.response.artifacts],
Alex Kleinb9d810b2019-07-01 12:38:02 -0600342 [expected_archive])
343 bundle_patch.assert_called_once_with(chroot, sysroot, output_dir)
344
345 def testBundleTastFiles(self):
346 """BundleTastFiles calls service correctly."""
Alex Kleinb49be8a2019-12-20 10:23:03 -0700347 chroot = chroot_lib.Chroot(self.chroot_path)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600348
Alex Klein68c8fdf2019-09-25 15:09:11 -0600349 expected_archive = os.path.join(self.output_dir,
350 artifacts_svc.TAST_BUNDLE_NAME)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600351 # Patch the service being called.
352 bundle_patch = self.PatchObject(artifacts_svc, 'BundleTastFiles',
353 return_value=expected_archive)
354
Alex Klein68c8fdf2019-09-25 15:09:11 -0600355 artifacts.BundleTastFiles(self.sysroot_request, self.response,
356 self.api_config)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600357
358 # Make sure the artifact got recorded successfully.
Alex Klein68c8fdf2019-09-25 15:09:11 -0600359 self.assertTrue(self.response.artifacts)
360 self.assertEqual(expected_archive, self.response.artifacts[0].path)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600361 # Make sure the service got called correctly.
Alex Klein68c8fdf2019-09-25 15:09:11 -0600362 bundle_patch.assert_called_once_with(chroot, self.sysroot, self.output_dir)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600363
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600364
365class BundlePinnedGuestImagesTest(BundleTestCase):
366 """Unittests for BundlePinnedGuestImages."""
367
Alex Klein231d2da2019-07-22 16:44:45 -0600368 def testValidateOnly(self):
369 """Sanity check that a validate only call does not execute any logic."""
370 patch = self.PatchObject(commands, 'BuildPinnedGuestImagesTarball')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600371 artifacts.BundlePinnedGuestImages(self.target_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600372 self.validate_only_config)
373 patch.assert_not_called()
374
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700375 def testMockCall(self):
376 """Test that a mock call does not execute logic, returns mocked value."""
377 patch = self.PatchObject(commands, 'BuildPinnedGuestImagesTarball')
378 artifacts.BundlePinnedGuestImages(self.target_request, self.response,
379 self.mock_call_config)
380 patch.assert_not_called()
381 self.assertEqual(len(self.response.artifacts), 1)
382 self.assertEqual(self.response.artifacts[0].path,
383 os.path.join(self.output_dir,
384 'pinned-guest-images.tar.gz'))
385
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600386 def testBundlePinnedGuestImages(self):
387 """BundlePinnedGuestImages calls cbuildbot/commands with correct args."""
388 build_pinned_guest_images_tarball = self.PatchObject(
389 commands,
390 'BuildPinnedGuestImagesTarball',
391 return_value='pinned-guest-images.tar.gz')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600392 artifacts.BundlePinnedGuestImages(self.target_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600393 self.api_config)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600394 self.assertEqual(
Alex Klein68c8fdf2019-09-25 15:09:11 -0600395 [artifact.path for artifact in self.response.artifacts],
Alex Klein231d2da2019-07-22 16:44:45 -0600396 [os.path.join(self.output_dir, 'pinned-guest-images.tar.gz')])
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600397 self.assertEqual(build_pinned_guest_images_tarball.call_args_list,
Alex Klein231d2da2019-07-22 16:44:45 -0600398 [mock.call(self.source_root, 'target', self.output_dir)])
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600399
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600400 def testBundlePinnedGuestImagesNoLogs(self):
Evan Hernandezde445982019-04-22 13:42:34 -0600401 """BundlePinnedGuestImages does not die when no pinned images found."""
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600402 self.PatchObject(commands, 'BuildPinnedGuestImagesTarball',
403 return_value=None)
Alex Klein68c8fdf2019-09-25 15:09:11 -0600404 artifacts.BundlePinnedGuestImages(self.target_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600405 self.api_config)
Alex Klein68c8fdf2019-09-25 15:09:11 -0600406 self.assertFalse(self.response.artifacts)
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600407
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600408
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700409class FetchPinnedGuestImagesTest(cros_test_lib.MockTempDirTestCase,
410 api_config.ApiConfigMixin, BundleRequestMixin):
411 """Unittests for FetchPinnedGuestImages."""
412
413 def setUp(self):
414 self.build_target = 'board'
415 self.chroot_dir = os.path.join(self.tempdir, 'chroot_dir')
416 self.sysroot_path = '/sysroot'
417 self.sysroot_dir = os.path.join(self.chroot_dir, 'sysroot')
418 osutils.SafeMakedirs(self.sysroot_dir)
419
420 self.input_request = artifacts_pb2.PinnedGuestImageUriRequest(
421 sysroot={'path': self.sysroot_path,
422 'build_target': {'name': self.build_target}},
423 chroot={'path': self.chroot_dir})
424
425 self.response = artifacts_pb2.PinnedGuestImageUriResponse()
426
427 def testValidateOnly(self):
428 """Sanity check that a validate only call does not execute any logic."""
429 patch = self.PatchObject(artifacts_svc, 'FetchPinnedGuestImages')
430 artifacts.FetchPinnedGuestImages(self.input_request, self.response,
431 self.validate_only_config)
432 patch.assert_not_called()
433
434 def testMockCall(self):
435 """Test that a mock call does not execute logic, returns mocked value."""
436 patch = self.PatchObject(artifacts_svc, 'FetchPinnedGuestImages')
437 artifacts.FetchPinnedGuestImages(self.input_request, self.response,
438 self.mock_call_config)
439 patch.assert_not_called()
440 self.assertEqual(len(self.response.pinned_images), 1)
441 self.assertEqual(self.response.pinned_images[0].filename,
442 'pinned_file.tar.gz')
443 self.assertEqual(self.response.pinned_images[0].uri,
444 'https://testuri.com')
445
446 def testFetchPinnedGuestImages(self):
447 """FetchPinnedGuestImages calls service with correct args."""
448 pins = []
449 pins.append(PinnedGuestImage(
450 filename='my_pinned_file.tar.gz', uri='https://the_testuri.com'))
451 self.PatchObject(artifacts_svc, 'FetchPinnedGuestImages',
452 return_value=pins)
453 artifacts.FetchPinnedGuestImages(self.input_request, self.response,
454 self.api_config)
455 self.assertEqual(len(self.response.pinned_images), 1)
456 self.assertEqual(self.response.pinned_images[0].filename,
457 'my_pinned_file.tar.gz')
458 self.assertEqual(self.response.pinned_images[0].uri,
459 'https://the_testuri.com')
460
461
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600462class BundleFirmwareTest(BundleTestCase):
463 """Unittests for BundleFirmware."""
464
Alex Klein231d2da2019-07-22 16:44:45 -0600465 def testValidateOnly(self):
466 """Sanity check that a validate only call does not execute any logic."""
467 patch = self.PatchObject(artifacts_svc, 'BundleTastFiles')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600468 artifacts.BundleFirmware(self.sysroot_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600469 self.validate_only_config)
470 patch.assert_not_called()
Michael Mortensen38675192019-06-28 16:52:55 +0000471
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700472 def testMockCall(self):
473 """Test that a mock call does not execute logic, returns mocked value."""
474 patch = self.PatchObject(artifacts_svc, 'BundleTastFiles')
475 artifacts.BundleFirmware(self.sysroot_request, self.response,
476 self.mock_call_config)
477 patch.assert_not_called()
478 self.assertEqual(len(self.response.artifacts), 1)
479 self.assertEqual(self.response.artifacts[0].path,
480 os.path.join(self.output_dir, 'firmware.tar.gz'))
481
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600482 def testBundleFirmware(self):
483 """BundleFirmware calls cbuildbot/commands with correct args."""
Alex Klein231d2da2019-07-22 16:44:45 -0600484 self.PatchObject(
485 artifacts_svc,
486 'BuildFirmwareArchive',
487 return_value=os.path.join(self.output_dir, 'firmware.tar.gz'))
488
Alex Klein68c8fdf2019-09-25 15:09:11 -0600489 artifacts.BundleFirmware(self.sysroot_request, self.response,
490 self.api_config)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600491 self.assertEqual(
Alex Klein231d2da2019-07-22 16:44:45 -0600492 [artifact.path for artifact in self.response.artifacts],
493 [os.path.join(self.output_dir, 'firmware.tar.gz')])
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600494
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600495 def testBundleFirmwareNoLogs(self):
496 """BundleFirmware dies when no firmware found."""
497 self.PatchObject(commands, 'BuildFirmwareArchive', return_value=None)
498 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein68c8fdf2019-09-25 15:09:11 -0600499 artifacts.BundleFirmware(self.sysroot_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600500 self.api_config)
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600501
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600502
503class BundleEbuildLogsTest(BundleTestCase):
504 """Unittests for BundleEbuildLogs."""
505
Alex Klein231d2da2019-07-22 16:44:45 -0600506 def testValidateOnly(self):
507 """Sanity check that a validate only call does not execute any logic."""
508 patch = self.PatchObject(commands, 'BuildEbuildLogsTarball')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600509 artifacts.BundleEbuildLogs(self.target_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600510 self.validate_only_config)
511 patch.assert_not_called()
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600512
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700513 def testMockCall(self):
514 """Test that a mock call does not execute logic, returns mocked value."""
515 patch = self.PatchObject(commands, 'BuildEbuildLogsTarball')
516 artifacts.BundleEbuildLogs(self.target_request, self.response,
517 self.mock_call_config)
518 patch.assert_not_called()
519 self.assertEqual(len(self.response.artifacts), 1)
520 self.assertEqual(self.response.artifacts[0].path,
521 os.path.join(self.output_dir, 'ebuild-logs.tar.gz'))
522
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600523 def testBundleEbuildLogs(self):
524 """BundleEbuildLogs calls cbuildbot/commands with correct args."""
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600525 bundle_ebuild_logs_tarball = self.PatchObject(
526 artifacts_svc, 'BundleEBuildLogsTarball',
527 return_value='ebuild-logs.tar.gz')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600528 artifacts.BundleEbuildLogs(self.sysroot_request, self.response,
529 self.api_config)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600530 self.assertEqual(
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600531 [artifact.path for artifact in self.response.artifacts],
Alex Klein68c8fdf2019-09-25 15:09:11 -0600532 [os.path.join(self.output_dir, 'ebuild-logs.tar.gz')])
Evan Hernandeza478d802019-04-08 15:08:24 -0600533 self.assertEqual(
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600534 bundle_ebuild_logs_tarball.call_args_list,
Alex Klein68c8fdf2019-09-25 15:09:11 -0600535 [mock.call(mock.ANY, self.sysroot, self.output_dir)])
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600536
537 def testBundleEBuildLogsOldProto(self):
538 bundle_ebuild_logs_tarball = self.PatchObject(
539 artifacts_svc, 'BundleEBuildLogsTarball',
540 return_value='ebuild-logs.tar.gz')
Alex Klein231d2da2019-07-22 16:44:45 -0600541
Alex Klein68c8fdf2019-09-25 15:09:11 -0600542 artifacts.BundleEbuildLogs(self.target_request, self.response,
Alex Klein231d2da2019-07-22 16:44:45 -0600543 self.api_config)
544
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600545 self.assertEqual(
546 bundle_ebuild_logs_tarball.call_args_list,
Alex Klein68c8fdf2019-09-25 15:09:11 -0600547 [mock.call(mock.ANY, self.sysroot, self.output_dir)])
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600548
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600549 def testBundleEbuildLogsNoLogs(self):
550 """BundleEbuildLogs dies when no logs found."""
551 self.PatchObject(commands, 'BuildEbuildLogsTarball', return_value=None)
552 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein68c8fdf2019-09-25 15:09:11 -0600553 artifacts.BundleEbuildLogs(self.sysroot_request, self.response,
554 self.api_config)
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600555
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600556
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600557class BundleChromeOSConfigTest(BundleTestCase):
558 """Unittests for BundleChromeOSConfig"""
559
560 def testValidateOnly(self):
561 """Sanity check that a validate only call does not execute any logic."""
562 patch = self.PatchObject(artifacts_svc, 'BundleChromeOSConfig')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600563 artifacts.BundleChromeOSConfig(self.target_request, self.response,
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600564 self.validate_only_config)
565 patch.assert_not_called()
566
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700567 def testMockCall(self):
568 """Test that a mock call does not execute logic, returns mocked value."""
569 patch = self.PatchObject(artifacts_svc, 'BundleChromeOSConfig')
570 artifacts.BundleChromeOSConfig(self.target_request, self.response,
571 self.mock_call_config)
572 patch.assert_not_called()
573 self.assertEqual(len(self.response.artifacts), 1)
574 self.assertEqual(self.response.artifacts[0].path,
575 os.path.join(self.output_dir, 'config.yaml'))
576
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600577 def testBundleChromeOSConfigCallWithSysroot(self):
578 """Call with a request that sets sysroot."""
579 bundle_chromeos_config = self.PatchObject(
580 artifacts_svc, 'BundleChromeOSConfig', return_value='config.yaml')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600581 artifacts.BundleChromeOSConfig(self.sysroot_request, self.response,
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600582 self.api_config)
583 self.assertEqual(
Alex Klein68c8fdf2019-09-25 15:09:11 -0600584 [artifact.path for artifact in self.response.artifacts],
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600585 [os.path.join(self.output_dir, 'config.yaml')])
586
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600587 self.assertEqual(bundle_chromeos_config.call_args_list,
Alex Klein68c8fdf2019-09-25 15:09:11 -0600588 [mock.call(mock.ANY, self.sysroot, self.output_dir)])
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600589
590 def testBundleChromeOSConfigCallWithBuildTarget(self):
591 """Call with a request that sets build_target."""
592 bundle_chromeos_config = self.PatchObject(
593 artifacts_svc, 'BundleChromeOSConfig', return_value='config.yaml')
Alex Klein68c8fdf2019-09-25 15:09:11 -0600594 artifacts.BundleChromeOSConfig(self.target_request, self.response,
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600595 self.api_config)
596
597 self.assertEqual(
Alex Klein68c8fdf2019-09-25 15:09:11 -0600598 [artifact.path for artifact in self.response.artifacts],
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600599 [os.path.join(self.output_dir, 'config.yaml')])
600
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600601 self.assertEqual(bundle_chromeos_config.call_args_list,
Alex Klein68c8fdf2019-09-25 15:09:11 -0600602 [mock.call(mock.ANY, self.sysroot, self.output_dir)])
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600603
604 def testBundleChromeOSConfigNoConfigFound(self):
605 """An error is raised if the config payload isn't found."""
606 self.PatchObject(artifacts_svc, 'BundleChromeOSConfig', return_value=None)
607
608 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein68c8fdf2019-09-25 15:09:11 -0600609 artifacts.BundleChromeOSConfig(self.sysroot_request, self.response,
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600610 self.api_config)
611
612
Alex Klein231d2da2019-07-22 16:44:45 -0600613class BundleTestUpdatePayloadsTest(cros_test_lib.MockTempDirTestCase,
614 api_config.ApiConfigMixin):
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600615 """Unittests for BundleTestUpdatePayloads."""
616
617 def setUp(self):
618 self.source_root = os.path.join(self.tempdir, 'cros')
619 osutils.SafeMakedirs(self.source_root)
620
621 self.archive_root = os.path.join(self.tempdir, 'output')
622 osutils.SafeMakedirs(self.archive_root)
623
624 self.target = 'target'
Evan Hernandez59690b72019-04-08 16:24:45 -0600625 self.image_root = os.path.join(self.source_root,
626 'src/build/images/target/latest')
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600627
628 self.input_proto = artifacts_pb2.BundleRequest()
629 self.input_proto.build_target.name = self.target
630 self.input_proto.output_dir = self.archive_root
631 self.output_proto = artifacts_pb2.BundleResponse()
632
633 self.PatchObject(constants, 'SOURCE_ROOT', new=self.source_root)
634
Alex Kleincb541e82019-06-26 15:06:11 -0600635 def MockPayloads(image_path, archive_dir):
636 osutils.WriteFile(os.path.join(archive_dir, 'payload1.bin'), image_path)
637 osutils.WriteFile(os.path.join(archive_dir, 'payload2.bin'), image_path)
638 return [os.path.join(archive_dir, 'payload1.bin'),
639 os.path.join(archive_dir, 'payload2.bin')]
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600640
Alex Kleincb541e82019-06-26 15:06:11 -0600641 self.bundle_patch = self.PatchObject(
642 artifacts_svc, 'BundleTestUpdatePayloads', side_effect=MockPayloads)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600643
Alex Klein231d2da2019-07-22 16:44:45 -0600644 def testValidateOnly(self):
645 """Sanity check that a validate only call does not execute any logic."""
646 patch = self.PatchObject(artifacts_svc, 'BundleTestUpdatePayloads')
647 artifacts.BundleTestUpdatePayloads(self.input_proto, self.output_proto,
648 self.validate_only_config)
649 patch.assert_not_called()
650
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700651 def testMockCall(self):
652 """Test that a mock call does not execute logic, returns mocked value."""
653 patch = self.PatchObject(artifacts_svc, 'BundleTestUpdatePayloads')
654 artifacts.BundleTestUpdatePayloads(self.input_proto, self.output_proto,
655 self.mock_call_config)
656 patch.assert_not_called()
657 self.assertEqual(len(self.output_proto.artifacts), 1)
658 self.assertEqual(self.output_proto.artifacts[0].path,
659 os.path.join(self.archive_root, 'payload1.bin'))
660
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600661 def testBundleTestUpdatePayloads(self):
662 """BundleTestUpdatePayloads calls cbuildbot/commands with correct args."""
663 image_path = os.path.join(self.image_root, constants.BASE_IMAGE_BIN)
664 osutils.WriteFile(image_path, 'image!', makedirs=True)
665
Alex Klein231d2da2019-07-22 16:44:45 -0600666 artifacts.BundleTestUpdatePayloads(self.input_proto, self.output_proto,
667 self.api_config)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600668
669 actual = [
670 os.path.relpath(artifact.path, self.archive_root)
671 for artifact in self.output_proto.artifacts
672 ]
Alex Kleincb541e82019-06-26 15:06:11 -0600673 expected = ['payload1.bin', 'payload2.bin']
Mike Frysinger678735c2019-09-28 18:23:28 -0400674 self.assertCountEqual(actual, expected)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600675
676 actual = [
677 os.path.relpath(path, self.archive_root)
678 for path in osutils.DirectoryIterator(self.archive_root)
679 ]
Mike Frysinger678735c2019-09-28 18:23:28 -0400680 self.assertCountEqual(actual, expected)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600681
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600682 def testBundleTestUpdatePayloadsNoImageDir(self):
683 """BundleTestUpdatePayloads dies if no image dir is found."""
684 # Intentionally do not write image directory.
Alex Kleind2bf1462019-10-24 16:37:04 -0600685 artifacts.BundleTestUpdatePayloads(self.input_proto, self.output_proto,
686 self.api_config)
687 self.assertFalse(self.output_proto.artifacts)
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600688
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600689 def testBundleTestUpdatePayloadsNoImage(self):
690 """BundleTestUpdatePayloads dies if no usable image is found for target."""
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600691 # Intentionally do not write image, but create the directory.
692 osutils.SafeMakedirs(self.image_root)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600693 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600694 artifacts.BundleTestUpdatePayloads(self.input_proto, self.output_proto,
695 self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600696
697
Alex Klein231d2da2019-07-22 16:44:45 -0600698class BundleSimpleChromeArtifactsTest(cros_test_lib.MockTempDirTestCase,
699 api_config.ApiConfigMixin):
Alex Klein2275d692019-04-23 16:04:12 -0600700 """BundleSimpleChromeArtifacts tests."""
701
702 def setUp(self):
703 self.chroot_dir = os.path.join(self.tempdir, 'chroot_dir')
704 self.sysroot_path = '/sysroot'
705 self.sysroot_dir = os.path.join(self.chroot_dir, 'sysroot')
706 osutils.SafeMakedirs(self.sysroot_dir)
707 self.output_dir = os.path.join(self.tempdir, 'output_dir')
708 osutils.SafeMakedirs(self.output_dir)
709
710 self.does_not_exist = os.path.join(self.tempdir, 'does_not_exist')
711
Alex Klein231d2da2019-07-22 16:44:45 -0600712 self.response = artifacts_pb2.BundleResponse()
713
Alex Klein2275d692019-04-23 16:04:12 -0600714 def _GetRequest(self, chroot=None, sysroot=None, build_target=None,
715 output_dir=None):
716 """Helper to create a request message instance.
717
718 Args:
719 chroot (str): The chroot path.
720 sysroot (str): The sysroot path.
721 build_target (str): The build target name.
722 output_dir (str): The output directory.
723 """
724 return artifacts_pb2.BundleRequest(
725 sysroot={'path': sysroot, 'build_target': {'name': build_target}},
726 chroot={'path': chroot}, output_dir=output_dir)
727
Alex Klein231d2da2019-07-22 16:44:45 -0600728 def testValidateOnly(self):
729 """Sanity check that a validate only call does not execute any logic."""
730 patch = self.PatchObject(artifacts_svc, 'BundleSimpleChromeArtifacts')
731 request = self._GetRequest(chroot=self.chroot_dir,
732 sysroot=self.sysroot_path,
733 build_target='board', output_dir=self.output_dir)
734 artifacts.BundleSimpleChromeArtifacts(request, self.response,
735 self.validate_only_config)
736 patch.assert_not_called()
Alex Klein2275d692019-04-23 16:04:12 -0600737
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700738 def testMockCall(self):
739 """Test that a mock call does not execute logic, returns mocked value."""
740 patch = self.PatchObject(artifacts_svc, 'BundleSimpleChromeArtifacts')
741 request = self._GetRequest(chroot=self.chroot_dir,
742 sysroot=self.sysroot_path,
743 build_target='board', output_dir=self.output_dir)
744 artifacts.BundleSimpleChromeArtifacts(request, self.response,
745 self.mock_call_config)
746 patch.assert_not_called()
747 self.assertEqual(len(self.response.artifacts), 1)
748 self.assertEqual(self.response.artifacts[0].path,
749 os.path.join(self.output_dir, 'simple_chrome.txt'))
750
Alex Klein2275d692019-04-23 16:04:12 -0600751 def testNoBuildTarget(self):
752 """Test no build target fails."""
753 request = self._GetRequest(chroot=self.chroot_dir,
754 sysroot=self.sysroot_path,
755 output_dir=self.output_dir)
Alex Klein231d2da2019-07-22 16:44:45 -0600756 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600757 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600758 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600759
760 def testNoSysroot(self):
761 """Test no sysroot fails."""
762 request = self._GetRequest(build_target='board', output_dir=self.output_dir)
Alex Klein231d2da2019-07-22 16:44:45 -0600763 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600764 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600765 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600766
767 def testSysrootDoesNotExist(self):
768 """Test no sysroot fails."""
769 request = self._GetRequest(build_target='board', output_dir=self.output_dir,
770 sysroot=self.does_not_exist)
Alex Klein231d2da2019-07-22 16:44:45 -0600771 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600772 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600773 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600774
775 def testNoOutputDir(self):
776 """Test no output dir fails."""
777 request = self._GetRequest(chroot=self.chroot_dir,
778 sysroot=self.sysroot_path,
779 build_target='board')
Alex Klein231d2da2019-07-22 16:44:45 -0600780 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600781 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600782 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600783
784 def testOutputDirDoesNotExist(self):
785 """Test no output dir fails."""
786 request = self._GetRequest(chroot=self.chroot_dir,
787 sysroot=self.sysroot_path,
788 build_target='board',
789 output_dir=self.does_not_exist)
Alex Klein231d2da2019-07-22 16:44:45 -0600790 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600791 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600792 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600793
794 def testOutputHandling(self):
795 """Test response output."""
796 files = ['file1', 'file2', 'file3']
797 expected_files = [os.path.join(self.output_dir, f) for f in files]
798 self.PatchObject(artifacts_svc, 'BundleSimpleChromeArtifacts',
799 return_value=expected_files)
800 request = self._GetRequest(chroot=self.chroot_dir,
801 sysroot=self.sysroot_path,
802 build_target='board', output_dir=self.output_dir)
Alex Klein231d2da2019-07-22 16:44:45 -0600803 response = self.response
Alex Klein2275d692019-04-23 16:04:12 -0600804
Alex Klein231d2da2019-07-22 16:44:45 -0600805 artifacts.BundleSimpleChromeArtifacts(request, response, self.api_config)
Alex Klein2275d692019-04-23 16:04:12 -0600806
807 self.assertTrue(response.artifacts)
Mike Frysinger678735c2019-09-28 18:23:28 -0400808 self.assertCountEqual(expected_files, [a.path for a in response.artifacts])
Alex Klein2275d692019-04-23 16:04:12 -0600809
810
Alex Klein231d2da2019-07-22 16:44:45 -0600811class BundleVmFilesTest(cros_test_lib.MockTempDirTestCase,
812 api_config.ApiConfigMixin):
Alex Klein6504eca2019-04-18 15:37:56 -0600813 """BuildVmFiles tests."""
814
Alex Klein231d2da2019-07-22 16:44:45 -0600815 def setUp(self):
816 self.output_dir = os.path.join(self.tempdir, 'output')
817 osutils.SafeMakedirs(self.output_dir)
818
819 self.response = artifacts_pb2.BundleResponse()
820
Alex Klein6504eca2019-04-18 15:37:56 -0600821 def _GetInput(self, chroot=None, sysroot=None, test_results_dir=None,
822 output_dir=None):
823 """Helper to build out an input message instance.
824
825 Args:
826 chroot (str|None): The chroot path.
827 sysroot (str|None): The sysroot path relative to the chroot.
828 test_results_dir (str|None): The test results directory relative to the
829 sysroot.
830 output_dir (str|None): The directory where the results tarball should be
831 saved.
832 """
833 return artifacts_pb2.BundleVmFilesRequest(
834 chroot={'path': chroot}, sysroot={'path': sysroot},
835 test_results_dir=test_results_dir, output_dir=output_dir,
836 )
837
Alex Klein231d2da2019-07-22 16:44:45 -0600838 def testValidateOnly(self):
839 """Sanity check that a validate only call does not execute any logic."""
840 patch = self.PatchObject(artifacts_svc, 'BundleVmFiles')
841 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
842 test_results_dir='/test/results',
843 output_dir=self.output_dir)
844 artifacts.BundleVmFiles(in_proto, self.response, self.validate_only_config)
845 patch.assert_not_called()
Alex Klein6504eca2019-04-18 15:37:56 -0600846
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700847 def testMockCall(self):
848 """Test that a mock call does not execute logic, returns mocked value."""
849 patch = self.PatchObject(artifacts_svc, 'BundleVmFiles')
850 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
851 test_results_dir='/test/results',
852 output_dir=self.output_dir)
853 artifacts.BundleVmFiles(in_proto, self.response, self.mock_call_config)
854 patch.assert_not_called()
855 self.assertEqual(len(self.response.artifacts), 1)
856 self.assertEqual(self.response.artifacts[0].path,
857 os.path.join(self.output_dir, 'f1.tar'))
858
Alex Klein6504eca2019-04-18 15:37:56 -0600859 def testChrootMissing(self):
860 """Test error handling for missing chroot."""
861 in_proto = self._GetInput(sysroot='/build/board',
862 test_results_dir='/test/results',
Alex Klein231d2da2019-07-22 16:44:45 -0600863 output_dir=self.output_dir)
Alex Klein6504eca2019-04-18 15:37:56 -0600864
865 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600866 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600867
Alex Klein6504eca2019-04-18 15:37:56 -0600868 def testTestResultsDirMissing(self):
869 """Test error handling for missing test results directory."""
870 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
Alex Klein231d2da2019-07-22 16:44:45 -0600871 output_dir=self.output_dir)
Alex Klein6504eca2019-04-18 15:37:56 -0600872
873 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600874 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600875
876 def testOutputDirMissing(self):
877 """Test error handling for missing output directory."""
878 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
879 test_results_dir='/test/results')
Alex Klein6504eca2019-04-18 15:37:56 -0600880
881 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600882 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
883
884 def testOutputDirDoesNotExist(self):
885 """Test error handling for output directory that does not exist."""
886 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
887 output_dir=os.path.join(self.tempdir, 'dne'),
888 test_results_dir='/test/results')
889
890 with self.assertRaises(cros_build_lib.DieSystemExit):
891 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600892
893 def testValidCall(self):
894 """Test image dir building."""
895 in_proto = self._GetInput(chroot='/chroot/dir', sysroot='/build/board',
896 test_results_dir='/test/results',
Alex Klein231d2da2019-07-22 16:44:45 -0600897 output_dir=self.output_dir)
898
Alex Klein6504eca2019-04-18 15:37:56 -0600899 expected_files = ['/tmp/output/f1.tar', '/tmp/output/f2.tar']
Michael Mortensen51f06722019-07-18 09:55:50 -0600900 patch = self.PatchObject(artifacts_svc, 'BundleVmFiles',
Alex Klein6504eca2019-04-18 15:37:56 -0600901 return_value=expected_files)
902
Alex Klein231d2da2019-07-22 16:44:45 -0600903 artifacts.BundleVmFiles(in_proto, self.response, self.api_config)
Alex Klein6504eca2019-04-18 15:37:56 -0600904
Alex Klein231d2da2019-07-22 16:44:45 -0600905 patch.assert_called_with(mock.ANY, '/test/results', self.output_dir)
Alex Klein6504eca2019-04-18 15:37:56 -0600906
907 # Make sure we have artifacts, and that every artifact is an expected file.
Alex Klein231d2da2019-07-22 16:44:45 -0600908 self.assertTrue(self.response.artifacts)
909 for artifact in self.response.artifacts:
Alex Klein6504eca2019-04-18 15:37:56 -0600910 self.assertIn(artifact.path, expected_files)
911 expected_files.remove(artifact.path)
912
913 # Make sure we've seen all of the expected files.
914 self.assertFalse(expected_files)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700915
Alex Kleinb9d810b2019-07-01 12:38:02 -0600916
Tiancong Wang50b80a92019-08-01 14:46:15 -0700917
918class BundleAFDOGenerationArtifactsTestCase(
Alex Klein231d2da2019-07-22 16:44:45 -0600919 cros_test_lib.MockTempDirTestCase, api_config.ApiConfigMixin):
Tiancong Wang50b80a92019-08-01 14:46:15 -0700920 """Unittests for BundleAFDOGenerationArtifacts."""
921
922 @staticmethod
923 def mock_die(message, *args):
924 raise cros_build_lib.DieSystemExit(message % args)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700925
926 def setUp(self):
927 self.chroot_dir = os.path.join(self.tempdir, 'chroot_dir')
928 osutils.SafeMakedirs(self.chroot_dir)
929 temp_dir = os.path.join(self.chroot_dir, 'tmp')
930 osutils.SafeMakedirs(temp_dir)
931 self.output_dir = os.path.join(self.tempdir, 'output_dir')
932 osutils.SafeMakedirs(self.output_dir)
Tiancong Wang2ade7932019-09-27 14:15:40 -0700933 self.chrome_root = os.path.join(self.tempdir, 'chrome_root')
934 osutils.SafeMakedirs(self.chrome_root)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700935 self.build_target = 'board'
Tiancong Wang24a3df72019-08-20 15:48:51 -0700936 self.valid_artifact_type = toolchain_pb2.ORDERFILE
937 self.invalid_artifact_type = toolchain_pb2.NONE_TYPE
Tiancong Wangc4805b72019-06-11 12:12:03 -0700938 self.does_not_exist = os.path.join(self.tempdir, 'does_not_exist')
Tiancong Wang50b80a92019-08-01 14:46:15 -0700939 self.PatchObject(cros_build_lib, 'Die', new=self.mock_die)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700940
Alex Klein231d2da2019-07-22 16:44:45 -0600941 self.response = artifacts_pb2.BundleResponse()
942
Tiancong Wang2ade7932019-09-27 14:15:40 -0700943 def _GetRequest(self, chroot=None, build_target=None, chrome_root=None,
944 output_dir=None, artifact_type=None):
Tiancong Wangc4805b72019-06-11 12:12:03 -0700945 """Helper to create a request message instance.
946
947 Args:
948 chroot (str): The chroot path.
949 build_target (str): The build target name.
Tiancong Wang2ade7932019-09-27 14:15:40 -0700950 chrome_root (str): The path to Chrome root.
Tiancong Wangc4805b72019-06-11 12:12:03 -0700951 output_dir (str): The output directory.
Tiancong Wang50b80a92019-08-01 14:46:15 -0700952 artifact_type (artifacts_pb2.AFDOArtifactType):
953 The type of the artifact.
Tiancong Wangc4805b72019-06-11 12:12:03 -0700954 """
Tiancong Wang50b80a92019-08-01 14:46:15 -0700955 return artifacts_pb2.BundleChromeAFDORequest(
Tiancong Wang2ade7932019-09-27 14:15:40 -0700956 chroot={'path': chroot, 'chrome_dir': chrome_root},
Tiancong Wang50b80a92019-08-01 14:46:15 -0700957 build_target={'name': build_target},
958 output_dir=output_dir,
959 artifact_type=artifact_type,
Tiancong Wangc4805b72019-06-11 12:12:03 -0700960 )
961
Alex Klein231d2da2019-07-22 16:44:45 -0600962 def testValidateOnly(self):
963 """Sanity check that a validate only call does not execute any logic."""
964 patch = self.PatchObject(artifacts_svc,
Tiancong Wang50b80a92019-08-01 14:46:15 -0700965 'BundleAFDOGenerationArtifacts')
Alex Klein231d2da2019-07-22 16:44:45 -0600966 request = self._GetRequest(chroot=self.chroot_dir,
967 build_target=self.build_target,
Tiancong Wang2ade7932019-09-27 14:15:40 -0700968 chrome_root=self.chrome_root,
Tiancong Wang50b80a92019-08-01 14:46:15 -0700969 output_dir=self.output_dir,
970 artifact_type=self.valid_artifact_type)
971 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
972 self.validate_only_config)
Alex Klein231d2da2019-07-22 16:44:45 -0600973 patch.assert_not_called()
Tiancong Wangc4805b72019-06-11 12:12:03 -0700974
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700975 def testMockCall(self):
976 """Test that a mock call does not execute logic, returns mocked value."""
977 patch = self.PatchObject(artifacts_svc,
978 'BundleAFDOGenerationArtifacts')
979 request = self._GetRequest(chroot=self.chroot_dir,
980 build_target=self.build_target,
981 chrome_root=self.chrome_root,
982 output_dir=self.output_dir,
983 artifact_type=self.valid_artifact_type)
984 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
985 self.mock_call_config)
986 patch.assert_not_called()
987 self.assertEqual(len(self.response.artifacts), 1)
988 self.assertEqual(self.response.artifacts[0].path,
989 os.path.join(self.output_dir, 'artifact1'))
990
Tiancong Wangc4805b72019-06-11 12:12:03 -0700991 def testNoBuildTarget(self):
992 """Test no build target fails."""
993 request = self._GetRequest(chroot=self.chroot_dir,
Tiancong Wang2ade7932019-09-27 14:15:40 -0700994 chrome_root=self.chrome_root,
Tiancong Wang50b80a92019-08-01 14:46:15 -0700995 output_dir=self.output_dir,
996 artifact_type=self.valid_artifact_type)
997 with self.assertRaises(cros_build_lib.DieSystemExit) as context:
998 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
999 self.api_config)
1000 self.assertEqual('build_target.name is required.',
1001 str(context.exception))
Tiancong Wangc4805b72019-06-11 12:12:03 -07001002
Tiancong Wang2ade7932019-09-27 14:15:40 -07001003 def testNoChromeRoot(self):
1004 """Test no chrome root fails."""
1005 request = self._GetRequest(chroot=self.chroot_dir,
1006 build_target=self.build_target,
1007 output_dir=self.output_dir,
1008 artifact_type=self.valid_artifact_type)
1009 with self.assertRaises(cros_build_lib.DieSystemExit) as context:
1010 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
1011 self.api_config)
1012 self.assertEqual('chroot.chrome_dir path does not exist: ',
1013 str(context.exception))
1014
Tiancong Wangc4805b72019-06-11 12:12:03 -07001015 def testNoOutputDir(self):
1016 """Test no output dir fails."""
1017 request = self._GetRequest(chroot=self.chroot_dir,
Tiancong Wang50b80a92019-08-01 14:46:15 -07001018 build_target=self.build_target,
Tiancong Wang2ade7932019-09-27 14:15:40 -07001019 chrome_root=self.chrome_root,
Tiancong Wang50b80a92019-08-01 14:46:15 -07001020 artifact_type=self.valid_artifact_type)
1021 with self.assertRaises(cros_build_lib.DieSystemExit) as context:
1022 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
1023 self.api_config)
1024 self.assertEqual('output_dir is required.',
1025 str(context.exception))
Tiancong Wangc4805b72019-06-11 12:12:03 -07001026
1027 def testOutputDirDoesNotExist(self):
1028 """Test output directory not existing fails."""
1029 request = self._GetRequest(chroot=self.chroot_dir,
Tiancong Wangc4805b72019-06-11 12:12:03 -07001030 build_target=self.build_target,
Tiancong Wang2ade7932019-09-27 14:15:40 -07001031 chrome_root=self.chrome_root,
Tiancong Wang50b80a92019-08-01 14:46:15 -07001032 output_dir=self.does_not_exist,
1033 artifact_type=self.valid_artifact_type)
1034 with self.assertRaises(cros_build_lib.DieSystemExit) as context:
1035 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
1036 self.api_config)
1037 self.assertEqual(
1038 'output_dir path does not exist: %s' % self.does_not_exist,
1039 str(context.exception))
Tiancong Wangc4805b72019-06-11 12:12:03 -07001040
Tiancong Wang50b80a92019-08-01 14:46:15 -07001041 def testNoArtifactType(self):
1042 """Test no artifact type."""
1043 request = self._GetRequest(chroot=self.chroot_dir,
1044 build_target=self.build_target,
Tiancong Wang2ade7932019-09-27 14:15:40 -07001045 chrome_root=self.chrome_root,
Tiancong Wang50b80a92019-08-01 14:46:15 -07001046 output_dir=self.output_dir)
1047 with self.assertRaises(cros_build_lib.DieSystemExit) as context:
1048 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
1049 self.api_config)
1050 self.assertIn('artifact_type (0) must be in',
1051 str(context.exception))
1052
1053 def testWrongArtifactType(self):
1054 """Test passing wrong artifact type."""
1055 request = self._GetRequest(chroot=self.chroot_dir,
1056 build_target=self.build_target,
Tiancong Wang2ade7932019-09-27 14:15:40 -07001057 chrome_root=self.chrome_root,
Tiancong Wang50b80a92019-08-01 14:46:15 -07001058 output_dir=self.output_dir,
1059 artifact_type=self.invalid_artifact_type)
1060 with self.assertRaises(cros_build_lib.DieSystemExit) as context:
1061 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
1062 self.api_config)
Tiancong Wang24a3df72019-08-20 15:48:51 -07001063 self.assertIn('artifact_type (%d) must be in' % self.invalid_artifact_type,
Tiancong Wang50b80a92019-08-01 14:46:15 -07001064 str(context.exception))
1065
1066 def testOutputHandlingOnOrderfile(self,
Tiancong Wang24a3df72019-08-20 15:48:51 -07001067 artifact_type=toolchain_pb2.ORDERFILE):
Tiancong Wang50b80a92019-08-01 14:46:15 -07001068 """Test response output for orderfile."""
1069 files = ['artifact1', 'artifact2', 'artifact3']
Tiancong Wangc4805b72019-06-11 12:12:03 -07001070 expected_files = [os.path.join(self.output_dir, f) for f in files]
Tiancong Wang50b80a92019-08-01 14:46:15 -07001071 self.PatchObject(artifacts_svc, 'BundleAFDOGenerationArtifacts',
Tiancong Wangc4805b72019-06-11 12:12:03 -07001072 return_value=expected_files)
Alex Klein231d2da2019-07-22 16:44:45 -06001073
Tiancong Wangc4805b72019-06-11 12:12:03 -07001074 request = self._GetRequest(chroot=self.chroot_dir,
Tiancong Wangc4805b72019-06-11 12:12:03 -07001075 build_target=self.build_target,
Tiancong Wang2ade7932019-09-27 14:15:40 -07001076 chrome_root=self.chrome_root,
Tiancong Wang50b80a92019-08-01 14:46:15 -07001077 output_dir=self.output_dir,
1078 artifact_type=artifact_type)
Tiancong Wangc4805b72019-06-11 12:12:03 -07001079
Tiancong Wang50b80a92019-08-01 14:46:15 -07001080 artifacts.BundleAFDOGenerationArtifacts(request, self.response,
1081 self.api_config)
Tiancong Wangc4805b72019-06-11 12:12:03 -07001082
Tiancong Wang50b80a92019-08-01 14:46:15 -07001083 self.assertTrue(self.response.artifacts)
Mike Frysinger678735c2019-09-28 18:23:28 -04001084 self.assertCountEqual(expected_files,
Tiancong Wang50b80a92019-08-01 14:46:15 -07001085 [a.path for a in self.response.artifacts])
1086
1087 def testOutputHandlingOnAFDO(self):
1088 """Test response output for AFDO."""
1089 self.testOutputHandlingOnOrderfile(
Tiancong Wang24a3df72019-08-20 15:48:51 -07001090 artifact_type=toolchain_pb2.BENCHMARK_AFDO)
Alex Klein0b1cbfc2019-08-14 10:09:58 -06001091
1092
1093class ExportCpeReportTest(cros_test_lib.MockTempDirTestCase,
1094 api_config.ApiConfigMixin):
1095 """ExportCpeReport tests."""
1096
1097 def setUp(self):
1098 self.response = artifacts_pb2.BundleResponse()
1099
1100 def testValidateOnly(self):
1101 """Sanity check validate only calls don't execute."""
1102 patch = self.PatchObject(artifacts_svc, 'GenerateCpeReport')
1103
1104 request = artifacts_pb2.BundleRequest()
1105 request.build_target.name = 'board'
1106 request.output_dir = self.tempdir
1107
1108 artifacts.ExportCpeReport(request, self.response, self.validate_only_config)
1109
1110 patch.assert_not_called()
1111
Michael Mortensen2d6a2402019-11-26 13:40:40 -07001112 def testMockCall(self):
1113 """Test that a mock call does not execute logic, returns mocked value."""
1114 patch = self.PatchObject(artifacts_svc, 'GenerateCpeReport')
1115
1116 request = artifacts_pb2.BundleRequest()
1117 request.build_target.name = 'board'
1118 request.output_dir = self.tempdir
1119
1120 artifacts.ExportCpeReport(request, self.response, self.mock_call_config)
1121
1122 patch.assert_not_called()
1123 self.assertEqual(len(self.response.artifacts), 2)
1124 self.assertEqual(self.response.artifacts[0].path,
1125 os.path.join(self.tempdir, 'cpe_report.txt'))
1126 self.assertEqual(self.response.artifacts[1].path,
1127 os.path.join(self.tempdir, 'cpe_warnings.txt'))
1128
Alex Klein0b1cbfc2019-08-14 10:09:58 -06001129 def testNoBuildTarget(self):
1130 request = artifacts_pb2.BundleRequest()
1131 request.output_dir = self.tempdir
1132
1133 with self.assertRaises(cros_build_lib.DieSystemExit):
1134 artifacts.ExportCpeReport(request, self.response, self.api_config)
1135
1136 def testSuccess(self):
1137 """Test success case."""
1138 expected = artifacts_svc.CpeResult(
1139 report='/output/report.json', warnings='/output/warnings.json')
1140 self.PatchObject(artifacts_svc, 'GenerateCpeReport', return_value=expected)
1141
1142 request = artifacts_pb2.BundleRequest()
1143 request.build_target.name = 'board'
1144 request.output_dir = self.tempdir
1145
1146 artifacts.ExportCpeReport(request, self.response, self.api_config)
1147
1148 for artifact in self.response.artifacts:
1149 self.assertIn(artifact.path, [expected.report, expected.warnings])