Implement Sysroot.GenerateArchive.

Regenerated api/gen/chromite/api/sysroot_pb2.py by running
compile_build_api_proto.  This ports the code in
cbuildbot/stages/artifact_stage.py (_GenerateSysroot).

BUG=chromium:1042402
TEST=manual, run_tests

Change-Id: I71ea25babdd696162fd512dffa8859346f03e348
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/chromite/+/2044369
Reviewed-by: Alex Klein <saklein@chromium.org>
Tested-by: Michael Mortensen <mmortensen@google.com>
diff --git a/api/controller/sysroot_unittest.py b/api/controller/sysroot_unittest.py
index 94fe3dd..cd335ee 100644
--- a/api/controller/sysroot_unittest.py
+++ b/api/controller/sysroot_unittest.py
@@ -14,6 +14,7 @@
 from chromite.api import controller
 from chromite.api.controller import sysroot as sysroot_controller
 from chromite.api.gen.chromite.api import sysroot_pb2
+from chromite.api.gen.chromiumos import common_pb2
 from chromite.lib import build_target_util
 from chromite.lib import cros_build_lib
 from chromite.lib import cros_test_lib
@@ -199,6 +200,86 @@
     patch.assert_called_once()
 
 
+class GenerateArchiveTest(cros_test_lib.MockTempDirTestCase,
+                          api_config.ApiConfigMixin):
+  """GenerateArchive function tests."""
+
+  def setUp(self):
+    self.chroot_path = '/path/to/chroot'
+    self.board = 'board'
+
+  def _InputProto(self, build_target=None, chroot_path=None, pkg_list=None):
+    """Helper to build and input proto instance."""
+    # pkg_list will be a list of category/package strings such as
+    # ['virtual/target-fuzzers'].
+    if pkg_list:
+      package_list = []
+      for pkg in pkg_list:
+        pkg_string_parts = pkg.split('/')
+        package_info = common_pb2.PackageInfo(
+            category=pkg_string_parts[0],
+            package_name=pkg_string_parts[1])
+        package_list.append(package_info)
+    else:
+      package_list = []
+
+    return sysroot_pb2.SysrootGenerateArchiveRequest(
+        build_target={'name': build_target},
+        chroot={'path': chroot_path},
+        packages=package_list)
+
+  def _OutputProto(self):
+    """Helper to build output proto instance."""
+    return sysroot_pb2.SysrootGenerateArchiveResponse()
+
+  def testValidateOnly(self):
+    """Sanity check that a validate only call does not execute any logic."""
+    patch = self.PatchObject(sysroot_service, 'GenerateArchive')
+
+    in_proto = self._InputProto(build_target=self.board,
+                                chroot_path=self.chroot_path,
+                                pkg_list=['virtual/target-fuzzers'])
+    sysroot_controller.GenerateArchive(in_proto, self._OutputProto(),
+                                       self.validate_only_config)
+    patch.assert_not_called()
+
+  def testMockCall(self):
+    """Sanity check that a mock call does not execute any logic."""
+    patch = self.PatchObject(sysroot_service, 'GenerateArchive')
+
+    in_proto = self._InputProto(build_target=self.board,
+                                chroot_path=self.chroot_path,
+                                pkg_list=['virtual/target-fuzzers'])
+    sysroot_controller.GenerateArchive(in_proto,
+                                       self._OutputProto(),
+                                       self.mock_call_config)
+    patch.assert_not_called()
+
+  def testArgumentValidation(self):
+    """Test the input argument validation."""
+    # Error when no build target provided.
+    in_proto = self._InputProto()
+    out_proto = self._OutputProto()
+    with self.assertRaises(cros_build_lib.DieSystemExit):
+      sysroot_controller.GenerateArchive(in_proto, out_proto, self.api_config)
+
+    # Error when packages is not specified.
+    in_proto = self._InputProto(build_target='board',
+                                chroot_path=self.chroot_path)
+    with self.assertRaises(cros_build_lib.DieSystemExit):
+      sysroot_controller.GenerateArchive(in_proto, out_proto, self.api_config)
+
+    # Valid when board, chroot path, and package are specified.
+    patch = self.PatchObject(sysroot_service, 'GenerateArchive',
+                             return_value='/path/to/sysroot/tar.bz')
+    in_proto = self._InputProto(build_target='board',
+                                chroot_path=self.chroot_path,
+                                pkg_list=['virtual/target-fuzzers'])
+    out_proto = self._OutputProto()
+    sysroot_controller.GenerateArchive(in_proto, out_proto, self.api_config)
+    patch.assert_called_once()
+
+
 class InstallToolchainTest(cros_test_lib.MockTempDirTestCase,
                            api_config.ApiConfigMixin):
   """Install toolchain function tests."""