Build API: Enter chroot on INSIDE assertion.
BUG=chromium:953049
TEST=run_tests
TEST=manual - called INSIDE endpoint and verified entry
Cq-Depend: chromium:1569042
Change-Id: I78ad1a249d90b5de112ed6da4db319bcf19ff836
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/chromite/+/1570352
Tested-by: Alex Klein <saklein@chromium.org>
Reviewed-by: Evan Hernandez <evanhernandez@chromium.org>
Reviewed-by: Sean Abraham <seanabraham@chromium.org>
diff --git a/scripts/build_api_unittest.py b/scripts/build_api_unittest.py
index efa1669..957e73c 100644
--- a/scripts/build_api_unittest.py
+++ b/scripts/build_api_unittest.py
@@ -16,9 +16,9 @@
from chromite.scripts import build_api
-class RouterTest(cros_test_lib.MockTempDirTestCase):
+class RouterTest(cros_test_lib.RunCommandTempDirTestCase):
"""Test Router functionality."""
- _INPUT_JSON = '{"id":"Input ID"}'
+ _INPUT_JSON_TEMPLATE = '{"id":"Input ID", "chroot":{"path": "%s"}}'
def setUp(self):
self.router = build_api.Router()
@@ -27,7 +27,13 @@
self.input_file = os.path.join(self.tempdir, 'input.json')
self.output_file = os.path.join(self.tempdir, 'output.json')
- osutils.WriteFile(self.input_file, self._INPUT_JSON)
+ self.chroot_dir = os.path.join(self.tempdir, 'chroot')
+ chroot_tmp = os.path.join(self.chroot_dir, 'tmp')
+ # Make the tmp dir for the re-exec inside chroot input/output files.
+ osutils.SafeMakedirs(chroot_tmp)
+
+ osutils.WriteFile(self.input_file,
+ self._INPUT_JSON_TEMPLATE % self.chroot_dir)
def testInputOutputMethod(self):
"""Test input/output handling."""
@@ -51,83 +57,92 @@
self.router.Route('chromite.api.TestApiService', 'RenamedMethod',
self.input_file, self.output_file)
- def testInsideServiceChrootAsserts(self):
- """Test the chroot assertion handling with service inside configured."""
- # Helper variables/functions to make the patches simpler.
- should_be_called = False
- is_inside = False
+ def _mock_callable(self, expect_called):
+ """Helper to create the implementation mock to test chroot assertions.
+
+ Args:
+ expect_called (bool): Whether the implementation should be called.
+ When False, an assertion will fail if it is called.
+
+ Returns:
+ callable - The implementation.
+ """
def impl(_input_msg, _output_msg):
- self.assertTrue(should_be_called,
+ self.assertTrue(expect_called,
'The implementation should not have been called.')
- def inside():
- return is_inside
- self.PatchObject(self.router, '_GetMethod', return_value=impl)
- self.PatchObject(cros_build_lib, 'IsInsideChroot', side_effect=inside)
+ return impl
- # Not inside chroot with inside requirement should raise an error.
- with self.assertRaises(cros_build_lib.DieSystemExit):
- self.router.Route('chromite.api.InsideChrootApiService',
- 'InsideServiceInsideMethod', self.input_file,
- self.output_file)
-
- # Inside chroot with inside requirement.
- is_inside = should_be_called = True
+ def testInsideServiceInsideMethodInsideChroot(self):
+ """Test inside/inside/inside works correctly."""
+ self.PatchObject(self.router, '_GetMethod',
+ return_value=self._mock_callable(expect_called=True))
+ self.PatchObject(cros_build_lib, 'IsInsideChroot', return_value=True)
self.router.Route('chromite.api.InsideChrootApiService',
'InsideServiceInsideMethod', self.input_file,
self.output_file)
- # Inside chroot with outside override should raise assertion.
- is_inside = True
- should_be_called = False
+ def testInsideServiceOutsideMethodOutsideChroot(self):
+ """Test the outside method override works as expected."""
+ self.PatchObject(self.router, '_GetMethod',
+ return_value=self._mock_callable(expect_called=True))
+ self.PatchObject(cros_build_lib, 'IsInsideChroot', return_value=False)
+ self.router.Route('chromite.api.InsideChrootApiService',
+ 'InsideServiceOutsideMethod', self.input_file,
+ self.output_file)
+
+ def testInsideServiceInsideMethodOutsideChroot(self):
+ """Test calling an inside method from outside the chroot."""
+ self.PatchObject(self.router, '_GetMethod',
+ return_value=self._mock_callable(expect_called=False))
+ self.PatchObject(cros_build_lib, 'IsInsideChroot', return_value=False)
+ self.rc.return_value = cros_build_lib.CommandResult(returncode=0)
+
+ service = 'chromite.api.InsideChrootApiService'
+ method = 'InsideServiceInsideMethod'
+ service_method = '%s/%s' % (service, method)
+ self.router.Route(service, method, self.input_file, self.output_file)
+
+ self.assertCommandContains(['build_api', service_method])
+
+ def testInsideServiceOutsideMethodInsideChroot(self):
+ """Test inside chroot for outside method raises an error."""
+ self.PatchObject(self.router, '_GetMethod',
+ return_value=self._mock_callable(expect_called=False))
+ self.PatchObject(cros_build_lib, 'IsInsideChroot', return_value=True)
with self.assertRaises(cros_build_lib.DieSystemExit):
self.router.Route('chromite.api.InsideChrootApiService',
'InsideServiceOutsideMethod', self.input_file,
self.output_file)
- is_inside = False
- should_be_called = True
- self.router.Route('chromite.api.InsideChrootApiService',
- 'InsideServiceOutsideMethod', self.input_file,
- self.output_file)
-
- def testOutsideServiceChrootAsserts(self):
- """Test the chroot assertion handling with service outside configured."""
- # Helper variables/functions to make the patches simpler.
- should_be_called = False
- is_inside = False
- def impl(_input_msg, _output_msg):
- self.assertTrue(should_be_called,
- 'The implementation should not have been called.')
-
- self.PatchObject(self.router, '_GetMethod', return_value=impl)
- self.PatchObject(cros_build_lib, 'IsInsideChroot',
- side_effect=lambda: is_inside)
-
- # Outside chroot with outside requirement should be fine.
- is_inside = False
- should_be_called = True
+ def testOutsideServiceOutsideMethodOutsideChroot(self):
+ """Test outside/outside/outside works correctly."""
+ self.PatchObject(self.router, '_GetMethod',
+ return_value=self._mock_callable(expect_called=True))
+ self.PatchObject(cros_build_lib, 'IsInsideChroot', return_value=False)
self.router.Route('chromite.api.OutsideChrootApiService',
'OutsideServiceOutsideMethod', self.input_file,
self.output_file)
- # Inside chroot with outside requirement should raise error.
- is_inside = True
- should_be_called = False
- with self.assertRaises(cros_build_lib.DieSystemExit):
- self.router.Route('chromite.api.OutsideChrootApiService',
- 'OutsideServiceOutsideMethod', self.input_file,
- self.output_file)
-
- # Outside chroot with inside override should raise error.
- is_inside = should_be_called = False
- with self.assertRaises(cros_build_lib.DieSystemExit):
- self.router.Route('chromite.api.OutsideChrootApiService',
- 'OutsideServiceInsideMethod', self.input_file,
- self.output_file)
-
- # Inside chroot with inside override should be fine.
- is_inside = should_be_called = True
+ def testOutsideServiceInsideMethodInsideChroot(self):
+ """Test the inside method assertion override works properly."""
+ self.PatchObject(self.router, '_GetMethod',
+ return_value=self._mock_callable(expect_called=True))
+ self.PatchObject(cros_build_lib, 'IsInsideChroot', return_value=True)
self.router.Route('chromite.api.OutsideChrootApiService',
'OutsideServiceInsideMethod', self.input_file,
self.output_file)
+
+ def testOutsideServiceInsideMethodOutsideChroot(self):
+ """Test calling an inside override method from outside the chroot."""
+ self.PatchObject(self.router, '_GetMethod',
+ return_value=self._mock_callable(expect_called=False))
+ self.PatchObject(cros_build_lib, 'IsInsideChroot', return_value=False)
+ self.rc.return_value = cros_build_lib.CommandResult(returncode=0)
+
+ service = 'chromite.api.OutsideChrootApiService'
+ method = 'OutsideServiceInsideMethod'
+ service_method = '%s/%s' % (service, method)
+ self.router.Route(service, method, self.input_file, self.output_file)
+
+ self.assertCommandContains(['build_api', service_method])