blob: d6487ca95af0973f651fe6497425dfb8edbb303a [file] [log] [blame]
Alex Kleina2e42c42019-04-17 16:13:19 -06001# Copyright 2019 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""The test controller tests."""
6
Alex Klein9f915782020-02-14 23:15:09 +00007import contextlib
Mike Frysingeref94e4c2020-02-10 23:59:54 -05008import os
Mike Frysinger166fea02021-02-12 05:30:33 -05009from unittest import mock
Mike Frysingeref94e4c2020-02-10 23:59:54 -050010
Alex Klein231d2da2019-07-22 16:44:45 -060011from chromite.api import api_config
Alex Klein8cb365a2019-05-15 16:24:53 -060012from chromite.api import controller
Alex Kleina2e42c42019-04-17 16:13:19 -060013from chromite.api.controller import test as test_controller
Evan Hernandez4e388a52019-05-01 12:16:33 -060014from chromite.api.gen.chromiumos import common_pb2
Alex Kleina2e42c42019-04-17 16:13:19 -060015from chromite.api.gen.chromite.api import test_pb2
Sean McAllister3834fef2021-10-08 15:45:18 -060016from chromite.api.gen.chromiumos.build.api import container_metadata_pb2
Andrew Lamb763e3be2021-07-27 17:22:02 -060017from chromite.api.gen.chromiumos.build.api import system_image_pb2
18from chromite.api.gen.chromiumos.build.api import portage_pb2
Andrew Lambd814afa2021-08-11 11:04:20 -060019from chromite.api.gen.chromiumos.config.payload import flat_config_pb2
20from chromite.api.gen.chromiumos.config.api import design_pb2
21from chromite.api.gen.chromiumos.config.api import design_id_pb2
Andrew Lamb763e3be2021-07-27 17:22:02 -060022from chromite.api.gen.chromiumos.test.api import coverage_rule_pb2
23from chromite.api.gen.chromiumos.test.api import dut_attribute_pb2
24from chromite.api.gen.chromiumos.test.api import test_suite_pb2
25from chromite.api.gen.chromiumos.test.plan import source_test_plan_pb2
Jack Neusc9707c32021-07-23 21:48:54 +000026from chromite.lib import build_target_lib
Evan Hernandeze1e05d32019-07-19 12:32:18 -060027from chromite.lib import chroot_lib
Alex Kleina2e42c42019-04-17 16:13:19 -060028from chromite.lib import cros_build_lib
29from chromite.lib import cros_test_lib
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -060030from chromite.lib import image_lib
Alex Kleina2e42c42019-04-17 16:13:19 -060031from chromite.lib import osutils
David Wellingc1433c22021-06-25 16:29:48 +000032from chromite.lib import sysroot_lib
Alex Klein18a60af2020-06-11 12:08:47 -060033from chromite.lib.parser import package_info
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -060034from chromite.scripts import cros_set_lsb_release
35from chromite.service import test as test_service
Andrew Lamb763e3be2021-07-27 17:22:02 -060036from chromite.third_party.google.protobuf import json_format
Mike Frysingere652ba12019-09-08 00:57:43 -040037from chromite.utils import key_value_store
Alex Kleina2e42c42019-04-17 16:13:19 -060038
39
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -070040class DebugInfoTestTest(cros_test_lib.MockTempDirTestCase,
41 api_config.ApiConfigMixin):
42 """Tests for the DebugInfoTest function."""
43
44 def setUp(self):
45 self.board = 'board'
46 self.chroot_path = os.path.join(self.tempdir, 'chroot')
47 self.sysroot_path = '/build/board'
48 self.full_sysroot_path = os.path.join(self.chroot_path,
49 self.sysroot_path.lstrip(os.sep))
50 osutils.SafeMakedirs(self.full_sysroot_path)
51
52 def _GetInput(self, sysroot_path=None, build_target=None):
53 """Helper to build an input message instance."""
54 proto = test_pb2.DebugInfoTestRequest()
55 if sysroot_path:
56 proto.sysroot.path = sysroot_path
57 if build_target:
58 proto.sysroot.build_target.name = build_target
59 return proto
60
61 def _GetOutput(self):
62 """Helper to get an empty output message instance."""
63 return test_pb2.DebugInfoTestResponse()
64
65 def testValidateOnly(self):
66 """Sanity check that a validate only call does not execute any logic."""
67 patch = self.PatchObject(test_service, 'DebugInfoTest')
68 input_msg = self._GetInput(sysroot_path=self.full_sysroot_path)
69 test_controller.DebugInfoTest(input_msg, self._GetOutput(),
70 self.validate_only_config)
71 patch.assert_not_called()
72
Michael Mortensen85d38402019-12-12 09:50:29 -070073 def testMockError(self):
74 """Test mock error call does not execute any logic, returns error."""
75 patch = self.PatchObject(test_service, 'DebugInfoTest')
76
77 input_msg = self._GetInput(sysroot_path=self.full_sysroot_path)
78 rc = test_controller.DebugInfoTest(input_msg, self._GetOutput(),
79 self.mock_error_config)
80 patch.assert_not_called()
81 self.assertEqual(controller.RETURN_CODE_COMPLETED_UNSUCCESSFULLY, rc)
82
83 def testMockCall(self):
84 """Test mock call does not execute any logic, returns success."""
85 patch = self.PatchObject(test_service, 'DebugInfoTest')
86
87 input_msg = self._GetInput(sysroot_path=self.full_sysroot_path)
88 rc = test_controller.DebugInfoTest(input_msg, self._GetOutput(),
89 self.mock_call_config)
90 patch.assert_not_called()
91 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
92
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -070093 def testNoBuildTargetNoSysrootFails(self):
94 """Test missing build target name and sysroot path fails."""
95 input_msg = self._GetInput()
96 output_msg = self._GetOutput()
97 with self.assertRaises(cros_build_lib.DieSystemExit):
98 test_controller.DebugInfoTest(input_msg, output_msg, self.api_config)
99
100 def testDebugInfoTest(self):
101 """Call DebugInfoTest with valid sysroot_path."""
102 request = self._GetInput(sysroot_path=self.full_sysroot_path)
103
104 test_controller.DebugInfoTest(request, self._GetOutput(), self.api_config)
105
106
Alex Klein231d2da2019-07-22 16:44:45 -0600107class BuildTargetUnitTestTest(cros_test_lib.MockTempDirTestCase,
108 api_config.ApiConfigMixin):
Alex Kleina2e42c42019-04-17 16:13:19 -0600109 """Tests for the UnitTest function."""
110
Navil Perezc0b29a82020-07-07 14:17:48 +0000111 def _GetInput(self,
112 board=None,
113 result_path=None,
114 chroot_path=None,
115 cache_dir=None,
116 empty_sysroot=None,
117 packages=None,
Alex Kleinb64e5f82020-09-23 10:55:31 -0600118 blocklist=None):
Alex Kleina2e42c42019-04-17 16:13:19 -0600119 """Helper to build an input message instance."""
Navil Perezc0b29a82020-07-07 14:17:48 +0000120 formatted_packages = []
121 for pkg in packages or []:
122 formatted_packages.append({
123 'category': pkg.category,
124 'package_name': pkg.package
125 })
Alex Kleinb64e5f82020-09-23 10:55:31 -0600126 formatted_blocklist = []
127 for pkg in blocklist or []:
128 formatted_blocklist.append({'category': pkg.category,
Alex Kleinf2674462019-05-16 16:47:24 -0600129 'package_name': pkg.package})
130
Alex Kleina2e42c42019-04-17 16:13:19 -0600131 return test_pb2.BuildTargetUnitTestRequest(
132 build_target={'name': board}, result_path=result_path,
Alex Kleinfa6ebdc2019-05-10 10:57:31 -0600133 chroot={'path': chroot_path, 'cache_dir': cache_dir},
Alex Kleinf2674462019-05-16 16:47:24 -0600134 flags={'empty_sysroot': empty_sysroot},
Alex Klein64ac34c2020-09-23 10:21:33 -0600135 packages=formatted_packages,
Alex Klein157caf42021-07-01 14:36:43 -0600136 package_blocklist=formatted_blocklist,
Alex Kleina2e42c42019-04-17 16:13:19 -0600137 )
138
139 def _GetOutput(self):
140 """Helper to get an empty output message instance."""
141 return test_pb2.BuildTargetUnitTestResponse()
142
Alex Klein231d2da2019-07-22 16:44:45 -0600143 def testValidateOnly(self):
144 """Sanity check that a validate only call does not execute any logic."""
145 patch = self.PatchObject(test_service, 'BuildTargetUnitTest')
146
147 input_msg = self._GetInput(board='board', result_path=self.tempdir)
148 test_controller.BuildTargetUnitTest(input_msg, self._GetOutput(),
149 self.validate_only_config)
150 patch.assert_not_called()
151
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700152 def testMockCall(self):
153 """Test that a mock call does not execute logic, returns mocked value."""
154 patch = self.PatchObject(test_service, 'BuildTargetUnitTest')
155
156 input_msg = self._GetInput(board='board', result_path=self.tempdir)
157 response = self._GetOutput()
158 test_controller.BuildTargetUnitTest(input_msg, response,
159 self.mock_call_config)
160 patch.assert_not_called()
161 self.assertEqual(response.tarball_path,
162 os.path.join(input_msg.result_path, 'unit_tests.tar'))
163
164 def testMockError(self):
Michael Mortensen85d38402019-12-12 09:50:29 -0700165 """Test that a mock error does not execute logic, returns error."""
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700166 patch = self.PatchObject(test_service, 'BuildTargetUnitTest')
167
168 input_msg = self._GetInput(board='board', result_path=self.tempdir)
169 response = self._GetOutput()
170 rc = test_controller.BuildTargetUnitTest(input_msg, response,
171 self.mock_error_config)
172 patch.assert_not_called()
173 self.assertEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
174 self.assertTrue(response.failed_packages)
175 self.assertEqual(response.failed_packages[0].category, 'foo')
176 self.assertEqual(response.failed_packages[0].package_name, 'bar')
177 self.assertEqual(response.failed_packages[1].category, 'cat')
178 self.assertEqual(response.failed_packages[1].package_name, 'pkg')
179
Alex Kleina2e42c42019-04-17 16:13:19 -0600180 def testNoArgumentFails(self):
181 """Test no arguments fails."""
182 input_msg = self._GetInput()
183 output_msg = self._GetOutput()
184 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600185 test_controller.BuildTargetUnitTest(input_msg, output_msg,
186 self.api_config)
Alex Kleina2e42c42019-04-17 16:13:19 -0600187
188 def testNoBuildTargetFails(self):
189 """Test missing build target name fails."""
190 input_msg = self._GetInput(result_path=self.tempdir)
191 output_msg = self._GetOutput()
192 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600193 test_controller.BuildTargetUnitTest(input_msg, output_msg,
194 self.api_config)
Alex Kleina2e42c42019-04-17 16:13:19 -0600195
196 def testNoResultPathFails(self):
197 """Test missing result path fails."""
198 # Missing result_path.
199 input_msg = self._GetInput(board='board')
200 output_msg = self._GetOutput()
201 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600202 test_controller.BuildTargetUnitTest(input_msg, output_msg,
203 self.api_config)
Alex Kleina2e42c42019-04-17 16:13:19 -0600204
Alex Klein64ac34c2020-09-23 10:21:33 -0600205 def testInvalidPackageFails(self):
206 """Test missing result path fails."""
207 # Missing result_path.
208 pkg = package_info.PackageInfo(package='bar')
209 input_msg = self._GetInput(board='board', result_path=self.tempdir,
210 packages=[pkg])
211 output_msg = self._GetOutput()
212 with self.assertRaises(cros_build_lib.DieSystemExit):
213 test_controller.BuildTargetUnitTest(input_msg, output_msg,
214 self.api_config)
215
Alex Kleina2e42c42019-04-17 16:13:19 -0600216 def testPackageBuildFailure(self):
217 """Test handling of raised BuildPackageFailure."""
218 tempdir = osutils.TempDir(base_dir=self.tempdir)
219 self.PatchObject(osutils, 'TempDir', return_value=tempdir)
220
221 pkgs = ['cat/pkg', 'foo/bar']
222 expected = [('cat', 'pkg'), ('foo', 'bar')]
Alex Kleina2e42c42019-04-17 16:13:19 -0600223
Alex Klein38c7d9e2019-05-08 09:31:19 -0600224 result = test_service.BuildTargetUnitTestResult(1, None)
Alex Kleinea0c89e2021-09-09 15:17:35 -0600225 result.failed_pkgs = [package_info.parse(p) for p in pkgs]
Alex Klein38c7d9e2019-05-08 09:31:19 -0600226 self.PatchObject(test_service, 'BuildTargetUnitTest', return_value=result)
Alex Kleina2e42c42019-04-17 16:13:19 -0600227
228 input_msg = self._GetInput(board='board', result_path=self.tempdir)
229 output_msg = self._GetOutput()
230
Alex Klein231d2da2019-07-22 16:44:45 -0600231 rc = test_controller.BuildTargetUnitTest(input_msg, output_msg,
232 self.api_config)
Alex Kleina2e42c42019-04-17 16:13:19 -0600233
Alex Klein8cb365a2019-05-15 16:24:53 -0600234 self.assertEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
Alex Kleina2e42c42019-04-17 16:13:19 -0600235 self.assertTrue(output_msg.failed_packages)
236 failed = []
237 for pi in output_msg.failed_packages:
238 failed.append((pi.category, pi.package_name))
Mike Frysinger678735c2019-09-28 18:23:28 -0400239 self.assertCountEqual(expected, failed)
Alex Kleina2e42c42019-04-17 16:13:19 -0600240
241 def testOtherBuildScriptFailure(self):
242 """Test build script failure due to non-package emerge error."""
243 tempdir = osutils.TempDir(base_dir=self.tempdir)
244 self.PatchObject(osutils, 'TempDir', return_value=tempdir)
245
Alex Klein38c7d9e2019-05-08 09:31:19 -0600246 result = test_service.BuildTargetUnitTestResult(1, None)
247 self.PatchObject(test_service, 'BuildTargetUnitTest', return_value=result)
Alex Kleina2e42c42019-04-17 16:13:19 -0600248
Alex Kleinf2674462019-05-16 16:47:24 -0600249 pkgs = ['foo/bar', 'cat/pkg']
Alex Kleinb64e5f82020-09-23 10:55:31 -0600250 blocklist = [package_info.SplitCPV(p, strict=False) for p in pkgs]
Alex Kleinfa6ebdc2019-05-10 10:57:31 -0600251 input_msg = self._GetInput(board='board', result_path=self.tempdir,
Alex Kleinb64e5f82020-09-23 10:55:31 -0600252 empty_sysroot=True, blocklist=blocklist)
Alex Kleina2e42c42019-04-17 16:13:19 -0600253 output_msg = self._GetOutput()
254
Alex Klein231d2da2019-07-22 16:44:45 -0600255 rc = test_controller.BuildTargetUnitTest(input_msg, output_msg,
256 self.api_config)
Alex Kleina2e42c42019-04-17 16:13:19 -0600257
Alex Klein8cb365a2019-05-15 16:24:53 -0600258 self.assertEqual(controller.RETURN_CODE_COMPLETED_UNSUCCESSFULLY, rc)
Alex Kleina2e42c42019-04-17 16:13:19 -0600259 self.assertFalse(output_msg.failed_packages)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600260
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700261 def testBuildTargetUnitTest(self):
262 """Test BuildTargetUnitTest successful call."""
Navil Perezc0b29a82020-07-07 14:17:48 +0000263 pkgs = ['foo/bar', 'cat/pkg']
Alex Klein18a60af2020-06-11 12:08:47 -0600264 packages = [package_info.SplitCPV(p, strict=False) for p in pkgs]
Navil Perezc0b29a82020-07-07 14:17:48 +0000265 input_msg = self._GetInput(
266 board='board', result_path=self.tempdir, packages=packages)
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700267
268 result = test_service.BuildTargetUnitTestResult(0, None)
269 self.PatchObject(test_service, 'BuildTargetUnitTest', return_value=result)
270
271 tarball_result = os.path.join(input_msg.result_path, 'unit_tests.tar')
272 self.PatchObject(test_service, 'BuildTargetUnitTestTarball',
273 return_value=tarball_result)
274
275 response = self._GetOutput()
276 test_controller.BuildTargetUnitTest(input_msg, response,
277 self.api_config)
278 self.assertEqual(response.tarball_path,
279 os.path.join(input_msg.result_path, 'unit_tests.tar'))
280
Evan Hernandez4e388a52019-05-01 12:16:33 -0600281
Sean McAllister17eed8d2021-09-21 10:41:16 -0600282class DockerConstraintsTest(cros_test_lib.MockTestCase):
283 """Tests for Docker argument constraints."""
284
285 def assertValid(self, output):
286 return output is None
287
288 def assertInvalid(self, output):
289 return not self.assertValid(output)
290
291 def testValidDockerTag(self):
292 """Check logic for validating docker tag format."""
293 # pylint: disable=protected-access
294
295 invalid_tags = [
296 '.invalid-tag',
297 '-invalid-tag',
298 'invalid-tag;',
299 'invalid'*100,
300 ]
301
302 for tag in invalid_tags:
303 self.assertInvalid(test_controller._ValidDockerTag(tag))
304
305 valid_tags = [
306 'valid-tag',
307 'valid-tag-',
308 'valid.tag.',
309 ]
310
311 for tag in valid_tags:
312 self.assertValid(test_controller._ValidDockerTag(tag))
313
314
315 def testValidDockerLabelKey(self):
316 """Check logic for validating docker label key format."""
317 # pylint: disable=protected-access
318
319 invalid_keys = [
320 'Invalid-keY',
321 'Invalid-key',
322 'invalid-keY',
323 'iNVALID-KEy',
324 'invalid_key',
325 'invalid-key;',
326 ]
327
328 for key in invalid_keys:
329 self.assertInvalid(test_controller._ValidDockerLabelKey(key))
330
331 valid_keys = [
332 'chromeos.valid-key',
333 'chromeos.valid-key-2',
334 ]
335
336 for key in valid_keys:
337 self.assertValid(test_controller._ValidDockerLabelKey(key))
338
339
Sean McAllister3834fef2021-10-08 15:45:18 -0600340class BuildTestServiceContainers(cros_test_lib.RunCommandTempDirTestCase,
David Wellingc1433c22021-06-25 16:29:48 +0000341 api_config.ApiConfigMixin):
C Shapiro91af1ce2021-06-17 12:42:09 -0500342 """Tests for the BuildTestServiceContainers function."""
343
344 def setUp(self):
345 self.request = test_pb2.BuildTestServiceContainersRequest(
346 chroot={'path': '/path/to/chroot'},
347 build_target={'name': 'build_target'},
David Wellingc1433c22021-06-25 16:29:48 +0000348 version='R93-14033.0.0',
C Shapiro91af1ce2021-06-17 12:42:09 -0500349 )
350
C Shapiro91af1ce2021-06-17 12:42:09 -0500351 def testSuccess(self):
352 """Check passing case with mocked cros_build_lib.run."""
Sean McAllister3834fef2021-10-08 15:45:18 -0600353
354 def ContainerMetadata():
355 """Return mocked ContainerImageInfo proto"""
356 metadata = container_metadata_pb2.ContainerImageInfo()
357 metadata.repository.hostname = 'gcr.io'
358 metadata.repository.project = 'chromeos-bot'
359 metadata.name = 'random-container-name'
360 metadata.digest = (
361 '09b730f8b6a862f9c2705cb3acf3554563325f5fca5c784bf5c98beb2e56f6db')
362 metadata.tags[:] = [
363 'staging-cq-amd64-generic.R96-1.2.3',
364 '8834106026340379089',
365 ]
366 return metadata
367
368 def WriteContainerMetadata(path):
369 """Write json formatted metadata to the given file."""
370 osutils.WriteFile(
371 path,
372 json_format.MessageToJson(ContainerMetadata()),
373 )
374
375 # Write out mocked container metadata to a temporary file.
376 output_path = os.path.join(self.tempdir, 'metadata.jsonpb')
377 self.rc.SetDefaultCmdResult(
378 returncode=0,
379 side_effect=lambda *_, **__: WriteContainerMetadata(output_path)
380 )
381
382 # Patch TempDir so that we always use this test's directory.
383 self.PatchObject(osutils.TempDir, '__enter__', return_value=self.tempdir)
C Shapiro91af1ce2021-06-17 12:42:09 -0500384
385 response = test_pb2.BuildTestServiceContainersResponse()
386 test_controller.BuildTestServiceContainers(
387 self.request,
388 response,
389 self.api_config)
Sean McAllister3834fef2021-10-08 15:45:18 -0600390
391 self.assertTrue(self.rc.called)
C Shapiro91af1ce2021-06-17 12:42:09 -0500392 for result in response.results:
393 self.assertEqual(result.WhichOneof('result'), 'success')
Sean McAllister3834fef2021-10-08 15:45:18 -0600394 self.assertEqual(result.success.image_info, ContainerMetadata())
C Shapiro91af1ce2021-06-17 12:42:09 -0500395
C Shapiro91af1ce2021-06-17 12:42:09 -0500396 def testFailure(self):
397 """Check failure case with mocked cros_build_lib.run."""
398 patch = self.PatchObject(
399 cros_build_lib, 'run',
400 return_value=cros_build_lib.CommandResult(returncode=1))
401
402 response = test_pb2.BuildTestServiceContainersResponse()
403 test_controller.BuildTestServiceContainers(
404 self.request,
405 response,
406 self.api_config)
407 patch.assert_called()
408 for result in response.results:
409 self.assertEqual(result.WhichOneof('result'), 'failure')
410
411
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -0700412class ChromiteUnitTestTest(cros_test_lib.MockTestCase,
413 api_config.ApiConfigMixin):
414 """Tests for the ChromiteInfoTest function."""
415
416 def setUp(self):
417 self.board = 'board'
418 self.chroot_path = '/path/to/chroot'
419
420 def _GetInput(self, chroot_path=None):
421 """Helper to build an input message instance."""
422 proto = test_pb2.ChromiteUnitTestRequest(
423 chroot={'path': chroot_path},
424 )
425 return proto
426
427 def _GetOutput(self):
428 """Helper to get an empty output message instance."""
429 return test_pb2.ChromiteUnitTestResponse()
430
431 def testValidateOnly(self):
432 """Sanity check that a validate only call does not execute any logic."""
433 patch = self.PatchObject(cros_build_lib, 'run')
434
435 input_msg = self._GetInput(chroot_path=self.chroot_path)
436 test_controller.ChromiteUnitTest(input_msg, self._GetOutput(),
437 self.validate_only_config)
438 patch.assert_not_called()
439
Michael Mortensen7a860eb2019-12-03 20:25:15 -0700440 def testMockError(self):
441 """Test mock error call does not execute any logic, returns error."""
442 patch = self.PatchObject(cros_build_lib, 'run')
443
444 input_msg = self._GetInput(chroot_path=self.chroot_path)
445 rc = test_controller.ChromiteUnitTest(input_msg, self._GetOutput(),
446 self.mock_error_config)
447 patch.assert_not_called()
448 self.assertEqual(controller.RETURN_CODE_COMPLETED_UNSUCCESSFULLY, rc)
449
450 def testMockCall(self):
451 """Test mock call does not execute any logic, returns success."""
452 patch = self.PatchObject(cros_build_lib, 'run')
453
454 input_msg = self._GetInput(chroot_path=self.chroot_path)
455 rc = test_controller.ChromiteUnitTest(input_msg, self._GetOutput(),
456 self.mock_call_config)
457 patch.assert_not_called()
458 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
459
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -0700460 def testChromiteUnitTest(self):
461 """Call ChromiteUnitTest with mocked cros_build_lib.run."""
462 request = self._GetInput(chroot_path=self.chroot_path)
463 patch = self.PatchObject(
464 cros_build_lib, 'run',
465 return_value=cros_build_lib.CommandResult(returncode=0))
466
467 test_controller.ChromiteUnitTest(request, self._GetOutput(),
468 self.api_config)
469 patch.assert_called_once()
470
471
Alex Klein4bc8f4f2019-08-16 14:53:30 -0600472class CrosSigningTestTest(cros_test_lib.RunCommandTestCase,
473 api_config.ApiConfigMixin):
474 """CrosSigningTest tests."""
475
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700476 def setUp(self):
477 self.chroot_path = '/path/to/chroot'
478
479 def _GetInput(self, chroot_path=None):
480 """Helper to build an input message instance."""
481 proto = test_pb2.CrosSigningTestRequest(
482 chroot={'path': chroot_path},
483 )
484 return proto
485
486 def _GetOutput(self):
487 """Helper to get an empty output message instance."""
488 return test_pb2.CrosSigningTestResponse()
489
Alex Klein4bc8f4f2019-08-16 14:53:30 -0600490 def testValidateOnly(self):
491 """Sanity check that a validate only call does not execute any logic."""
492 test_controller.CrosSigningTest(None, None, self.validate_only_config)
493 self.assertFalse(self.rc.call_count)
494
Michael Mortensen7a7646d2019-12-12 15:36:14 -0700495 def testMockCall(self):
496 """Test mock call does not execute any logic, returns success."""
497 rc = test_controller.CrosSigningTest(None, None, self.mock_call_config)
498 self.assertFalse(self.rc.call_count)
499 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
500
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700501 def testCrosSigningTest(self):
502 """Call CrosSigningTest with mocked cros_build_lib.run."""
503 request = self._GetInput(chroot_path=self.chroot_path)
504 patch = self.PatchObject(
505 cros_build_lib, 'run',
506 return_value=cros_build_lib.CommandResult(returncode=0))
507
508 test_controller.CrosSigningTest(request, self._GetOutput(),
509 self.api_config)
510 patch.assert_called_once()
511
Alex Klein4bc8f4f2019-08-16 14:53:30 -0600512
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600513class SimpleChromeWorkflowTestTest(cros_test_lib.MockTestCase,
514 api_config.ApiConfigMixin):
515 """Test the SimpleChromeWorkflowTest endpoint."""
516
517 @staticmethod
518 def _Output():
519 return test_pb2.SimpleChromeWorkflowTestResponse()
520
David Wellingc1433c22021-06-25 16:29:48 +0000521 def _Input(self,
522 sysroot_path=None,
523 build_target=None,
524 chrome_root=None,
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600525 goma_config=None):
526 proto = test_pb2.SimpleChromeWorkflowTestRequest()
527 if sysroot_path:
528 proto.sysroot.path = sysroot_path
529 if build_target:
530 proto.sysroot.build_target.name = build_target
531 if chrome_root:
532 proto.chrome_root = chrome_root
533 if goma_config:
534 proto.goma_config = goma_config
535 return proto
536
537 def setUp(self):
538 self.chrome_path = 'path/to/chrome'
539 self.sysroot_dir = 'build/board'
540 self.build_target = 'amd64'
541 self.mock_simple_chrome_workflow_test = self.PatchObject(
542 test_service, 'SimpleChromeWorkflowTest')
543
544 def testMissingBuildTarget(self):
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700545 """Test SimpleChromeWorkflowTest dies when build_target not set."""
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600546 input_proto = self._Input(build_target=None, sysroot_path='/sysroot/dir',
547 chrome_root='/chrome/path')
548 with self.assertRaises(cros_build_lib.DieSystemExit):
549 test_controller.SimpleChromeWorkflowTest(input_proto, None,
550 self.api_config)
551
552 def testMissingSysrootPath(self):
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700553 """Test SimpleChromeWorkflowTest dies when build_target not set."""
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600554 input_proto = self._Input(build_target='board', sysroot_path=None,
555 chrome_root='/chrome/path')
556 with self.assertRaises(cros_build_lib.DieSystemExit):
557 test_controller.SimpleChromeWorkflowTest(input_proto, None,
558 self.api_config)
559
560 def testMissingChromeRoot(self):
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700561 """Test SimpleChromeWorkflowTest dies when build_target not set."""
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600562 input_proto = self._Input(build_target='board', sysroot_path='/sysroot/dir',
563 chrome_root=None)
564 with self.assertRaises(cros_build_lib.DieSystemExit):
565 test_controller.SimpleChromeWorkflowTest(input_proto, None,
566 self.api_config)
567
568 def testSimpleChromeWorkflowTest(self):
569 """Call SimpleChromeWorkflowTest with valid args and temp dir."""
570 request = self._Input(sysroot_path='sysroot_path', build_target='board',
571 chrome_root='/path/to/chrome')
572 response = self._Output()
573
574 test_controller.SimpleChromeWorkflowTest(request, response, self.api_config)
575 self.mock_simple_chrome_workflow_test.assert_called()
576
577 def testValidateOnly(self):
578 request = self._Input(sysroot_path='sysroot_path', build_target='board',
579 chrome_root='/path/to/chrome')
580 test_controller.SimpleChromeWorkflowTest(request, self._Output(),
581 self.validate_only_config)
582 self.mock_simple_chrome_workflow_test.assert_not_called()
583
Michael Mortensen7a7646d2019-12-12 15:36:14 -0700584 def testMockCall(self):
585 """Test mock call does not execute any logic, returns success."""
586 patch = self.mock_simple_chrome_workflow_test = self.PatchObject(
587 test_service, 'SimpleChromeWorkflowTest')
588
589 request = self._Input(sysroot_path='sysroot_path', build_target='board',
590 chrome_root='/path/to/chrome')
591 rc = test_controller.SimpleChromeWorkflowTest(request, self._Output(),
592 self.mock_call_config)
593 patch.assert_not_called()
594 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
595
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600596
Alex Klein231d2da2019-07-22 16:44:45 -0600597class VmTestTest(cros_test_lib.RunCommandTestCase, api_config.ApiConfigMixin):
Evan Hernandez4e388a52019-05-01 12:16:33 -0600598 """Test the VmTest endpoint."""
599
600 def _GetInput(self, **kwargs):
601 values = dict(
602 build_target=common_pb2.BuildTarget(name='target'),
Alex Klein311b8022019-06-05 16:00:07 -0600603 vm_path=common_pb2.Path(path='/path/to/image.bin',
604 location=common_pb2.Path.INSIDE),
Evan Hernandez4e388a52019-05-01 12:16:33 -0600605 test_harness=test_pb2.VmTestRequest.TAST,
606 vm_tests=[test_pb2.VmTestRequest.VmTest(pattern='suite')],
607 ssh_options=test_pb2.VmTestRequest.SshOptions(
Alex Klein231d2da2019-07-22 16:44:45 -0600608 port=1234, private_key_path={'path': '/path/to/id_rsa',
Alex Kleinaa705412019-06-04 15:00:30 -0600609 'location': common_pb2.Path.INSIDE}),
Evan Hernandez4e388a52019-05-01 12:16:33 -0600610 )
611 values.update(kwargs)
612 return test_pb2.VmTestRequest(**values)
613
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700614 def _Output(self):
615 return test_pb2.VmTestResponse()
616
Alex Klein231d2da2019-07-22 16:44:45 -0600617 def testValidateOnly(self):
618 """Sanity check that a validate only call does not execute any logic."""
619 test_controller.VmTest(self._GetInput(), None, self.validate_only_config)
620 self.assertEqual(0, self.rc.call_count)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600621
Michael Mortensen7a7646d2019-12-12 15:36:14 -0700622 def testMockCall(self):
623 """Test mock call does not execute any logic."""
624 patch = self.PatchObject(cros_build_lib, 'run')
625
626 request = self._GetInput()
627 response = self._Output()
628 # VmTest does not return a value, checking mocked value is flagged by lint.
629 test_controller.VmTest(request, response, self.mock_call_config)
630 patch.assert_not_called()
631
Evan Hernandez4e388a52019-05-01 12:16:33 -0600632 def testTastAllOptions(self):
633 """Test VmTest for Tast with all options set."""
Alex Klein231d2da2019-07-22 16:44:45 -0600634 test_controller.VmTest(self._GetInput(), None, self.api_config)
635 self.assertCommandContains([
Achuith Bhandarkara9e9c3d2019-05-22 13:56:11 -0700636 'cros_run_test', '--debug', '--no-display', '--copy-on-write',
Evan Hernandez4e388a52019-05-01 12:16:33 -0600637 '--board', 'target',
638 '--image-path', '/path/to/image.bin',
639 '--tast', 'suite',
640 '--ssh-port', '1234',
641 '--private-key', '/path/to/id_rsa',
642 ])
643
644 def testAutotestAllOptions(self):
645 """Test VmTest for Autotest with all options set."""
646 input_proto = self._GetInput(test_harness=test_pb2.VmTestRequest.AUTOTEST)
Alex Klein231d2da2019-07-22 16:44:45 -0600647 test_controller.VmTest(input_proto, None, self.api_config)
648 self.assertCommandContains([
Achuith Bhandarkara9e9c3d2019-05-22 13:56:11 -0700649 'cros_run_test', '--debug', '--no-display', '--copy-on-write',
Evan Hernandez4e388a52019-05-01 12:16:33 -0600650 '--board', 'target',
651 '--image-path', '/path/to/image.bin',
652 '--autotest', 'suite',
653 '--ssh-port', '1234',
654 '--private-key', '/path/to/id_rsa',
Greg Edelstondcb0e912020-08-31 11:09:40 -0600655 '--test_that-args=--allow-chrome-crashes',
Evan Hernandez4e388a52019-05-01 12:16:33 -0600656 ])
657
658 def testMissingBuildTarget(self):
659 """Test VmTest dies when build_target not set."""
660 input_proto = self._GetInput(build_target=None)
661 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600662 test_controller.VmTest(input_proto, None, self.api_config)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600663
664 def testMissingVmImage(self):
665 """Test VmTest dies when vm_image not set."""
Alex Klein311b8022019-06-05 16:00:07 -0600666 input_proto = self._GetInput(vm_path=None)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600667 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600668 test_controller.VmTest(input_proto, None, self.api_config)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600669
670 def testMissingTestHarness(self):
671 """Test VmTest dies when test_harness not specified."""
672 input_proto = self._GetInput(
673 test_harness=test_pb2.VmTestRequest.UNSPECIFIED)
674 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600675 test_controller.VmTest(input_proto, None, self.api_config)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600676
677 def testMissingVmTests(self):
678 """Test VmTest dies when vm_tests not set."""
679 input_proto = self._GetInput(vm_tests=[])
680 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600681 test_controller.VmTest(input_proto, None, self.api_config)
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600682
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700683 def testVmTest(self):
684 """Call VmTest with valid args and temp dir."""
685 request = self._GetInput()
686 response = self._Output()
687 patch = self.PatchObject(
688 cros_build_lib, 'run',
689 return_value=cros_build_lib.CommandResult(returncode=0))
690
691 test_controller.VmTest(request, response, self.api_config)
692 patch.assert_called()
693
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600694
Alex Klein231d2da2019-07-22 16:44:45 -0600695class MoblabVmTestTest(cros_test_lib.MockTestCase, api_config.ApiConfigMixin):
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600696 """Test the MoblabVmTest endpoint."""
697
698 @staticmethod
699 def _Payload(path):
700 return test_pb2.MoblabVmTestRequest.Payload(
701 path=common_pb2.Path(path=path))
702
703 @staticmethod
704 def _Output():
705 return test_pb2.MoblabVmTestResponse()
706
707 def _Input(self):
708 return test_pb2.MoblabVmTestRequest(
Evan Hernandeze1e05d32019-07-19 12:32:18 -0600709 chroot=common_pb2.Chroot(path=self.chroot_dir),
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600710 image_payload=self._Payload(self.image_payload_dir),
711 cache_payloads=[self._Payload(self.autotest_payload_dir)])
712
713 def setUp(self):
Evan Hernandeze1e05d32019-07-19 12:32:18 -0600714 self.chroot_dir = '/chroot'
715 self.chroot_tmp_dir = '/chroot/tmp'
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600716 self.image_payload_dir = '/payloads/image'
717 self.autotest_payload_dir = '/payloads/autotest'
718 self.builder = 'moblab-generic-vm/R12-3.4.5-67.890'
719 self.image_cache_dir = '/mnt/moblab/cache'
720 self.image_mount_dir = '/mnt/image'
721
Evan Hernandeze1e05d32019-07-19 12:32:18 -0600722 self.PatchObject(chroot_lib.Chroot, 'tempdir', osutils.TempDir)
Evan Hernandez655e8042019-06-13 12:50:44 -0600723
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600724 self.mock_create_moblab_vms = self.PatchObject(
725 test_service, 'CreateMoblabVm')
726 self.mock_prepare_moblab_vm_image_cache = self.PatchObject(
727 test_service, 'PrepareMoblabVmImageCache',
728 return_value=self.image_cache_dir)
729 self.mock_run_moblab_vm_tests = self.PatchObject(
730 test_service, 'RunMoblabVmTest')
731 self.mock_validate_moblab_vm_tests = self.PatchObject(
732 test_service, 'ValidateMoblabVmTest')
733
734 @contextlib.contextmanager
Alex Klein38c7d9e2019-05-08 09:31:19 -0600735 def MockLoopbackPartitions(*_args, **_kwargs):
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600736 mount = mock.MagicMock()
Evan Hernandez40ee7452019-06-13 12:51:43 -0600737 mount.Mount.return_value = [self.image_mount_dir]
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600738 yield mount
Alex Klein231d2da2019-07-22 16:44:45 -0600739
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600740 self.PatchObject(image_lib, 'LoopbackPartitions', MockLoopbackPartitions)
741
Alex Klein231d2da2019-07-22 16:44:45 -0600742 def testValidateOnly(self):
743 """Sanity check that a validate only call does not execute any logic."""
744 test_controller.MoblabVmTest(self._Input(), self._Output(),
745 self.validate_only_config)
746 self.mock_create_moblab_vms.assert_not_called()
747
Michael Mortensen7a7646d2019-12-12 15:36:14 -0700748 def testMockCall(self):
749 """Test mock call does not execute any logic."""
750 patch = self.PatchObject(key_value_store, 'LoadFile')
751
752 # MoblabVmTest does not return a value, checking mocked value is flagged by
753 # lint.
754 test_controller.MoblabVmTest(self._Input(), self._Output(),
755 self.mock_call_config)
756 patch.assert_not_called()
757
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600758 def testImageContainsBuilder(self):
759 """MoblabVmTest calls service with correct args."""
760 request = self._Input()
761 response = self._Output()
762
763 self.PatchObject(
Mike Frysingere652ba12019-09-08 00:57:43 -0400764 key_value_store, 'LoadFile',
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600765 return_value={cros_set_lsb_release.LSB_KEY_BUILDER_PATH: self.builder})
766
Alex Klein231d2da2019-07-22 16:44:45 -0600767 test_controller.MoblabVmTest(request, response, self.api_config)
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600768
769 self.assertEqual(
770 self.mock_create_moblab_vms.call_args_list,
Evan Hernandeze1e05d32019-07-19 12:32:18 -0600771 [mock.call(mock.ANY, self.chroot_dir, self.image_payload_dir)])
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600772 self.assertEqual(
773 self.mock_prepare_moblab_vm_image_cache.call_args_list,
774 [mock.call(mock.ANY, self.builder, [self.autotest_payload_dir])])
775 self.assertEqual(
776 self.mock_run_moblab_vm_tests.call_args_list,
Evan Hernandez655e8042019-06-13 12:50:44 -0600777 [mock.call(mock.ANY, mock.ANY, self.builder, self.image_cache_dir,
778 mock.ANY)])
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600779 self.assertEqual(
780 self.mock_validate_moblab_vm_tests.call_args_list,
781 [mock.call(mock.ANY)])
782
783 def testImageMissingBuilder(self):
784 """MoblabVmTest dies when builder path not found in lsb-release."""
785 request = self._Input()
786 response = self._Output()
787
Mike Frysingere652ba12019-09-08 00:57:43 -0400788 self.PatchObject(key_value_store, 'LoadFile', return_value={})
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600789
790 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600791 test_controller.MoblabVmTest(request, response, self.api_config)
David Wellingc1433c22021-06-25 16:29:48 +0000792
793
794class GetArtifactsTest(cros_test_lib.MockTempDirTestCase):
795 """Test GetArtifacts."""
796
797 CODE_COVERAGE_LLVM_ARTIFACT_TYPE = (
798 common_pb2.ArtifactsByService.Test.ArtifactType.CODE_COVERAGE_LLVM_JSON
799 )
George Engelbrecht764b1cd2021-06-18 17:01:07 -0600800 UNIT_TEST_ARTIFACT_TYPE = (
801 common_pb2.ArtifactsByService.Test.ArtifactType.UNIT_TESTS
802 )
David Wellingc1433c22021-06-25 16:29:48 +0000803
804 def setUp(self):
805 """Set up the class for tests."""
806 chroot_dir = os.path.join(self.tempdir, 'chroot')
807 osutils.SafeMakedirs(chroot_dir)
808 osutils.SafeMakedirs(os.path.join(chroot_dir, 'tmp'))
809 self.chroot = chroot_lib.Chroot(chroot_dir)
810
811 sysroot_path = os.path.join(chroot_dir, 'build', 'board')
812 osutils.SafeMakedirs(sysroot_path)
813 self.sysroot = sysroot_lib.Sysroot(sysroot_path)
814
Jack Neusc9707c32021-07-23 21:48:54 +0000815 self.build_target = build_target_lib.BuildTarget('board')
816
David Wellingc1433c22021-06-25 16:29:48 +0000817 def testReturnsEmptyListWhenNoOutputArtifactsProvided(self):
818 """Test empty list is returned when there are no output_artifacts."""
819 result = test_controller.GetArtifacts(
820 common_pb2.ArtifactsByService.Test(output_artifacts=[]),
Jack Neusc9707c32021-07-23 21:48:54 +0000821 self.chroot, self.sysroot, self.build_target, self.tempdir)
David Wellingc1433c22021-06-25 16:29:48 +0000822
823 self.assertEqual(len(result), 0)
824
825 def testShouldCallBundleCodeCoverageLlvmJsonForEachValidArtifact(self):
826 """Test BundleCodeCoverageLlvmJson is called on each valid artifact."""
Sean McAllister17eed8d2021-09-21 10:41:16 -0600827 BundleCodeCoverageLlvmJson_mock = (
828 self.PatchObject(
829 test_service,
830 'BundleCodeCoverageLlvmJson',
831 return_value='test'))
David Wellingc1433c22021-06-25 16:29:48 +0000832
833 test_controller.GetArtifacts(
834 common_pb2.ArtifactsByService.Test(output_artifacts=[
835 # Valid
836 common_pb2.ArtifactsByService.Test.ArtifactInfo(
837 artifact_types=[
838 self.CODE_COVERAGE_LLVM_ARTIFACT_TYPE
839 ]
840 ),
841
842 # Invalid
843 common_pb2.ArtifactsByService.Test.ArtifactInfo(
844 artifact_types=[
845 common_pb2.ArtifactsByService.Test.ArtifactType.UNIT_TESTS
846 ]
847 ),
848 ]),
Jack Neusc9707c32021-07-23 21:48:54 +0000849 self.chroot, self.sysroot, self.build_target, self.tempdir)
David Wellingc1433c22021-06-25 16:29:48 +0000850
851 BundleCodeCoverageLlvmJson_mock.assert_called_once()
852
853 def testShouldReturnValidResult(self):
854 """Test result contains paths and code_coverage_llvm_json type."""
855 self.PatchObject(test_service, 'BundleCodeCoverageLlvmJson',
Sean McAllister17eed8d2021-09-21 10:41:16 -0600856 return_value='test')
George Engelbrecht764b1cd2021-06-18 17:01:07 -0600857 self.PatchObject(test_service, 'BuildTargetUnitTestTarball',
Sean McAllister17eed8d2021-09-21 10:41:16 -0600858 return_value='unit_tests.tar')
David Wellingc1433c22021-06-25 16:29:48 +0000859
860 result = test_controller.GetArtifacts(
861 common_pb2.ArtifactsByService.Test(output_artifacts=[
862 # Valid
863 common_pb2.ArtifactsByService.Test.ArtifactInfo(
864 artifact_types=[
George Engelbrecht764b1cd2021-06-18 17:01:07 -0600865 self.UNIT_TEST_ARTIFACT_TYPE
866 ]
867 ),
868 common_pb2.ArtifactsByService.Test.ArtifactInfo(
869 artifact_types=[
David Wellingc1433c22021-06-25 16:29:48 +0000870 self.CODE_COVERAGE_LLVM_ARTIFACT_TYPE
871 ]
872 ),
873 ]),
Jack Neusc9707c32021-07-23 21:48:54 +0000874 self.chroot, self.sysroot, self.build_target, self.tempdir)
David Wellingc1433c22021-06-25 16:29:48 +0000875
George Engelbrecht764b1cd2021-06-18 17:01:07 -0600876 self.assertEqual(result[0]['paths'], ['unit_tests.tar'])
877 self.assertEqual(result[0]['type'], self.UNIT_TEST_ARTIFACT_TYPE)
878 self.assertEqual(result[1]['paths'], ['test'])
879 self.assertEqual(result[1]['type'], self.CODE_COVERAGE_LLVM_ARTIFACT_TYPE)
Andrew Lamb763e3be2021-07-27 17:22:02 -0600880
881
882class GetCoverageRulesTest(cros_test_lib.RunCommandTempDirTestCase,
883 api_config.ApiConfigMixin):
884 """Tests for GetCoverageRules."""
885
Andrew Lambd814afa2021-08-11 11:04:20 -0600886 def _Input(self):
Andrew Lamb763e3be2021-07-27 17:22:02 -0600887 """Returns a sample GetCoverageRulesRequest for testing."""
Andrew Lambd814afa2021-08-11 11:04:20 -0600888 build_metadata_list_path = os.path.join(self.tempdir,
889 'build_metadata_list.jsonproto')
890 build_metadata_list = system_image_pb2.SystemImage.BuildMetadataList(
891 values=[
Andrew Lamb763e3be2021-07-27 17:22:02 -0600892 system_image_pb2.SystemImage.BuildMetadata(
893 build_target=system_image_pb2.SystemImage.BuildTarget(
894 portage_build_target=portage_pb2.Portage.BuildTarget(
895 overlay_name='overlayA')),
896 package_summary=system_image_pb2.SystemImage.BuildMetadata
897 .PackageSummary(
898 kernel=system_image_pb2.SystemImage.BuildMetadata.Kernel(
899 version='4.4')))
Andrew Lambd814afa2021-08-11 11:04:20 -0600900 ])
901 osutils.WriteFile(build_metadata_list_path,
902 json_format.MessageToJson(build_metadata_list))
903
904 dut_attribute_list_path = os.path.join(self.tempdir,
905 'dut_attribute_list.jsonproto')
906 dut_attribute_list = dut_attribute_pb2.DutAttributeList(dut_attributes=[
907 dut_attribute_pb2.DutAttribute(
908 id=dut_attribute_pb2.DutAttribute.Id(value='system_build_target'))
909 ])
910 osutils.WriteFile(dut_attribute_list_path,
911 json_format.MessageToJson(dut_attribute_list))
912
913 flat_config_list_path = os.path.join(self.tempdir,
914 'flat_config_list.jsonproto')
915 flat_config_list = flat_config_pb2.FlatConfigList(values=[
916 flat_config_pb2.FlatConfig(
917 hw_design=design_pb2.Design(
918 id=design_id_pb2.DesignId(value='design1')
919 )
920 )
921 ])
922 osutils.WriteFile(flat_config_list_path,
923 json_format.MessageToJson(flat_config_list))
924
925 return test_pb2.GetCoverageRulesRequest(
926 source_test_plans=[
927 source_test_plan_pb2.SourceTestPlan(
928 requirements=source_test_plan_pb2.SourceTestPlan.Requirements(
929 kernel_versions=source_test_plan_pb2.SourceTestPlan
930 .Requirements.KernelVersions()),
931 test_tags=['kernel']),
932 ],
933 build_metadata_list=common_pb2.Path(
934 path=build_metadata_list_path, location=common_pb2.Path.OUTSIDE),
935 dut_attribute_list=common_pb2.Path(
936 path=dut_attribute_list_path, location=common_pb2.Path.OUTSIDE),
937 flat_config_list=common_pb2.Path(
938 path=flat_config_list_path, location=common_pb2.Path.OUTSIDE),
939 )
Andrew Lamb763e3be2021-07-27 17:22:02 -0600940
941 @staticmethod
942 def _Output():
943 """Returns a sample GetCoverageRulesResponse for testing."""
944 return test_pb2.GetCoverageRulesResponse(coverage_rules=[
945 coverage_rule_pb2.CoverageRule(
946 name='kernel:4.4',
947 test_suites=[
948 test_suite_pb2.TestSuite(
949 test_case_tag_criteria=test_suite_pb2.TestSuite
950 .TestCaseTagCriteria(tags=['kernel']))
951 ],
952 dut_criteria=[
953 dut_attribute_pb2.DutCriterion(
954 attribute_id=dut_attribute_pb2.DutAttribute.Id(
955 value='system_build_target'),
956 values=['overlayA'],
957 )
958 ])
959 ])
960
961 @staticmethod
962 def _write_coverage_rules(path, coverage_rules):
963 """Write a list of CoverageRules in the same format as testplan."""
964 osutils.WriteFile(
965 path, '\n'.join(
966 json_format.MessageToJson(rule).replace('\n', '')
967 for rule in coverage_rules))
968
969 def testWritesInputsAndReturnsCoverageRules(self):
970 """Test inputs are written, and output of testplan is parsed."""
971 output_proto = test_pb2.GetCoverageRulesResponse()
972
973 self.rc.SetDefaultCmdResult(
974 side_effect=lambda _: self._write_coverage_rules(
975 os.path.join(self.tempdir, 'out.jsonpb'),
976 self._Output().coverage_rules))
977 self.PatchObject(osutils.TempDir, '__enter__', return_value=self.tempdir)
978
979 test_controller.GetCoverageRules(self._Input(), output_proto,
980 self.api_config)
981
Andrew Lamb763e3be2021-07-27 17:22:02 -0600982 self.assertEqual(output_proto, self._Output())