mgmt+face: move protocol-specific face creation checks into protocol factories

Also brought implementation of faces/create in line with design

refs #3731

Change-Id: I4f48079136b42c7fdbd4fdfba37116d2565f9dc1
diff --git a/tests/daemon/face/ethernet-factory.t.cpp b/tests/daemon/face/ethernet-factory.t.cpp
index 6148b3b..b9e9cda 100644
--- a/tests/daemon/face/ethernet-factory.t.cpp
+++ b/tests/daemon/face/ethernet-factory.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2015,  Regents of the University of California,
+ * Copyright (c) 2014-2016,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -25,6 +25,7 @@
 
 #include "face/ethernet-factory.hpp"
 
+#include "factory-test-common.hpp"
 #include "network-interface-fixture.hpp"
 
 namespace nfd {
@@ -65,23 +66,20 @@
 {
   EthernetFactory factory;
 
-  BOOST_CHECK_THROW(factory.createFace(FaceUri("ether://[08:00:27:01:01:01]"),
-                                       ndn::nfd::FACE_PERSISTENCY_PERMANENT,
-                                       bind([]{}),
-                                       bind([]{})),
-                    ProtocolFactory::Error);
+  createFace(factory,
+             FaceUri("ether://[08:00:27:01:01:01]"),
+             ndn::nfd::FACE_PERSISTENCY_PERMANENT,
+             {CreateFaceExpectedResult::FAILURE, 406, "Unsupported protocol"});
 
-  BOOST_CHECK_THROW(factory.createFace(FaceUri("ether://[08:00:27:01:01:01]"),
-                                       ndn::nfd::FACE_PERSISTENCY_ON_DEMAND,
-                                       bind([]{}),
-                                       bind([]{})),
-                    ProtocolFactory::Error);
+  createFace(factory,
+             FaceUri("ether://[08:00:27:01:01:01]"),
+             ndn::nfd::FACE_PERSISTENCY_ON_DEMAND,
+             {CreateFaceExpectedResult::FAILURE, 406, "Unsupported protocol"});
 
-  BOOST_CHECK_THROW(factory.createFace(FaceUri("ether://[08:00:27:01:01:01]"),
-                                       ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
-                                       bind([]{}),
-                                       bind([]{})),
-                    ProtocolFactory::Error);
+  createFace(factory,
+             FaceUri("ether://[08:00:27:01:01:01]"),
+             ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
+             {CreateFaceExpectedResult::FAILURE, 406, "Unsupported protocol"});
 }
 
 BOOST_AUTO_TEST_SUITE_END() // TestEthernetFactory
diff --git a/tests/daemon/face/factory-test-common.hpp b/tests/daemon/face/factory-test-common.hpp
new file mode 100644
index 0000000..8676be5
--- /dev/null
+++ b/tests/daemon/face/factory-test-common.hpp
@@ -0,0 +1,68 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2016,  Regents of the University of California,
+ *                           Arizona Board of Regents,
+ *                           Colorado State University,
+ *                           University Pierre & Marie Curie, Sorbonne University,
+ *                           Washington University in St. Louis,
+ *                           Beijing Institute of Technology,
+ *                           The University of Memphis.
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NFD_TESTS_DAEMON_FACE_FACTORY_TEST_COMMON_HPP
+#define NFD_TESTS_DAEMON_FACE_FACTORY_TEST_COMMON_HPP
+
+#include "face/protocol-factory.hpp"
+
+#include "tests/test-common.hpp"
+
+namespace nfd {
+namespace tests {
+
+struct CreateFaceExpectedResult
+{
+  enum { FAILURE, SUCCESS } result;
+  uint32_t status;
+  std::string reason;
+};
+
+inline void
+createFace(ProtocolFactory& factory,
+           const FaceUri& uri,
+           ndn::nfd::FacePersistency persistency,
+           const CreateFaceExpectedResult& expected)
+{
+  factory.createFace(uri, persistency,
+                     [expected] (const shared_ptr<Face>& newFace) {
+                       BOOST_CHECK_EQUAL(CreateFaceExpectedResult::SUCCESS, expected.result);
+                     },
+                     [expected] (uint32_t actualStatus, const std::string& actualReason) {
+                       BOOST_CHECK_EQUAL(CreateFaceExpectedResult::FAILURE, expected.result);
+                       BOOST_CHECK_EQUAL(actualStatus, expected.status);
+                       BOOST_CHECK_EQUAL(actualReason, expected.reason);
+                     });
+}
+
+inline void
+failIfError(uint32_t status, const std::string& reason) {
+  BOOST_FAIL("No error expected, but got: [" << status << ": " << reason << "]");
+}
+
+} // namespace tests
+} // namespace nfd
+
+#endif // NFD_TESTS_DAEMON_FACE_FACTORY_TEST_COMMON_HPP
diff --git a/tests/daemon/face/tcp-channel.t.cpp b/tests/daemon/face/tcp-channel.t.cpp
index f829aa2..d04ea26 100644
--- a/tests/daemon/face/tcp-channel.t.cpp
+++ b/tests/daemon/face/tcp-channel.t.cpp
@@ -27,7 +27,7 @@
 
 #include "test-ip.hpp"
 #include "tests/limited-io.hpp"
-#include "tests/test-common.hpp"
+#include "factory-test-common.hpp"
 
 #include <boost/mpl/vector.hpp>
 
@@ -71,10 +71,7 @@
         listenerFaces.push_back(newFace);
         limitedIo.afterOp();
       },
