blob: 500d431a53b51e230a2cce5a30577a43391743b0 [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
Alex Klein9f915782020-02-14 23:15:09 +000010import contextlib
Mike Frysingeref94e4c2020-02-10 23:59:54 -050011import os
Mike Frysingeref94e4c2020-02-10 23:59:54 -050012
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
Alex Klein18a60af2020-06-11 12:08:47 -060025from chromite.lib.parser import package_info
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
Navil Perezc0b29a82020-07-07 14:17:48 +0000102 def _GetInput(self,
103 board=None,
104 result_path=None,
105 chroot_path=None,
106 cache_dir=None,
107 empty_sysroot=None,
108 packages=None,
Alex Kleinb64e5f82020-09-23 10:55:31 -0600109 blocklist=None):
Alex Kleina2e42c42019-04-17 16:13:19 -0600110 """Helper to build an input message instance."""
Navil Perezc0b29a82020-07-07 14:17:48 +0000111 formatted_packages = []
112 for pkg in packages or []:
113 formatted_packages.append({
114 'category': pkg.category,
115 'package_name': pkg.package
116 })
Alex Kleinb64e5f82020-09-23 10:55:31 -0600117 formatted_blocklist = []
118 for pkg in blocklist or []:
119 formatted_blocklist.append({'category': pkg.category,
Alex Kleinf2674462019-05-16 16:47:24 -0600120 'package_name': pkg.package})
121
Alex Kleina2e42c42019-04-17 16:13:19 -0600122 return test_pb2.BuildTargetUnitTestRequest(
123 build_target={'name': board}, result_path=result_path,
Alex Kleinfa6ebdc2019-05-10 10:57:31 -0600124 chroot={'path': chroot_path, 'cache_dir': cache_dir},
Alex Kleinf2674462019-05-16 16:47:24 -0600125 flags={'empty_sysroot': empty_sysroot},
Alex Klein64ac34c2020-09-23 10:21:33 -0600126 packages=formatted_packages,
Alex Kleinb64e5f82020-09-23 10:55:31 -0600127 package_blacklist=formatted_blocklist,
Alex Kleina2e42c42019-04-17 16:13:19 -0600128 )
129
130 def _GetOutput(self):
131 """Helper to get an empty output message instance."""
132 return test_pb2.BuildTargetUnitTestResponse()
133
Alex Klein231d2da2019-07-22 16:44:45 -0600134 def testValidateOnly(self):
135 """Sanity check that a validate only call does not execute any logic."""
136 patch = self.PatchObject(test_service, 'BuildTargetUnitTest')
137
138 input_msg = self._GetInput(board='board', result_path=self.tempdir)
139 test_controller.BuildTargetUnitTest(input_msg, self._GetOutput(),
140 self.validate_only_config)
141 patch.assert_not_called()
142
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700143 def testMockCall(self):
144 """Test that a mock call does not execute logic, returns mocked value."""
145 patch = self.PatchObject(test_service, 'BuildTargetUnitTest')
146
147 input_msg = self._GetInput(board='board', result_path=self.tempdir)
148 response = self._GetOutput()
149 test_controller.BuildTargetUnitTest(input_msg, response,
150 self.mock_call_config)
151 patch.assert_not_called()
152 self.assertEqual(response.tarball_path,
153 os.path.join(input_msg.result_path, 'unit_tests.tar'))
154
155 def testMockError(self):
Michael Mortensen85d38402019-12-12 09:50:29 -0700156 """Test that a mock error does not execute logic, returns error."""
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700157 patch = self.PatchObject(test_service, 'BuildTargetUnitTest')
158
159 input_msg = self._GetInput(board='board', result_path=self.tempdir)
160 response = self._GetOutput()
161 rc = test_controller.BuildTargetUnitTest(input_msg, response,
162 self.mock_error_config)
163 patch.assert_not_called()
164 self.assertEqual(controller.RETURN_CODE_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
165 self.assertTrue(response.failed_packages)
166 self.assertEqual(response.failed_packages[0].category, 'foo')
167 self.assertEqual(response.failed_packages[0].package_name, 'bar')
168 self.assertEqual(response.failed_packages[1].category, 'cat')
169 self.assertEqual(response.failed_packages[1].package_name, 'pkg')
170
Alex Kleina2e42c42019-04-17 16:13:19 -0600171 def testNoArgumentFails(self):
172 """Test no arguments fails."""
173 input_msg = self._GetInput()
174 output_msg = self._GetOutput()
175 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600176 test_controller.BuildTargetUnitTest(input_msg, output_msg,
177 self.api_config)
Alex Kleina2e42c42019-04-17 16:13:19 -0600178
179 def testNoBuildTargetFails(self):
180 """Test missing build target name fails."""
181 input_msg = self._GetInput(result_path=self.tempdir)
182 output_msg = self._GetOutput()
183 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600184 test_controller.BuildTargetUnitTest(input_msg, output_msg,
185 self.api_config)
Alex Kleina2e42c42019-04-17 16:13:19 -0600186
187 def testNoResultPathFails(self):
188 """Test missing result path fails."""
189 # Missing result_path.
190 input_msg = self._GetInput(board='board')
191 output_msg = self._GetOutput()
192 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600193 test_controller.BuildTargetUnitTest(input_msg, output_msg,
194 self.api_config)
Alex Kleina2e42c42019-04-17 16:13:19 -0600195
Alex Klein64ac34c2020-09-23 10:21:33 -0600196 def testInvalidPackageFails(self):
197 """Test missing result path fails."""
198 # Missing result_path.
199 pkg = package_info.PackageInfo(package='bar')
200 input_msg = self._GetInput(board='board', result_path=self.tempdir,
201 packages=[pkg])
202 output_msg = self._GetOutput()
203 with self.assertRaises(cros_build_lib.DieSystemExit):
204 test_controller.BuildTargetUnitTest(input_msg, output_msg,
205 self.api_config)
206
Alex Kleina2e42c42019-04-17 16:13:19 -0600207 def testPackageBuildFailure(self):
208 """Test handling of raised BuildPackageFailure."""
209 tempdir = osutils.TempDir(base_dir=self.tempdir)
210 self.PatchObject(osutils, 'TempDir', return_value=tempdir)
211
212 pkgs = ['cat/pkg', 'foo/bar']
213 expected = [('cat', 'pkg'), ('foo', 'bar')]
Alex Kleina2e42c42019-04-17 16:13:19 -0600214
Alex Klein38c7d9e2019-05-08 09:31:19 -0600215 result = test_service.BuildTargetUnitTestResult(1, None)
Alex Klein18a60af2020-06-11 12:08:47 -0600216 result.failed_cpvs = [package_info.SplitCPV(p, strict=False) for p in pkgs]
Alex Klein38c7d9e2019-05-08 09:31:19 -0600217 self.PatchObject(test_service, 'BuildTargetUnitTest', return_value=result)
Alex Kleina2e42c42019-04-17 16:13:19 -0600218
219 input_msg = self._GetInput(board='board', result_path=self.tempdir)
220 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_UNSUCCESSFUL_RESPONSE_AVAILABLE, rc)
Alex Kleina2e42c42019-04-17 16:13:19 -0600226 self.assertTrue(output_msg.failed_packages)
227 failed = []
228 for pi in output_msg.failed_packages:
229 failed.append((pi.category, pi.package_name))
Mike Frysinger678735c2019-09-28 18:23:28 -0400230 self.assertCountEqual(expected, failed)
Alex Kleina2e42c42019-04-17 16:13:19 -0600231
232 def testOtherBuildScriptFailure(self):
233 """Test build script failure due to non-package emerge error."""
234 tempdir = osutils.TempDir(base_dir=self.tempdir)
235 self.PatchObject(osutils, 'TempDir', return_value=tempdir)
236
Alex Klein38c7d9e2019-05-08 09:31:19 -0600237 result = test_service.BuildTargetUnitTestResult(1, None)
238 self.PatchObject(test_service, 'BuildTargetUnitTest', return_value=result)
Alex Kleina2e42c42019-04-17 16:13:19 -0600239
Alex Kleinf2674462019-05-16 16:47:24 -0600240 pkgs = ['foo/bar', 'cat/pkg']
Alex Kleinb64e5f82020-09-23 10:55:31 -0600241 blocklist = [package_info.SplitCPV(p, strict=False) for p in pkgs]
Alex Kleinfa6ebdc2019-05-10 10:57:31 -0600242 input_msg = self._GetInput(board='board', result_path=self.tempdir,
Alex Kleinb64e5f82020-09-23 10:55:31 -0600243 empty_sysroot=True, blocklist=blocklist)
Alex Kleina2e42c42019-04-17 16:13:19 -0600244 output_msg = self._GetOutput()
245
Alex Klein231d2da2019-07-22 16:44:45 -0600246 rc = test_controller.BuildTargetUnitTest(input_msg, output_msg,
247 self.api_config)
Alex Kleina2e42c42019-04-17 16:13:19 -0600248
Alex Klein8cb365a2019-05-15 16:24:53 -0600249 self.assertEqual(controller.RETURN_CODE_COMPLETED_UNSUCCESSFULLY, rc)
Alex Kleina2e42c42019-04-17 16:13:19 -0600250 self.assertFalse(output_msg.failed_packages)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600251
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700252 def testBuildTargetUnitTest(self):
253 """Test BuildTargetUnitTest successful call."""
Navil Perezc0b29a82020-07-07 14:17:48 +0000254 pkgs = ['foo/bar', 'cat/pkg']
Alex Klein18a60af2020-06-11 12:08:47 -0600255 packages = [package_info.SplitCPV(p, strict=False) for p in pkgs]
Navil Perezc0b29a82020-07-07 14:17:48 +0000256 input_msg = self._GetInput(
257 board='board', result_path=self.tempdir, packages=packages)
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700258
259 result = test_service.BuildTargetUnitTestResult(0, None)
260 self.PatchObject(test_service, 'BuildTargetUnitTest', return_value=result)
261
262 tarball_result = os.path.join(input_msg.result_path, 'unit_tests.tar')
263 self.PatchObject(test_service, 'BuildTargetUnitTestTarball',
264 return_value=tarball_result)
265
266 response = self._GetOutput()
267 test_controller.BuildTargetUnitTest(input_msg, response,
268 self.api_config)
269 self.assertEqual(response.tarball_path,
270 os.path.join(input_msg.result_path, 'unit_tests.tar'))
271
Evan Hernandez4e388a52019-05-01 12:16:33 -0600272
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -0700273class ChromiteUnitTestTest(cros_test_lib.MockTestCase,
274 api_config.ApiConfigMixin):
275 """Tests for the ChromiteInfoTest function."""
276
277 def setUp(self):
278 self.board = 'board'
279 self.chroot_path = '/path/to/chroot'
280
281 def _GetInput(self, chroot_path=None):
282 """Helper to build an input message instance."""
283 proto = test_pb2.ChromiteUnitTestRequest(
284 chroot={'path': chroot_path},
285 )
286 return proto
287
288 def _GetOutput(self):
289 """Helper to get an empty output message instance."""
290 return test_pb2.ChromiteUnitTestResponse()
291
292 def testValidateOnly(self):
293 """Sanity check that a validate only call does not execute any logic."""
294 patch = self.PatchObject(cros_build_lib, 'run')
295
296 input_msg = self._GetInput(chroot_path=self.chroot_path)
297 test_controller.ChromiteUnitTest(input_msg, self._GetOutput(),
298 self.validate_only_config)
299 patch.assert_not_called()
300
Michael Mortensen7a860eb2019-12-03 20:25:15 -0700301 def testMockError(self):
302 """Test mock error call does not execute any logic, returns error."""
303 patch = self.PatchObject(cros_build_lib, 'run')
304
305 input_msg = self._GetInput(chroot_path=self.chroot_path)
306 rc = test_controller.ChromiteUnitTest(input_msg, self._GetOutput(),
307 self.mock_error_config)
308 patch.assert_not_called()
309 self.assertEqual(controller.RETURN_CODE_COMPLETED_UNSUCCESSFULLY, rc)
310
311 def testMockCall(self):
312 """Test mock call does not execute any logic, returns success."""
313 patch = self.PatchObject(cros_build_lib, 'run')
314
315 input_msg = self._GetInput(chroot_path=self.chroot_path)
316 rc = test_controller.ChromiteUnitTest(input_msg, self._GetOutput(),
317 self.mock_call_config)
318 patch.assert_not_called()
319 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
320
Michael Mortensen8ca4d3b2019-11-27 09:35:22 -0700321 def testChromiteUnitTest(self):
322 """Call ChromiteUnitTest with mocked cros_build_lib.run."""
323 request = self._GetInput(chroot_path=self.chroot_path)
324 patch = self.PatchObject(
325 cros_build_lib, 'run',
326 return_value=cros_build_lib.CommandResult(returncode=0))
327
328 test_controller.ChromiteUnitTest(request, self._GetOutput(),
329 self.api_config)
330 patch.assert_called_once()
331
332
Alex Klein4bc8f4f2019-08-16 14:53:30 -0600333class CrosSigningTestTest(cros_test_lib.RunCommandTestCase,
334 api_config.ApiConfigMixin):
335 """CrosSigningTest tests."""
336
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700337 def setUp(self):
338 self.chroot_path = '/path/to/chroot'
339
340 def _GetInput(self, chroot_path=None):
341 """Helper to build an input message instance."""
342 proto = test_pb2.CrosSigningTestRequest(
343 chroot={'path': chroot_path},
344 )
345 return proto
346
347 def _GetOutput(self):
348 """Helper to get an empty output message instance."""
349 return test_pb2.CrosSigningTestResponse()
350
Alex Klein4bc8f4f2019-08-16 14:53:30 -0600351 def testValidateOnly(self):
352 """Sanity check that a validate only call does not execute any logic."""
353 test_controller.CrosSigningTest(None, None, self.validate_only_config)
354 self.assertFalse(self.rc.call_count)
355
Michael Mortensen7a7646d2019-12-12 15:36:14 -0700356 def testMockCall(self):
357 """Test mock call does not execute any logic, returns success."""
358 rc = test_controller.CrosSigningTest(None, None, self.mock_call_config)
359 self.assertFalse(self.rc.call_count)
360 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
361
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700362 def testCrosSigningTest(self):
363 """Call CrosSigningTest with mocked cros_build_lib.run."""
364 request = self._GetInput(chroot_path=self.chroot_path)
365 patch = self.PatchObject(
366 cros_build_lib, 'run',
367 return_value=cros_build_lib.CommandResult(returncode=0))
368
369 test_controller.CrosSigningTest(request, self._GetOutput(),
370 self.api_config)
371 patch.assert_called_once()
372
Alex Klein4bc8f4f2019-08-16 14:53:30 -0600373
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600374class SimpleChromeWorkflowTestTest(cros_test_lib.MockTestCase,
375 api_config.ApiConfigMixin):
376 """Test the SimpleChromeWorkflowTest endpoint."""
377
378 @staticmethod
379 def _Output():
380 return test_pb2.SimpleChromeWorkflowTestResponse()
381
382 def _Input(self, sysroot_path=None, build_target=None, chrome_root=None,
383 goma_config=None):
384 proto = test_pb2.SimpleChromeWorkflowTestRequest()
385 if sysroot_path:
386 proto.sysroot.path = sysroot_path
387 if build_target:
388 proto.sysroot.build_target.name = build_target
389 if chrome_root:
390 proto.chrome_root = chrome_root
391 if goma_config:
392 proto.goma_config = goma_config
393 return proto
394
395 def setUp(self):
396 self.chrome_path = 'path/to/chrome'
397 self.sysroot_dir = 'build/board'
398 self.build_target = 'amd64'
399 self.mock_simple_chrome_workflow_test = self.PatchObject(
400 test_service, 'SimpleChromeWorkflowTest')
401
402 def testMissingBuildTarget(self):
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700403 """Test SimpleChromeWorkflowTest dies when build_target not set."""
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600404 input_proto = self._Input(build_target=None, sysroot_path='/sysroot/dir',
405 chrome_root='/chrome/path')
406 with self.assertRaises(cros_build_lib.DieSystemExit):
407 test_controller.SimpleChromeWorkflowTest(input_proto, None,
408 self.api_config)
409
410 def testMissingSysrootPath(self):
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700411 """Test SimpleChromeWorkflowTest dies when build_target not set."""
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600412 input_proto = self._Input(build_target='board', sysroot_path=None,
413 chrome_root='/chrome/path')
414 with self.assertRaises(cros_build_lib.DieSystemExit):
415 test_controller.SimpleChromeWorkflowTest(input_proto, None,
416 self.api_config)
417
418 def testMissingChromeRoot(self):
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700419 """Test SimpleChromeWorkflowTest dies when build_target not set."""
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600420 input_proto = self._Input(build_target='board', sysroot_path='/sysroot/dir',
421 chrome_root=None)
422 with self.assertRaises(cros_build_lib.DieSystemExit):
423 test_controller.SimpleChromeWorkflowTest(input_proto, None,
424 self.api_config)
425
426 def testSimpleChromeWorkflowTest(self):
427 """Call SimpleChromeWorkflowTest with valid args and temp dir."""
428 request = self._Input(sysroot_path='sysroot_path', build_target='board',
429 chrome_root='/path/to/chrome')
430 response = self._Output()
431
432 test_controller.SimpleChromeWorkflowTest(request, response, self.api_config)
433 self.mock_simple_chrome_workflow_test.assert_called()
434
435 def testValidateOnly(self):
436 request = self._Input(sysroot_path='sysroot_path', build_target='board',
437 chrome_root='/path/to/chrome')
438 test_controller.SimpleChromeWorkflowTest(request, self._Output(),
439 self.validate_only_config)
440 self.mock_simple_chrome_workflow_test.assert_not_called()
441
Michael Mortensen7a7646d2019-12-12 15:36:14 -0700442 def testMockCall(self):
443 """Test mock call does not execute any logic, returns success."""
444 patch = self.mock_simple_chrome_workflow_test = self.PatchObject(
445 test_service, 'SimpleChromeWorkflowTest')
446
447 request = self._Input(sysroot_path='sysroot_path', build_target='board',
448 chrome_root='/path/to/chrome')
449 rc = test_controller.SimpleChromeWorkflowTest(request, self._Output(),
450 self.mock_call_config)
451 patch.assert_not_called()
452 self.assertEqual(controller.RETURN_CODE_SUCCESS, rc)
453
Michael Mortensenc28d6f12019-10-03 13:34:51 -0600454
Alex Klein231d2da2019-07-22 16:44:45 -0600455class VmTestTest(cros_test_lib.RunCommandTestCase, api_config.ApiConfigMixin):
Evan Hernandez4e388a52019-05-01 12:16:33 -0600456 """Test the VmTest endpoint."""
457
458 def _GetInput(self, **kwargs):
459 values = dict(
460 build_target=common_pb2.BuildTarget(name='target'),
Alex Klein311b8022019-06-05 16:00:07 -0600461 vm_path=common_pb2.Path(path='/path/to/image.bin',
462 location=common_pb2.Path.INSIDE),
Evan Hernandez4e388a52019-05-01 12:16:33 -0600463 test_harness=test_pb2.VmTestRequest.TAST,
464 vm_tests=[test_pb2.VmTestRequest.VmTest(pattern='suite')],
465 ssh_options=test_pb2.VmTestRequest.SshOptions(
Alex Klein231d2da2019-07-22 16:44:45 -0600466 port=1234, private_key_path={'path': '/path/to/id_rsa',
Alex Kleinaa705412019-06-04 15:00:30 -0600467 'location': common_pb2.Path.INSIDE}),
Evan Hernandez4e388a52019-05-01 12:16:33 -0600468 )
469 values.update(kwargs)
470 return test_pb2.VmTestRequest(**values)
471
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700472 def _Output(self):
473 return test_pb2.VmTestResponse()
474
Alex Klein231d2da2019-07-22 16:44:45 -0600475 def testValidateOnly(self):
476 """Sanity check that a validate only call does not execute any logic."""
477 test_controller.VmTest(self._GetInput(), None, self.validate_only_config)
478 self.assertEqual(0, self.rc.call_count)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600479
Michael Mortensen7a7646d2019-12-12 15:36:14 -0700480 def testMockCall(self):
481 """Test mock call does not execute any logic."""
482 patch = self.PatchObject(cros_build_lib, 'run')
483
484 request = self._GetInput()
485 response = self._Output()
486 # VmTest does not return a value, checking mocked value is flagged by lint.
487 test_controller.VmTest(request, response, self.mock_call_config)
488 patch.assert_not_called()
489
Evan Hernandez4e388a52019-05-01 12:16:33 -0600490 def testTastAllOptions(self):
491 """Test VmTest for Tast with all options set."""
Alex Klein231d2da2019-07-22 16:44:45 -0600492 test_controller.VmTest(self._GetInput(), None, self.api_config)
493 self.assertCommandContains([
Achuith Bhandarkara9e9c3d2019-05-22 13:56:11 -0700494 'cros_run_test', '--debug', '--no-display', '--copy-on-write',
Evan Hernandez4e388a52019-05-01 12:16:33 -0600495 '--board', 'target',
496 '--image-path', '/path/to/image.bin',
497 '--tast', 'suite',
498 '--ssh-port', '1234',
499 '--private-key', '/path/to/id_rsa',
500 ])
501
502 def testAutotestAllOptions(self):
503 """Test VmTest for Autotest with all options set."""
504 input_proto = self._GetInput(test_harness=test_pb2.VmTestRequest.AUTOTEST)
Alex Klein231d2da2019-07-22 16:44:45 -0600505 test_controller.VmTest(input_proto, None, self.api_config)
506 self.assertCommandContains([
Achuith Bhandarkara9e9c3d2019-05-22 13:56:11 -0700507 'cros_run_test', '--debug', '--no-display', '--copy-on-write',
Evan Hernandez4e388a52019-05-01 12:16:33 -0600508 '--board', 'target',
509 '--image-path', '/path/to/image.bin',
510 '--autotest', 'suite',
511 '--ssh-port', '1234',
512 '--private-key', '/path/to/id_rsa',
Greg Edelstondcb0e912020-08-31 11:09:40 -0600513 '--test_that-args=--allow-chrome-crashes',
Evan Hernandez4e388a52019-05-01 12:16:33 -0600514 ])
515
516 def testMissingBuildTarget(self):
517 """Test VmTest dies when build_target not set."""
518 input_proto = self._GetInput(build_target=None)
519 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600520 test_controller.VmTest(input_proto, None, self.api_config)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600521
522 def testMissingVmImage(self):
523 """Test VmTest dies when vm_image not set."""
Alex Klein311b8022019-06-05 16:00:07 -0600524 input_proto = self._GetInput(vm_path=None)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600525 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600526 test_controller.VmTest(input_proto, None, self.api_config)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600527
528 def testMissingTestHarness(self):
529 """Test VmTest dies when test_harness not specified."""
530 input_proto = self._GetInput(
531 test_harness=test_pb2.VmTestRequest.UNSPECIFIED)
532 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600533 test_controller.VmTest(input_proto, None, self.api_config)
Evan Hernandez4e388a52019-05-01 12:16:33 -0600534
535 def testMissingVmTests(self):
536 """Test VmTest dies when vm_tests not set."""
537 input_proto = self._GetInput(vm_tests=[])
538 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600539 test_controller.VmTest(input_proto, None, self.api_config)
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600540
Michael Mortensen82cd62d2019-12-01 14:58:54 -0700541 def testVmTest(self):
542 """Call VmTest with valid args and temp dir."""
543 request = self._GetInput()
544 response = self._Output()
545 patch = self.PatchObject(
546 cros_build_lib, 'run',
547 return_value=cros_build_lib.CommandResult(returncode=0))
548
549 test_controller.VmTest(request, response, self.api_config)
550 patch.assert_called()
551
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600552
Alex Klein231d2da2019-07-22 16:44:45 -0600553class MoblabVmTestTest(cros_test_lib.MockTestCase, api_config.ApiConfigMixin):
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600554 """Test the MoblabVmTest endpoint."""
555
556 @staticmethod
557 def _Payload(path):
558 return test_pb2.MoblabVmTestRequest.Payload(
559 path=common_pb2.Path(path=path))
560
561 @staticmethod
562 def _Output():
563 return test_pb2.MoblabVmTestResponse()
564
565 def _Input(self):
566 return test_pb2.MoblabVmTestRequest(
Evan Hernandeze1e05d32019-07-19 12:32:18 -0600567 chroot=common_pb2.Chroot(path=self.chroot_dir),
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600568 image_payload=self._Payload(self.image_payload_dir),
569 cache_payloads=[self._Payload(self.autotest_payload_dir)])
570
571 def setUp(self):
Evan Hernandeze1e05d32019-07-19 12:32:18 -0600572 self.chroot_dir = '/chroot'
573 self.chroot_tmp_dir = '/chroot/tmp'
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600574 self.image_payload_dir = '/payloads/image'
575 self.autotest_payload_dir = '/payloads/autotest'
576 self.builder = 'moblab-generic-vm/R12-3.4.5-67.890'
577 self.image_cache_dir = '/mnt/moblab/cache'
578 self.image_mount_dir = '/mnt/image'
579
Evan Hernandeze1e05d32019-07-19 12:32:18 -0600580 self.PatchObject(chroot_lib.Chroot, 'tempdir', osutils.TempDir)
Evan Hernandez655e8042019-06-13 12:50:44 -0600581
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600582 self.mock_create_moblab_vms = self.PatchObject(
583 test_service, 'CreateMoblabVm')
584 self.mock_prepare_moblab_vm_image_cache = self.PatchObject(
585 test_service, 'PrepareMoblabVmImageCache',
586 return_value=self.image_cache_dir)
587 self.mock_run_moblab_vm_tests = self.PatchObject(
588 test_service, 'RunMoblabVmTest')
589 self.mock_validate_moblab_vm_tests = self.PatchObject(
590 test_service, 'ValidateMoblabVmTest')
591
592 @contextlib.contextmanager
Alex Klein38c7d9e2019-05-08 09:31:19 -0600593 def MockLoopbackPartitions(*_args, **_kwargs):
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600594 mount = mock.MagicMock()
Evan Hernandez40ee7452019-06-13 12:51:43 -0600595 mount.Mount.return_value = [self.image_mount_dir]
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600596 yield mount
Alex Klein231d2da2019-07-22 16:44:45 -0600597
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600598 self.PatchObject(image_lib, 'LoopbackPartitions', MockLoopbackPartitions)
599
Alex Klein231d2da2019-07-22 16:44:45 -0600600 def testValidateOnly(self):
601 """Sanity check that a validate only call does not execute any logic."""
602 test_controller.MoblabVmTest(self._Input(), self._Output(),
603 self.validate_only_config)
604 self.mock_create_moblab_vms.assert_not_called()
605
Michael Mortensen7a7646d2019-12-12 15:36:14 -0700606 def testMockCall(self):
607 """Test mock call does not execute any logic."""
608 patch = self.PatchObject(key_value_store, 'LoadFile')
609
610 # MoblabVmTest does not return a value, checking mocked value is flagged by
611 # lint.
612 test_controller.MoblabVmTest(self._Input(), self._Output(),
613 self.mock_call_config)
614 patch.assert_not_called()
615
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600616 def testImageContainsBuilder(self):
617 """MoblabVmTest calls service with correct args."""
618 request = self._Input()
619 response = self._Output()
620
621 self.PatchObject(
Mike Frysingere652ba12019-09-08 00:57:43 -0400622 key_value_store, 'LoadFile',
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600623 return_value={cros_set_lsb_release.LSB_KEY_BUILDER_PATH: self.builder})
624
Alex Klein231d2da2019-07-22 16:44:45 -0600625 test_controller.MoblabVmTest(request, response, self.api_config)
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600626
627 self.assertEqual(
628 self.mock_create_moblab_vms.call_args_list,
Evan Hernandeze1e05d32019-07-19 12:32:18 -0600629 [mock.call(mock.ANY, self.chroot_dir, self.image_payload_dir)])
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600630 self.assertEqual(
631 self.mock_prepare_moblab_vm_image_cache.call_args_list,
632 [mock.call(mock.ANY, self.builder, [self.autotest_payload_dir])])
633 self.assertEqual(
634 self.mock_run_moblab_vm_tests.call_args_list,
Evan Hernandez655e8042019-06-13 12:50:44 -0600635 [mock.call(mock.ANY, mock.ANY, self.builder, self.image_cache_dir,
636 mock.ANY)])
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600637 self.assertEqual(
638 self.mock_validate_moblab_vm_tests.call_args_list,
639 [mock.call(mock.ANY)])
640
641 def testImageMissingBuilder(self):
642 """MoblabVmTest dies when builder path not found in lsb-release."""
643 request = self._Input()
644 response = self._Output()
645
Mike Frysingere652ba12019-09-08 00:57:43 -0400646 self.PatchObject(key_value_store, 'LoadFile', return_value={})
Evan Hernandezdc3f0bb2019-06-06 12:46:52 -0600647
648 with self.assertRaises(cros_build_lib.DieSystemExit):
Alex Klein231d2da2019-07-22 16:44:45 -0600649 test_controller.MoblabVmTest(request, response, self.api_config)