face: ProtocolFactory::createFace with FacePersistency

Change-Id: If02510bd631e9aaa63b3cca89ced31a42e192ded
Refs: #2989
diff --git a/daemon/face/ethernet-factory.cpp b/daemon/face/ethernet-factory.cpp
index c422b3d..9387fe6 100644
--- a/daemon/face/ethernet-factory.cpp
+++ b/daemon/face/ethernet-factory.cpp
@@ -67,6 +67,7 @@
 
 void
 EthernetFactory::createFace(const FaceUri& uri,
+                            ndn::nfd::FacePersistency persistency,
                             const FaceCreatedCallback& onCreated,
                             const FaceConnectFailedCallback& onConnectFailed)
 {
diff --git a/daemon/face/ethernet-factory.hpp b/daemon/face/ethernet-factory.hpp
index aa7861f..2441571 100644
--- a/daemon/face/ethernet-factory.hpp
+++ b/daemon/face/ethernet-factory.hpp
@@ -55,8 +55,9 @@
   // from ProtocolFactory
   virtual void
   createFace(const FaceUri& uri,
+             ndn::nfd::FacePersistency persistency,
              const FaceCreatedCallback& onCreated,
-             const FaceConnectFailedCallback& onConnectFailed);
+             const FaceConnectFailedCallback& onConnectFailed) DECL_OVERRIDE;
 
   /**
    * \brief Create an EthernetFace to communicate with the given multicast group
diff --git a/daemon/face/protocol-factory.hpp b/daemon/face/protocol-factory.hpp
index 1c12cc0..49e1a31 100644
--- a/daemon/face/protocol-factory.hpp
+++ b/daemon/face/protocol-factory.hpp
@@ -58,15 +58,17 @@
     Error(const std::string& what) : std::runtime_error(what) {}
   };
 
-  /** \brief Try to create Face using the supplied Face URI
+  /** \brief Try to create Face using the supplied FaceUri
    *
-   * This method should automatically choose channel, based on supplied Face URI
+   * This method should automatically choose channel, based on supplied FaceUri
    * and create face.
    *
-   * \throws Factory::Error if Factory does not support connect operation
+   * \throw Error Factory does not support connect operation
+   * \throw Error specified \p persistency is not supported
    */
   virtual void
   createFace(const FaceUri& uri,
+             ndn::nfd::FacePersistency persistency,
              const FaceCreatedCallback& onCreated,
              const FaceConnectFailedCallback& onConnectFailed) = 0;
 
diff --git a/daemon/face/tcp-factory.cpp b/daemon/face/tcp-factory.cpp
index dc7e369..9c640a1 100644
--- a/daemon/face/tcp-factory.cpp
+++ b/daemon/face/tcp-factory.cpp
@@ -127,9 +127,14 @@
 
 void
 TcpFactory::createFace(const FaceUri& uri,
+                       ndn::nfd::FacePersistency persistency,
                        const FaceCreatedCallback& onCreated,
                        const FaceConnectFailedCallback& onConnectFailed)
 {
+  if (persistency != ndn::nfd::FACE_PERSISTENCY_PERSISTENT) {
+    throw Error("TcpFactory only supports persistent face");
+  }
+
   BOOST_ASSERT(uri.isCanonical());
   boost::asio::ip::address ipAddress = boost::asio::ip::address::from_string(uri.getHost());
   tcp::Endpoint endpoint(ipAddress, boost::lexical_cast<uint16_t>(uri.getPort()));
diff --git a/daemon/face/tcp-factory.hpp b/daemon/face/tcp-factory.hpp
index c577854..2667915 100644
--- a/daemon/face/tcp-factory.hpp
+++ b/daemon/face/tcp-factory.hpp
@@ -77,12 +77,13 @@
   shared_ptr<TcpChannel>
   createChannel(const std::string& localIp, const std::string& localPort);
 
-  // from Factory
+  // from ProtocolFactory
 
   virtual void
   createFace(const FaceUri& uri,
+             ndn::nfd::FacePersistency persistency,
              const FaceCreatedCallback& onCreated,
-             const FaceConnectFailedCallback& onConnectFailed);
+             const FaceConnectFailedCallback& onConnectFailed) DECL_OVERRIDE;
 
   virtual std::list<shared_ptr<const Channel> >
   getChannels() const;