-      [this] (const std::string& reason) {
-        BOOST_FAIL(reason);
-        limitedIo.afterOp();
-      });
+      &failIfError);
   }
 
   void
@@ -87,10 +84,7 @@
         clientFaces.push_back(newFace);
         limitedIo.afterOp();
       },
-      [this] (const std::string& reason) {
-        BOOST_FAIL(reason);
-        limitedIo.afterOp();
-      });
+      &failIfError);
   }
 
 protected:
@@ -188,7 +182,7 @@
       BOOST_FAIL("Connect succeeded when it should have failed");
       this->limitedIo.afterOp();
     },
-    [this] (const std::string& reason) {
+    [this] (uint32_t status, const std::string& reason) {
       BOOST_CHECK_EQUAL(reason.empty(), false);
       this->limitedIo.afterOp();
     },
diff --git a/tests/daemon/face/tcp-factory.t.cpp b/tests/daemon/face/tcp-factory.t.cpp
index ee796ab..7418b26 100644
--- a/tests/daemon/face/tcp-factory.t.cpp
+++ b/tests/daemon/face/tcp-factory.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2015,  Regents of the University of California,
+ * Copyright (c) 2014-2016,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -26,7 +26,7 @@
 #include "face/tcp-factory.hpp"
 
 #include "core/network-interface.hpp"
-#include "tests/test-common.hpp"
+#include "factory-test-common.hpp"
 #include "tests/limited-io.hpp"
 
 namespace nfd {
@@ -72,38 +72,21 @@
   BOOST_CHECK_EQUAL(expectedChannels.size(), 0);
 }
 
-class FaceCreateFixture : public BaseFixture
-{
-public:
-  void
-  checkError(const std::string& errorActual, const std::string& errorExpected)
-  {
-    BOOST_CHECK_EQUAL(errorActual, errorExpected);
-  }
-
-  void
-  failIfError(const std::string& errorActual)
-  {
-    BOOST_FAIL("No error expected, but got: [" << errorActual << "]");
-  }
-};
-
-BOOST_FIXTURE_TEST_CASE(FaceCreate, FaceCreateFixture)
+BOOST_AUTO_TEST_CASE(FaceCreate)
 {
   TcpFactory factory;
 
-  factory.createFace(FaceUri("tcp4://127.0.0.1:6363"),
-                     ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
-                     bind([]{}),
-                     bind(&FaceCreateFixture::checkError, this, _1,
-                          "No channels available to connect to 127.0.0.1:6363"));
+  createFace(factory,
+             FaceUri("tcp4://127.0.0.1:6363"),
+             ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
+             {CreateFaceExpectedResult::FAILURE, 504, "No channels available to connect"});
 
   factory.createChannel("127.0.0.1", "20071");
 
-  factory.createFace(FaceUri("tcp4://127.0.0.1:20070"),
-                     ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
-                     bind([]{}),
-                     bind(&FaceCreateFixture::failIfError, this, _1));
+  createFace(factory,
+             FaceUri("tcp4://127.0.0.1:20070"),
+             ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
+             {CreateFaceExpectedResult::SUCCESS, 0, ""});
 }
 
 BOOST_AUTO_TEST_CASE(UnsupportedFaceCreate)
@@ -113,17 +96,17 @@
   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);
