face: change Transport static properties initialization

Transport constructor now initializes static properties to invalid values.
Subclass constructor must explicitly set every static property.

refs #3259

Change-Id: I7ac3819694e0772c33a8a5d573e260f0eb944bff
diff --git a/daemon/face/internal-transport.cpp b/daemon/face/internal-transport.cpp
index d9dc238..070a4b5 100644
--- a/daemon/face/internal-transport.cpp
+++ b/daemon/face/internal-transport.cpp
@@ -40,6 +40,7 @@
   this->setScope(scope);
   this->setPersistency(ndn::nfd::FACE_PERSISTENCY_PERMANENT);
   this->setLinkType(linkType);
+  this->setMtu(MTU_UNLIMITED);
 
   NFD_LOG_FACE_INFO("Creating transport");
 }
diff --git a/daemon/face/transport.cpp b/daemon/face/transport.cpp
index d6008f7..0c4f4ee 100644
--- a/daemon/face/transport.cpp
+++ b/daemon/face/transport.cpp
@@ -60,15 +60,13 @@
 Transport::Transport()
   : m_face(nullptr)
   , m_service(nullptr)
-  , m_scope(ndn::nfd::FACE_SCOPE_NON_LOCAL)
-  , m_persistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT)
-  , m_linkType(ndn::nfd::LINK_TYPE_POINT_TO_POINT)
-  , m_mtu(MTU_UNLIMITED)
+  , m_scope(ndn::nfd::FACE_SCOPE_NONE)
+  , m_persistency(ndn::nfd::FACE_PERSISTENCY_NONE)
+  , m_linkType(ndn::nfd::LINK_TYPE_NONE)
+  , m_mtu(MTU_INVALID)
   , m_state(TransportState::UP)
   , m_counters(nullptr)
 {
-  // warning: Subclass constructor must explicitly initialize all static properties
-  // using setters, and should not rely on the defaults here.
 }
 
 Transport::~Transport()
diff --git a/daemon/face/transport.hpp b/daemon/face/transport.hpp
index b7f1c30..55efe3b 100644
--- a/daemon/face/transport.hpp
+++ b/daemon/face/transport.hpp
@@ -55,6 +55,10 @@
  */
 const ssize_t MTU_UNLIMITED = -1;
 
+/** \brief (for internal use) indicates MTU field is unset
+ */
+const ssize_t MTU_INVALID = -2;
+
 /** \brief the lower part of an LpFace
  *  \sa LpFace
  */
@@ -89,6 +93,14 @@
     EndpointId remoteEndpoint;
   };
 
+  /** \brief constructor
+   *
+   *  Transport constructor initializes static properties to invalid values.
+   *  Subclass constructor must explicitly set every static property.
+   *
+   *  This constructor initializes TransportState to UP;
+   *  subclass constructor can rely on this default value.
+   */
   Transport();
 
   virtual
diff --git a/tests/daemon/face/dummy-transport.hpp b/tests/daemon/face/dummy-transport.hpp
index df8fa54..c5c5268 100644
--- a/tests/daemon/face/dummy-transport.hpp
+++ b/tests/daemon/face/dummy-transport.hpp
@@ -51,6 +51,7 @@
     this->setScope(scope);
     this->setPersistency(persistency);
     this->setLinkType(linkType);
+    this->setMtu(MTU_UNLIMITED);
   }
 
   void
diff --git a/tests/daemon/face/internal-face.t.cpp b/tests/daemon/face/internal-face.t.cpp
index eab0b67..05e133f 100644
--- a/tests/daemon/face/internal-face.t.cpp
+++ b/tests/daemon/face/internal-face.t.cpp
@@ -25,6 +25,8 @@
 
 #include "face/internal-face.hpp"
 #include "face/lp-face-wrapper.hpp"
+#include "transport-properties.hpp"
+
 #include "tests/test-common.hpp"
 #include "tests/identity-management-fixture.hpp"
 
