blob: 156a3d2c1a5e59e5282a5feffb06f53a54bd1d8e [file] [log] [blame]
Alex Kleina2e42c42019-04-17 16:13:19 -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"""The test controller tests."""
7
8from __future__ import print_function
9
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -070010import os
11
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -060012import contextlib
Alex Kleinfa6ebdc2019-05-10 10:57:31 -060013import mock
14
Alex Klein231d2da2019-07-22 16:44:45 -060015from chromite.api import api_config
Alex Klein8cb365a2019-05-15 16:24:53 -060016from chromite.api import controller
Alex Kleina2e42c42019-04-17 16:13:19 -060017from chromite.api.controller import test as test_controller
Evan Hernandez4e388a52019-05-01 12:16:33 -060018from chromite.api.gen.chromiumos import common_pb2
Alex Kleina2e42c42019-04-17 16:13:19 -060019from chromite.api.gen.chromite.api import test_pb2
Evan Hernandeze1e05d32019-07-19 12:32:18 -060020from chromite.lib import chroot_lib
Alex Kleina2e42c42019-04-17 16:13:19 -060021from chromite.lib import cros_build_lib
22from chromite.lib import cros_test_lib
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -060023from chromite.lib import image_lib
Alex Kleina2e42c42019-04-17 16:13:19 -060024from chromite.lib import osutils
25from chromite.lib import portage_util
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -060026from chromite.scripts import cros_set_lsb_release
27from chromite.service import test as test_service
Mike Frysingere652ba12019-09-08 00:57:43 -040028from chromite.utils import key_value_store
Alex Kleina2e42c42019-04-17 16:13:19 -060029
30
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -070031class DebugInfoTestTest(cros_test_lib.MockTempDirTestCase,
32 api_config.ApiConfigMixin):
33 """Tests for the DebugInfoTest function."""
34
35 def setUp(self):
36 self.board = 'board'
37 self.chroot_path = os.path.join(self.tempdir, 'chroot')
38 self.sysroot_path = '/build/board'
39 self.full_sysroot_path = os.path.join(self.chroot_path,
40 self.sysroot_path.lstrip(os.sep))
41 osutils.SafeMakedirs(self.full_sysroot_path)
42
43 def _GetInput(self, sysroot_path=None, build_target=None):
44 """Helper to build an input message instance."""
45 proto = test_pb2.DebugInfoTestRequest()
46 if sysroot_path:
47 proto.sysroot.path = sysroot_path
48 if build_target:
49 proto.sysroot.build_target.name = build_target
50 return proto
51
52 def _GetOutput(self):
53 """Helper to get an empty output message instance."""
54 return test_pb2.DebugInfoTestResponse()
55
56 def testValidateOnly(self):
57 """Sanity check that a validate only call does not execute any logic."""
58 patch = self.PatchObject(test_service, 'DebugInfoTest')
59 input_msg = self._GetInput(sysroot_path=self.full_sysroot_path)
60 test_controller.DebugInfoTest(input_msg, self._GetOutput(),
61 self.validate_only_config)
62 patch.assert_not_called()
63
Michael Mortensen85d38402019-12-12 09:50:29 -070064 def testMockError(self):
65 """Test mock error call does not execute any logic, returns error."""
66 patch = self.PatchObject(test_service, 'DebugInfoTest')
67
68 input_msg = self._GetInput(sysroot_path=self.full_sysroot_path)
69 rc = test_controller.DebugInfoTest(input_msg, self._GetOutput(),
70 self.mock_error_config)
71 patch.assert_not_called()
72 self.assertEqual(controller.RETURN_CODE_COMPLETED_UNSUCCESSFULLY, rc)
73
74 def testMockCall(self):
75 """Test mock call does not execute any logic, returns success."""
76 patch = self.PatchObject(test_service, 'DebugInfoTest')
77
78 input_msg = self._GetInput(sysroot_path=self.full_sysroot_path)
79 rc = test_controller.DebugInfoTest(input_msg, self._GetOutput(),
80 self.mock_call_config)
81 patch.assert_not_called()
82 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
83
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -070084 def testNoBuildTargetNoSysrootFails(self):
85 """Test missing build target name and sysroot path fails."""
86 input_msg = self._GetInput()
87 output_msg = self._GetOutput()
88 with self.assertRaises(cros_build_lib.DieSystemExit):
89 test_controller.DebugInfoTest(input_msg, output_msg, self.api_config)
90
91 def testDebugInfoTest(self):
92 """Call DebugInfoTest with valid sysroot_path."""
93 request = self._GetInput(sysroot_path=self.full_sysroot_path)
94
95 test_controller.DebugInfoTest(request, self._GetOutput(), self.api_config)
96
97
Alex Klein231d2da2019-07-22 16:44:45 -060098class BuildTargetUnitTestTest(cros_test_lib.MockTempDirTestCase,
99 api_config.ApiConfigMixin):
Alex Kleina2e42c42019-04-17 16:13:19 -0600100 """Tests for the UnitTest function."""
101
102 def _GetInput(self, board=None, result_path=None, chroot_path=None,
Alex Kleinf2674462019-05-16 16:47:24 -0600103 cache_dir=None, empty_sysroot=None, blacklist=None):
Alex Kleina2e42c42019-04-17 16:13:19 -0600104 """Helper to build an input message instance."""
Alex Kleinf2674462019-05-16 16:47:24 -0600105 formatted_blacklist = []
106 for pkg in blacklist or []:
107 formatted_blacklist.append({'category': pkg.category,
108 'package_name': pkg.package})
109
Alex Kleina2e42c42019-04-17 16:13:19 -0600110 return test_pb2.BuildTargetUnitTestRequest(
111 build_target={'name': board}, result_path=result_path,
Alex Kleinfa6ebdc2019-05-10 10:57:31 -0600112 chroot={'path': chroot_path, 'cache_dir': cache_dir},
Alex Kleinf2674462019-05-16 16:47:24 -0600113 flags={'empty_sysroot': empty_sysroot},
114 package_blacklist=formatted_blacklist,
Alex Kleina2e42c42019-04-17 16:13:19 -0600115 )
116
117 def _GetOutput(self):
118 """Helper to get an empty output message instance."""
119 return test_pb2.BuildTargetUnitTestResponse()
120
Alex Klein231d2da2019-07-22 16:44:45 -0600121 def testValidateOnly(self):
122 """Sanity check that a validate only call does not execute any logic."""
123 patch = self.PatchObject(test_service, 'BuildTargetUnitTest')
124
125 input_msg = self._GetInput(board='board', result_path=self.tempdir)
126 test_controller.BuildTargetUnitTest(input_msg, self._GetOutput(),
127 self.validate_only_config)
128 patch.assert_not_called()
129
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700130 def testMockCall(self):
131 """Test that a mock call does not execute logic, returns mocked value."""
132 patch = self.PatchObject(test_service, 'BuildTargetUnitTest')
133
134 input_msg = self._GetInput(board='board', result_path=self.tempdir)
135 response = self._GetOutput()
136 test_controller.BuildTargetUnitTest(input_msg, response,
137 self.mock_call_config)
138 patch.assert_not_called()
139 self.assertEqual(response.tarball_path,
140 os.path.join(input_msg.result_path, 'unit_tests.tar'))
141
142 def testMockError(self):
Michael Mortensen85d38402019-12-12 09:50:29 -0700143 """Test that a mock error does not execute logic, returns error."""
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700144 patch = self.PatchObject(test_service, 'BuildTargetUnitTest')
145
146 input_msg = self._GetInput(board='board', result_path=self.tempdir)
147 response = self._GetOutput()
148 rc = test_controller.BuildTargetUnitTest(input_msg, response,
149 self.mock_error_config)
150 patch.assert_not_called()
151 self.assertEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
152 self.assertTrue(response.failed_packages)
153 self.assertEqual(response.failed_packages[0].category, 'foo')
154 self.assertEqual(response.failed_packages[0].package_name, 'bar')
155 self.assertEqual(response.failed_packages[1].category, 'cat')
156 self.assertEqual(response.failed_packages[1].package_name, 'pkg')
157
Alex Kleina2e42c42019-04-17 16:13:19 -0600158 def testNoArgumentFails(self):
159 """Test no arguments fails."""
160 input_msg = self._GetInput()
161 output_msg = self._GetOutput()
162 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600163 test_controller.BuildTargetUnitTest(input_msg, output_msg,
164 self.api_config)
Alex Kleina2e42c42019-04-17 16:13:19 -0600165
166 def testNoBuildTargetFails(self):
167 """Test missing build target name fails."""
168 input_msg = self._GetInput(result_path=self.tempdir)
169 output_msg = self._GetOutput()
170 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600171 test_controller.BuildTargetUnitTest(input_msg, output_msg,
172 self.api_config)
Alex Kleina2e42c42019-04-17 16:13:19 -0600173
174 def testNoResultPathFails(self):
175 """Test missing result path fails."""
176 # Missing result_path.
177 input_msg = self._GetInput(board='board')
178 output_msg = self._GetOutput()
179 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600180 test_controller.BuildTargetUnitTest(input_msg, output_msg,
181 self.api_config)
Alex Kleina2e42c42019-04-17 16:13:19 -0600182
183 def testPackageBuildFailure(self):
184 """Test handling of raised BuildPackageFailure."""
185 tempdir = osutils.TempDir(base_dir=self.tempdir)
186 self.PatchObject(osutils, 'TempDir', return_value=tempdir)
187
188 pkgs = ['cat/pkg', 'foo/bar']
189 expected = [('cat', 'pkg'), ('foo', 'bar')]
Alex Kleina2e42c42019-04-17 16:13:19 -0600190
Alex Klein38c7d9e2019-05-08 09:31:19 -0600191 result = test_service.BuildTargetUnitTestResult(1, None)
192 result.failed_cpvs = [portage_util.SplitCPV(p, strict=False) for p in pkgs]
193 self.PatchObject(test_service, 'BuildTargetUnitTest', return_value=result)
Alex Kleina2e42c42019-04-17 16:13:19 -0600194
195 input_msg = self._GetInput(board='board', result_path=self.tempdir)
196 output_msg = self._GetOutput()
197
Alex Klein231d2da2019-07-22 16:44:45 -0600198 rc = test_controller.BuildTargetUnitTest(input_msg, output_msg,
199 self.api_config)
Alex Kleina2e42c42019-04-17 16:13:19 -0600200
Alex Klein8cb365a2019-05-15 16:24:53 -0600201 self.assertEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
Alex Kleina2e42c42019-04-17 16:13:19 -0600202 self.assertTrue(output_msg.failed_packages)
203 failed = []
204 for pi in output_msg.failed_packages:
205 failed.append((pi.category, pi.package_name))
Mike Frysinger678735c2019-09-28 18:23:28 -0400206 self.assertCountEqual(expected, failed)
Alex Kleina2e42c42019-04-17 16:13:19 -0600207
208 def testOtherBuildScriptFailure(self):
209 """Test build script failure due to non-package emerge error."""
210 tempdir = osutils.TempDir(base_dir=self.tempdir)
211 self.PatchObject(osutils, 'TempDir', return_value=tempdir)
212
Alex Klein38c7d9e2019-05-08 09:31:19 -0600213 result = test_service.BuildTargetUnitTestResult(1, None)
214 self.PatchObject(test_service, 'BuildTargetUnitTest', return_value=result)
Alex Kleina2e42c42019-04-17 16:13:19 -0600215
Alex Kleinf2674462019-05-16 16:47:24 -0600216 pkgs = ['foo/bar', 'cat/pkg']
217 blacklist = [portage_util.SplitCPV(p, strict=False) for p in pkgs]
Alex Kleinfa6ebdc2019-05-10 10:57:31 -0600218 input_msg = self._GetInput(board='board', result_path=self.tempdir,
Alex Kleinf2674462019-05-16 16:47:24 -0600219 empty_sysroot=True, blacklist=blacklist)
Alex Kleina2e42c42019-04-17 16:13:19 -0600220 output_msg = self._GetOutput()
221
Alex Klein231d2da2019-07-22 16:44:45 -0600222 rc = test_controller.BuildTargetUnitTest(input_msg, output_msg,
223 self.api_config)
Alex Kleina2e42c42019-04-17 16:13:19 -0600224
Alex Klein8cb365a2019-05-15 16:24:53 -0600225 self.assertEqual(controller.RETURN_CODE_COMPLETED_UNSUCCESSFULLY, rc)
Alex Kleina2e42c42019-04-17 16:13:19 -0600226 self.assertFalse(output_msg.failed_packages)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600227
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700228 def testBuildTargetUnitTest(self):
229 """Test BuildTargetUnitTest successful call."""
230 input_msg = self._GetInput(board='board', result_path=self.tempdir)
231
232 result = test_service.BuildTargetUnitTestResult(0, None)
233 self.PatchObject(test_service, 'BuildTargetUnitTest', return_value=result)
234
235 tarball_result = os.path.join(input_msg.result_path, 'unit_tests.tar')
236 self.PatchObject(test_service, 'BuildTargetUnitTestTarball',
237 return_value=tarball_result)
238
239 response = self._GetOutput()
240 test_controller.BuildTargetUnitTest(input_msg, response,
241 self.api_config)
242 self.assertEqual(response.tarball_path,
243 os.path.join(input_msg.result_path, 'unit_tests.tar'))
244
Evan Hernandez4e388a52019-05-01 12:16:33 -0600245
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -0700246class ChromiteUnitTestTest(cros_test_lib.MockTestCase,
247 api_config.ApiConfigMixin):
248 """Tests for the ChromiteInfoTest function."""
249
250 def setUp(self):
251 self.board = 'board'
252 self.chroot_path = '/path/to/chroot'
253
254 def _GetInput(self, chroot_path=None):
255 """Helper to build an input message instance."""
256 proto = test_pb2.ChromiteUnitTestRequest(
257 chroot={'path': chroot_path},
258 )
259 return proto
260
261 def _GetOutput(self):
262 """Helper to get an empty output message instance."""
263 return test_pb2.ChromiteUnitTestResponse()
264
265 def testValidateOnly(self):
266 """Sanity check that a validate only call does not execute any logic."""
267 patch = self.PatchObject(cros_build_lib, 'run')
268
269 input_msg = self._GetInput(chroot_path=self.chroot_path)
270 test_controller.ChromiteUnitTest(input_msg, self._GetOutput(),
271 self.validate_only_config)
272 patch.assert_not_called()
273
Michael Mortensen7a860eb2019-12-03 20:25:15 -0700274 def testMockError(self):
275 """Test mock error call does not execute any logic, returns error."""
276 patch = self.PatchObject(cros_build_lib, 'run')
277
278 input_msg = self._GetInput(chroot_path=self.chroot_path)
279 rc = test_controller.ChromiteUnitTest(input_msg, self._GetOutput(),
280 self.mock_error_config)
281 patch.assert_not_called()
282 self.assertEqual(controller.RETURN_CODE_COMPLETED_UNSUCCESSFULLY, rc)
283
284 def testMockCall(self):
285 """Test mock call does not execute any logic, returns success."""
286 patch = self.PatchObject(cros_build_lib, 'run')
287
288 input_msg = self._GetInput(chroot_path=self.chroot_path)
289 rc = test_controller.ChromiteUnitTest(input_msg, self._GetOutput(),
290 self.mock_call_config)
291 patch.assert_not_called()
292 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
293
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -0700294 def testChromiteUnitTest(self):
295 """Call ChromiteUnitTest with mocked cros_build_lib.run."""
296 request = self._GetInput(chroot_path=self.chroot_path)
297 patch = self.PatchObject(
298 cros_build_lib, 'run',
299 return_value=cros_build_lib.CommandResult(returncode=0))
300
301 test_controller.ChromiteUnitTest(request, self._GetOutput(),
302 self.api_config)
303 patch.assert_called_once()
304
305
Alex Klein4bc8f4f2019-08-16 14:53:30 -0600306class CrosSigningTestTest(cros_test_lib.RunCommandTestCase,
307 api_config.ApiConfigMixin):
308 """CrosSigningTest tests."""
309
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700310 def setUp(self):
311 self.chroot_path = '/path/to/chroot'
312
313 def _GetInput(self, chroot_path=None):
314 """Helper to build an input message instance."""
315 proto = test_pb2.CrosSigningTestRequest(
316 chroot={'path': chroot_path},
317 )
318 return proto
319
320 def _GetOutput(self):
321 """Helper to get an empty output message instance."""
322 return test_pb2.CrosSigningTestResponse()
323
Alex Klein4bc8f4f2019-08-16 14:53:30 -0600324 def testValidateOnly(self):
325 """Sanity check that a validate only call does not execute any logic."""
326 test_controller.CrosSigningTest(None, None, self.validate_only_config)
327 self.assertFalse(self.rc.call_count)
328
Michael Mortensen7a7646d2019-12-12 15:36:14 -0700329 def testMockCall(self):
330 """Test mock call does not execute any logic, returns success."""
331 rc = test_controller.CrosSigningTest(None, None, self.mock_call_config)
332 self.assertFalse(self.rc.call_count)
333 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
334
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700335 def testCrosSigningTest(self):
336 """Call CrosSigningTest with mocked cros_build_lib.run."""
337 request = self._GetInput(chroot_path=self.chroot_path)
338 patch = self.PatchObject(
339 cros_build_lib, 'run',
340 return_value=cros_build_lib.CommandResult(returncode=0))
341
342 test_controller.CrosSigningTest(request, self._GetOutput(),
343 self.api_config)
344 patch.assert_called_once()
345
Alex Klein4bc8f4f2019-08-16 14:53:30 -0600346
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600347class SimpleChromeWorkflowTestTest(cros_test_lib.MockTestCase,
348 api_config.ApiConfigMixin):
349 """Test the SimpleChromeWorkflowTest endpoint."""
350
351 @staticmethod
352 def _Output():
353 return test_pb2.SimpleChromeWorkflowTestResponse()
354
355 def _Input(self, sysroot_path=None, build_target=None, chrome_root=None,
356 goma_config=None):
357 proto = test_pb2.SimpleChromeWorkflowTestRequest()
358 if sysroot_path:
359 proto.sysroot.path = sysroot_path
360 if build_target:
361 proto.sysroot.build_target.name = build_target
362 if chrome_root:
363 proto.chrome_root = chrome_root
364 if goma_config:
365 proto.goma_config = goma_config
366 return proto
367
368 def setUp(self):
369 self.chrome_path = 'path/to/chrome'
370 self.sysroot_dir = 'build/board'
371 self.build_target = 'amd64'
372 self.mock_simple_chrome_workflow_test = self.PatchObject(
373 test_service, 'SimpleChromeWorkflowTest')
374
375 def testMissingBuildTarget(self):
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700376 """Test SimpleChromeWorkflowTest dies when build_target not set."""
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600377 input_proto = self._Input(build_target=None, sysroot_path='/sysroot/dir',
378 chrome_root='/chrome/path')
379 with self.assertRaises(cros_build_lib.DieSystemExit):
380 test_controller.SimpleChromeWorkflowTest(input_proto, None,
381 self.api_config)
382
383 def testMissingSysrootPath(self):
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700384 """Test SimpleChromeWorkflowTest dies when build_target not set."""
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600385 input_proto = self._Input(build_target='board', sysroot_path=None,
386 chrome_root='/chrome/path')
387 with self.assertRaises(cros_build_lib.DieSystemExit):
388 test_controller.SimpleChromeWorkflowTest(input_proto, None,
389 self.api_config)
390
391 def testMissingChromeRoot(self):
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700392 """Test SimpleChromeWorkflowTest dies when build_target not set."""
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600393 input_proto = self._Input(build_target='board', sysroot_path='/sysroot/dir',
394 chrome_root=None)
395 with self.assertRaises(cros_build_lib.DieSystemExit):
396 test_controller.SimpleChromeWorkflowTest(input_proto, None,
397 self.api_config)
398
399 def testSimpleChromeWorkflowTest(self):
400 """Call SimpleChromeWorkflowTest with valid args and temp dir."""
401 request = self._Input(sysroot_path='sysroot_path', build_target='board',
402 chrome_root='/path/to/chrome')
403 response = self._Output()
404
405 test_controller.SimpleChromeWorkflowTest(request, response, self.api_config)
406 self.mock_simple_chrome_workflow_test.assert_called()
407
408 def testValidateOnly(self):
409 request = self._Input(sysroot_path='sysroot_path', build_target='board',
410 chrome_root='/path/to/chrome')
411 test_controller.SimpleChromeWorkflowTest(request, self._Output(),
412 self.validate_only_config)
413 self.mock_simple_chrome_workflow_test.assert_not_called()
414
Michael Mortensen7a7646d2019-12-12 15:36:14 -0700415 def testMockCall(self):
416 """Test mock call does not execute any logic, returns success."""
417 patch = self.mock_simple_chrome_workflow_test = self.PatchObject(
418 test_service, 'SimpleChromeWorkflowTest')
419
420 request = self._Input(sysroot_path='sysroot_path', build_target='board',
421 chrome_root='/path/to/chrome')
422 rc = test_controller.SimpleChromeWorkflowTest(request, self._Output(),
423 self.mock_call_config)
424 patch.assert_not_called()
425 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
426
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600427
Alex Klein231d2da2019-07-22 16:44:45 -0600428class VmTestTest(cros_test_lib.RunCommandTestCase, api_config.ApiConfigMixin):
Evan Hernandez4e388a52019-05-01 12:16:33 -0600429 """Test the VmTest endpoint."""
430
431 def _GetInput(self, **kwargs):
432 values = dict(
433 build_target=common_pb2.BuildTarget(name='target'),
Alex Klein311b8022019-06-05 16:00:07 -0600434 vm_path=common_pb2.Path(path='/path/to/image.bin',
435 location=common_pb2.Path.INSIDE),
Evan Hernandez4e388a52019-05-01 12:16:33 -0600436 test_harness=test_pb2.VmTestRequest.TAST,
437 vm_tests=[test_pb2.VmTestRequest.VmTest(pattern='suite')],
438 ssh_options=test_pb2.VmTestRequest.SshOptions(
Alex Klein231d2da2019-07-22 16:44:45 -0600439 port=1234, private_key_path={'path': '/path/to/id_rsa',
Alex Kleinaa705412019-06-04 15:00:30 -0600440 'location': common_pb2.Path.INSIDE}),
Evan Hernandez4e388a52019-05-01 12:16:33 -0600441 )
442 values.update(kwargs)
443 return test_pb2.VmTestRequest(**values)
444
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700445 def _Output(self):
446 return test_pb2.VmTestResponse()
447
Alex Klein231d2da2019-07-22 16:44:45 -0600448 def testValidateOnly(self):
449 """Sanity check that a validate only call does not execute any logic."""
450 test_controller.VmTest(self._GetInput(), None, self.validate_only_config)
451 self.assertEqual(0, self.rc.call_count)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600452
Michael Mortensen7a7646d2019-12-12 15:36:14 -0700453 def testMockCall(self):
454 """Test mock call does not execute any logic."""
455 patch = self.PatchObject(cros_build_lib, 'run')
456
457 request = self._GetInput()
458 response = self._Output()
459 # VmTest does not return a value, checking mocked value is flagged by lint.
460 test_controller.VmTest(request, response, self.mock_call_config)
461 patch.assert_not_called()
462
Evan Hernandez4e388a52019-05-01 12:16:33 -0600463 def testTastAllOptions(self):
464 """Test VmTest for Tast with all options set."""
Alex Klein231d2da2019-07-22 16:44:45 -0600465 test_controller.VmTest(self._GetInput(), None, self.api_config)
466 self.assertCommandContains([
Achuith Bhandarkara9e9c3d2019-05-22 13:56:11 -0700467 'cros_run_test', '--debug', '--no-display', '--copy-on-write',
Evan Hernandez4e388a52019-05-01 12:16:33 -0600468 '--board', 'target',
469 '--image-path', '/path/to/image.bin',
470 '--tast', 'suite',
471 '--ssh-port', '1234',
472 '--private-key', '/path/to/id_rsa',
473 ])
474
475 def testAutotestAllOptions(self):
476 """Test VmTest for Autotest with all options set."""
477 input_proto = self._GetInput(test_harness=test_pb2.VmTestRequest.AUTOTEST)
Alex Klein231d2da2019-07-22 16:44:45 -0600478 test_controller.VmTest(input_proto, None, self.api_config)
479 self.assertCommandContains([
Achuith Bhandarkara9e9c3d2019-05-22 13:56:11 -0700480 'cros_run_test', '--debug', '--no-display', '--copy-on-write',
Evan Hernandez4e388a52019-05-01 12:16:33 -0600481 '--board', 'target',
482 '--image-path', '/path/to/image.bin',
483 '--autotest', 'suite',
484 '--ssh-port', '1234',
485 '--private-key', '/path/to/id_rsa',
486 '--test_that-args=--whitelist-chrome-crashes',
487 ])
488
489 def testMissingBuildTarget(self):
490 """Test VmTest dies when build_target not set."""
491 input_proto = self._GetInput(build_target=None)
492 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600493 test_controller.VmTest(input_proto, None, self.api_config)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600494
495 def testMissingVmImage(self):
496 """Test VmTest dies when vm_image not set."""
Alex Klein311b8022019-06-05 16:00:07 -0600497 input_proto = self._GetInput(vm_path=None)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600498 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600499 test_controller.VmTest(input_proto, None, self.api_config)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600500
501 def testMissingTestHarness(self):
502 """Test VmTest dies when test_harness not specified."""
503 input_proto = self._GetInput(
504 test_harness=test_pb2.VmTestRequest.UNSPECIFIED)
505 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600506 test_controller.VmTest(input_proto, None, self.api_config)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600507
508 def testMissingVmTests(self):
509 """Test VmTest dies when vm_tests not set."""
510 input_proto = self._GetInput(vm_tests=[])
511 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600512 test_controller.VmTest(input_proto, None, self.api_config)
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600513
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700514 def testVmTest(self):
515 """Call VmTest with valid args and temp dir."""
516 request = self._GetInput()
517 response = self._Output()
518 patch = self.PatchObject(
519 cros_build_lib, 'run',
520 return_value=cros_build_lib.CommandResult(returncode=0))
521
522 test_controller.VmTest(request, response, self.api_config)
523 patch.assert_called()
524
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600525
Alex Klein231d2da2019-07-22 16:44:45 -0600526class MoblabVmTestTest(cros_test_lib.MockTestCase, api_config.ApiConfigMixin):
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600527 """Test the MoblabVmTest endpoint."""
528
529 @staticmethod
530 def _Payload(path):
531 return test_pb2.MoblabVmTestRequest.Payload(
532 path=common_pb2.Path(path=path))
533
534 @staticmethod
535 def _Output():
536 return test_pb2.MoblabVmTestResponse()
537
538 def _Input(self):
539 return test_pb2.MoblabVmTestRequest(
Evan Hernandeze1e05d32019-07-19 12:32:18 -0600540 chroot=common_pb2.Chroot(path=self.chroot_dir),
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600541 image_payload=self._Payload(self.image_payload_dir),
542 cache_payloads=[self._Payload(self.autotest_payload_dir)])
543
544 def setUp(self):
Evan Hernandeze1e05d32019-07-19 12:32:18 -0600545 self.chroot_dir = '/chroot'
546 self.chroot_tmp_dir = '/chroot/tmp'
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600547 self.image_payload_dir = '/payloads/image'
548 self.autotest_payload_dir = '/payloads/autotest'
549 self.builder = 'moblab-generic-vm/R12-3.4.5-67.890'
550 self.image_cache_dir = '/mnt/moblab/cache'
551 self.image_mount_dir = '/mnt/image'
552
Evan Hernandeze1e05d32019-07-19 12:32:18 -0600553 self.PatchObject(chroot_lib.Chroot, 'tempdir', osutils.TempDir)
Evan Hernandez655e8042019-06-13 12:50:44 -0600554
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600555 self.mock_create_moblab_vms = self.PatchObject(
556 test_service, 'CreateMoblabVm')
557 self.mock_prepare_moblab_vm_image_cache = self.PatchObject(
558 test_service, 'PrepareMoblabVmImageCache',
559 return_value=self.image_cache_dir)
560 self.mock_run_moblab_vm_tests = self.PatchObject(
561 test_service, 'RunMoblabVmTest')
562 self.mock_validate_moblab_vm_tests = self.PatchObject(
563 test_service, 'ValidateMoblabVmTest')
564
565 @contextlib.contextmanager
Alex Klein38c7d9e2019-05-08 09:31:19 -0600566 def MockLoopbackPartitions(*_args, **_kwargs):
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600567 mount = mock.MagicMock()
Evan Hernandez40ee7452019-06-13 12:51:43 -0600568 mount.Mount.return_value = [self.image_mount_dir]
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600569 yield mount
Alex Klein231d2da2019-07-22 16:44:45 -0600570
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600571 self.PatchObject(image_lib, 'LoopbackPartitions', MockLoopbackPartitions)
572
Alex Klein231d2da2019-07-22 16:44:45 -0600573 def testValidateOnly(self):
574 """Sanity check that a validate only call does not execute any logic."""
575 test_controller.MoblabVmTest(self._Input(), self._Output(),
576 self.validate_only_config)
577 self.mock_create_moblab_vms.assert_not_called()
578
Michael Mortensen7a7646d2019-12-12 15:36:14 -0700579 def testMockCall(self):
580 """Test mock call does not execute any logic."""
581 patch = self.PatchObject(key_value_store, 'LoadFile')
582
583 # MoblabVmTest does not return a value, checking mocked value is flagged by
584 # lint.
585 test_controller.MoblabVmTest(self._Input(), self._Output(),
586 self.mock_call_config)
587 patch.assert_not_called()
588
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600589 def testImageContainsBuilder(self):
590 """MoblabVmTest calls service with correct args."""
591 request = self._Input()
592 response = self._Output()
593
594 self.PatchObject(
Mike Frysingere652ba12019-09-08 00:57:43 -0400595 key_value_store, 'LoadFile',
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600596 return_value={cros_set_lsb_release.LSB_KEY_BUILDER_PATH: self.builder})
597
Alex Klein231d2da2019-07-22 16:44:45 -0600598 test_controller.MoblabVmTest(request, response, self.api_config)
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600599
600 self.assertEqual(
601 self.mock_create_moblab_vms.call_args_list,
Evan Hernandeze1e05d32019-07-19 12:32:18 -0600602 [mock.call(mock.ANY, self.chroot_dir, self.image_payload_dir)])
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600603 self.assertEqual(
604 self.mock_prepare_moblab_vm_image_cache.call_args_list,
605 [mock.call(mock.ANY, self.builder, [self.autotest_payload_dir])])
606 self.assertEqual(
607 self.mock_run_moblab_vm_tests.call_args_list,
Evan Hernandez655e8042019-06-13 12:50:44 -0600608 [mock.call(mock.ANY, mock.ANY, self.builder, self.image_cache_dir,
609 mock.ANY)])
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600610 self.assertEqual(
611 self.mock_validate_moblab_vm_tests.call_args_list,
612 [mock.call(mock.ANY)])
613
614 def testImageMissingBuilder(self):
615 """MoblabVmTest dies when builder path not found in lsb-release."""
616 request = self._Input()
617 response = self._Output()
618
Mike Frysingere652ba12019-09-08 00:57:43 -0400619 self.PatchObject(key_value_store, 'LoadFile', return_value={})
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600620
621 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600622 test_controller.MoblabVmTest(request, response, self.api_config)