+  createFace(factory,
+             FaceUri("tcp4://127.0.0.1:20070"),
+             ndn::nfd::FACE_PERSISTENCY_PERMANENT,
+             {CreateFaceExpectedResult::FAILURE, 406,
+               "Outgoing TCP faces only support persistent persistency"});
 
-  BOOST_CHECK_THROW(factory.createFace(FaceUri("tcp4://127.0.0.1:20071"),
-                                       ndn::nfd::FACE_PERSISTENCY_ON_DEMAND,
-                                       bind([]{}),
-                                       bind([]{})),
-                    ProtocolFactory::Error);
+  createFace(factory,
+             FaceUri("tcp4://127.0.0.1:20071"),
+             ndn::nfd::FACE_PERSISTENCY_ON_DEMAND,
+             {CreateFaceExpectedResult::FAILURE, 406,
+               "Outgoing TCP faces only support persistent persistency"});
 }
 
 class FaceCreateTimeoutFixture : public BaseFixture
@@ -161,7 +144,7 @@
   factory.createFace(FaceUri("tcp4://192.0.2.1:20070"),
                      ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
                      bind(&FaceCreateTimeoutFixture::onFaceCreated, this, _1),
-                     bind(&FaceCreateTimeoutFixture::onConnectFailed, this, _1));
+                     bind(&FaceCreateTimeoutFixture::onConnectFailed, this, _2));
 
   BOOST_CHECK_MESSAGE(limitedIo.run(1, time::seconds(10)) == LimitedIo::EXCEED_OPS,
                       "TcpChannel error: cannot connect or cannot accept connection");
diff --git a/tests/daemon/face/udp-channel.t.cpp b/tests/daemon/face/udp-channel.t.cpp
index d945012..1438b88 100644
--- a/tests/daemon/face/udp-channel.t.cpp
+++ b/tests/daemon/face/udp-channel.t.cpp
@@ -28,7 +28,7 @@
 
 #include "test-ip.hpp"
 #include "tests/limited-io.hpp"
-#include "tests/test-common.hpp"
+#include "factory-test-common.hpp"
 
 #include <boost/mpl/vector.hpp>
 
@@ -72,9 +72,7 @@
         listenerFaces.push_back(newFace);
         limitedIo.afterOp();
       },
-      [] (const std::string& reason) {
-        BOOST_FAIL(reason);
-      });
+      &failIfError);
   }
 
   void
@@ -90,9 +88,7 @@
           newFace->getTransport()->send(std::move(pkt));
           limitedIo.afterOp();
         },
-        [] (const std::string& reason) {
-          BOOST_FAIL(reason);
-        });
+        &failIfError);
     });
   }
 
diff --git a/tests/daemon/face/udp-factory.t.cpp b/tests/daemon/face/udp-factory.t.cpp
index be7a73b..eb27f3a 100644
--- a/tests/daemon/face/udp-factory.t.cpp
+++ b/tests/daemon/face/udp-factory.t.cpp
@@ -25,8 +25,8 @@
 
 #include "face/udp-factory.hpp"
 
+#include "factory-test-common.hpp"
 #include "core/network-interface.hpp"
-#include "tests/test-common.hpp"
 #include "tests/limited-io.hpp"
 
 namespace nfd {
@@ -144,61 +144,44 @@
                         });
 }
 
