mgmt: allow omitted FaceId in faces/create command

Change-Id: I27655e8b7e67dce88e787a0b4b18fe34cafbf5d5
Refs: #2031
diff --git a/AUTHORS.md b/AUTHORS.md
index aef5ace..6538fcb 100644
--- a/AUTHORS.md
+++ b/AUTHORS.md
@@ -18,7 +18,7 @@
 * Lixia Zhang         <http://www.cs.ucla.edu/~lixia/>
 
 
-## All project authors and contributors and their affiliations:
+## Main project authors and their affiliations:
 
 * University of California, Los Angeles
 
@@ -63,3 +63,11 @@
     * Syed Obaid Amin     <http://obaidamin.weebly.com/>
     * Vince Lehman        <vslehman@memphis.edu>
     * Lan Wang            <http://www.cs.memphis.edu/~lanwang/>
+
+## Project contributors
+
+The following is an inevitably incomplete list of MUCH-APPRECIATED CONTRIBUTORS,
+people who have reported bugs, submitted patches, and implemented new features
+in the library:
+
+* Tai-Lin Chu             <https://www.linkedin.com/pub/tai-lin-chu/55/5b2/669>
diff --git a/daemon/mgmt/fib-manager.cpp b/daemon/mgmt/fib-manager.cpp
index bda1681..5c91547 100644
--- a/daemon/mgmt/fib-manager.cpp
+++ b/daemon/mgmt/fib-manager.cpp
@@ -143,14 +143,15 @@
   if (verbProcessor != m_signedVerbDispatch.end())
     {
       ControlParameters parameters;
-      if (!extractParameters(parameterComponent, parameters) || !parameters.hasFaceId())
+      if (!extractParameters(parameterComponent, parameters))
         {
           NFD_LOG_DEBUG("command result: malformed verb: " << verb);
           sendResponse(command, 400, "Malformed command");
           return;
         }
 
-      if (parameters.getFaceId() == 0)
+      bool isSelfRegistration = (!parameters.hasFaceId() || parameters.getFaceId() == 0);
+      if (isSelfRegistration)
         {
           parameters.setFaceId(request->getIncomingFaceId());
         }
diff --git a/tests/daemon/mgmt/fib-manager.cpp b/tests/daemon/mgmt/fib-manager.cpp
index 8101cd4..6f5a006 100644
--- a/tests/daemon/mgmt/fib-manager.cpp
+++ b/tests/daemon/mgmt/fib-manager.cpp
@@ -175,8 +175,8 @@
   ndn::KeyChain m_keyChain;
 };
 
-template <typename T> class AuthorizedCommandFixture:
-    public CommandFixture<T>
+template <typename T>
+class AuthorizedCommandFixture : public CommandFixture<T>
 {
 public:
   AuthorizedCommandFixture()
@@ -407,42 +407,49 @@
   BOOST_REQUIRE(addedNextHopWithCost(getFib(), "/hello", 0, 101) == false);
 }
 
-BOOST_AUTO_TEST_CASE(TestImplicitFaceId)
+BOOST_AUTO_TEST_CASE(AddNextHopVerbImplicitFaceId)
 {
   addFace(make_shared<DummyFace>());
 
   shared_ptr<InternalFace> face = getInternalFace();
 
-  ControlParameters parameters;
-  parameters.setName("/hello");
-  parameters.setFaceId(0);
-  parameters.setCost(101);
+  std::vector<ControlParameters> testedParameters;
+  testedParameters.push_back(ControlParameters().setName("/hello").setCost(101).setFaceId(0));
+  testedParameters.push_back(ControlParameters().setName("/hello").setCost(101));
 
-  Block encodedParameters(parameters.wireEncode());
+  for (std::vector<ControlParameters>::iterator parameters = testedParameters.begin();
+       parameters != testedParameters.end(); ++parameters) {
 
-  Name commandName("/localhost/nfd/fib");
-  commandName.append("add-nexthop");
-  commandName.append(encodedParameters);
+    Block encodedParameters(parameters->wireEncode());
 
-  ControlParameters expectedParameters;
-  expectedParameters.setName("/hello");
-  expectedParameters.setFaceId(1);
-  expectedParameters.setCost(101);
+    Name commandName("/localhost/nfd/fib");
+    commandName.append("add-nexthop");
+    commandName.append(encodedParameters);
 
-  Block encodedExpectedParameters(expectedParameters.wireEncode());
+    ControlParameters expectedParameters;
+    expectedParameters.setName("/hello");
+    expectedParameters.setFaceId(1);
+    expectedParameters.setCost(101);
 
-  shared_ptr<Interest> command(make_shared<Interest>(commandName));
-  command->setIncomingFaceId(1);
-  generateCommand(*command);
+    Block encodedExpectedParameters(expectedParameters.wireEncode());
 
-  face->onReceiveData +=
-    bind(&FibManagerFixture::validateControlResponse, this, _1,
-         command->getName(), 200, "Success", encodedExpectedParameters);
+    shared_ptr<Interest> command(make_shared<Interest>(commandName));
+    command->setIncomingFaceId(1);
+    generateCommand(*command);
 
-  getFibManager().onFibRequest(*command);
+    face->onReceiveData +=
+      bind(&FibManagerFixture::validateControlResponse, this, _1,
+           command->getName(), 200, "Success", encodedExpectedParameters);
 
-  BOOST_REQUIRE(didCallbackFire());
-  BOOST_REQUIRE(addedNextHopWithFace(getFib(), "/hello", 0, 101, getFace(1)));
+    getFibManager().onFibRequest(*command);
+
+    BOOST_REQUIRE(didCallbackFire());
+    BOOST_REQUIRE(addedNextHopWithFace(getFib(), "/hello", 0, 101, getFace(1)));
+
+    face->onReceiveData.clear();
+    getFib().erase("/hello");
+    BOOST_REQUIRE_EQUAL(getFib().size(), 0);
+  }
 }
 
 BOOST_AUTO_TEST_CASE(AddNextHopVerbInitialAdd)
