face+util: Add protected Face::getTransport method and simplify DummyClientFace implementation

Change-Id: I42e7e5705f27b6823ed18107b374c9841d2a7500
Refs: #3146
diff --git a/src/face.cpp b/src/face.cpp
index 0212fd7..a4f3615 100644
--- a/src/face.cpp
+++ b/src/face.cpp
@@ -133,6 +133,12 @@
 
 Face::~Face() = default;
 
+shared_ptr<Transport>
+Face::getTransport()
+{
+  return m_transport;
+}
+
 const PendingInterestId*
 Face::expressInterest(const Interest& interest,
                       const DataCallback& afterSatisfied,
diff --git a/src/face.hpp b/src/face.hpp
index 9a01d17..9e6faa4 100644
--- a/src/face.hpp
+++ b/src/face.hpp
@@ -672,6 +672,13 @@
     return m_ioService;
   }
 
+NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PROTECTED:
+  /**
+   * @brief Get the underlying transport of the face
+   */
+  shared_ptr<Transport>
+  getTransport();
+
 private:
 
   /**
diff --git a/src/util/dummy-client-face.cpp b/src/util/dummy-client-face.cpp
index aadb6bc..1db5b8d 100644
--- a/src/util/dummy-client-face.cpp
+++ b/src/util/dummy-client-face.cpp
@@ -82,17 +82,21 @@
   Signal<Transport, Block> onSendBlock;
 };
 
-DummyClientFace::DummyClientFace(const Options& options, shared_ptr<Transport> transport)
-  : Face(transport)
-  , m_transport(transport)
+DummyClientFace::DummyClientFace(const Options& options/* = DummyClientFace::DEFAULT_OPTIONS*/)
+  : Face(make_shared<DummyClientFace::Transport>())
+#ifdef NDN_UTIL_DUMMY_FACE_KEEP_DEPRECATED
+  , sentDatas(sentData)
+#endif // NDN_UTIL_DUMMY_FACE_KEEP_DEPRECATED
 {
   this->construct(options);
 }
 
-DummyClientFace::DummyClientFace(const Options& options, shared_ptr<Transport> transport,
-                                 boost::asio::io_service& ioService)
-  : Face(transport, ioService)
-  , m_transport(transport)
+DummyClientFace::DummyClientFace(boost::asio::io_service& ioService,
+                                 const Options& options/* = DummyClientFace::DEFAULT_OPTIONS*/)
+  : Face(make_shared<DummyClientFace::Transport>(), ioService)
+#ifdef NDN_UTIL_DUMMY_FACE_KEEP_DEPRECATED
+  , sentDatas(sentData)
+#endif // NDN_UTIL_DUMMY_FACE_KEEP_DEPRECATED
 {
   this->construct(options);
 }
@@ -100,7 +104,7 @@
 void
 DummyClientFace::construct(const Options& options)
 {
-  m_transport->onSendBlock.connect([this] (const Block& blockFromDaemon) {
+  static_pointer_cast<Transport>(getTransport())->onSendBlock.connect([this] (const Block& blockFromDaemon) {
     Block packet(blockFromDaemon);
     packet.encode();
     lp::Packet lpPacket(packet);
@@ -151,7 +155,7 @@
     this->sentInterests.push_back(interest);
   });
   onSendData.connect([this] (const Data& data) {
-    this->sentDatas.push_back(data);
+    this->sentData.push_back(data);
   });
   onSendNack.connect([this] (const lp::Nack& nack) {
     this->sentNacks.push_back(nack);
@@ -204,7 +208,7 @@
   if (nextHopFaceIdTag != nullptr) {
     lpPacket.add<lp::NextHopFaceIdField>(*nextHopFaceIdTag);
   }
-  m_transport->receive(lpPacket.wireEncode());
+  static_pointer_cast<Transport>(getTransport())->receive(lpPacket.wireEncode());
 }
 
 template void
@@ -227,15 +231,16 @@
     lpPacket.add<lp::IncomingFaceIdField>(*incomingFaceIdTag);
   }
 
-  m_transport->receive(lpPacket.wireEncode());
+  static_pointer_cast<Transport>(getTransport())->receive(lpPacket.wireEncode());
 }
 
+#ifdef NDN_UTIL_DUMMY_FACE_KEEP_DEPRECATED
+
 shared_ptr<DummyClientFace>
 makeDummyClientFace(const DummyClientFace::Options& options)
 {
   // cannot use make_shared<DummyClientFace> because DummyClientFace constructor is private
-  return shared_ptr<DummyClientFace>(
-         new DummyClientFace(options, make_shared<DummyClientFace::Transport>()));
+  return shared_ptr<DummyClientFace>(new DummyClientFace(options));
 }
 
 shared_ptr<DummyClientFace>
@@ -243,10 +248,10 @@
                     const DummyClientFace::Options& options)
 {
   // cannot use make_shared<DummyClientFace> because DummyClientFace constructor is private
-  return shared_ptr<DummyClientFace>(
-         new DummyClientFace(options, make_shared<DummyClientFace::Transport>(),
-                             ref(ioService)));
+  return shared_ptr<DummyClientFace>(new DummyClientFace(ref(ioService), options));
 }
 
+#endif // NDN_UTIL_DUMMY_FACE_KEEP_DEPRECATED
+
 } // namespace util
 } // namespace ndn