-class FaceCreateFixture : protected BaseFixture
-{
-public:
-  void
-  checkError(const std::string& errorActual, const std::string& errorExpected)
-  {
-    BOOST_CHECK_EQUAL(errorActual, errorExpected);
-  }
-
-  void
-  failIfError(const std::string& errorActual)
-  {
-    BOOST_FAIL("No error expected, but got: [" << errorActual << "]");
-  }
-};
-
-BOOST_FIXTURE_TEST_CASE(FaceCreate, FaceCreateFixture)
+BOOST_AUTO_TEST_CASE(FaceCreate)
 {
   UdpFactory factory = UdpFactory();
 
-  factory.createFace(FaceUri("udp4://127.0.0.1:6363"),
-                     ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
-                     bind([]{}),
-                     bind(&FaceCreateFixture::checkError, this, _1,
-                          "No channels available to connect to 127.0.0.1:6363"));
+  createFace(factory,
+             FaceUri("udp4://127.0.0.1:6363"),
+             ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
+             {CreateFaceExpectedResult::FAILURE, 504, "No channels available to connect"});
 
   factory.createChannel("127.0.0.1", "20071");
 
-  factory.createFace(FaceUri("udp4://127.0.0.1:20070"),
-                     ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
-                     bind([]{}),
-                     bind(&FaceCreateFixture::failIfError, this, _1));
+  createFace(factory,
+             FaceUri("udp4://127.0.0.1:20070"),
+             ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
+             {CreateFaceExpectedResult::SUCCESS, 0, ""});
   //test the upgrade
-  factory.createFace(FaceUri("udp4://127.0.0.1:20070"),
-                     ndn::nfd::FACE_PERSISTENCY_PERMANENT,
-                     bind([]{}),
-                     bind(&FaceCreateFixture::failIfError, this, _1));
+  createFace(factory,
+             FaceUri("udp4://127.0.0.1:20070"),
+             ndn::nfd::FACE_PERSISTENCY_PERMANENT,
+             {CreateFaceExpectedResult::SUCCESS, 0, ""});
 
-  factory.createFace(FaceUri("udp4://127.0.0.1:20072"),
-                     ndn::nfd::FACE_PERSISTENCY_PERMANENT,
-                     bind([]{}),
-                     bind(&FaceCreateFixture::failIfError, this, _1));
+  createFace(factory,
+             FaceUri("udp4://127.0.0.1:20072"),
+             ndn::nfd::FACE_PERSISTENCY_PERMANENT,
+             {CreateFaceExpectedResult::SUCCESS, 0, ""});
 }
 
 BOOST_AUTO_TEST_CASE(UnsupportedFaceCreate)
 {
-  UdpFactory factory;
+  UdpFactory factory = UdpFactory();
 
   factory.createChannel("127.0.0.1", "20070");
 
-  BOOST_CHECK_THROW(factory.createFace(FaceUri("udp4://127.0.0.1:20070"),
-                                       ndn::nfd::FACE_PERSISTENCY_ON_DEMAND,
-                                       bind([]{}),
-                                       bind([]{})),
-                    ProtocolFactory::Error);
+  createFace(factory,
+             FaceUri("udp4://127.0.0.1:20070"),
+             ndn::nfd::FACE_PERSISTENCY_ON_DEMAND,
+             {CreateFaceExpectedResult::FAILURE, 406,
+               "Outgoing unicast UDP faces do not support on-demand persistency"});
 }
 
 class FakeNetworkInterfaceFixture : public BaseFixture
diff --git a/tests/daemon/face/unix-stream-channel.t.cpp b/tests/daemon/face/unix-stream-channel.t.cpp
index 6d523ff..37eae6d 100644
--- a/tests/daemon/face/unix-stream-channel.t.cpp
+++ b/tests/daemon/face/unix-stream-channel.t.cpp
@@ -26,7 +26,7 @@
 #include "face/unix-stream-channel.hpp"
 
 #include "tests/limited-io.hpp"
-#include "tests/test-common.hpp"
+#include "factory-test-common.hpp"
 
 #include <boost/filesystem.hpp>
 #include <fstream>
@@ -65,10 +65,7 @@
         listenerFaces.push_back(newFace);
         limitedIo.afterOp();
       },
-      [this] (const std::string& reason) {
-        BOOST_FAIL(reason);
-        limitedIo.afterOp();
-      });
+      &failIfError);
   }
 
   void
diff --git a/tests/daemon/face/unix-stream-factory.t.cpp b/tests/daemon/face/unix-stream-factory.t.cpp
index 2be2536..1c33122 100644
--- a/tests/daemon/face/unix-stream-factory.t.cpp
+++ b/tests/daemon/face/unix-stream-factory.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2015,  Regents of the University of California,
+ * Copyright (c) 2014-2016,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -25,7 +25,7 @@
 
 #include "face/unix-stream-factory.hpp"
 