diff --git a/daemon/face/udp-factory.cpp b/daemon/face/udp-factory.cpp
index ddef35e..3a55b7c 100644
--- a/daemon/face/udp-factory.cpp
+++ b/daemon/face/udp-factory.cpp
@@ -250,9 +250,14 @@
 
 void
 UdpFactory::createFace(const FaceUri& uri,
+                       ndn::nfd::FacePersistency persistency,
                        const FaceCreatedCallback& onCreated,
                        const FaceConnectFailedCallback& onConnectFailed)
 {
+  if (persistency != ndn::nfd::FACE_PERSISTENCY_PERSISTENT) {
+    throw Error("UdpFactory only supports persistent face");
+  }
+
   BOOST_ASSERT(uri.isCanonical());
 
   boost::asio::ip::address ipAddress = boost::asio::ip::address::from_string(uri.getHost());
diff --git a/daemon/face/udp-factory.hpp b/daemon/face/udp-factory.hpp
index e59275d..8a4e87a 100644
--- a/daemon/face/udp-factory.hpp
+++ b/daemon/face/udp-factory.hpp
@@ -145,8 +145,9 @@
   // from ProtocolFactory
   virtual void
   createFace(const FaceUri& uri,
+             ndn::nfd::FacePersistency persistency,
              const FaceCreatedCallback& onCreated,
-             const FaceConnectFailedCallback& onConnectFailed);
+             const FaceConnectFailedCallback& onConnectFailed) DECL_OVERRIDE;
 
   virtual std::list<shared_ptr<const Channel>>
   getChannels() const;
diff --git a/daemon/face/unix-stream-factory.cpp b/daemon/face/unix-stream-factory.cpp
index d7513f6..16a01a9 100644
--- a/daemon/face/unix-stream-factory.cpp
+++ b/daemon/face/unix-stream-factory.cpp
@@ -57,6 +57,7 @@
 
 void
 UnixStreamFactory::createFace(const FaceUri& uri,
+                              ndn::nfd::FacePersistency persistency,
                               const FaceCreatedCallback& onCreated,
                               const FaceConnectFailedCallback& onConnectFailed)
 {
diff --git a/daemon/face/unix-stream-factory.hpp b/daemon/face/unix-stream-factory.hpp
index e2aff30..ecb679b 100644
--- a/daemon/face/unix-stream-factory.hpp
+++ b/daemon/face/unix-stream-factory.hpp
@@ -61,8 +61,9 @@
 
   virtual void
   createFace(const FaceUri& uri,
+             ndn::nfd::FacePersistency persistency,
              const FaceCreatedCallback& onCreated,
-             const FaceConnectFailedCallback& onConnectFailed);
+             const FaceConnectFailedCallback& onConnectFailed) DECL_OVERRIDE;
 
   virtual std::list<shared_ptr<const Channel> >
   getChannels() const;
diff --git a/daemon/face/websocket-factory.cpp b/daemon/face/websocket-factory.cpp
index 5fbdf25..e911827 100644
--- a/daemon/face/websocket-factory.cpp
+++ b/daemon/face/websocket-factory.cpp
@@ -67,6 +67,7 @@
 
 void
 WebSocketFactory::createFace(const FaceUri& uri,
+                             ndn::nfd::FacePersistency persistency,
                              const FaceCreatedCallback& onCreated,
                              const FaceConnectFailedCallback& onConnectFailed)
 {
diff --git a/daemon/face/websocket-factory.hpp b/daemon/face/websocket-factory.hpp
index a522036..3859893 100644
--- a/daemon/face/websocket-factory.hpp
+++ b/daemon/face/websocket-factory.hpp
@@ -81,8 +81,9 @@
   // from ProtocolFactory
   virtual void
   createFace(const FaceUri& uri,
+             ndn::nfd::FacePersistency persistency,
              const FaceCreatedCallback& onCreated,
-             const FaceConnectFailedCallback& onConnectFailed);
+             const FaceConnectFailedCallback& onConnectFailed) DECL_OVERRIDE;
 
   virtual std::list<shared_ptr<const Channel> >
   getChannels() const;
