mgmt: support rib/announce control command

This commit adds support for a new control command type,
RibAnnounceCommand. A new command format class is also added,
ApplicationParametersCommandFormat, to support encoding the
request information in the ApplicationParameters element of
the interest instead of using ControlParameters.

Refs: #4650
Change-Id: I351d3852062a80349fb67d7f18db4c883551835c
diff --git a/tests/unit/mgmt/nfd/control-command.t.cpp b/tests/unit/mgmt/nfd/control-command.t.cpp
index dc8cff0..8aa7f50 100644
--- a/tests/unit/mgmt/nfd/control-command.t.cpp
+++ b/tests/unit/mgmt/nfd/control-command.t.cpp
@@ -22,6 +22,7 @@
 #include "ndn-cxx/mgmt/nfd/control-command.hpp"
 
 #include "tests/boost-test.hpp"
+#include "tests/key-chain-fixture.hpp"
 
 namespace ndn::tests {
 
@@ -492,6 +493,51 @@
   BOOST_CHECK_THROW(Command::validateResponse(p2), ArgumentError);
 }
 
+BOOST_FIXTURE_TEST_CASE(RibAnnounce, KeyChainFixture)
+{
+  using Command = RibAnnounceCommand;
+
+  // Good request
+  PrefixAnnouncement pa1;
+  pa1.setAnnouncedName("ndn:/");
+  pa1.setExpiration(1_min);
+  pa1.toData(m_keyChain);
+  RibAnnounceParameters p1;
+  p1.setPrefixAnnouncement(pa1);
+  BOOST_CHECK_NO_THROW(Command::validateRequest(p1));
+  Name n1 = Command::createRequest("/PREFIX", p1).getName();
+  BOOST_CHECK(Name("ndn:/PREFIX/rib/announce").isPrefixOf(n1));
+
+  // Good response
+  ControlParameters p2;
+  p2.setName("ndn:/")
+    .setFaceId(22)
+    .setOrigin(ndn::nfd::ROUTE_ORIGIN_PREFIXANN)
+    .setCost(2048)
+    .setFlags(ndn::nfd::ROUTE_FLAG_CHILD_INHERIT)
+    .setExpirationPeriod(1_min);
+  BOOST_CHECK_NO_THROW(Command::validateResponse(p2));
+
+  // Bad request (PrefixAnnouncement must be signed)
+  PrefixAnnouncement pa2;
+  pa2.setAnnouncedName("ndn:/");
+  pa2.setExpiration(1_min);
+  RibAnnounceParameters p3;
+  BOOST_CHECK_THROW(Command::validateRequest(p3), ArgumentError);
+  p3.setPrefixAnnouncement(pa2);
+  BOOST_CHECK_THROW(Command::validateRequest(p3), ArgumentError);
+
+  // Bad response (FaceId must be valid)
+  ControlParameters p4;
+  p4.setName("ndn:/")
+    .setFaceId(0)
+    .setOrigin(ndn::nfd::ROUTE_ORIGIN_PREFIXANN)
+    .setCost(2048)
+    .setFlags(ndn::nfd::ROUTE_FLAG_CHILD_INHERIT)
+    .setExpirationPeriod(1_min);
+  BOOST_CHECK_THROW(Command::validateResponse(p4), ArgumentError);
+}
+
 BOOST_AUTO_TEST_SUITE_END() // TestControlCommand
 BOOST_AUTO_TEST_SUITE_END() // Nfd
 BOOST_AUTO_TEST_SUITE_END() // Mgmt
diff --git a/tests/unit/mgmt/nfd/controller.t.cpp b/tests/unit/mgmt/nfd/controller.t.cpp
index 8be9d23..9fad4ec 100644
--- a/tests/unit/mgmt/nfd/controller.t.cpp
+++ b/tests/unit/mgmt/nfd/controller.t.cpp
@@ -140,11 +140,15 @@
 
 BOOST_AUTO_TEST_CASE(InvalidRequest)
 {
-  ControlParameters parameters;
-  parameters.setName("ndn:/should-not-have-this-field");
+  ControlParameters p1;
+  p1.setName("/should-not-have-this-field");
   // Uri is missing
+  BOOST_CHECK_THROW(controller.start<FaceCreateCommand>(p1, succeedCallback, commandFailCallback),
+                    ArgumentError);
 
-  BOOST_CHECK_THROW(controller.start<FaceCreateCommand>(parameters, succeedCallback, commandFailCallback),
+  RibAnnounceParameters p2;
+  // PrefixAnnouncement not signed
+  BOOST_CHECK_THROW(controller.start<RibAnnounceCommand>(p2, succeedCallback, commandFailCallback),
                     ArgumentError);
 }