@@ -42,19 +44,21 @@
 public:
   InternalFaceFixture()
   {
-    std::tie(forwarderFace, clientFace) = makeInternalFace(m_keyChain);;
+    std::tie(forwarderFaceW, clientFace) = makeInternalFace(m_keyChain);;
+    forwarderFace = static_pointer_cast<LpFaceWrapper>(forwarderFaceW)->getLpFace();
+    // TODO#3172 eliminate wrapper
 
-    // TODO#3172 connect to afterReceive* signals
-    forwarderFace->onReceiveInterest.connect(
+    forwarderFace->afterReceiveInterest.connect(
       [this] (const Interest& interest) { receivedInterests.push_back(interest); } );
-    forwarderFace->onReceiveData.connect(
+    forwarderFace->afterReceiveData.connect(
       [this] (const Data& data) { receivedData.push_back(data); } );
-    forwarderFace->onReceiveNack.connect(
+    forwarderFace->afterReceiveNack.connect(
       [this] (const lp::Nack& nack) { receivedNacks.push_back(nack); } );
   }
 
 protected:
-  shared_ptr<nfd::Face> forwarderFace;
+  shared_ptr<nfd::Face> forwarderFaceW;
+  LpFace* forwarderFace;
   shared_ptr<ndn::Face> clientFace;
 
   std::vector<Interest> receivedInterests;
@@ -64,9 +68,22 @@
 
 BOOST_FIXTURE_TEST_SUITE(TestInternalFace, InternalFaceFixture)
 
+BOOST_AUTO_TEST_CASE(TransportStaticProperties)
+{
+  Transport* transport = forwarderFace->getTransport();
+  checkStaticPropertiesInitialized(*transport);
+
+  BOOST_CHECK_EQUAL(transport->getLocalUri(), FaceUri("internal://"));
+  BOOST_CHECK_EQUAL(transport->getRemoteUri(), FaceUri("internal://"));
+  BOOST_CHECK_EQUAL(transport->getScope(), ndn::nfd::FACE_SCOPE_LOCAL);
+  BOOST_CHECK_EQUAL(transport->getPersistency(), ndn::nfd::FACE_PERSISTENCY_PERMANENT);
+  BOOST_CHECK_EQUAL(transport->getLinkType(), ndn::nfd::LINK_TYPE_POINT_TO_POINT);
+  BOOST_CHECK_EQUAL(transport->getMtu(), MTU_UNLIMITED);
+}
+
 // note: "send" and "receive" in test case names refer to the direction seen on forwarderFace.
 // i.e. "send" means transmission from forwarder to client,
-//      "receive" means transmission client to forwarder.
+//      "receive" means transmission from client to forwarder.
 
 BOOST_AUTO_TEST_CASE(ReceiveInterestTimeout)
 {
@@ -182,8 +199,8 @@
 {
   forwarderFace->close();
   this->advanceClocks(time::milliseconds(1), 10);
-  BOOST_CHECK_EQUAL(static_pointer_cast<face::LpFaceWrapper>(forwarderFace)->getLpFace()->getState(), FaceState::CLOSED);
-  forwarderFace.reset();
+  BOOST_CHECK_EQUAL(forwarderFace->getState(), FaceState::CLOSED);
+  forwarderFaceW.reset();
 
   shared_ptr<Interest> interest = makeInterest("/zpHsVesu0B");
   interest->setInterestLifetime(time::milliseconds(100));
diff --git a/tests/daemon/face/multicast-udp-transport.t.cpp b/tests/daemon/face/multicast-udp-transport.t.cpp
index e895970..457cb4a 100644
--- a/tests/daemon/face/multicast-udp-transport.t.cpp
+++ b/tests/daemon/face/multicast-udp-transport.t.cpp
@@ -24,6 +24,7 @@
  */
 
 #include "face/multicast-udp-transport.hpp"
+#include "transport-properties.hpp"
 
 #include "tests/test-common.hpp"
 
@@ -53,6 +54,7 @@
   MulticastUdpTransport transport(sockRx.local_endpoint(),
                                   udp::endpoint(ip::address::from_string("230.15.19.47"), 7001),
                                   std::move(sockRx), std::move(sockTx));
+  checkStaticPropertiesInitialized(transport);
 
   BOOST_CHECK_EQUAL(transport.getLocalUri(), FaceUri("udp4://127.0.0.1:7001"));
   BOOST_CHECK_EQUAL(transport.getRemoteUri(), FaceUri("udp4://230.15.19.47:7001"));
diff --git a/tests/daemon/face/transport-properties.hpp b/tests/daemon/face/transport-properties.hpp
new file mode 100644
index 0000000..50a9666
--- /dev/null
+++ b/tests/daemon/face/transport-properties.hpp
@@ -0,0 +1,59 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015,  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_TRANSPORT_PROPERTIES_HPP
+#define NFD_TESTS_DAEMON_FACE_TRANSPORT_PROPERTIES_HPP
+
+#include "face/transport.hpp"
+
+#include "tests/test-common.hpp"
+
+namespace nfd {
+namespace face {
+namespace tests {
+
+/** \brief check a transport has all its static properties set after initialization
+ *
+ *  This check shall be inserted to the StaticProperties test case for each transport,
+ *  in addition to checking the values of properties.
+ *  When a new static property is defined, this test case shall be updated.
+ *  Thus, if a transport forgets to set a static property, this check would fail.
+ */
+inline void
+checkStaticPropertiesInitialized(const Transport& transport)
+{
+  BOOST_CHECK(!transport.getLocalUri().getScheme().empty());
+  BOOST_CHECK(!transport.getRemoteUri().getScheme().empty());
+  BOOST_CHECK_NE(transport.getScope(), ndn::nfd::FACE_SCOPE_NONE);
+  BOOST_CHECK_NE(transport.getPersistency(), ndn::nfd::FACE_PERSISTENCY_NONE);
+  BOOST_CHECK_NE(transport.getLinkType(), ndn::nfd::LINK_TYPE_NONE);
+  BOOST_CHECK_NE(transport.getMtu(), MTU_INVALID);
+}
+
+} // namespace tests
+} // namespace face
+} // namespace nfd
+
+#endif // NFD_TESTS_DAEMON_FACE_TRANSPORT_PROPERTIES_HPP
diff --git a/tests/daemon/face/unicast-udp-transport.t.cpp b/tests/daemon/face/unicast-udp-transport.t.cpp
index acf6d61..81ccc84 100644
--- a/tests/daemon/face/unicast-udp-transport.t.cpp
+++ b/tests/daemon/face/unicast-udp-transport.t.cpp
@@ -24,6 +24,7 @@
  */
 
 #include "face/unicast-udp-transport.hpp"
+#include "transport-properties.hpp"
 
 #include "tests/test-common.hpp"
 
@@ -43,6 +44,7 @@
   udp::socket sock(g_io, udp::endpoint(ip::address_v4::loopback(), 7001));
   sock.connect(udp::endpoint(ip::address_v4::loopback(), 7002));
   UnicastUdpTransport transport(std::move(sock), ndn::nfd::FACE_PERSISTENCY_PERSISTENT, time::seconds(300));
+  checkStaticPropertiesInitialized(transport);
 
   BOOST_CHECK_EQUAL(transport.getLocalUri(), FaceUri("udp4://127.0.0.1:7001"));
   BOOST_CHECK_EQUAL(transport.getRemoteUri(), FaceUri("udp4://127.0.0.1:7002"));
@@ -57,6 +59,7 @@
   udp::socket sock(g_io, udp::endpoint(ip::address_v6::loopback(), 7001));
   sock.connect(udp::endpoint(ip::address_v6::loopback(), 7002));
   UnicastUdpTransport transport(std::move(sock), ndn::nfd::FACE_PERSISTENCY_ON_DEMAND, time::seconds(300));
+  checkStaticPropertiesInitialized(transport);
 
   BOOST_CHECK_EQUAL(transport.getLocalUri(), FaceUri("udp6://[::1]:7001"));
   BOOST_CHECK_EQUAL(transport.getRemoteUri(), FaceUri("udp6://[::1]:7002"));
diff --git a/tests/daemon/face/unix-stream-transport.t.cpp b/tests/daemon/face/unix-stream-transport.t.cpp
index 5049678..32142eb 100644
--- a/tests/daemon/face/unix-stream-transport.t.cpp
+++ b/tests/daemon/face/unix-stream-transport.t.cpp
@@ -24,6 +24,7 @@
  */
 
 #include "face/unix-stream-transport.hpp"
+#include "transport-properties.hpp"
 
 #include "tests/test-common.hpp"
 #include <boost/filesystem.hpp>
@@ -88,6 +89,7 @@
   BOOST_CHECK(connectToAcceptor(acceptor1, sock1, sock2));
 
   UnixStreamTransport transport(std::move(sock1));
+  checkStaticPropertiesInitialized(transport);
 
   BOOST_CHECK_EQUAL(transport.getLocalUri().getScheme(), "unix");
   BOOST_CHECK_EQUAL(transport.getLocalUri().getHost(), "");