blob: 5fc60e231f990f32d3aa251fb17951561bb08260 [file] [log] [blame]
Mike Frysingerf1ba7ad2022-09-12 05:42:57 -04001# Copyright 2018 The ChromiumOS Authors
Alex Kleinf4dc4f52018-12-05 13:55:12 -07002# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
Alex Klein2bfacb22019-02-04 11:42:17 -07005"""Tests for the build_api script covering the base Build API functionality."""
6
Alex Klein5bcb4d22019-03-21 13:51:54 -06007import os
Tomasz Tylendab4292302021-08-08 18:59:36 +09008from typing import Callable
Alex Klein5bcb4d22019-03-21 13:51:54 -06009
Mike Frysinger2c024062021-05-22 15:43:22 -040010from chromite.third_party.google.protobuf import json_format
Alex Kleinbd6edf82019-07-18 10:30:49 -060011
Alex Klein69339cc2019-07-22 14:08:35 -060012from chromite.api import api_config
Alex Kleine191ed62020-02-27 15:59:55 -070013from chromite.api import message_util
Alex Klein146d4772019-06-20 13:48:25 -060014from chromite.api import router
Alex Klein7107bdd2019-03-14 17:14:31 -060015from chromite.api.gen.chromite.api import build_api_test_pb2
Alex Kleinc7d647f2020-01-06 12:00:48 -070016from chromite.lib import chroot_lib
Alex Klein12fc7ca2023-04-26 18:23:18 -060017from chromite.lib import constants
Alex Klein2bfacb22019-02-04 11:42:17 -070018from chromite.lib import cros_build_lib
Alex Kleinf4dc4f52018-12-05 13:55:12 -070019from chromite.lib import cros_test_lib
Alex Klein5bcb4d22019-03-21 13:51:54 -060020from chromite.lib import osutils
Alex Kleinf4dc4f52018-12-05 13:55:12 -070021
22
Alex Klein1699fab2022-09-08 08:46:06 -060023class RouterTest(
24 cros_test_lib.RunCommandTempDirTestCase, api_config.ApiConfigMixin
25):
26 """Test Router functionality."""
Alex Kleinf4dc4f52018-12-05 13:55:12 -070027
Alex Klein1699fab2022-09-08 08:46:06 -060028 def setUp(self):
29 self.router = router.Router()
30 self.router.Register(build_api_test_pb2)
Alex Kleinf4dc4f52018-12-05 13:55:12 -070031
Brian Norris2712b402023-05-01 18:31:45 -070032 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=False)
33
34 self.chroot_dir = self.tempdir / "chroot"
35 self.out_dir = self.tempdir / "out"
36 chroot = chroot_lib.Chroot(
37 path=self.chroot_dir,
38 out_path=self.out_dir,
39 )
40 # Make sure basic path structures exist.
41 osutils.SafeMakedirs(self.chroot_dir)
42 osutils.SafeMakedirs(self.out_dir)
Alex Klein1699fab2022-09-08 08:46:06 -060043 # Make the tmp dir for the re-exec inside chroot input/output files.
Brian Norris2712b402023-05-01 18:31:45 -070044 osutils.SafeMakedirs(chroot.tmp)
Alex Klein00aa8072019-04-15 16:36:00 -060045
Alex Klein1699fab2022-09-08 08:46:06 -060046 # Build the input/output/config paths we'll be using in the tests.
47 self.json_input_file = os.path.join(self.tempdir, "input.json")
48 self.json_output_file = os.path.join(self.tempdir, "output.json")
49 self.json_config_file = os.path.join(self.tempdir, "config.json")
50 self.binary_input_file = os.path.join(self.tempdir, "input.bin")
51 self.binary_output_file = os.path.join(self.tempdir, "output.bin")
52 self.binary_config_file = os.path.join(self.tempdir, "config.bin")
Alex Kleine191ed62020-02-27 15:59:55 -070053
Alex Klein1699fab2022-09-08 08:46:06 -060054 # The message handlers for the respective files.
55 self.json_input_handler = message_util.get_message_handler(
56 self.json_input_file, message_util.FORMAT_JSON
57 )
58 self.json_output_handler = message_util.get_message_handler(
59 self.json_output_file, message_util.FORMAT_JSON
60 )
61 self.json_config_handler = message_util.get_message_handler(
62 self.json_config_file, message_util.FORMAT_JSON
63 )
64 self.binary_input_handler = message_util.get_message_handler(
65 self.binary_input_file, message_util.FORMAT_BINARY
66 )
67 self.binary_output_handler = message_util.get_message_handler(
68 self.binary_output_file, message_util.FORMAT_BINARY
69 )
70 self.binary_config_handler = message_util.get_message_handler(
71 self.binary_config_file, message_util.FORMAT_BINARY
72 )
Alex Kleine191ed62020-02-27 15:59:55 -070073
Alex Klein1699fab2022-09-08 08:46:06 -060074 # Build an input message to use.
75 self.expected_id = "input id"
76 input_msg = build_api_test_pb2.TestRequestMessage()
77 input_msg.id = self.expected_id
Brian Norris2712b402023-05-01 18:31:45 -070078 input_msg.chroot.path = str(self.chroot_dir)
79 input_msg.chroot.out_path = str(self.out_dir)
Alex Kleine191ed62020-02-27 15:59:55 -070080
Alex Klein1699fab2022-09-08 08:46:06 -060081 # Write out base input and config messages.
82 osutils.WriteFile(
83 self.json_input_file, json_format.MessageToJson(input_msg)
84 )
85 osutils.WriteFile(
86 self.binary_input_file, input_msg.SerializeToString(), mode="wb"
87 )
Alex Kleine191ed62020-02-27 15:59:55 -070088
Alex Klein1699fab2022-09-08 08:46:06 -060089 config_msg = self.api_config.get_proto()
90 osutils.WriteFile(
91 self.json_config_file, json_format.MessageToJson(config_msg)
92 )
93 osutils.WriteFile(
94 self.binary_config_file, config_msg.SerializeToString(), mode="wb"
95 )
Alex Kleinbd6edf82019-07-18 10:30:49 -060096
Alex Klein1699fab2022-09-08 08:46:06 -060097 self.subprocess_tempdir = os.path.join(self.chroot_dir, "tempdir")
98 osutils.SafeMakedirs(self.subprocess_tempdir)
Alex Klein5bcb4d22019-03-21 13:51:54 -060099
Alex Klein1699fab2022-09-08 08:46:06 -0600100 def testJsonInputOutputMethod(self):
101 """Test json input/output handling."""
Alex Kleinf4dc4f52018-12-05 13:55:12 -0700102
Alex Klein1699fab2022-09-08 08:46:06 -0600103 def impl(input_msg, output_msg, config):
104 self.assertIsInstance(
105 input_msg, build_api_test_pb2.TestRequestMessage
106 )
107 self.assertIsInstance(
108 output_msg, build_api_test_pb2.TestResultMessage
109 )
110 self.assertIsInstance(config, api_config.ApiConfig)
111 self.assertEqual(config, self.api_config)
Alex Kleinf4dc4f52018-12-05 13:55:12 -0700112
Alex Klein1699fab2022-09-08 08:46:06 -0600113 self.PatchObject(self.router, "_GetMethod", return_value=impl)
Alex Kleine191ed62020-02-27 15:59:55 -0700114
Alex Klein1699fab2022-09-08 08:46:06 -0600115 self.router.Route(
116 "chromite.api.TestApiService",
117 "InputOutputMethod",
118 self.api_config,
119 self.json_input_handler,
120 [self.json_output_handler],
121 self.json_config_handler,
122 )
Alex Kleine191ed62020-02-27 15:59:55 -0700123
Alex Klein1699fab2022-09-08 08:46:06 -0600124 def testBinaryInputOutputMethod(self):
125 """Test binary input/output handling."""
Alex Kleine191ed62020-02-27 15:59:55 -0700126
Alex Klein1699fab2022-09-08 08:46:06 -0600127 def impl(input_msg, output_msg, config):
128 self.assertIsInstance(
129 input_msg, build_api_test_pb2.TestRequestMessage
130 )
131 self.assertIsInstance(
132 output_msg, build_api_test_pb2.TestResultMessage
133 )
134 self.assertIsInstance(config, api_config.ApiConfig)
135 self.assertEqual(config, self.api_config)
Alex Kleine191ed62020-02-27 15:59:55 -0700136
Alex Klein1699fab2022-09-08 08:46:06 -0600137 self.PatchObject(self.router, "_GetMethod", return_value=impl)
Alex Kleine191ed62020-02-27 15:59:55 -0700138
Alex Klein1699fab2022-09-08 08:46:06 -0600139 self.router.Route(
140 "chromite.api.TestApiService",
141 "InputOutputMethod",
142 self.api_config,
143 self.binary_input_handler,
144 [self.binary_output_handler],
145 self.binary_config_handler,
146 )
Alex Kleine191ed62020-02-27 15:59:55 -0700147
Alex Klein1699fab2022-09-08 08:46:06 -0600148 def testMultipleOutputHandling(self):
149 """Test multiple output handling."""
150 expected_result = "Success!"
Alex Kleine191ed62020-02-27 15:59:55 -0700151
Alex Klein1699fab2022-09-08 08:46:06 -0600152 def impl(input_msg, output_msg, config):
153 self.assertIsInstance(
154 input_msg, build_api_test_pb2.TestRequestMessage
155 )
156 self.assertIsInstance(
157 output_msg, build_api_test_pb2.TestResultMessage
158 )
159 self.assertIsInstance(config, api_config.ApiConfig)
160 self.assertEqual(config, self.api_config)
161 # Set the property on the output to test against.
162 output_msg.result = expected_result
Alex Kleine191ed62020-02-27 15:59:55 -0700163
Alex Klein1699fab2022-09-08 08:46:06 -0600164 self.PatchObject(self.router, "_GetMethod", return_value=impl)
Alex Kleine191ed62020-02-27 15:59:55 -0700165
Alex Klein1699fab2022-09-08 08:46:06 -0600166 self.router.Route(
167 "chromite.api.TestApiService",
168 "InputOutputMethod",
169 self.api_config,
170 self.binary_input_handler,
171 [self.binary_output_handler, self.json_output_handler],
172 self.binary_config_handler,
173 )
Alex Kleine191ed62020-02-27 15:59:55 -0700174
Alex Klein1699fab2022-09-08 08:46:06 -0600175 # Make sure it did write out all the expected files.
176 self.assertExists(self.binary_output_file)
177 self.assertExists(self.json_output_file)
Alex Kleinf4dc4f52018-12-05 13:55:12 -0700178
Alex Klein1699fab2022-09-08 08:46:06 -0600179 # Parse the output files back into a message.
180 binary_msg = build_api_test_pb2.TestResultMessage()
181 json_msg = build_api_test_pb2.TestResultMessage()
182 self.binary_output_handler.read_into(binary_msg)
183 self.json_output_handler.read_into(json_msg)
Alex Klein2bfacb22019-02-04 11:42:17 -0700184
Alex Klein1699fab2022-09-08 08:46:06 -0600185 # Make sure the parsed messages have the expected content.
186 self.assertEqual(binary_msg.result, expected_result)
187 self.assertEqual(json_msg.result, expected_result)
Alex Klein2bfacb22019-02-04 11:42:17 -0700188
Alex Klein1699fab2022-09-08 08:46:06 -0600189 def testRenameMethod(self):
190 """Test implementation name config."""
Alex Klein2bfacb22019-02-04 11:42:17 -0700191
Alex Klein1699fab2022-09-08 08:46:06 -0600192 def _GetMethod(_, method_name):
193 self.assertEqual("CorrectName", method_name)
194 return lambda x, y, z: None
Alex Klein00aa8072019-04-15 16:36:00 -0600195
Alex Klein1699fab2022-09-08 08:46:06 -0600196 self.PatchObject(self.router, "_GetMethod", side_effect=_GetMethod)
Alex Klein00aa8072019-04-15 16:36:00 -0600197
Alex Klein1699fab2022-09-08 08:46:06 -0600198 self.router.Route(
199 "chromite.api.TestApiService",
200 "RenamedMethod",
201 self.api_config,
202 self.binary_input_handler,
203 [self.binary_output_handler],
204 self.binary_config_handler,
205 )
Alex Klein2bfacb22019-02-04 11:42:17 -0700206
Alex Klein1699fab2022-09-08 08:46:06 -0600207 def _mock_callable(self, expect_called: bool) -> Callable:
208 """Helper to create the implementation mock to test chroot assertions.
Alex Klein2bfacb22019-02-04 11:42:17 -0700209
Alex Klein1699fab2022-09-08 08:46:06 -0600210 Args:
Alex Kleina0442682022-10-10 13:47:38 -0600211 expect_called: Whether the implementation should be called.
212 When False, an assertion will fail if it is called.
Alex Kleinbd6edf82019-07-18 10:30:49 -0600213
Alex Klein1699fab2022-09-08 08:46:06 -0600214 Returns:
Alex Kleina0442682022-10-10 13:47:38 -0600215 The implementation.
Alex Klein1699fab2022-09-08 08:46:06 -0600216 """
Alex Kleinbd6edf82019-07-18 10:30:49 -0600217
Alex Klein1699fab2022-09-08 08:46:06 -0600218 def impl(_input_msg, _output_msg, _config):
219 self.assertTrue(
220 expect_called, "The implementation should not have been called."
221 )
Alex Klein2bfacb22019-02-04 11:42:17 -0700222
Alex Klein1699fab2022-09-08 08:46:06 -0600223 return impl
Alex Klein00aa8072019-04-15 16:36:00 -0600224
Alex Klein1699fab2022-09-08 08:46:06 -0600225 def _writeChrootCallOutput(self, content="{}", mode="w"):
226 def impl(*_args, **_kwargs):
227 """Side effect for inside-chroot calls to the API."""
228 osutils.WriteFile(
229 os.path.join(
230 self.subprocess_tempdir, router.Router.REEXEC_OUTPUT_FILE
231 ),
232 content,
233 mode=mode,
234 )
Alex Klein00aa8072019-04-15 16:36:00 -0600235
Alex Klein1699fab2022-09-08 08:46:06 -0600236 return impl
Alex Klein00aa8072019-04-15 16:36:00 -0600237
Alex Klein1699fab2022-09-08 08:46:06 -0600238 def testInsideServiceInsideMethodInsideChroot(self):
239 """Test inside/inside/inside works correctly."""
240 self.PatchObject(
241 self.router,
242 "_GetMethod",
243 return_value=self._mock_callable(expect_called=True),
244 )
245 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=True)
246 self.router.Route(
247 "chromite.api.InsideChrootApiService",
248 "InsideServiceInsideMethod",
249 self.api_config,
250 self.binary_input_handler,
251 [self.binary_output_handler],
252 self.binary_config_handler,
253 )
Alex Klein00aa8072019-04-15 16:36:00 -0600254
Alex Klein1699fab2022-09-08 08:46:06 -0600255 def testInsideServiceOutsideMethodOutsideChroot(self):
256 """Test the outside method override works as expected."""
257 self.PatchObject(
258 self.router,
259 "_GetMethod",
260 return_value=self._mock_callable(expect_called=True),
261 )
262 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=False)
263 self.router.Route(
264 "chromite.api.InsideChrootApiService",
265 "InsideServiceOutsideMethod",
266 self.api_config,
267 self.binary_input_handler,
268 [self.binary_output_handler],
269 self.binary_config_handler,
270 )
Alex Klein2bfacb22019-02-04 11:42:17 -0700271
Alex Klein1699fab2022-09-08 08:46:06 -0600272 def testInsideServiceInsideMethodOutsideChroot(self):
273 """Test calling an inside method from outside the chroot."""
274 self.PatchObject(
275 self.router,
276 "_GetMethod",
277 return_value=self._mock_callable(expect_called=False),
278 )
279 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=False)
Alex Klein2bfacb22019-02-04 11:42:17 -0700280
Alex Klein1699fab2022-09-08 08:46:06 -0600281 service = "chromite.api.InsideChrootApiService"
282 method = "InsideServiceInsideMethod"
283 service_method = "%s/%s" % (service, method)
284 self.router.Route(
285 service,
286 method,
287 self.api_config,
288 self.binary_input_handler,
289 [self.binary_output_handler],
290 self.binary_config_handler,
291 )
Alex Klein00aa8072019-04-15 16:36:00 -0600292
Alex Klein1699fab2022-09-08 08:46:06 -0600293 self.assertCommandContains(
294 ["build_api", service_method], enter_chroot=True
295 )
Alex Klein00aa8072019-04-15 16:36:00 -0600296
Alex Klein1699fab2022-09-08 08:46:06 -0600297 def testInsideServiceOutsideMethodInsideChroot(self):
298 """Test inside chroot for outside method raises an error."""
299 self.PatchObject(
300 self.router,
301 "_GetMethod",
302 return_value=self._mock_callable(expect_called=False),
303 )
304 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=True)
305 with self.assertRaises(cros_build_lib.DieSystemExit):
306 self.router.Route(
307 "chromite.api.InsideChrootApiService",
308 "InsideServiceOutsideMethod",
309 self.api_config,
310 self.binary_input_handler,
311 [self.binary_output_handler],
312 self.binary_config_handler,
313 )
Alex Klein00aa8072019-04-15 16:36:00 -0600314
Alex Klein1699fab2022-09-08 08:46:06 -0600315 def testOutsideServiceOutsideMethodOutsideChroot(self):
316 """Test outside/outside/outside works correctly."""
317 self.PatchObject(
318 self.router,
319 "_GetMethod",
320 return_value=self._mock_callable(expect_called=True),
321 )
322 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=False)
323 self.router.Route(
324 "chromite.api.OutsideChrootApiService",
325 "OutsideServiceOutsideMethod",
326 self.api_config,
327 self.binary_input_handler,
328 [self.binary_output_handler],
329 self.binary_config_handler,
330 )
Alex Kleinbd6edf82019-07-18 10:30:49 -0600331
Alex Klein1699fab2022-09-08 08:46:06 -0600332 def testOutsideServiceInsideMethodInsideChroot(self):
333 """Test the inside method assertion override works properly."""
334 self.PatchObject(
335 self.router,
336 "_GetMethod",
337 return_value=self._mock_callable(expect_called=True),
338 )
339 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=True)
340 self.router.Route(
341 "chromite.api.OutsideChrootApiService",
342 "OutsideServiceInsideMethod",
343 self.api_config,
344 self.binary_input_handler,
345 [self.binary_output_handler],
346 self.binary_config_handler,
347 )
Alex Kleinc7d647f2020-01-06 12:00:48 -0700348
Alex Klein1699fab2022-09-08 08:46:06 -0600349 def testOutsideServiceInsideMethodOutsideChroot(self):
350 """Test calling an inside override method from outside the chroot."""
351 self.PatchObject(
352 self.router,
353 "_GetMethod",
354 return_value=self._mock_callable(expect_called=False),
355 )
356 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=False)
Alex Kleinc7d647f2020-01-06 12:00:48 -0700357
Alex Klein1699fab2022-09-08 08:46:06 -0600358 service = "chromite.api.OutsideChrootApiService"
359 method = "OutsideServiceInsideMethod"
360 service_method = "%s/%s" % (service, method)
361 self.router.Route(
362 service,
363 method,
364 self.api_config,
365 self.binary_input_handler,
366 [self.binary_output_handler],
367 self.binary_config_handler,
368 )
Alex Kleine191ed62020-02-27 15:59:55 -0700369
Alex Klein1699fab2022-09-08 08:46:06 -0600370 self.assertCommandContains(
371 ["build_api", service_method], enter_chroot=True
372 )
Alex Kleinbd6edf82019-07-18 10:30:49 -0600373
Alex Klein1699fab2022-09-08 08:46:06 -0600374 def testReexecNonemptyOutput(self):
375 """Test calling an inside chroot method that produced output."""
376 self.PatchObject(
377 self.router,
378 "_GetMethod",
379 return_value=self._mock_callable(expect_called=False),
380 )
381 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=False)
Alex Kleinbd6edf82019-07-18 10:30:49 -0600382
Alex Klein54c891a2023-01-24 10:45:41 -0700383 # Patch the chroot tempdir method to return a tempdir with our
384 # subprocess tempdir so the output file will be in the expected
385 # location.
Alex Klein1699fab2022-09-08 08:46:06 -0600386 tempdir = osutils.TempDir()
387 original = tempdir.tempdir
388 tempdir.tempdir = self.subprocess_tempdir
389 self.PatchObject(chroot_lib.Chroot, "tempdir", return_value=tempdir)
Alex Kleinbd6edf82019-07-18 10:30:49 -0600390
Alex Klein1699fab2022-09-08 08:46:06 -0600391 expected_output_msg = build_api_test_pb2.TestResultMessage()
392 expected_output_msg.result = "foo"
Alex Kleinbd6edf82019-07-18 10:30:49 -0600393
Alex Klein1699fab2022-09-08 08:46:06 -0600394 # Set the command side effect to write out our expected output to the
395 # output file for the inside the chroot reexecution of the endpoint.
Alex Klein54c891a2023-01-24 10:45:41 -0700396 # This lets us make sure the logic moving everything out works as
397 # intended.
Alex Klein1699fab2022-09-08 08:46:06 -0600398 self.rc.SetDefaultCmdResult(
399 side_effect=self._writeChrootCallOutput(
400 content=expected_output_msg.SerializeToString(), mode="wb"
401 )
402 )
Alex Kleinc7d647f2020-01-06 12:00:48 -0700403
Alex Klein1699fab2022-09-08 08:46:06 -0600404 service = "chromite.api.OutsideChrootApiService"
405 method = "OutsideServiceInsideMethod"
406 service_method = "%s/%s" % (service, method)
407 self.router.Route(
408 service,
409 method,
410 self.api_config,
411 self.binary_input_handler,
412 [self.binary_output_handler],
413 self.binary_config_handler,
414 )
Alex Kleine191ed62020-02-27 15:59:55 -0700415
Alex Klein1699fab2022-09-08 08:46:06 -0600416 self.assertCommandContains(
417 ["build_api", service_method], enter_chroot=True
418 )
Alex Kleine191ed62020-02-27 15:59:55 -0700419
Alex Klein1699fab2022-09-08 08:46:06 -0600420 # It should be writing the result out to our output file.
421 output_msg = build_api_test_pb2.TestResultMessage()
422 self.binary_output_handler.read_into(output_msg)
423 self.assertEqual(expected_output_msg, output_msg)
Alex Kleine191ed62020-02-27 15:59:55 -0700424
Alex Klein1699fab2022-09-08 08:46:06 -0600425 tempdir.tempdir = original
426 del tempdir
Alex Kleine191ed62020-02-27 15:59:55 -0700427
Alex Klein1699fab2022-09-08 08:46:06 -0600428 def testReexecEmptyOutput(self):
429 """Test calling an inside chroot method that produced no output."""
430 self.PatchObject(
431 self.router,
432 "_GetMethod",
433 return_value=self._mock_callable(expect_called=False),
434 )
435 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=False)
436 expected_output_msg = build_api_test_pb2.TestResultMessage()
Alex Kleine191ed62020-02-27 15:59:55 -0700437
Alex Klein1699fab2022-09-08 08:46:06 -0600438 # Set the command side effect to write out our expected output to the
439 # output file for the inside the chroot reexecution of the endpoint.
Alex Klein54c891a2023-01-24 10:45:41 -0700440 # This lets us make sure the logic moving everything out works as
441 # intended.
Alex Klein1699fab2022-09-08 08:46:06 -0600442 self.rc.SetDefaultCmdResult(
443 side_effect=self._writeChrootCallOutput(
444 content=expected_output_msg.SerializeToString(), mode="wb"
445 )
446 )
Alex Kleinbd6edf82019-07-18 10:30:49 -0600447
Alex Klein1699fab2022-09-08 08:46:06 -0600448 service = "chromite.api.OutsideChrootApiService"
449 method = "OutsideServiceInsideMethod"
450 service_method = "%s/%s" % (service, method)
451 self.router.Route(
452 service,
453 method,
454 self.api_config,
455 self.binary_input_handler,
456 [self.binary_output_handler],
457 self.binary_config_handler,
458 )
Alex Kleinbd6edf82019-07-18 10:30:49 -0600459
Alex Klein1699fab2022-09-08 08:46:06 -0600460 self.assertCommandContains(
461 ["build_api", service_method], enter_chroot=True
462 )
Alex Kleine191ed62020-02-27 15:59:55 -0700463
Alex Klein1699fab2022-09-08 08:46:06 -0600464 output_msg = build_api_test_pb2.TestResultMessage()
465 self.binary_output_handler.read_into(output_msg)
466 self.assertEqual(expected_output_msg, output_msg)
Alex Klein6431d3a2019-08-29 10:16:08 -0600467
Alex Klein1699fab2022-09-08 08:46:06 -0600468 def testReexecNoOutput(self):
469 """Test calling an inside chroot method that produced no output."""
470 self.PatchObject(
471 self.router,
472 "_GetMethod",
473 return_value=self._mock_callable(expect_called=False),
474 )
475 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=False)
476 self.rc.SetDefaultCmdResult(returncode=1)
Alex Klein6431d3a2019-08-29 10:16:08 -0600477
Alex Klein1699fab2022-09-08 08:46:06 -0600478 service = "chromite.api.OutsideChrootApiService"
479 method = "OutsideServiceInsideMethod"
480 service_method = "%s/%s" % (service, method)
481 self.router.Route(
482 service,
483 method,
484 self.api_config,
485 self.binary_input_handler,
486 [self.binary_output_handler],
487 self.binary_config_handler,
488 )
Alex Klein6431d3a2019-08-29 10:16:08 -0600489
Alex Klein1699fab2022-09-08 08:46:06 -0600490 self.assertCommandContains(
491 ["build_api", service_method], enter_chroot=True
492 )
Alex Klein6431d3a2019-08-29 10:16:08 -0600493
Alex Klein1699fab2022-09-08 08:46:06 -0600494 output_msg = build_api_test_pb2.TestResultMessage()
495 empty_msg = build_api_test_pb2.TestResultMessage()
496 self.binary_output_handler.read_into(output_msg)
497 self.assertEqual(empty_msg, output_msg)
Alex Klein6cce6f62021-03-02 14:24:05 -0700498
Alex Klein12fc7ca2023-04-26 18:23:18 -0600499 def test_tot_service_tot_method(self):
500 """Test no re-exec for ToT->ToT."""
501 self.PatchObject(
502 self.router,
503 "_GetMethod",
504 return_value=self._mock_callable(expect_called=True),
505 )
506 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=False)
507 self.PatchObject(constants, "IS_BRANCHED_CHROMITE", new=False)
508
509 self.router.Route(
510 "chromite.api.TotExecutionService",
511 "TotServiceTotMethod",
512 self.api_config,
513 self.binary_input_handler,
514 [self.binary_output_handler],
515 self.binary_config_handler,
516 )
517
518 def test_tot_service_tot_method_inside(self):
519 """Test error raised when method runs ToT & inside the SDK."""
520 self.PatchObject(
521 self.router,
522 "_GetMethod",
523 return_value=self._mock_callable(expect_called=False),
524 )
525 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=False)
526 self.PatchObject(constants, "IS_BRANCHED_CHROMITE", new=False)
527
528 with self.assertRaises(router.TotSdkError):
529 self.router.Route(
530 "chromite.api.TotExecutionService",
531 "TotServiceTotMethodInside",
532 self.api_config,
533 self.binary_input_handler,
534 [self.binary_output_handler],
535 self.binary_config_handler,
536 )
537
538 def test_tot_service_branched_method(self):
539 """Re-execute branched BAPI."""
540 self.PatchObject(
541 self.router,
542 "_GetMethod",
543 return_value=self._mock_callable(expect_called=False),
544 )
545 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=False)
546 self.PatchObject(constants, "IS_BRANCHED_CHROMITE", new=False)
547 self.PatchObject(constants, "BRANCHED_CHROMITE_DIR", new=self.tempdir)
548
549 service = "chromite.api.TotExecutionService"
550 method = "TotServiceBranchedMethod"
551 self.router.Route(
552 service,
553 method,
554 self.api_config,
555 self.binary_input_handler,
556 [self.binary_output_handler],
557 self.binary_config_handler,
558 )
559
560 self.assertCommandContains(
561 [self.tempdir / "bin" / "build_api", f"{service}/{method}"]
562 )
563
564 def test_tot_service_branched_method_inside(self):
565 """Re-execute branched BAPI.
566
567 Chroot handling delegated to the branched BAPI, so should be identical
568 to the branched method case above.
569 """
570 self.PatchObject(
571 self.router,
572 "_GetMethod",
573 return_value=self._mock_callable(expect_called=False),
574 )
575 self.PatchObject(cros_build_lib, "IsInsideChroot", return_value=False)
576 self.PatchObject(constants, "IS_BRANCHED_CHROMITE", new=False)
577 self.PatchObject(constants, "BRANCHED_CHROMITE_DIR", new=self.tempdir)
578
579 service = "chromite.api.TotExecutionService"
580 method = "TotServiceBranchedMethodInside"
581 self.router.Route(
582 service,
583 method,
584 self.api_config,
585 self.binary_input_handler,
586 [self.binary_output_handler],
587 self.binary_config_handler,
588 )
589
590 self.assertCommandContains(
591 [self.tempdir / "bin" / "build_api", f"{service}/{method}"]
592 )
593
Alex Klein1699fab2022-09-08 08:46:06 -0600594 def testInvalidService(self):
595 """Test invalid service call."""
596 service = "chromite.api.DoesNotExist"
597 method = "OutsideServiceInsideMethod"
Alex Klein6cce6f62021-03-02 14:24:05 -0700598
Alex Klein1699fab2022-09-08 08:46:06 -0600599 with self.assertRaises(router.UnknownServiceError):
600 self.router.Route(
601 service,
602 method,
603 self.api_config,
604 self.binary_input_handler,
605 [self.binary_output_handler],
606 self.binary_config_handler,
607 )
608
609 def testInvalidMethod(self):
610 """Test invalid method call."""
611 service = "chromite.api.OutsideChrootApiService"
612 method = "DoesNotExist"
613
614 with self.assertRaises(router.UnknownMethodError):
615 self.router.Route(
616 service,
617 method,
618 self.api_config,
619 self.binary_input_handler,
620 [self.binary_output_handler],
621 self.binary_config_handler,
622 )
623
624 def testListVisibility(self):
625 """Test visibility options."""
626 service = "HiddenService"
627 method = "HiddenMethod"
628
629 for current in self.router.ListMethods():
630 self.assertNotIn(service, current)
631 self.assertNotIn(method, current)