diff --git a/src/util/dummy-client-face.hpp b/src/util/dummy-client-face.hpp
index 8d47a75..b5ec7d7 100644
--- a/src/util/dummy-client-face.hpp
+++ b/src/util/dummy-client-face.hpp
@@ -26,6 +26,8 @@
 #include "signal.hpp"
 #include "../lp/packet.hpp"
 
+#define NDN_UTIL_DUMMY_FACE_KEEP_DEPRECATED
+
 namespace ndn {
 namespace util {
 
@@ -48,6 +50,16 @@
     bool enableRegistrationReply;
   };
 
+  /**
+   * @brief Create a dummy face with internal IO service
+   */
+  DummyClientFace(const Options& options = DummyClientFace::DEFAULT_OPTIONS);
+
+  /**
+   * @brief Create a dummy face with the provided IO service
+   */
+  DummyClientFace(boost::asio::io_service& ioService, const Options& options = DummyClientFace::DEFAULT_OPTIONS);
+
   /** \brief cause the Face to receive a packet
    *  \tparam Packet either Interest or Data
    */
@@ -58,22 +70,9 @@
 private: // constructors
   class Transport;
 
-  // constructors are private; use makeDummyClientFace to create DummyClientFace
-
-  DummyClientFace(const Options& options, shared_ptr<Transport> transport);
-
-  DummyClientFace(const Options& options, shared_ptr<Transport> transport,
-                  boost::asio::io_service& ioService);
-
   void
   construct(const Options& options);
 
-  friend shared_ptr<DummyClientFace>
-  makeDummyClientFace(const DummyClientFace::Options& options);
-
-  friend shared_ptr<DummyClientFace>
-  makeDummyClientFace(boost::asio::io_service& ioService, const DummyClientFace::Options& options);
-
 private:
   void
   enablePacketLogging();
@@ -103,7 +102,11 @@
    *  User of this class is responsible for cleaning up the container, if necessary.
    *  After .put, .processEvents must be called before the Data would show up here.
    */
-  std::vector<Data> sentDatas;
+  std::vector<Data> sentData;
+
+#ifdef NDN_UTIL_DUMMY_FACE_KEEP_DEPRECATED
+  std::vector<Data>& sentDatas; ///< deprecated alias to sentData
+#endif // NDN_UTIL_DUMMY_FACE_KEEP_DEPRECATED
 
   /** \brief NACKs sent out of this DummyClientFace
    *
@@ -130,21 +133,28 @@
    *  After .put, .processEvents must be called before this signal would be emitted.
    */
   Signal<DummyClientFace, lp::Nack> onSendNack;
-
-private:
-  shared_ptr<Transport> m_transport;
 };
 
 template<>
 void
 DummyClientFace::receive(const lp::Nack& nack);
 
+#ifdef NDN_UTIL_DUMMY_FACE_KEEP_DEPRECATED
+/**
+ * @brief Create a dummy face with internal IO service
+ * @deprecated Use the DummyFace constructor directly
+ */
 shared_ptr<DummyClientFace>
 makeDummyClientFace(const DummyClientFace::Options& options = DummyClientFace::DEFAULT_OPTIONS);
 
+/**
+ * @brief Create a dummy face with the provided IO service
+ * @deprecated Use the DummyFace constructor directly
+ */
 shared_ptr<DummyClientFace>
 makeDummyClientFace(boost::asio::io_service& ioService,
                     const DummyClientFace::Options& options = DummyClientFace::DEFAULT_OPTIONS);
+#endif // NDN_UTIL_DUMMY_FACE_KEEP_DEPRECATED
 
 } // namespace util
 } // namespace ndn
diff --git a/tests/unit-tests/face.t.cpp b/tests/unit-tests/face.t.cpp
index ccd7df4..43164a6 100644
--- a/tests/unit-tests/face.t.cpp
+++ b/tests/unit-tests/face.t.cpp
@@ -23,6 +23,7 @@
 #include "util/scheduler.hpp"
 #include "security/key-chain.hpp"
 #include "util/dummy-client-face.hpp"
+#include "transport/tcp-transport.hpp"
 
 #include "boost-test.hpp"
 #include "unit-test-time-fixture.hpp"
@@ -595,6 +596,22 @@
   // should not segfault
 }
 
+BOOST_AUTO_TEST_CASE(FaceTransport)
+{
+  KeyChain keyChain;
+
+  BOOST_CHECK(Face().getTransport() != nullptr);
+
+  BOOST_CHECK(Face(shared_ptr<Transport>()).getTransport() == nullptr);
+  BOOST_CHECK(Face(shared_ptr<Transport>(), io).getTransport() == nullptr);
+  BOOST_CHECK(Face(shared_ptr<Transport>(), io, keyChain).getTransport() == nullptr);
+
+  auto transport = make_shared<TcpTransport>("localhost", "6363"); // no real io operations will be scheduled
+  BOOST_CHECK(Face(transport).getTransport() == transport);
+  BOOST_CHECK(Face(transport, io).getTransport() == transport);
+  BOOST_CHECK(Face(transport, io, keyChain).getTransport() == transport);
+}
+
 BOOST_AUTO_TEST_SUITE_END()
 
 } // tests