tools: create face during nfdc route add

refs #4332

Change-Id: I1a30bf87abd57bab08a2c027870e779392de0104
diff --git a/tests/tools/nfdc/face-module.t.cpp b/tests/tools/nfdc/face-module.t.cpp
index 84031dd..e2c9a86 100644
--- a/tests/tools/nfdc/face-module.t.cpp
+++ b/tests/tools/nfdc/face-module.t.cpp
@@ -863,7 +863,8 @@
   this->execute("face create invalid://");
   BOOST_CHECK_EQUAL(exitCode, 4);
   BOOST_CHECK(out.is_empty());
-  BOOST_CHECK(err.is_equal("Error when canonizing 'invalid://': scheme not supported\n"));
+  BOOST_CHECK(err.is_equal("Error during canonization of remote FaceUri 'invalid://': "
+                           "scheme not supported\n"));
 }
 
 BOOST_AUTO_TEST_CASE(ErrorCanonizeLocal)
@@ -871,7 +872,8 @@
   this->execute("face create udp4://24.37.20.47:6363 local invalid://");
   BOOST_CHECK_EQUAL(exitCode, 4);
   BOOST_CHECK(out.is_empty());
-  BOOST_CHECK(err.is_equal("Error when canonizing 'invalid://': scheme not supported\n"));
+  BOOST_CHECK(err.is_equal("Error during canonization of local FaceUri 'invalid://': "
+                           "scheme not supported\n"));
 }
 
 BOOST_AUTO_TEST_CASE(ErrorCreate)
@@ -1002,7 +1004,7 @@
   this->execute("face destroy udp6://32.38.164.64:10445");
   BOOST_CHECK_EQUAL(exitCode, 4);
   BOOST_CHECK(out.is_empty());
-  BOOST_CHECK(err.is_equal("Error during remote FaceUri canonization: "
+  BOOST_CHECK(err.is_equal("Error during canonization of 'udp6://32.38.164.64:10445': "
                            "IPv4/v6 mismatch\n"));
 }
 
diff --git a/tests/tools/nfdc/mock-nfd-mgmt-fixture.hpp b/tests/tools/nfdc/mock-nfd-mgmt-fixture.hpp
index 5242c9b..239faa9 100644
--- a/tests/tools/nfdc/mock-nfd-mgmt-fixture.hpp
+++ b/tests/tools/nfdc/mock-nfd-mgmt-fixture.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2019,  Regents of the University of California,
+ * Copyright (c) 2014-2020,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -40,7 +40,7 @@
 class MockNfdMgmtFixture : public nfd::tools::tests::MockNfdMgmtFixture
 {
 protected:
-  /** \brief respond to specific FaceQuery requests
+  /** \brief respond to FaceQuery requests
    *  \retval true the Interest matches one of the defined patterns and is responded
    *  \retval false the Interest is not responded
    */
@@ -54,8 +54,8 @@
     if (!Name("/localhost/nfd/faces/query").isPrefixOf(interest.getName())) {
       return false;
     }
-    BOOST_CHECK_EQUAL(interest.getName().size(), 5);
-    FaceQueryFilter filter(interest.getName().at(4).blockFromValue());
+    BOOST_REQUIRE_EQUAL(interest.getName().size(), 5);
+    FaceQueryFilter filter(interest.getName()[-1].blockFromValue());
 
     if (filter == FaceQueryFilter().setFaceId(10156)) {
       FaceStatus faceStatus;
@@ -96,6 +96,8 @@
       return true;
     }
 
+    // Return empty dataset
+    this->sendEmptyDataset(interest.getName());
     return false;
   }
 };
diff --git a/tests/tools/nfdc/rib-module.t.cpp b/tests/tools/nfdc/rib-module.t.cpp
index 624fca6..7f268dd 100644
--- a/tests/tools/nfdc/rib-module.t.cpp
+++ b/tests/tools/nfdc/rib-module.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2019,  Regents of the University of California,
+ * Copyright (c) 2014-2020,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -263,7 +263,7 @@
   BOOST_CHECK(err.is_empty());
 }
 
