Add api/controllers endpoint for BundleFpmcuUnittests

Implementations to bundle fingerprint MCU unittest binaries are
done in http://crrev/c/2405306 (there are one service/artifacts.py
implementation and one cbuildbot/commands.py implementation that
calls into the service/ one). This change exposes the service/
implementation through api/controllers, so that infra recipes can
call it and get the bundled artifact.

BUG=b:158580909
TEST=run_pytest api/controllers/artifacts_unittest.py

Change-Id: I2718a4c25deabae07b6aed4bee4a4a6a60044e96
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/chromite/+/2424851
Tested-by: Yicheng Li <yichengli@chromium.org>
Commit-Queue: Yicheng Li <yichengli@chromium.org>
Reviewed-by: LaMont Jones <lamontjones@chromium.org>
Reviewed-by: Alex Klein <saklein@chromium.org>
diff --git a/api/controller/artifacts_unittest.py b/api/controller/artifacts_unittest.py
index 1d6267f..a0d14fd 100644
--- a/api/controller/artifacts_unittest.py
+++ b/api/controller/artifacts_unittest.py
@@ -501,6 +501,48 @@
                                self.api_config)
 
 
+class BundleFpmcuUnittestsTest(BundleTestCase):
+  """Unittests for BundleFpmcuUnittests."""
+
+  def testValidateOnly(self):
+    """Sanity check that a validate only call does not execute any logic."""
+    patch = self.PatchObject(artifacts_svc, 'BundleFpmcuUnittests')
+    artifacts.BundleFpmcuUnittests(self.sysroot_request, self.response,
+                                   self.validate_only_config)
+    patch.assert_not_called()
+
+  def testMockCall(self):
+    """Test that a mock call does not execute logic, returns mocked value."""
+    patch = self.PatchObject(artifacts_svc, 'BundleFpmcuUnittests')
+    artifacts.BundleFpmcuUnittests(self.sysroot_request, self.response,
+                                   self.mock_call_config)
+    patch.assert_not_called()
+    self.assertEqual(len(self.response.artifacts), 1)
+    self.assertEqual(self.response.artifacts[0].path,
+                     os.path.join(self.output_dir,
+                                  'fpmcu_unittests.tar.gz'))
+
+  def testBundleFpmcuUnittests(self):
+    """BundleFpmcuUnittests calls cbuildbot/commands with correct args."""
+    self.PatchObject(
+        artifacts_svc,
+        'BundleFpmcuUnittests',
+        return_value=os.path.join(self.output_dir, 'fpmcu_unittests.tar.gz'))
+    artifacts.BundleFpmcuUnittests(self.sysroot_request, self.response,
+                                   self.api_config)
+    self.assertEqual(
+        [artifact.path for artifact in self.response.artifacts],
+        [os.path.join(self.output_dir, 'fpmcu_unittests.tar.gz')])
+
+  def testBundleFpmcuUnittestsNoLogs(self):
+    """BundleFpmcuUnittests does not die when no fpmcu unittests found."""
+    self.PatchObject(artifacts_svc, 'BundleFpmcuUnittests',
+                     return_value=None)
+    artifacts.BundleFpmcuUnittests(self.sysroot_request, self.response,
+                                   self.api_config)
+    self.assertFalse(self.response.artifacts)
+
+
 class BundleEbuildLogsTest(BundleTestCase):
   """Unittests for BundleEbuildLogs."""