blob: 6797b763936fe63a647dd4ce6dbd5e755e2567fb [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
Evan Hernandeze1e05d32019-07-19 12:32:18 -060016from chromite.lib import chroot_lib
Alex Kleina2e42c42019-04-17 16:13:19 -060017from chromite.lib import cros_build_lib
18from chromite.lib import cros_test_lib
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -060019from chromite.lib import image_lib
Alex Kleina2e42c42019-04-17 16:13:19 -060020from chromite.lib import osutils
David Wellingc1433c22021-06-25 16:29:48 +000021from chromite.lib import sysroot_lib
Alex Klein18a60af2020-06-11 12:08:47 -060022from chromite.lib.parser import package_info
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -060023from chromite.scripts import cros_set_lsb_release
24from chromite.service import test as test_service
Mike Frysingere652ba12019-09-08 00:57:43 -040025from chromite.utils import key_value_store
Alex Kleina2e42c42019-04-17 16:13:19 -060026
27
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -070028class DebugInfoTestTest(cros_test_lib.MockTempDirTestCase,
29 api_config.ApiConfigMixin):
30 """Tests for the DebugInfoTest function."""
31
32 def setUp(self):
33 self.board = 'board'
34 self.chroot_path = os.path.join(self.tempdir, 'chroot')
35 self.sysroot_path = '/build/board'
36 self.full_sysroot_path = os.path.join(self.chroot_path,
37 self.sysroot_path.lstrip(os.sep))
38 osutils.SafeMakedirs(self.full_sysroot_path)
39
40 def _GetInput(self, sysroot_path=None, build_target=None):
41 """Helper to build an input message instance."""
42 proto = test_pb2.DebugInfoTestRequest()
43 if sysroot_path:
44 proto.sysroot.path = sysroot_path
45 if build_target:
46 proto.sysroot.build_target.name = build_target
47 return proto
48
49 def _GetOutput(self):
50 """Helper to get an empty output message instance."""
51 return test_pb2.DebugInfoTestResponse()
52
53 def testValidateOnly(self):
54 """Sanity check that a validate only call does not execute any logic."""
55 patch = self.PatchObject(test_service, 'DebugInfoTest')
56 input_msg = self._GetInput(sysroot_path=self.full_sysroot_path)
57 test_controller.DebugInfoTest(input_msg, self._GetOutput(),
58 self.validate_only_config)
59 patch.assert_not_called()
60
Michael Mortensen85d38402019-12-12 09:50:29 -070061 def testMockError(self):
62 """Test mock error call does not execute any logic, returns error."""
63 patch = self.PatchObject(test_service, 'DebugInfoTest')
64
65 input_msg = self._GetInput(sysroot_path=self.full_sysroot_path)
66 rc = test_controller.DebugInfoTest(input_msg, self._GetOutput(),
67 self.mock_error_config)
68 patch.assert_not_called()
69 self.assertEqual(controller.RETURN_CODE_COMPLETED_UNSUCCESSFULLY, rc)
70
71 def testMockCall(self):
72 """Test mock call does not execute any logic, returns success."""
73 patch = self.PatchObject(test_service, 'DebugInfoTest')
74
75 input_msg = self._GetInput(sysroot_path=self.full_sysroot_path)
76 rc = test_controller.DebugInfoTest(input_msg, self._GetOutput(),
77 self.mock_call_config)
78 patch.assert_not_called()
79 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
80
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -070081 def testNoBuildTargetNoSysrootFails(self):
82 """Test missing build target name and sysroot path fails."""
83 input_msg = self._GetInput()
84 output_msg = self._GetOutput()
85 with self.assertRaises(cros_build_lib.DieSystemExit):
86 test_controller.DebugInfoTest(input_msg, output_msg, self.api_config)
87
88 def testDebugInfoTest(self):
89 """Call DebugInfoTest with valid sysroot_path."""
90 request = self._GetInput(sysroot_path=self.full_sysroot_path)
91
92 test_controller.DebugInfoTest(request, self._GetOutput(), self.api_config)
93
94
Alex Klein231d2da2019-07-22 16:44:45 -060095class BuildTargetUnitTestTest(cros_test_lib.MockTempDirTestCase,
96 api_config.ApiConfigMixin):
Alex Kleina2e42c42019-04-17 16:13:19 -060097 """Tests for the UnitTest function."""
98
Navil Perezc0b29a82020-07-07 14:17:48 +000099 def _GetInput(self,
100 board=None,
101 result_path=None,
102 chroot_path=None,
103 cache_dir=None,
104 empty_sysroot=None,
105 packages=None,
Alex Kleinb64e5f82020-09-23 10:55:31 -0600106 blocklist=None):
Alex Kleina2e42c42019-04-17 16:13:19 -0600107 """Helper to build an input message instance."""
Navil Perezc0b29a82020-07-07 14:17:48 +0000108 formatted_packages = []
109 for pkg in packages or []:
110 formatted_packages.append({
111 'category': pkg.category,
112 'package_name': pkg.package
113 })
Alex Kleinb64e5f82020-09-23 10:55:31 -0600114 formatted_blocklist = []
115 for pkg in blocklist or []:
116 formatted_blocklist.append({'category': pkg.category,
Alex Kleinf2674462019-05-16 16:47:24 -0600117 'package_name': pkg.package})
118
Alex Kleina2e42c42019-04-17 16:13:19 -0600119 return test_pb2.BuildTargetUnitTestRequest(
120 build_target={'name': board}, result_path=result_path,
Alex Kleinfa6ebdc2019-05-10 10:57:31 -0600121 chroot={'path': chroot_path, 'cache_dir': cache_dir},
Alex Kleinf2674462019-05-16 16:47:24 -0600122 flags={'empty_sysroot': empty_sysroot},
Alex Klein64ac34c2020-09-23 10:21:33 -0600123 packages=formatted_packages,
Alex Klein157caf42021-07-01 14:36:43 -0600124 package_blocklist=formatted_blocklist,
Alex Kleina2e42c42019-04-17 16:13:19 -0600125 )
126
127 def _GetOutput(self):
128 """Helper to get an empty output message instance."""
129 return test_pb2.BuildTargetUnitTestResponse()
130
Alex Klein231d2da2019-07-22 16:44:45 -0600131 def testValidateOnly(self):
132 """Sanity check that a validate only call does not execute any logic."""
133 patch = self.PatchObject(test_service, 'BuildTargetUnitTest')
134
135 input_msg = self._GetInput(board='board', result_path=self.tempdir)
136 test_controller.BuildTargetUnitTest(input_msg, self._GetOutput(),
137 self.validate_only_config)
138 patch.assert_not_called()
139
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700140 def testMockCall(self):
141 """Test that a mock call does not execute logic, returns mocked value."""
142 patch = self.PatchObject(test_service, 'BuildTargetUnitTest')
143
144 input_msg = self._GetInput(board='board', result_path=self.tempdir)
145 response = self._GetOutput()
146 test_controller.BuildTargetUnitTest(input_msg, response,
147 self.mock_call_config)
148 patch.assert_not_called()
149 self.assertEqual(response.tarball_path,
150 os.path.join(input_msg.result_path, 'unit_tests.tar'))
151
152 def testMockError(self):
Michael Mortensen85d38402019-12-12 09:50:29 -0700153 """Test that a mock error does not execute logic, returns error."""
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700154 patch = self.PatchObject(test_service, 'BuildTargetUnitTest')
155
156 input_msg = self._GetInput(board='board', result_path=self.tempdir)
157 response = self._GetOutput()
158 rc = test_controller.BuildTargetUnitTest(input_msg, response,
159 self.mock_error_config)
160 patch.assert_not_called()
161 self.assertEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
162 self.assertTrue(response.failed_packages)
163 self.assertEqual(response.failed_packages[0].category, 'foo')
164 self.assertEqual(response.failed_packages[0].package_name, 'bar')
165 self.assertEqual(response.failed_packages[1].category, 'cat')
166 self.assertEqual(response.failed_packages[1].package_name, 'pkg')
167
Alex Kleina2e42c42019-04-17 16:13:19 -0600168 def testNoArgumentFails(self):
169 """Test no arguments fails."""
170 input_msg = self._GetInput()
171 output_msg = self._GetOutput()
172 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600173 test_controller.BuildTargetUnitTest(input_msg, output_msg,
174 self.api_config)
Alex Kleina2e42c42019-04-17 16:13:19 -0600175
176 def testNoBuildTargetFails(self):
177 """Test missing build target name fails."""
178 input_msg = self._GetInput(result_path=self.tempdir)
179 output_msg = self._GetOutput()
180 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600181 test_controller.BuildTargetUnitTest(input_msg, output_msg,
182 self.api_config)
Alex Kleina2e42c42019-04-17 16:13:19 -0600183
184 def testNoResultPathFails(self):
185 """Test missing result path fails."""
186 # Missing result_path.
187 input_msg = self._GetInput(board='board')
188 output_msg = self._GetOutput()
189 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600190 test_controller.BuildTargetUnitTest(input_msg, output_msg,
191 self.api_config)
Alex Kleina2e42c42019-04-17 16:13:19 -0600192
Alex Klein64ac34c2020-09-23 10:21:33 -0600193 def testInvalidPackageFails(self):
194 """Test missing result path fails."""
195 # Missing result_path.
196 pkg = package_info.PackageInfo(package='bar')
197 input_msg = self._GetInput(board='board', result_path=self.tempdir,
198 packages=[pkg])
199 output_msg = self._GetOutput()
200 with self.assertRaises(cros_build_lib.DieSystemExit):
201 test_controller.BuildTargetUnitTest(input_msg, output_msg,
202 self.api_config)
203
Alex Kleina2e42c42019-04-17 16:13:19 -0600204 def testPackageBuildFailure(self):
205 """Test handling of raised BuildPackageFailure."""
206 tempdir = osutils.TempDir(base_dir=self.tempdir)
207 self.PatchObject(osutils, 'TempDir', return_value=tempdir)
208
209 pkgs = ['cat/pkg', 'foo/bar']
210 expected = [('cat', 'pkg'), ('foo', 'bar')]
Alex Kleina2e42c42019-04-17 16:13:19 -0600211
Alex Klein38c7d9e2019-05-08 09:31:19 -0600212 result = test_service.BuildTargetUnitTestResult(1, None)
Alex Klein18a60af2020-06-11 12:08:47 -0600213 result.failed_cpvs = [package_info.SplitCPV(p, strict=False) for p in pkgs]
Alex Klein38c7d9e2019-05-08 09:31:19 -0600214 self.PatchObject(test_service, 'BuildTargetUnitTest', return_value=result)
Alex Kleina2e42c42019-04-17 16:13:19 -0600215
216 input_msg = self._GetInput(board='board', result_path=self.tempdir)
217 output_msg = self._GetOutput()
218
Alex Klein231d2da2019-07-22 16:44:45 -0600219 rc = test_controller.BuildTargetUnitTest(input_msg, output_msg,
220 self.api_config)
Alex Kleina2e42c42019-04-17 16:13:19 -0600221
Alex Klein8cb365a2019-05-15 16:24:53 -0600222 self.assertEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
Alex Kleina2e42c42019-04-17 16:13:19 -0600223 self.assertTrue(output_msg.failed_packages)
224 failed = []
225 for pi in output_msg.failed_packages:
226 failed.append((pi.category, pi.package_name))
Mike Frysinger678735c2019-09-28 18:23:28 -0400227 self.assertCountEqual(expected, failed)
Alex Kleina2e42c42019-04-17 16:13:19 -0600228
229 def testOtherBuildScriptFailure(self):
230 """Test build script failure due to non-package emerge error."""
231 tempdir = osutils.TempDir(base_dir=self.tempdir)
232 self.PatchObject(osutils, 'TempDir', return_value=tempdir)
233
Alex Klein38c7d9e2019-05-08 09:31:19 -0600234 result = test_service.BuildTargetUnitTestResult(1, None)
235 self.PatchObject(test_service, 'BuildTargetUnitTest', return_value=result)
Alex Kleina2e42c42019-04-17 16:13:19 -0600236
Alex Kleinf2674462019-05-16 16:47:24 -0600237 pkgs = ['foo/bar', 'cat/pkg']
Alex Kleinb64e5f82020-09-23 10:55:31 -0600238 blocklist = [package_info.SplitCPV(p, strict=False) for p in pkgs]
Alex Kleinfa6ebdc2019-05-10 10:57:31 -0600239 input_msg = self._GetInput(board='board', result_path=self.tempdir,
Alex Kleinb64e5f82020-09-23 10:55:31 -0600240 empty_sysroot=True, blocklist=blocklist)
Alex Kleina2e42c42019-04-17 16:13:19 -0600241 output_msg = self._GetOutput()
242
Alex Klein231d2da2019-07-22 16:44:45 -0600243 rc = test_controller.BuildTargetUnitTest(input_msg, output_msg,
244 self.api_config)
Alex Kleina2e42c42019-04-17 16:13:19 -0600245
Alex Klein8cb365a2019-05-15 16:24:53 -0600246 self.assertEqual(controller.RETURN_CODE_COMPLETED_UNSUCCESSFULLY, rc)
Alex Kleina2e42c42019-04-17 16:13:19 -0600247 self.assertFalse(output_msg.failed_packages)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600248
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700249 def testBuildTargetUnitTest(self):
250 """Test BuildTargetUnitTest successful call."""
Navil Perezc0b29a82020-07-07 14:17:48 +0000251 pkgs = ['foo/bar', 'cat/pkg']
Alex Klein18a60af2020-06-11 12:08:47 -0600252 packages = [package_info.SplitCPV(p, strict=False) for p in pkgs]
Navil Perezc0b29a82020-07-07 14:17:48 +0000253 input_msg = self._GetInput(
254 board='board', result_path=self.tempdir, packages=packages)
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700255
256 result = test_service.BuildTargetUnitTestResult(0, None)
257 self.PatchObject(test_service, 'BuildTargetUnitTest', return_value=result)
258
259 tarball_result = os.path.join(input_msg.result_path, 'unit_tests.tar')
260 self.PatchObject(test_service, 'BuildTargetUnitTestTarball',
261 return_value=tarball_result)
262
263 response = self._GetOutput()
264 test_controller.BuildTargetUnitTest(input_msg, response,
265 self.api_config)
266 self.assertEqual(response.tarball_path,
267 os.path.join(input_msg.result_path, 'unit_tests.tar'))
268
Evan Hernandez4e388a52019-05-01 12:16:33 -0600269
C Shapiro91af1ce2021-06-17 12:42:09 -0500270class BuildTestServiceContainers(cros_test_lib.MockTestCase,
David Wellingc1433c22021-06-25 16:29:48 +0000271 api_config.ApiConfigMixin):
C Shapiro91af1ce2021-06-17 12:42:09 -0500272 """Tests for the BuildTestServiceContainers function."""
273
274 def setUp(self):
275 self.request = test_pb2.BuildTestServiceContainersRequest(
276 chroot={'path': '/path/to/chroot'},
277 build_target={'name': 'build_target'},
David Wellingc1433c22021-06-25 16:29:48 +0000278 version='R93-14033.0.0',
C Shapiro91af1ce2021-06-17 12:42:09 -0500279 )
280
C Shapiro91af1ce2021-06-17 12:42:09 -0500281 def testSuccess(self):
282 """Check passing case with mocked cros_build_lib.run."""
283 patch = self.PatchObject(
284 cros_build_lib, 'run',
285 return_value=cros_build_lib.CommandResult(returncode=0))
286
287 response = test_pb2.BuildTestServiceContainersResponse()
288 test_controller.BuildTestServiceContainers(
289 self.request,
290 response,
291 self.api_config)
292 patch.assert_called()
293 for result in response.results:
294 self.assertEqual(result.WhichOneof('result'), 'success')
295
C Shapiro91af1ce2021-06-17 12:42:09 -0500296 def testFailure(self):
297 """Check failure case with mocked cros_build_lib.run."""
298 patch = self.PatchObject(
299 cros_build_lib, 'run',
300 return_value=cros_build_lib.CommandResult(returncode=1))
301
302 response = test_pb2.BuildTestServiceContainersResponse()
303 test_controller.BuildTestServiceContainers(
304 self.request,
305 response,
306 self.api_config)
307 patch.assert_called()
308 for result in response.results:
309 self.assertEqual(result.WhichOneof('result'), 'failure')
310
311
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -0700312class ChromiteUnitTestTest(cros_test_lib.MockTestCase,
313 api_config.ApiConfigMixin):
314 """Tests for the ChromiteInfoTest function."""
315
316 def setUp(self):
317 self.board = 'board'
318 self.chroot_path = '/path/to/chroot'
319
320 def _GetInput(self, chroot_path=None):
321 """Helper to build an input message instance."""
322 proto = test_pb2.ChromiteUnitTestRequest(
323 chroot={'path': chroot_path},
324 )
325 return proto
326
327 def _GetOutput(self):
328 """Helper to get an empty output message instance."""
329 return test_pb2.ChromiteUnitTestResponse()
330
331 def testValidateOnly(self):
332 """Sanity check that a validate only call does not execute any logic."""
333 patch = self.PatchObject(cros_build_lib, 'run')
334
335 input_msg = self._GetInput(chroot_path=self.chroot_path)
336 test_controller.ChromiteUnitTest(input_msg, self._GetOutput(),
337 self.validate_only_config)
338 patch.assert_not_called()
339
Michael Mortensen7a860eb2019-12-03 20:25:15 -0700340 def testMockError(self):
341 """Test mock error call does not execute any logic, returns error."""
342 patch = self.PatchObject(cros_build_lib, 'run')
343
344 input_msg = self._GetInput(chroot_path=self.chroot_path)
345 rc = test_controller.ChromiteUnitTest(input_msg, self._GetOutput(),
346 self.mock_error_config)
347 patch.assert_not_called()
348 self.assertEqual(controller.RETURN_CODE_COMPLETED_UNSUCCESSFULLY, rc)
349
350 def testMockCall(self):
351 """Test mock call does not execute any logic, returns success."""
352 patch = self.PatchObject(cros_build_lib, 'run')
353
354 input_msg = self._GetInput(chroot_path=self.chroot_path)
355 rc = test_controller.ChromiteUnitTest(input_msg, self._GetOutput(),
356 self.mock_call_config)
357 patch.assert_not_called()
358 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
359
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -0700360 def testChromiteUnitTest(self):
361 """Call ChromiteUnitTest with mocked cros_build_lib.run."""
362 request = self._GetInput(chroot_path=self.chroot_path)
363 patch = self.PatchObject(
364 cros_build_lib, 'run',
365 return_value=cros_build_lib.CommandResult(returncode=0))
366
367 test_controller.ChromiteUnitTest(request, self._GetOutput(),
368 self.api_config)
369 patch.assert_called_once()
370
371
Alex Klein4bc8f4f2019-08-16 14:53:30 -0600372class CrosSigningTestTest(cros_test_lib.RunCommandTestCase,
373 api_config.ApiConfigMixin):
374 """CrosSigningTest tests."""
375
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700376 def setUp(self):
377 self.chroot_path = '/path/to/chroot'
378
379 def _GetInput(self, chroot_path=None):
380 """Helper to build an input message instance."""
381 proto = test_pb2.CrosSigningTestRequest(
382 chroot={'path': chroot_path},
383 )
384 return proto
385
386 def _GetOutput(self):
387 """Helper to get an empty output message instance."""
388 return test_pb2.CrosSigningTestResponse()
389
Alex Klein4bc8f4f2019-08-16 14:53:30 -0600390 def testValidateOnly(self):
391 """Sanity check that a validate only call does not execute any logic."""
392 test_controller.CrosSigningTest(None, None, self.validate_only_config)
393 self.assertFalse(self.rc.call_count)
394
Michael Mortensen7a7646d2019-12-12 15:36:14 -0700395 def testMockCall(self):
396 """Test mock call does not execute any logic, returns success."""
397 rc = test_controller.CrosSigningTest(None, None, self.mock_call_config)
398 self.assertFalse(self.rc.call_count)
399 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
400
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700401 def testCrosSigningTest(self):
402 """Call CrosSigningTest with mocked cros_build_lib.run."""
403 request = self._GetInput(chroot_path=self.chroot_path)
404 patch = self.PatchObject(
405 cros_build_lib, 'run',
406 return_value=cros_build_lib.CommandResult(returncode=0))
407
408 test_controller.CrosSigningTest(request, self._GetOutput(),
409 self.api_config)
410 patch.assert_called_once()
411
Alex Klein4bc8f4f2019-08-16 14:53:30 -0600412
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600413class SimpleChromeWorkflowTestTest(cros_test_lib.MockTestCase,
414 api_config.ApiConfigMixin):
415 """Test the SimpleChromeWorkflowTest endpoint."""
416
417 @staticmethod
418 def _Output():
419 return test_pb2.SimpleChromeWorkflowTestResponse()
420
David Wellingc1433c22021-06-25 16:29:48 +0000421 def _Input(self,
422 sysroot_path=None,
423 build_target=None,
424 chrome_root=None,
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600425 goma_config=None):
426 proto = test_pb2.SimpleChromeWorkflowTestRequest()
427 if sysroot_path:
428 proto.sysroot.path = sysroot_path
429 if build_target:
430 proto.sysroot.build_target.name = build_target
431 if chrome_root:
432 proto.chrome_root = chrome_root
433 if goma_config:
434 proto.goma_config = goma_config
435 return proto
436
437 def setUp(self):
438 self.chrome_path = 'path/to/chrome'
439 self.sysroot_dir = 'build/board'
440 self.build_target = 'amd64'
441 self.mock_simple_chrome_workflow_test = self.PatchObject(
442 test_service, 'SimpleChromeWorkflowTest')
443
444 def testMissingBuildTarget(self):
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700445 """Test SimpleChromeWorkflowTest dies when build_target not set."""
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600446 input_proto = self._Input(build_target=None, sysroot_path='/sysroot/dir',
447 chrome_root='/chrome/path')
448 with self.assertRaises(cros_build_lib.DieSystemExit):
449 test_controller.SimpleChromeWorkflowTest(input_proto, None,
450 self.api_config)
451
452 def testMissingSysrootPath(self):
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700453 """Test SimpleChromeWorkflowTest dies when build_target not set."""
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600454 input_proto = self._Input(build_target='board', sysroot_path=None,
455 chrome_root='/chrome/path')
456 with self.assertRaises(cros_build_lib.DieSystemExit):
457 test_controller.SimpleChromeWorkflowTest(input_proto, None,
458 self.api_config)
459
460 def testMissingChromeRoot(self):
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700461 """Test SimpleChromeWorkflowTest dies when build_target not set."""
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600462 input_proto = self._Input(build_target='board', sysroot_path='/sysroot/dir',
463 chrome_root=None)
464 with self.assertRaises(cros_build_lib.DieSystemExit):
465 test_controller.SimpleChromeWorkflowTest(input_proto, None,
466 self.api_config)
467
468 def testSimpleChromeWorkflowTest(self):
469 """Call SimpleChromeWorkflowTest with valid args and temp dir."""
470 request = self._Input(sysroot_path='sysroot_path', build_target='board',
471 chrome_root='/path/to/chrome')
472 response = self._Output()
473
474 test_controller.SimpleChromeWorkflowTest(request, response, self.api_config)
475 self.mock_simple_chrome_workflow_test.assert_called()
476
477 def testValidateOnly(self):
478 request = self._Input(sysroot_path='sysroot_path', build_target='board',
479 chrome_root='/path/to/chrome')
480 test_controller.SimpleChromeWorkflowTest(request, self._Output(),
481 self.validate_only_config)
482 self.mock_simple_chrome_workflow_test.assert_not_called()
483
Michael Mortensen7a7646d2019-12-12 15:36:14 -0700484 def testMockCall(self):
485 """Test mock call does not execute any logic, returns success."""
486 patch = self.mock_simple_chrome_workflow_test = self.PatchObject(
487 test_service, 'SimpleChromeWorkflowTest')
488
489 request = self._Input(sysroot_path='sysroot_path', build_target='board',
490 chrome_root='/path/to/chrome')
491 rc = test_controller.SimpleChromeWorkflowTest(request, self._Output(),
492 self.mock_call_config)
493 patch.assert_not_called()
494 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
495
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600496
Alex Klein231d2da2019-07-22 16:44:45 -0600497class VmTestTest(cros_test_lib.RunCommandTestCase, api_config.ApiConfigMixin):
Evan Hernandez4e388a52019-05-01 12:16:33 -0600498 """Test the VmTest endpoint."""
499
500 def _GetInput(self, **kwargs):
501 values = dict(
502 build_target=common_pb2.BuildTarget(name='target'),
Alex Klein311b8022019-06-05 16:00:07 -0600503 vm_path=common_pb2.Path(path='/path/to/image.bin',
504 location=common_pb2.Path.INSIDE),
Evan Hernandez4e388a52019-05-01 12:16:33 -0600505 test_harness=test_pb2.VmTestRequest.TAST,
506 vm_tests=[test_pb2.VmTestRequest.VmTest(pattern='suite')],
507 ssh_options=test_pb2.VmTestRequest.SshOptions(
Alex Klein231d2da2019-07-22 16:44:45 -0600508 port=1234, private_key_path={'path': '/path/to/id_rsa',
Alex Kleinaa705412019-06-04 15:00:30 -0600509 'location': common_pb2.Path.INSIDE}),
Evan Hernandez4e388a52019-05-01 12:16:33 -0600510 )
511 values.update(kwargs)
512 return test_pb2.VmTestRequest(**values)
513
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700514 def _Output(self):
515 return test_pb2.VmTestResponse()
516
Alex Klein231d2da2019-07-22 16:44:45 -0600517 def testValidateOnly(self):
518 """Sanity check that a validate only call does not execute any logic."""
519 test_controller.VmTest(self._GetInput(), None, self.validate_only_config)
520 self.assertEqual(0, self.rc.call_count)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600521
Michael Mortensen7a7646d2019-12-12 15:36:14 -0700522 def testMockCall(self):
523 """Test mock call does not execute any logic."""
524 patch = self.PatchObject(cros_build_lib, 'run')
525
526 request = self._GetInput()
527 response = self._Output()
528 # VmTest does not return a value, checking mocked value is flagged by lint.
529 test_controller.VmTest(request, response, self.mock_call_config)
530 patch.assert_not_called()
531
Evan Hernandez4e388a52019-05-01 12:16:33 -0600532 def testTastAllOptions(self):
533 """Test VmTest for Tast with all options set."""
Alex Klein231d2da2019-07-22 16:44:45 -0600534 test_controller.VmTest(self._GetInput(), None, self.api_config)
535 self.assertCommandContains([
Achuith Bhandarkara9e9c3d2019-05-22 13:56:11 -0700536 'cros_run_test', '--debug', '--no-display', '--copy-on-write',
Evan Hernandez4e388a52019-05-01 12:16:33 -0600537 '--board', 'target',
538 '--image-path', '/path/to/image.bin',
539 '--tast', 'suite',
540 '--ssh-port', '1234',
541 '--private-key', '/path/to/id_rsa',
542 ])
543
544 def testAutotestAllOptions(self):
545 """Test VmTest for Autotest with all options set."""
546 input_proto = self._GetInput(test_harness=test_pb2.VmTestRequest.AUTOTEST)
Alex Klein231d2da2019-07-22 16:44:45 -0600547 test_controller.VmTest(input_proto, None, self.api_config)
548 self.assertCommandContains([
Achuith Bhandarkara9e9c3d2019-05-22 13:56:11 -0700549 'cros_run_test', '--debug', '--no-display', '--copy-on-write',
Evan Hernandez4e388a52019-05-01 12:16:33 -0600550 '--board', 'target',
551 '--image-path', '/path/to/image.bin',
552 '--autotest', 'suite',
553 '--ssh-port', '1234',
554 '--private-key', '/path/to/id_rsa',
Greg Edelstondcb0e912020-08-31 11:09:40 -0600555 '--test_that-args=--allow-chrome-crashes',
Evan Hernandez4e388a52019-05-01 12:16:33 -0600556 ])
557
558 def testMissingBuildTarget(self):
559 """Test VmTest dies when build_target not set."""
560 input_proto = self._GetInput(build_target=None)
561 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600562 test_controller.VmTest(input_proto, None, self.api_config)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600563
564 def testMissingVmImage(self):
565 """Test VmTest dies when vm_image not set."""
Alex Klein311b8022019-06-05 16:00:07 -0600566 input_proto = self._GetInput(vm_path=None)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600567 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600568 test_controller.VmTest(input_proto, None, self.api_config)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600569
570 def testMissingTestHarness(self):
571 """Test VmTest dies when test_harness not specified."""
572 input_proto = self._GetInput(
573 test_harness=test_pb2.VmTestRequest.UNSPECIFIED)
574 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600575 test_controller.VmTest(input_proto, None, self.api_config)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600576
577 def testMissingVmTests(self):
578 """Test VmTest dies when vm_tests not set."""
579 input_proto = self._GetInput(vm_tests=[])
580 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600581 test_controller.VmTest(input_proto, None, self.api_config)
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600582
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700583 def testVmTest(self):
584 """Call VmTest with valid args and temp dir."""
585 request = self._GetInput()
586 response = self._Output()
587 patch = self.PatchObject(
588 cros_build_lib, 'run',
589 return_value=cros_build_lib.CommandResult(returncode=0))
590
591 test_controller.VmTest(request, response, self.api_config)
592 patch.assert_called()
593
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600594
Alex Klein231d2da2019-07-22 16:44:45 -0600595class MoblabVmTestTest(cros_test_lib.MockTestCase, api_config.ApiConfigMixin):
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600596 """Test the MoblabVmTest endpoint."""
597
598 @staticmethod
599 def _Payload(path):
600 return test_pb2.MoblabVmTestRequest.Payload(
601 path=common_pb2.Path(path=path))
602
603 @staticmethod
604 def _Output():
605 return test_pb2.MoblabVmTestResponse()
606
607 def _Input(self):
608 return test_pb2.MoblabVmTestRequest(
Evan Hernandeze1e05d32019-07-19 12:32:18 -0600609 chroot=common_pb2.Chroot(path=self.chroot_dir),
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600610 image_payload=self._Payload(self.image_payload_dir),
611 cache_payloads=[self._Payload(self.autotest_payload_dir)])
612
613 def setUp(self):
Evan Hernandeze1e05d32019-07-19 12:32:18 -0600614 self.chroot_dir = '/chroot'
615 self.chroot_tmp_dir = '/chroot/tmp'
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600616 self.image_payload_dir = '/payloads/image'
617 self.autotest_payload_dir = '/payloads/autotest'
618 self.builder = 'moblab-generic-vm/R12-3.4.5-67.890'
619 self.image_cache_dir = '/mnt/moblab/cache'
620 self.image_mount_dir = '/mnt/image'
621
Evan Hernandeze1e05d32019-07-19 12:32:18 -0600622 self.PatchObject(chroot_lib.Chroot, 'tempdir', osutils.TempDir)
Evan Hernandez655e8042019-06-13 12:50:44 -0600623
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600624 self.mock_create_moblab_vms = self.PatchObject(
625 test_service, 'CreateMoblabVm')
626 self.mock_prepare_moblab_vm_image_cache = self.PatchObject(
627 test_service, 'PrepareMoblabVmImageCache',
628 return_value=self.image_cache_dir)
629 self.mock_run_moblab_vm_tests = self.PatchObject(
630 test_service, 'RunMoblabVmTest')
631 self.mock_validate_moblab_vm_tests = self.PatchObject(
632 test_service, 'ValidateMoblabVmTest')
633
634 @contextlib.contextmanager
Alex Klein38c7d9e2019-05-08 09:31:19 -0600635 def MockLoopbackPartitions(*_args, **_kwargs):
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600636 mount = mock.MagicMock()
Evan Hernandez40ee7452019-06-13 12:51:43 -0600637 mount.Mount.return_value = [self.image_mount_dir]
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600638 yield mount
Alex Klein231d2da2019-07-22 16:44:45 -0600639
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600640 self.PatchObject(image_lib, 'LoopbackPartitions', MockLoopbackPartitions)
641
Alex Klein231d2da2019-07-22 16:44:45 -0600642 def testValidateOnly(self):
643 """Sanity check that a validate only call does not execute any logic."""
644 test_controller.MoblabVmTest(self._Input(), self._Output(),
645 self.validate_only_config)
646 self.mock_create_moblab_vms.assert_not_called()
647
Michael Mortensen7a7646d2019-12-12 15:36:14 -0700648 def testMockCall(self):
649 """Test mock call does not execute any logic."""
650 patch = self.PatchObject(key_value_store, 'LoadFile')
651
652 # MoblabVmTest does not return a value, checking mocked value is flagged by
653 # lint.
654 test_controller.MoblabVmTest(self._Input(), self._Output(),
655 self.mock_call_config)
656 patch.assert_not_called()
657
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600658 def testImageContainsBuilder(self):
659 """MoblabVmTest calls service with correct args."""
660 request = self._Input()
661 response = self._Output()
662
663 self.PatchObject(
Mike Frysingere652ba12019-09-08 00:57:43 -0400664 key_value_store, 'LoadFile',
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600665 return_value={cros_set_lsb_release.LSB_KEY_BUILDER_PATH: self.builder})
666
Alex Klein231d2da2019-07-22 16:44:45 -0600667 test_controller.MoblabVmTest(request, response, self.api_config)
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600668
669 self.assertEqual(
670 self.mock_create_moblab_vms.call_args_list,
Evan Hernandeze1e05d32019-07-19 12:32:18 -0600671 [mock.call(mock.ANY, self.chroot_dir, self.image_payload_dir)])
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600672 self.assertEqual(
673 self.mock_prepare_moblab_vm_image_cache.call_args_list,
674 [mock.call(mock.ANY, self.builder, [self.autotest_payload_dir])])
675 self.assertEqual(
676 self.mock_run_moblab_vm_tests.call_args_list,
Evan Hernandez655e8042019-06-13 12:50:44 -0600677 [mock.call(mock.ANY, mock.ANY, self.builder, self.image_cache_dir,
678 mock.ANY)])
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600679 self.assertEqual(
680 self.mock_validate_moblab_vm_tests.call_args_list,
681 [mock.call(mock.ANY)])
682
683 def testImageMissingBuilder(self):
684 """MoblabVmTest dies when builder path not found in lsb-release."""
685 request = self._Input()
686 response = self._Output()
687
Mike Frysingere652ba12019-09-08 00:57:43 -0400688 self.PatchObject(key_value_store, 'LoadFile', return_value={})
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600689
690 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600691 test_controller.MoblabVmTest(request, response, self.api_config)
David Wellingc1433c22021-06-25 16:29:48 +0000692
693
694class GetArtifactsTest(cros_test_lib.MockTempDirTestCase):
695 """Test GetArtifacts."""
696
697 CODE_COVERAGE_LLVM_ARTIFACT_TYPE = (
698 common_pb2.ArtifactsByService.Test.ArtifactType.CODE_COVERAGE_LLVM_JSON
699 )
700
701 def setUp(self):
702 """Set up the class for tests."""
703 chroot_dir = os.path.join(self.tempdir, 'chroot')
704 osutils.SafeMakedirs(chroot_dir)
705 osutils.SafeMakedirs(os.path.join(chroot_dir, 'tmp'))
706 self.chroot = chroot_lib.Chroot(chroot_dir)
707
708 sysroot_path = os.path.join(chroot_dir, 'build', 'board')
709 osutils.SafeMakedirs(sysroot_path)
710 self.sysroot = sysroot_lib.Sysroot(sysroot_path)
711
712 def testReturnsEmptyListWhenNoOutputArtifactsProvided(self):
713 """Test empty list is returned when there are no output_artifacts."""
714 result = test_controller.GetArtifacts(
715 common_pb2.ArtifactsByService.Test(output_artifacts=[]),
716 self.chroot, self.sysroot, self.tempdir)
717
718 self.assertEqual(len(result), 0)
719
720 def testShouldCallBundleCodeCoverageLlvmJsonForEachValidArtifact(self):
721 """Test BundleCodeCoverageLlvmJson is called on each valid artifact."""
722 BundleCodeCoverageLlvmJson_mock = self.PatchObject(
723 test_service, 'BundleCodeCoverageLlvmJson', return_value='test')
724
725 test_controller.GetArtifacts(
726 common_pb2.ArtifactsByService.Test(output_artifacts=[
727 # Valid
728 common_pb2.ArtifactsByService.Test.ArtifactInfo(
729 artifact_types=[
730 self.CODE_COVERAGE_LLVM_ARTIFACT_TYPE
731 ]
732 ),
733
734 # Invalid
735 common_pb2.ArtifactsByService.Test.ArtifactInfo(
736 artifact_types=[
737 common_pb2.ArtifactsByService.Test.ArtifactType.UNIT_TESTS
738 ]
739 ),
740 ]),
741 self.chroot, self.sysroot, self.tempdir)
742
743 BundleCodeCoverageLlvmJson_mock.assert_called_once()
744
745 def testShouldReturnValidResult(self):
746 """Test result contains paths and code_coverage_llvm_json type."""
747 self.PatchObject(test_service, 'BundleCodeCoverageLlvmJson',
748 return_value='test')
749
750 result = test_controller.GetArtifacts(
751 common_pb2.ArtifactsByService.Test(output_artifacts=[
752 # Valid
753 common_pb2.ArtifactsByService.Test.ArtifactInfo(
754 artifact_types=[
755 self.CODE_COVERAGE_LLVM_ARTIFACT_TYPE
756 ]
757 ),
758 ]),
759 self.chroot, self.sysroot, self.tempdir)
760
761 self.assertEqual(result[0]['paths'], ['test'])
762 self.assertEqual(result[0]['type'], self.CODE_COVERAGE_LLVM_ARTIFACT_TYPE)