@@ -658,33 +665,6 @@
   BOOST_REQUIRE(didCallbackFire());
 }
 
-BOOST_AUTO_TEST_CASE(AddNextHopVerbMissingFaceId)
-{
-  addFace(make_shared<DummyFace>());
-
-  shared_ptr<InternalFace> face = getInternalFace();
-
-  ControlParameters parameters;
-  parameters.setName("/hello");
-
-  Block encodedParameters(parameters.wireEncode());
-
-  Name commandName("/localhost/nfd/fib");
-  commandName.append("add-nexthop");
-  commandName.append(encodedParameters);
-
-  shared_ptr<Interest> command(make_shared<Interest>(commandName));
-  generateCommand(*command);
-
-  face->onReceiveData +=
-    bind(&FibManagerFixture::validateControlResponse, this, _1,
-         command->getName(), 400, "Malformed command");
-
-  getFibManager().onFibRequest(*command);
-
-  BOOST_REQUIRE(didCallbackFire());
-}
-
 bool
 removedNextHopWithCost(const Fib& fib, const Name& prefix, size_t oldSize, uint32_t cost)
 {
@@ -845,31 +825,42 @@
   BOOST_REQUIRE(didCallbackFire());
 }
 
-BOOST_AUTO_TEST_CASE(RemoveMissingFaceId)
+BOOST_AUTO_TEST_CASE(RemoveImplicitFaceId)
 {
   addFace(make_shared<DummyFace>());
 
   shared_ptr<InternalFace> face = getInternalFace();
 
-  ControlParameters parameters;
-  parameters.setName("/hello");
+  std::vector<ControlParameters> testedParameters;
+  testedParameters.push_back(ControlParameters().setName("/hello").setFaceId(0));
+  testedParameters.push_back(ControlParameters().setName("/hello"));
 
-  Block encodedParameters(parameters.wireEncode());
+  for (std::vector<ControlParameters>::iterator parameters = testedParameters.begin();
+       parameters != testedParameters.end(); ++parameters) {
+    Block encodedParameters(parameters->wireEncode());
 
-  Name commandName("/localhost/nfd/fib");
-  commandName.append("remove-nexthop");
-  commandName.append(encodedParameters);
+    Name commandName("/localhost/nfd/fib");
+    commandName.append("remove-nexthop");
+    commandName.append(encodedParameters);
 
-  shared_ptr<Interest> command(make_shared<Interest>(commandName));
-  generateCommand(*command);
+    shared_ptr<Interest> command(make_shared<Interest>(commandName));
+    command->setIncomingFaceId(1);
+    generateCommand(*command);
 
-  face->onReceiveData +=
-    bind(&FibManagerFixture::validateControlResponse, this, _1,
-         command->getName(), 400, "Malformed command");
+    ControlParameters resultParameters;
+    resultParameters.setFaceId(1);
+    resultParameters.setName("/hello");
 
-  getFibManager().onFibRequest(*command);
+    face->onReceiveData +=
+      bind(&FibManagerFixture::validateControlResponse, this, _1,
+           command->getName(), 200, "Success", resultParameters.wireEncode());
 
-  BOOST_REQUIRE(didCallbackFire());
+    getFibManager().onFibRequest(*command);
+
+    BOOST_REQUIRE(didCallbackFire());
+
+    face->onReceiveData.clear();
+  }
 }
 
 BOOST_FIXTURE_TEST_CASE(TestFibEnumerationRequest, FibManagerFixture)