diff --git a/daemon/mgmt/face-manager.cpp b/daemon/mgmt/face-manager.cpp
index 3c590f5..eecf25c 100644
--- a/daemon/mgmt/face-manager.cpp
+++ b/daemon/mgmt/face-manager.cpp
@@ -975,6 +975,7 @@
   try
     {
       factory->second->createFace(uri,
+                                  ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
                                   bind(&FaceManager::onCreated,
                                        this, requestName, parameters, _1),
                                   bind(&FaceManager::onConnectFailed,
diff --git a/tests/daemon/face/ethernet.t.cpp b/tests/daemon/face/ethernet.t.cpp
index e0e08f8..a6faf06 100644
--- a/tests/daemon/face/ethernet.t.cpp
+++ b/tests/daemon/face/ethernet.t.cpp
@@ -99,6 +99,29 @@
   BOOST_CHECK_NE(face1, face3);
 }
 
+BOOST_AUTO_TEST_CASE(UnsupportedFaceCreate)
+{
+  EthernetFactory factory;
+
+  BOOST_CHECK_THROW(factory.createFace(FaceUri("ether://[08:00:27:01:01:01]"),
+                                       ndn::nfd::FACE_PERSISTENCY_PERMANENT,
+                                       bind([]{}),
+                                       bind([]{})),
+                    ProtocolFactory::Error);
+
+  BOOST_CHECK_THROW(factory.createFace(FaceUri("ether://[08:00:27:01:01:01]"),
+                                       ndn::nfd::FACE_PERSISTENCY_ON_DEMAND,
+                                       bind([]{}),
+                                       bind([]{})),
+                    ProtocolFactory::Error);
+
+  BOOST_CHECK_THROW(factory.createFace(FaceUri("ether://[08:00:27:01:01:01]"),
+                                       ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
+                                       bind([]{}),
+                                       bind([]{})),
+                    ProtocolFactory::Error);
+}
+
 BOOST_AUTO_TEST_CASE(SendPacket)
 {
   if (m_interfaces.empty()) {
diff --git a/tests/daemon/face/tcp.t.cpp b/tests/daemon/face/tcp.t.cpp
index 2f85e37..bec87e1 100644
--- a/tests/daemon/face/tcp.t.cpp
+++ b/tests/daemon/face/tcp.t.cpp
@@ -79,11 +79,6 @@
 {
 public:
   void
-  ignore()
-  {
-  }
-
-  void
   checkError(const std::string& errorActual, const std::string& errorExpected)
   {
     BOOST_CHECK_EQUAL(errorActual, errorExpected);
@@ -98,20 +93,42 @@
 
 BOOST_FIXTURE_TEST_CASE(FaceCreate, FaceCreateFixture)
 {
-  TcpFactory factory = TcpFactory();
+  TcpFactory factory;
 
   factory.createFace(FaceUri("tcp4://127.0.0.1:6363"),
-                     bind(&FaceCreateFixture::ignore, this),
+                     ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
+                     bind([]{}),
                      bind(&FaceCreateFixture::checkError, this, _1,
                           "No channels available to connect to 127.0.0.1:6363"));
 
   factory.createChannel("127.0.0.1", "20071");
-
+  
   factory.createFace(FaceUri("tcp4://127.0.0.1:20070"),
-                     bind(&FaceCreateFixture::ignore, this),
+                     ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
+                     bind([]{}),
                      bind(&FaceCreateFixture::failIfError, this, _1));
 }
 
+BOOST_FIXTURE_TEST_CASE(UnsupportedFaceCreate, FaceCreateFixture)
+{
+  TcpFactory factory;
+
+  factory.createChannel("127.0.0.1", "20070");
+  factory.createChannel("127.0.0.1", "20071");
+
+  BOOST_CHECK_THROW(factory.createFace(FaceUri("tcp4://127.0.0.1:20070"),
+                                       ndn::nfd::FACE_PERSISTENCY_PERMANENT,
+                                       bind([]{}),
+                                       bind([]{})),
+                    ProtocolFactory::Error);
+
+  BOOST_CHECK_THROW(factory.createFace(FaceUri("tcp4://127.0.0.1:20071"),
+                                       ndn::nfd::FACE_PERSISTENCY_ON_DEMAND,
+                                       bind([]{}),
+                                       bind([]{})),
+                    ProtocolFactory::Error);
+}
+
 class EndToEndFixture : protected BaseFixture
 {
 public:
@@ -266,6 +283,7 @@
   factory2.createChannel("127.0.0.2", "20071");
 
   factory2.createFace(FaceUri("tcp4://127.0.0.1:20070"),
+                      ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
                       bind(&EndToEndFixture::channel2_onFaceCreated, this, _1),
                       bind(&EndToEndFixture::channel2_onConnectFailed, this, _1));
 
@@ -353,6 +371,7 @@
   factory2.createChannel("::2", "20070");
 
   factory2.createFace(FaceUri("tcp6://[::1]:20070"),
+                      ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
                       bind(&EndToEndFixture::channel2_onFaceCreated, this, _1),
                       bind(&EndToEndFixture::channel2_onConnectFailed, this, _1));
 
@@ -630,6 +649,7 @@
   shared_ptr<TcpChannel> channel = factory.createChannel("0.0.0.0", "20070");
 
   factory.createFace(FaceUri("tcp4://192.0.2.1:20070"),
+                     ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
                      bind(&FaceCreateTimeoutFixture::onFaceCreated, this, _1),
                      bind(&FaceCreateTimeoutFixture::onConnectFailed, this, _1));
 
@@ -659,6 +679,7 @@
   factory2.createChannel("127.0.0.2", "20071");
 
   factory2.createFace(FaceUri("tcp4://127.0.0.1:20070"),
+                      ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
                       bind(&EndToEndFixture::channel2_onFaceCreated, this, _1),
                       bind(&EndToEndFixture::channel2_onConnectFailed, this, _1));
 
diff --git a/tests/daemon/face/udp.t.cpp b/tests/daemon/face/udp.t.cpp
index 4eaafb2..ff0c710 100644
--- a/tests/daemon/face/udp.t.cpp
+++ b/tests/daemon/face/udp.t.cpp
@@ -200,11 +200,6 @@
 {
 public:
   void
-  ignore()
-  {
-  }
-
-  void
   checkError(const std::string& errorActual, const std::string& errorExpected)
   {
     BOOST_CHECK_EQUAL(errorActual, errorExpected);
@@ -222,17 +217,39 @@
   UdpFactory factory = UdpFactory();
 
   factory.createFace(FaceUri("udp4://127.0.0.1:6363"),
-                     bind(&FaceCreateFixture::ignore, this),
+                     ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
+                     bind([]{}),
                      bind(&FaceCreateFixture::checkError, this, _1,
                           "No channels available to connect to 127.0.0.1:6363"));
 
   factory.createChannel("127.0.0.1", "20071");
 
   factory.createFace(FaceUri("udp4://127.0.0.1:20070"),
-                     bind(&FaceCreateFixture::ignore, this),
+                     ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
+                     bind([]{}),
                      bind(&FaceCreateFixture::failIfError, this, _1));
 }
 
+BOOST_FIXTURE_TEST_CASE(UnsupportedFaceCreate, FaceCreateFixture)
+{
+  UdpFactory factory;
+
+  factory.createChannel("127.0.0.1", "20070");
+  factory.createChannel("127.0.0.1", "20071");
+
+  BOOST_CHECK_THROW(factory.createFace(FaceUri("udp4://127.0.0.1:20070"),
+                                       ndn::nfd::FACE_PERSISTENCY_PERMANENT,
+                                       bind([]{}),
+                                       bind([]{})),
+                    ProtocolFactory::Error);
+
+  BOOST_CHECK_THROW(factory.createFace(FaceUri("udp4://127.0.0.1:20071"),
+                                       ndn::nfd::FACE_PERSISTENCY_ON_DEMAND,
+                                       bind([]{}),
+                                       bind([]{})),
+                    ProtocolFactory::Error);
+}
+
 class EndToEndIpv4
 {
 public:
@@ -351,6 +368,7 @@
   shared_ptr<Face> face1;
   unique_ptr<FaceHistory> history1;
   factory.createFace(A::getFaceUri2(),
+                     ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
                      [&] (shared_ptr<Face> newFace) {
                        face1 = newFace;
                        history1.reset(new FaceHistory(*face1, limitedIo));
@@ -516,6 +534,7 @@
   shared_ptr<Face> face1;
   unique_ptr<FaceHistory> history1;
   factory.createFace(A::getFaceUri2(),
+                     ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
                      [&] (shared_ptr<Face> newFace) {
                        face1 = newFace;
                        history1.reset(new FaceHistory(*face1, limitedIo));
diff --git a/tests/daemon/face/unix-stream.t.cpp b/tests/daemon/face/unix-stream.t.cpp
index 44df52d..c5f5221 100644
--- a/tests/daemon/face/unix-stream.t.cpp
+++ b/tests/daemon/face/unix-stream.t.cpp
@@ -74,6 +74,29 @@
   BOOST_CHECK_EQUAL(expectedChannels.size(), 0);
 }
 
+BOOST_AUTO_TEST_CASE(UnsupportedFaceCreate)
+{
+  UnixStreamFactory factory;
+
+  BOOST_CHECK_THROW(factory.createFace(FaceUri("unix:///var/run/nfd.sock"),
+                                       ndn::nfd::FACE_PERSISTENCY_PERMANENT,
+                                       bind([]{}),
+                                       bind([]{})),
+                    ProtocolFactory::Error);
+
+  BOOST_CHECK_THROW(factory.createFace(FaceUri("unix:///var/run/nfd.sock"),
+                                       ndn::nfd::FACE_PERSISTENCY_ON_DEMAND,
+                                       bind([]{}),
+                                       bind([]{})),
+                    ProtocolFactory::Error);
+
+  BOOST_CHECK_THROW(factory.createFace(FaceUri("unix:///var/run/nfd.sock"),
+                                       ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
+                                       bind([]{}),
+                                       bind([]{})),
+                    ProtocolFactory::Error);
+}
+
 class EndToEndFixture : protected BaseFixture
 {
 public:
diff --git a/tests/daemon/face/websocket.t.cpp b/tests/daemon/face/websocket.t.cpp
index 7170e6c..d3da744 100644
--- a/tests/daemon/face/websocket.t.cpp
+++ b/tests/daemon/face/websocket.t.cpp
@@ -65,6 +65,29 @@
   BOOST_CHECK_EQUAL(expectedChannels.size(), 0);
 }
 
+BOOST_AUTO_TEST_CASE(UnsupportedFaceCreate)
+{
+  WebSocketFactory factory("19596");
+
+  BOOST_CHECK_THROW(factory.createFace(FaceUri("ws://127.0.0.1:20070"),
+                                       ndn::nfd::FACE_PERSISTENCY_PERMANENT,
+                                       bind([]{}),
+                                       bind([]{})),
+                    ProtocolFactory::Error);
+
+  BOOST_CHECK_THROW(factory.createFace(FaceUri("ws://127.0.0.1:20070"),
+                                       ndn::nfd::FACE_PERSISTENCY_ON_DEMAND,
+                                       bind([]{}),
+                                       bind([]{})),
+                    ProtocolFactory::Error);
+
+  BOOST_CHECK_THROW(factory.createFace(FaceUri("ws://127.0.0.1:20070"),
+                                       ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
+                                       bind([]{}),
+                                       bind([]{})),
+                    ProtocolFactory::Error);
+}
+
 class EndToEndFixture : protected BaseFixture
 {
 public:
diff --git a/tests/daemon/mgmt/channel-status-common.hpp b/tests/daemon/mgmt/channel-status-common.hpp
index 4954cc3..e04c0be 100644
--- a/tests/daemon/mgmt/channel-status-common.hpp
+++ b/tests/daemon/mgmt/channel-status-common.hpp
@@ -64,6 +64,7 @@
 
   virtual void
   createFace(const FaceUri& uri,
+             ndn::nfd::FacePersistency persistency,
              const FaceCreatedCallback& onCreated,
              const FaceConnectFailedCallback& onConnectFailed)
   {