-BOOST_AUTO_TEST_CASE(FaceNotExist)
+BOOST_AUTO_TEST_CASE(FaceNotExistFaceId)
 {
   this->processInterest = [this] (const Interest& interest) {
     BOOST_CHECK(this->respondFaceQuery(interest));
@@ -275,6 +275,76 @@
   BOOST_CHECK(err.is_equal("Face not found\n"));
 }
 
+BOOST_AUTO_TEST_CASE(FaceNotExistFaceUri)
+{
+  this->processInterest = [this] (const Interest& interest) {
+    if (Name("/localhost/nfd/faces/query").isPrefixOf(interest.getName())) {
+      this->respondFaceQuery(interest);
+    }
+    else if (Name("/localhost/nfd/faces/create").isPrefixOf(interest.getName())) {
+      ControlParameters req = MOCK_NFD_MGMT_REQUIRE_COMMAND_IS("/localhost/nfd/faces/create");
+      ndn::nfd::FaceCreateCommand cmd;
+      cmd.validateRequest(req);
+      cmd.applyDefaultsToRequest(req);
+      BOOST_CHECK_EQUAL(req.getUri(), "udp4://202.83.168.28:6363");
+
+      ControlParameters resp = req;
+      resp.setFaceId(255);
+      resp.setLocalUri("udp4://32.121.182.82:50000");
+      resp.setFacePersistency(FacePersistency::FACE_PERSISTENCY_PERSISTENT);
+      resp.setBaseCongestionMarkingInterval(100_ms);
+      resp.setDefaultCongestionThreshold(65536);
+      resp.setMtu(8800);
+      resp.setFlags(0);
+      this->succeedCommand(interest, resp);
+    }
+    else if (Name("/localhost/nfd/rib/register").isPrefixOf(interest.getName())) {
+      ControlParameters req = MOCK_NFD_MGMT_REQUIRE_COMMAND_IS("/localhost/nfd/rib/register");
+      ndn::nfd::RibRegisterCommand cmd;
+      cmd.validateRequest(req);
+      cmd.applyDefaultsToRequest(req);
+      BOOST_CHECK_EQUAL(req.getName(), "/634jfAfdf");
+      BOOST_CHECK_EQUAL(req.getFaceId(), 255);
+      BOOST_CHECK_EQUAL(req.getOrigin(), 17591);
+      BOOST_CHECK_EQUAL(req.getCost(), 702);
+      BOOST_CHECK_EQUAL(req.getFlags(), ndn::nfd::ROUTE_FLAG_CHILD_INHERIT |
+                                        ndn::nfd::ROUTE_FLAG_CAPTURE);
+      BOOST_REQUIRE_EQUAL(req.hasExpirationPeriod(), true);
+      BOOST_REQUIRE_EQUAL(req.getExpirationPeriod(), 727411987_ms);
+
+      ControlParameters resp = req;
+      resp.setExpirationPeriod(727411154_ms); // server side may change expiration
+      this->succeedCommand(interest, resp);
+    }
+  };
+
+  this->execute("route add /634jfAfdf udp4://202.83.168.28:6363 "
+                "origin 17591 cost 702 capture expires 727411987");
+  BOOST_CHECK(out.is_equal("face-created id=255 local=udp4://32.121.182.82:50000 "
+                           "remote=udp4://202.83.168.28:6363 persistency=persistent "
+                           "reliability=off congestion-marking=off "
+                           "congestion-marking-interval=100ms default-congestion-threshold=65536B "
+                           "mtu=8800\n"
+                           "route-add-accepted prefix=/634jfAfdf nexthop=255 origin=17591 "
+                           "cost=702 flags=child-inherit|capture expires=727411154ms\n"));
+  BOOST_CHECK(err.is_empty());
+  BOOST_CHECK_EQUAL(exitCode, 0);
+}
+
+BOOST_AUTO_TEST_CASE(FaceNotExistNotCanonizable)
+{
+  this->processInterest = [this] (const Interest& interest) {
+    BOOST_CHECK(this->respondFaceQuery(interest));
+  };
+
+  this->execute("route add /634jfAfdf udp6://202.83.168.28:6363 "
+                "origin 17591 cost 702 capture expires 727411987");
+  BOOST_CHECK(out.is_empty());
+  BOOST_CHECK(err.is_equal("Error during canonization of 'udp6://202.83.168.28:6363': "
+                           "IPv4/v6 mismatch\n"));
+  BOOST_CHECK_EQUAL(exitCode, 4);
+}
+
 BOOST_AUTO_TEST_CASE(Ambiguous)
 {
   this->processInterest = [this] (const Interest& interest) {
@@ -295,7 +365,7 @@
   this->execute("route add /bxJfGsVtDt udp6://32.38.164.64:10445");
   BOOST_CHECK_EQUAL(exitCode, 4);
   BOOST_CHECK(out.is_empty());
-  BOOST_CHECK(err.is_equal("Error during remote FaceUri canonization: "
+  BOOST_CHECK(err.is_equal("Error during canonization of 'udp6://32.38.164.64:10445': "
                            "IPv4/v6 mismatch\n"));
 }