-#include "tests/test-common.hpp"
+#include "factory-test-common.hpp"
 #include "tests/limited-io.hpp"
 
 namespace nfd {
@@ -77,23 +77,20 @@
 {
   UnixStreamFactory factory;
 
-  BOOST_CHECK_THROW(factory.createFace(FaceUri("unix:///var/run/nfd.sock"),
-                                       ndn::nfd::FACE_PERSISTENCY_PERMANENT,
-                                       bind([]{}),
-                                       bind([]{})),
-                    ProtocolFactory::Error);
+  createFace(factory,
+             FaceUri("unix:///var/run/nfd.sock"),
+             ndn::nfd::FACE_PERSISTENCY_PERMANENT,
+             {CreateFaceExpectedResult::FAILURE, 406, "Unsupported protocol"});
 
-  BOOST_CHECK_THROW(factory.createFace(FaceUri("unix:///var/run/nfd.sock"),
-                                       ndn::nfd::FACE_PERSISTENCY_ON_DEMAND,
-                                       bind([]{}),
-                                       bind([]{})),
-                    ProtocolFactory::Error);
+  createFace(factory,
+             FaceUri("unix:///var/run/nfd.sock"),
+             ndn::nfd::FACE_PERSISTENCY_ON_DEMAND,
+             {CreateFaceExpectedResult::FAILURE, 406, "Unsupported protocol"});
 
-  BOOST_CHECK_THROW(factory.createFace(FaceUri("unix:///var/run/nfd.sock"),
-                                       ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
-                                       bind([]{}),
-                                       bind([]{})),
-                    ProtocolFactory::Error);
+  createFace(factory,
+             FaceUri("unix:///var/run/nfd.sock"),
+             ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
+             {CreateFaceExpectedResult::FAILURE, 406, "Unsupported protocol"});
 }
 
 BOOST_AUTO_TEST_SUITE_END() // TestUnixStreamFactory
diff --git a/tests/daemon/face/websocket-factory.t.cpp b/tests/daemon/face/websocket-factory.t.cpp
index 9e469e8..cb00922 100644
--- a/tests/daemon/face/websocket-factory.t.cpp
+++ b/tests/daemon/face/websocket-factory.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2015,  Regents of the University of California,
+ * Copyright (c) 2014-2016,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -25,7 +25,7 @@
 
 #include "face/websocket-factory.hpp"
 
-#include "tests/test-common.hpp"
+#include "factory-test-common.hpp"
 #include "tests/limited-io.hpp"
 
 namespace nfd {
@@ -59,23 +59,20 @@
 {
   WebSocketFactory factory;
 
-  BOOST_CHECK_THROW(factory.createFace(FaceUri("ws://127.0.0.1:20070"),
-                                       ndn::nfd::FACE_PERSISTENCY_PERMANENT,
-                                       bind([]{}),
-                                       bind([]{})),
-                    ProtocolFactory::Error);
+  createFace(factory,
+             FaceUri("ws://127.0.0.1:20070"),
+             ndn::nfd::FACE_PERSISTENCY_PERMANENT,
+             {CreateFaceExpectedResult::FAILURE, 406, "Unsupported protocol"});
 
-  BOOST_CHECK_THROW(factory.createFace(FaceUri("ws://127.0.0.1:20070"),
-                                       ndn::nfd::FACE_PERSISTENCY_ON_DEMAND,
-                                       bind([]{}),
-                                       bind([]{})),
-                    ProtocolFactory::Error);
+  createFace(factory,
+             FaceUri("ws://127.0.0.1:20070"),
+             ndn::nfd::FACE_PERSISTENCY_ON_DEMAND,
+             {CreateFaceExpectedResult::FAILURE, 406, "Unsupported protocol"});
 
-  BOOST_CHECK_THROW(factory.createFace(FaceUri("ws://127.0.0.1:20070"),
-                                       ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
-                                       bind([]{}),
-                                       bind([]{})),
-                    ProtocolFactory::Error);
+  createFace(factory,
+             FaceUri("ws://127.0.0.1:20070"),
+             ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
+             {CreateFaceExpectedResult::FAILURE, 406, "Unsupported protocol"});
 }
 
 BOOST_AUTO_TEST_SUITE_END() // TestWebSocketFactory