blob: b7f12a9e17009ccae6d5d5ea7f1c9eb75cc83bd8 [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
64 def testNoBuildTargetNoSysrootFails(self):
65 """Test missing build target name and sysroot path fails."""
66 input_msg = self._GetInput()
67 output_msg = self._GetOutput()
68 with self.assertRaises(cros_build_lib.DieSystemExit):
69 test_controller.DebugInfoTest(input_msg, output_msg, self.api_config)
70
71 def testDebugInfoTest(self):
72 """Call DebugInfoTest with valid sysroot_path."""
73 request = self._GetInput(sysroot_path=self.full_sysroot_path)
74
75 test_controller.DebugInfoTest(request, self._GetOutput(), self.api_config)
76
77
Alex Klein231d2da2019-07-22 16:44:45 -060078class BuildTargetUnitTestTest(cros_test_lib.MockTempDirTestCase,
79 api_config.ApiConfigMixin):
Alex Kleina2e42c42019-04-17 16:13:19 -060080 """Tests for the UnitTest function."""
81
82 def _GetInput(self, board=None, result_path=None, chroot_path=None,
Alex Kleinf2674462019-05-16 16:47:24 -060083 cache_dir=None, empty_sysroot=None, blacklist=None):
Alex Kleina2e42c42019-04-17 16:13:19 -060084 """Helper to build an input message instance."""
Alex Kleinf2674462019-05-16 16:47:24 -060085 formatted_blacklist = []
86 for pkg in blacklist or []:
87 formatted_blacklist.append({'category': pkg.category,
88 'package_name': pkg.package})
89
Alex Kleina2e42c42019-04-17 16:13:19 -060090 return test_pb2.BuildTargetUnitTestRequest(
91 build_target={'name': board}, result_path=result_path,
Alex Kleinfa6ebdc2019-05-10 10:57:31 -060092 chroot={'path': chroot_path, 'cache_dir': cache_dir},
Alex Kleinf2674462019-05-16 16:47:24 -060093 flags={'empty_sysroot': empty_sysroot},
94 package_blacklist=formatted_blacklist,
Alex Kleina2e42c42019-04-17 16:13:19 -060095 )
96
97 def _GetOutput(self):
98 """Helper to get an empty output message instance."""
99 return test_pb2.BuildTargetUnitTestResponse()
100
Alex Klein231d2da2019-07-22 16:44:45 -0600101 def testValidateOnly(self):
102 """Sanity check that a validate only call does not execute any logic."""
103 patch = self.PatchObject(test_service, 'BuildTargetUnitTest')
104
105 input_msg = self._GetInput(board='board', result_path=self.tempdir)
106 test_controller.BuildTargetUnitTest(input_msg, self._GetOutput(),
107 self.validate_only_config)
108 patch.assert_not_called()
109
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700110 def testMockCall(self):
111 """Test that a mock call does not execute logic, returns mocked value."""
112 patch = self.PatchObject(test_service, 'BuildTargetUnitTest')
113
114 input_msg = self._GetInput(board='board', result_path=self.tempdir)
115 response = self._GetOutput()
116 test_controller.BuildTargetUnitTest(input_msg, response,
117 self.mock_call_config)
118 patch.assert_not_called()
119 self.assertEqual(response.tarball_path,
120 os.path.join(input_msg.result_path, 'unit_tests.tar'))
121
122 def testMockError(self):
123 """Test that a mock error does not execute logic, returns mocked value."""
124 patch = self.PatchObject(test_service, 'BuildTargetUnitTest')
125
126 input_msg = self._GetInput(board='board', result_path=self.tempdir)
127 response = self._GetOutput()
128 rc = test_controller.BuildTargetUnitTest(input_msg, response,
129 self.mock_error_config)
130 patch.assert_not_called()
131 self.assertEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
132 self.assertTrue(response.failed_packages)
133 self.assertEqual(response.failed_packages[0].category, 'foo')
134 self.assertEqual(response.failed_packages[0].package_name, 'bar')
135 self.assertEqual(response.failed_packages[1].category, 'cat')
136 self.assertEqual(response.failed_packages[1].package_name, 'pkg')
137
Alex Kleina2e42c42019-04-17 16:13:19 -0600138 def testNoArgumentFails(self):
139 """Test no arguments fails."""
140 input_msg = self._GetInput()
141 output_msg = self._GetOutput()
142 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600143 test_controller.BuildTargetUnitTest(input_msg, output_msg,
144 self.api_config)
Alex Kleina2e42c42019-04-17 16:13:19 -0600145
146 def testNoBuildTargetFails(self):
147 """Test missing build target name fails."""
148 input_msg = self._GetInput(result_path=self.tempdir)
149 output_msg = self._GetOutput()
150 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600151 test_controller.BuildTargetUnitTest(input_msg, output_msg,
152 self.api_config)
Alex Kleina2e42c42019-04-17 16:13:19 -0600153
154 def testNoResultPathFails(self):
155 """Test missing result path fails."""
156 # Missing result_path.
157 input_msg = self._GetInput(board='board')
158 output_msg = self._GetOutput()
159 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600160 test_controller.BuildTargetUnitTest(input_msg, output_msg,
161 self.api_config)
Alex Kleina2e42c42019-04-17 16:13:19 -0600162
163 def testPackageBuildFailure(self):
164 """Test handling of raised BuildPackageFailure."""
165 tempdir = osutils.TempDir(base_dir=self.tempdir)
166 self.PatchObject(osutils, 'TempDir', return_value=tempdir)
167
168 pkgs = ['cat/pkg', 'foo/bar']
169 expected = [('cat', 'pkg'), ('foo', 'bar')]
Alex Kleina2e42c42019-04-17 16:13:19 -0600170
Alex Klein38c7d9e2019-05-08 09:31:19 -0600171 result = test_service.BuildTargetUnitTestResult(1, None)
172 result.failed_cpvs = [portage_util.SplitCPV(p, strict=False) for p in pkgs]
173 self.PatchObject(test_service, 'BuildTargetUnitTest', return_value=result)
Alex Kleina2e42c42019-04-17 16:13:19 -0600174
175 input_msg = self._GetInput(board='board', result_path=self.tempdir)
176 output_msg = self._GetOutput()
177
Alex Klein231d2da2019-07-22 16:44:45 -0600178 rc = test_controller.BuildTargetUnitTest(input_msg, output_msg,
179 self.api_config)
Alex Kleina2e42c42019-04-17 16:13:19 -0600180
Alex Klein8cb365a2019-05-15 16:24:53 -0600181 self.assertEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
Alex Kleina2e42c42019-04-17 16:13:19 -0600182 self.assertTrue(output_msg.failed_packages)
183 failed = []
184 for pi in output_msg.failed_packages:
185 failed.append((pi.category, pi.package_name))
Mike Frysinger678735c2019-09-28 18:23:28 -0400186 self.assertCountEqual(expected, failed)
Alex Kleina2e42c42019-04-17 16:13:19 -0600187
188 def testOtherBuildScriptFailure(self):
189 """Test build script failure due to non-package emerge error."""
190 tempdir = osutils.TempDir(base_dir=self.tempdir)
191 self.PatchObject(osutils, 'TempDir', return_value=tempdir)
192
Alex Klein38c7d9e2019-05-08 09:31:19 -0600193 result = test_service.BuildTargetUnitTestResult(1, None)
194 self.PatchObject(test_service, 'BuildTargetUnitTest', return_value=result)
Alex Kleina2e42c42019-04-17 16:13:19 -0600195
Alex Kleinf2674462019-05-16 16:47:24 -0600196 pkgs = ['foo/bar', 'cat/pkg']
197 blacklist = [portage_util.SplitCPV(p, strict=False) for p in pkgs]
Alex Kleinfa6ebdc2019-05-10 10:57:31 -0600198 input_msg = self._GetInput(board='board', result_path=self.tempdir,
Alex Kleinf2674462019-05-16 16:47:24 -0600199 empty_sysroot=True, blacklist=blacklist)
Alex Kleina2e42c42019-04-17 16:13:19 -0600200 output_msg = self._GetOutput()
201
Alex Klein231d2da2019-07-22 16:44:45 -0600202 rc = test_controller.BuildTargetUnitTest(input_msg, output_msg,
203 self.api_config)
Alex Kleina2e42c42019-04-17 16:13:19 -0600204
Alex Klein8cb365a2019-05-15 16:24:53 -0600205 self.assertEqual(controller.RETURN_CODE_COMPLETED_UNSUCCESSFULLY, rc)
Alex Kleina2e42c42019-04-17 16:13:19 -0600206 self.assertFalse(output_msg.failed_packages)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600207
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700208 def testBuildTargetUnitTest(self):
209 """Test BuildTargetUnitTest successful call."""
210 input_msg = self._GetInput(board='board', result_path=self.tempdir)
211
212 result = test_service.BuildTargetUnitTestResult(0, None)
213 self.PatchObject(test_service, 'BuildTargetUnitTest', return_value=result)
214
215 tarball_result = os.path.join(input_msg.result_path, 'unit_tests.tar')
216 self.PatchObject(test_service, 'BuildTargetUnitTestTarball',
217 return_value=tarball_result)
218
219 response = self._GetOutput()
220 test_controller.BuildTargetUnitTest(input_msg, response,
221 self.api_config)
222 self.assertEqual(response.tarball_path,
223 os.path.join(input_msg.result_path, 'unit_tests.tar'))
224
Evan Hernandez4e388a52019-05-01 12:16:33 -0600225
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -0700226class ChromiteUnitTestTest(cros_test_lib.MockTestCase,
227 api_config.ApiConfigMixin):
228 """Tests for the ChromiteInfoTest function."""
229
230 def setUp(self):
231 self.board = 'board'
232 self.chroot_path = '/path/to/chroot'
233
234 def _GetInput(self, chroot_path=None):
235 """Helper to build an input message instance."""
236 proto = test_pb2.ChromiteUnitTestRequest(
237 chroot={'path': chroot_path},
238 )
239 return proto
240
241 def _GetOutput(self):
242 """Helper to get an empty output message instance."""
243 return test_pb2.ChromiteUnitTestResponse()
244
245 def testValidateOnly(self):
246 """Sanity check that a validate only call does not execute any logic."""
247 patch = self.PatchObject(cros_build_lib, 'run')
248
249 input_msg = self._GetInput(chroot_path=self.chroot_path)
250 test_controller.ChromiteUnitTest(input_msg, self._GetOutput(),
251 self.validate_only_config)
252 patch.assert_not_called()
253
Michael Mortensen7a860eb2019-12-03 20:25:15 -0700254 def testMockError(self):
255 """Test mock error call does not execute any logic, returns error."""
256 patch = self.PatchObject(cros_build_lib, 'run')
257
258 input_msg = self._GetInput(chroot_path=self.chroot_path)
259 rc = test_controller.ChromiteUnitTest(input_msg, self._GetOutput(),
260 self.mock_error_config)
261 patch.assert_not_called()
262 self.assertEqual(controller.RETURN_CODE_COMPLETED_UNSUCCESSFULLY, rc)
263
264 def testMockCall(self):
265 """Test mock call does not execute any logic, returns success."""
266 patch = self.PatchObject(cros_build_lib, 'run')
267
268 input_msg = self._GetInput(chroot_path=self.chroot_path)
269 rc = test_controller.ChromiteUnitTest(input_msg, self._GetOutput(),
270 self.mock_call_config)
271 patch.assert_not_called()
272 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
273
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -0700274 def testChromiteUnitTest(self):
275 """Call ChromiteUnitTest with mocked cros_build_lib.run."""
276 request = self._GetInput(chroot_path=self.chroot_path)
277 patch = self.PatchObject(
278 cros_build_lib, 'run',
279 return_value=cros_build_lib.CommandResult(returncode=0))
280
281 test_controller.ChromiteUnitTest(request, self._GetOutput(),
282 self.api_config)
283 patch.assert_called_once()
284
285
Alex Klein4bc8f4f2019-08-16 14:53:30 -0600286class CrosSigningTestTest(cros_test_lib.RunCommandTestCase,
287 api_config.ApiConfigMixin):
288 """CrosSigningTest tests."""
289
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700290 def setUp(self):
291 self.chroot_path = '/path/to/chroot'
292
293 def _GetInput(self, chroot_path=None):
294 """Helper to build an input message instance."""
295 proto = test_pb2.CrosSigningTestRequest(
296 chroot={'path': chroot_path},
297 )
298 return proto
299
300 def _GetOutput(self):
301 """Helper to get an empty output message instance."""
302 return test_pb2.CrosSigningTestResponse()
303
Alex Klein4bc8f4f2019-08-16 14:53:30 -0600304 def testValidateOnly(self):
305 """Sanity check that a validate only call does not execute any logic."""
306 test_controller.CrosSigningTest(None, None, self.validate_only_config)
307 self.assertFalse(self.rc.call_count)
308
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700309 def testCrosSigningTest(self):
310 """Call CrosSigningTest with mocked cros_build_lib.run."""
311 request = self._GetInput(chroot_path=self.chroot_path)
312 patch = self.PatchObject(
313 cros_build_lib, 'run',
314 return_value=cros_build_lib.CommandResult(returncode=0))
315
316 test_controller.CrosSigningTest(request, self._GetOutput(),
317 self.api_config)
318 patch.assert_called_once()
319
Alex Klein4bc8f4f2019-08-16 14:53:30 -0600320
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600321class SimpleChromeWorkflowTestTest(cros_test_lib.MockTestCase,
322 api_config.ApiConfigMixin):
323 """Test the SimpleChromeWorkflowTest endpoint."""
324
325 @staticmethod
326 def _Output():
327 return test_pb2.SimpleChromeWorkflowTestResponse()
328
329 def _Input(self, sysroot_path=None, build_target=None, chrome_root=None,
330 goma_config=None):
331 proto = test_pb2.SimpleChromeWorkflowTestRequest()
332 if sysroot_path:
333 proto.sysroot.path = sysroot_path
334 if build_target:
335 proto.sysroot.build_target.name = build_target
336 if chrome_root:
337 proto.chrome_root = chrome_root
338 if goma_config:
339 proto.goma_config = goma_config
340 return proto
341
342 def setUp(self):
343 self.chrome_path = 'path/to/chrome'
344 self.sysroot_dir = 'build/board'
345 self.build_target = 'amd64'
346 self.mock_simple_chrome_workflow_test = self.PatchObject(
347 test_service, 'SimpleChromeWorkflowTest')
348
349 def testMissingBuildTarget(self):
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700350 """Test SimpleChromeWorkflowTest dies when build_target not set."""
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600351 input_proto = self._Input(build_target=None, sysroot_path='/sysroot/dir',
352 chrome_root='/chrome/path')
353 with self.assertRaises(cros_build_lib.DieSystemExit):
354 test_controller.SimpleChromeWorkflowTest(input_proto, None,
355 self.api_config)
356
357 def testMissingSysrootPath(self):
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700358 """Test SimpleChromeWorkflowTest dies when build_target not set."""
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600359 input_proto = self._Input(build_target='board', sysroot_path=None,
360 chrome_root='/chrome/path')
361 with self.assertRaises(cros_build_lib.DieSystemExit):
362 test_controller.SimpleChromeWorkflowTest(input_proto, None,
363 self.api_config)
364
365 def testMissingChromeRoot(self):
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700366 """Test SimpleChromeWorkflowTest dies when build_target not set."""
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600367 input_proto = self._Input(build_target='board', sysroot_path='/sysroot/dir',
368 chrome_root=None)
369 with self.assertRaises(cros_build_lib.DieSystemExit):
370 test_controller.SimpleChromeWorkflowTest(input_proto, None,
371 self.api_config)
372
373 def testSimpleChromeWorkflowTest(self):
374 """Call SimpleChromeWorkflowTest with valid args and temp dir."""
375 request = self._Input(sysroot_path='sysroot_path', build_target='board',
376 chrome_root='/path/to/chrome')
377 response = self._Output()
378
379 test_controller.SimpleChromeWorkflowTest(request, response, self.api_config)
380 self.mock_simple_chrome_workflow_test.assert_called()
381
382 def testValidateOnly(self):
383 request = self._Input(sysroot_path='sysroot_path', build_target='board',
384 chrome_root='/path/to/chrome')
385 test_controller.SimpleChromeWorkflowTest(request, self._Output(),
386 self.validate_only_config)
387 self.mock_simple_chrome_workflow_test.assert_not_called()
388
389
Alex Klein231d2da2019-07-22 16:44:45 -0600390class VmTestTest(cros_test_lib.RunCommandTestCase, api_config.ApiConfigMixin):
Evan Hernandez4e388a52019-05-01 12:16:33 -0600391 """Test the VmTest endpoint."""
392
393 def _GetInput(self, **kwargs):
394 values = dict(
395 build_target=common_pb2.BuildTarget(name='target'),
Alex Klein311b8022019-06-05 16:00:07 -0600396 vm_path=common_pb2.Path(path='/path/to/image.bin',
397 location=common_pb2.Path.INSIDE),
Evan Hernandez4e388a52019-05-01 12:16:33 -0600398 test_harness=test_pb2.VmTestRequest.TAST,
399 vm_tests=[test_pb2.VmTestRequest.VmTest(pattern='suite')],
400 ssh_options=test_pb2.VmTestRequest.SshOptions(
Alex Klein231d2da2019-07-22 16:44:45 -0600401 port=1234, private_key_path={'path': '/path/to/id_rsa',
Alex Kleinaa705412019-06-04 15:00:30 -0600402 'location': common_pb2.Path.INSIDE}),
Evan Hernandez4e388a52019-05-01 12:16:33 -0600403 )
404 values.update(kwargs)
405 return test_pb2.VmTestRequest(**values)
406
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700407 def _Output(self):
408 return test_pb2.VmTestResponse()
409
Alex Klein231d2da2019-07-22 16:44:45 -0600410 def testValidateOnly(self):
411 """Sanity check that a validate only call does not execute any logic."""
412 test_controller.VmTest(self._GetInput(), None, self.validate_only_config)
413 self.assertEqual(0, self.rc.call_count)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600414
415 def testTastAllOptions(self):
416 """Test VmTest for Tast with all options set."""
Alex Klein231d2da2019-07-22 16:44:45 -0600417 test_controller.VmTest(self._GetInput(), None, self.api_config)
418 self.assertCommandContains([
Achuith Bhandarkara9e9c3d2019-05-22 13:56:11 -0700419 'cros_run_test', '--debug', '--no-display', '--copy-on-write',
Evan Hernandez4e388a52019-05-01 12:16:33 -0600420 '--board', 'target',
421 '--image-path', '/path/to/image.bin',
422 '--tast', 'suite',
423 '--ssh-port', '1234',
424 '--private-key', '/path/to/id_rsa',
425 ])
426
427 def testAutotestAllOptions(self):
428 """Test VmTest for Autotest with all options set."""
429 input_proto = self._GetInput(test_harness=test_pb2.VmTestRequest.AUTOTEST)
Alex Klein231d2da2019-07-22 16:44:45 -0600430 test_controller.VmTest(input_proto, None, self.api_config)
431 self.assertCommandContains([
Achuith Bhandarkara9e9c3d2019-05-22 13:56:11 -0700432 'cros_run_test', '--debug', '--no-display', '--copy-on-write',
Evan Hernandez4e388a52019-05-01 12:16:33 -0600433 '--board', 'target',
434 '--image-path', '/path/to/image.bin',
435 '--autotest', 'suite',
436 '--ssh-port', '1234',
437 '--private-key', '/path/to/id_rsa',
438 '--test_that-args=--whitelist-chrome-crashes',
439 ])
440
441 def testMissingBuildTarget(self):
442 """Test VmTest dies when build_target not set."""
443 input_proto = self._GetInput(build_target=None)
444 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600445 test_controller.VmTest(input_proto, None, self.api_config)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600446
447 def testMissingVmImage(self):
448 """Test VmTest dies when vm_image not set."""
Alex Klein311b8022019-06-05 16:00:07 -0600449 input_proto = self._GetInput(vm_path=None)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600450 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600451 test_controller.VmTest(input_proto, None, self.api_config)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600452
453 def testMissingTestHarness(self):
454 """Test VmTest dies when test_harness not specified."""
455 input_proto = self._GetInput(
456 test_harness=test_pb2.VmTestRequest.UNSPECIFIED)
457 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600458 test_controller.VmTest(input_proto, None, self.api_config)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600459
460 def testMissingVmTests(self):
461 """Test VmTest dies when vm_tests not set."""
462 input_proto = self._GetInput(vm_tests=[])
463 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600464 test_controller.VmTest(input_proto, None, self.api_config)
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600465
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700466 def testVmTest(self):
467 """Call VmTest with valid args and temp dir."""
468 request = self._GetInput()
469 response = self._Output()
470 patch = self.PatchObject(
471 cros_build_lib, 'run',
472 return_value=cros_build_lib.CommandResult(returncode=0))
473
474 test_controller.VmTest(request, response, self.api_config)
475 patch.assert_called()
476
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600477
Alex Klein231d2da2019-07-22 16:44:45 -0600478class MoblabVmTestTest(cros_test_lib.MockTestCase, api_config.ApiConfigMixin):
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600479 """Test the MoblabVmTest endpoint."""
480
481 @staticmethod
482 def _Payload(path):
483 return test_pb2.MoblabVmTestRequest.Payload(
484 path=common_pb2.Path(path=path))
485
486 @staticmethod
487 def _Output():
488 return test_pb2.MoblabVmTestResponse()
489
490 def _Input(self):
491 return test_pb2.MoblabVmTestRequest(
Evan Hernandeze1e05d32019-07-19 12:32:18 -0600492 chroot=common_pb2.Chroot(path=self.chroot_dir),
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600493 image_payload=self._Payload(self.image_payload_dir),
494 cache_payloads=[self._Payload(self.autotest_payload_dir)])
495
496 def setUp(self):
Evan Hernandeze1e05d32019-07-19 12:32:18 -0600497 self.chroot_dir = '/chroot'
498 self.chroot_tmp_dir = '/chroot/tmp'
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600499 self.image_payload_dir = '/payloads/image'
500 self.autotest_payload_dir = '/payloads/autotest'
501 self.builder = 'moblab-generic-vm/R12-3.4.5-67.890'
502 self.image_cache_dir = '/mnt/moblab/cache'
503 self.image_mount_dir = '/mnt/image'
504
Evan Hernandeze1e05d32019-07-19 12:32:18 -0600505 self.PatchObject(chroot_lib.Chroot, 'tempdir', osutils.TempDir)
Evan Hernandez655e8042019-06-13 12:50:44 -0600506
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600507 self.mock_create_moblab_vms = self.PatchObject(
508 test_service, 'CreateMoblabVm')
509 self.mock_prepare_moblab_vm_image_cache = self.PatchObject(
510 test_service, 'PrepareMoblabVmImageCache',
511 return_value=self.image_cache_dir)
512 self.mock_run_moblab_vm_tests = self.PatchObject(
513 test_service, 'RunMoblabVmTest')
514 self.mock_validate_moblab_vm_tests = self.PatchObject(
515 test_service, 'ValidateMoblabVmTest')
516
517 @contextlib.contextmanager
Alex Klein38c7d9e2019-05-08 09:31:19 -0600518 def MockLoopbackPartitions(*_args, **_kwargs):
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600519 mount = mock.MagicMock()
Evan Hernandez40ee7452019-06-13 12:51:43 -0600520 mount.Mount.return_value = [self.image_mount_dir]
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600521 yield mount
Alex Klein231d2da2019-07-22 16:44:45 -0600522
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600523 self.PatchObject(image_lib, 'LoopbackPartitions', MockLoopbackPartitions)
524
Alex Klein231d2da2019-07-22 16:44:45 -0600525 def testValidateOnly(self):
526 """Sanity check that a validate only call does not execute any logic."""
527 test_controller.MoblabVmTest(self._Input(), self._Output(),
528 self.validate_only_config)
529 self.mock_create_moblab_vms.assert_not_called()
530
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600531 def testImageContainsBuilder(self):
532 """MoblabVmTest calls service with correct args."""
533 request = self._Input()
534 response = self._Output()
535
536 self.PatchObject(
Mike Frysingere652ba12019-09-08 00:57:43 -0400537 key_value_store, 'LoadFile',
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600538 return_value={cros_set_lsb_release.LSB_KEY_BUILDER_PATH: self.builder})
539
Alex Klein231d2da2019-07-22 16:44:45 -0600540 test_controller.MoblabVmTest(request, response, self.api_config)
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600541
542 self.assertEqual(
543 self.mock_create_moblab_vms.call_args_list,
Evan Hernandeze1e05d32019-07-19 12:32:18 -0600544 [mock.call(mock.ANY, self.chroot_dir, self.image_payload_dir)])
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600545 self.assertEqual(
546 self.mock_prepare_moblab_vm_image_cache.call_args_list,
547 [mock.call(mock.ANY, self.builder, [self.autotest_payload_dir])])
548 self.assertEqual(
549 self.mock_run_moblab_vm_tests.call_args_list,
Evan Hernandez655e8042019-06-13 12:50:44 -0600550 [mock.call(mock.ANY, mock.ANY, self.builder, self.image_cache_dir,
551 mock.ANY)])
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600552 self.assertEqual(
553 self.mock_validate_moblab_vm_tests.call_args_list,
554 [mock.call(mock.ANY)])
555
556 def testImageMissingBuilder(self):
557 """MoblabVmTest dies when builder path not found in lsb-release."""
558 request = self._Input()
559 response = self._Output()
560
Mike Frysingere652ba12019-09-08 00:57:43 -0400561 self.PatchObject(key_value_store, 'LoadFile', return_value={})
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600562
563 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600564 test_controller.MoblabVmTest(request, response, self.api_config)