face: LinkService and Transport counters
refs #3177
Change-Id: Idc495c58c3103dae5f01a2b6ebbff47a2c4a5d2b
diff --git a/core/counter.hpp b/core/counter.hpp
new file mode 100644
index 0000000..bb50c66
--- /dev/null
+++ b/core/counter.hpp
@@ -0,0 +1,141 @@
+/* -*- 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_CORE_COUNTER_HPP
+#define NFD_CORE_COUNTER_HPP
+
+#include "common.hpp"
+
+namespace nfd {
+
+/** \brief represents a counter that encloses an integer value
+ *
+ * SimpleCounter is noncopyable, because increment should be called on the counter,
+ * not a copy of it; it's implicitly convertible to an integral type to be observed
+ */
+class SimpleCounter
+{
+public:
+ typedef uint64_t rep;
+
+ constexpr
+ SimpleCounter()
+ : m_value(0)
+ {
+ }
+
+ SimpleCounter(const SimpleCounter&) = delete;
+
+ SimpleCounter&
+ operator=(const SimpleCounter&) = delete;
+
+ /** \brief observe the counter
+ */
+ operator rep() const
+ {
+ return m_value;
+ }
+
+ /** \brief replace the counter value
+ */
+ void
+ set(rep value)
+ {
+ m_value = value;
+ }
+
+protected:
+ rep m_value;
+};
+
+/** \brief represents a counter of number of packets
+ *
+ * \warning The counter value may wrap after exceeding the range of underlying integer type.
+ */
+class PacketCounter : public SimpleCounter
+{
+public:
+ /** \brief increment the counter by one
+ */
+ PacketCounter&
+ operator++()
+ {
+ ++m_value;
+ return *this;
+ }
+ // postfix ++ operator is not provided because it's not needed
+};
+
+/** \brief represents a counter of number of bytes
+ *
+ * \warning The counter value may wrap after exceeding the range of underlying integer type.
+ */
+class ByteCounter : public SimpleCounter
+{
+public:
+ /** \brief increase the counter
+ */
+ ByteCounter&
+ operator+=(rep n)
+ {
+ m_value += n;
+ return *this;
+ }
+};
+
+/** \brief provides a counter that observes the size of a table
+ * \tparam T a type that provides a size() const member function
+ */
+template<typename T>
+class SizeCounter
+{
+public:
+ typedef size_t rep;
+
+ constexpr
+ SizeCounter(const T& table)
+ : m_table(table)
+ {
+ }
+
+ SizeCounter(const SizeCounter&) = delete;
+
+ SizeCounter&
+ operator=(const SizeCounter&) = delete;
+
+ /** \brief observe the counter
+ */
+ operator rep() const
+ {
+ return m_table.size();
+ }
+
+private:
+ const T& m_table;
+};
+
+} // namespace nfd
+
+#endif // NFD_CORE_COUNTER_HPP
diff --git a/daemon/face/face-counters.hpp b/daemon/face/face-counters.hpp
index 6dc1d6a..90cf106 100644
--- a/daemon/face/face-counters.hpp
+++ b/daemon/face/face-counters.hpp
@@ -1,12 +1,12 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014, 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
+ * 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.
@@ -26,83 +26,10 @@
#ifndef NFD_DAEMON_FACE_FACE_COUNTERS_HPP
#define NFD_DAEMON_FACE_FACE_COUNTERS_HPP
-#include "common.hpp"
+#include "core/counter.hpp"
namespace nfd {
-/** \brief represents a counter of number of packets
- */
-// PacketCounter is noncopyable, because increment should be called on the counter,
-// not a copy of it; it's implicitly convertible to uint64_t to be observed
-class PacketCounter : noncopyable
-{
-public:
- typedef uint64_t rep;
-
- PacketCounter()
- : m_value(0)
- {
- }
-
- operator rep() const
- {
- return m_value;
- }
-
- PacketCounter&
- operator++()
- {
- ++m_value;
- return *this;
- }
- // postfix ++ operator is not provided because it's not needed
-
- void
- set(rep value)
- {
- m_value = value;
- }
-
-private:
- rep m_value;
-};
-
-/** \brief represents a counter of number of bytes
- */
-// ByteCounter is noncopyable, because increment should be called on the counter,
-// not a copy of it; it's implicitly convertible to uint64_t to be observed
-class ByteCounter : noncopyable
-{
-public:
- typedef uint64_t rep;
-
- ByteCounter()
- : m_value(0)
- {
- }
-
- operator rep() const
- {
- return m_value;
- }
-
- ByteCounter&
- operator+=(rep n)
- {
- m_value += n;
- return *this;
- }
-
- void
- set(rep value)
- {
- m_value = value;
- }
-
-private:
- rep m_value;
-};
-
/** \brief contains network layer packet counters
*/
class NetworkLayerCounters : noncopyable
diff --git a/daemon/face/link-service.cpp b/daemon/face/link-service.cpp
index 3f19388..45194dd 100644
--- a/daemon/face/link-service.cpp
+++ b/daemon/face/link-service.cpp
@@ -35,7 +35,7 @@
LinkService::LinkService()
: m_face(nullptr)
, m_transport(nullptr)
- , m_counters(nullptr)
+ , m_oldCounters(nullptr)
{
}
@@ -51,7 +51,7 @@
m_face = &face;
m_transport = &transport;
- m_counters = &m_face->getMutableCounters();
+ m_oldCounters = &m_face->getMutableCounters();
}
void
@@ -60,7 +60,8 @@
BOOST_ASSERT(m_transport != nullptr);
NFD_LOG_FACE_TRACE(__func__);
- ++m_counters->getNOutInterests();
+ ++this->nOutInterests;
+ ++m_oldCounters->getNOutInterests();
doSendInterest(interest);
}
@@ -71,7 +72,8 @@
BOOST_ASSERT(m_transport != nullptr);
NFD_LOG_FACE_TRACE(__func__);
- ++m_counters->getNOutDatas();
+ ++this->nOutData;
+ ++m_oldCounters->getNOutDatas();
doSendData(data);
}
@@ -82,7 +84,7 @@
BOOST_ASSERT(m_transport != nullptr);
NFD_LOG_FACE_TRACE(__func__);
- // TODO#3177 increment counter
+ ++this->nOutNacks;
doSendNack(nack);
}
@@ -92,7 +94,8 @@
{
NFD_LOG_FACE_TRACE(__func__);
- ++m_counters->getNInInterests();
+ ++this->nInInterests;
+ ++m_oldCounters->getNInInterests();
afterReceiveInterest(interest);
}
@@ -102,7 +105,8 @@
{
NFD_LOG_FACE_TRACE(__func__);
- ++m_counters->getNInDatas();
+ ++this->nInData;
+ ++m_oldCounters->getNInDatas();
afterReceiveData(data);
}
@@ -112,7 +116,7 @@
{
NFD_LOG_FACE_TRACE(__func__);
- // TODO#3177 increment counter
+ ++this->nInNacks;
afterReceiveNack(nack);
}
diff --git a/daemon/face/link-service.hpp b/daemon/face/link-service.hpp
index 1b7bda8..ba7e72f 100644
--- a/daemon/face/link-service.hpp
+++ b/daemon/face/link-service.hpp
@@ -34,12 +34,49 @@
class LpFace;
+/** \brief counters provided by LinkService
+ * \note The type name 'LinkServiceCounters' is implementation detail.
+ * Use 'LinkService::Counters' in public API.
+ */
+class LinkServiceCounters
+{
+public:
+ /** \brief count of incoming Interests
+ */
+ PacketCounter nInInterests;
+
+ /** \brief count of outgoing Interests
+ */
+ PacketCounter nOutInterests;
+
+ /** \brief count of incoming Data
+ */
+ PacketCounter nInData;
+
+ /** \brief count of outgoing Data
+ */
+ PacketCounter nOutData;
+
+ /** \brief count of incoming Nacks
+ */
+ PacketCounter nInNacks;
+
+ /** \brief count of outgoing Nacks
+ */
+ PacketCounter nOutNacks;
+};
+
/** \brief the upper part of an LpFace
* \sa LpFace
*/
-class LinkService : noncopyable
+class LinkService : protected virtual LinkServiceCounters, noncopyable
{
public:
+ /** \brief counters provided by LinkService
+ */
+ typedef LinkServiceCounters Counters;
+
+public:
LinkService();
virtual
@@ -66,6 +103,9 @@
Transport*
getTransport();
+ virtual const Counters&
+ getCounters() const;
+
public: // upper interface to be used by forwarding
/** \brief send Interest
* \pre setTransport has been called
@@ -97,21 +137,11 @@
*/
signal::Signal<LinkService, lp::Nack> afterReceiveNack;
-private: // upper interface to be overridden in subclass (send path entrypoint)
- /** \brief performs LinkService specific operations to send an Interest
+public: // lower interface to be invoked by Transport
+ /** \brief performs LinkService specific operations to receive a lower-layer packet
*/
- virtual void
- doSendInterest(const Interest& interest) = 0;
-
- /** \brief performs LinkService specific operations to send a Data
- */
- virtual void
- doSendData(const Data& data) = 0;
-
- /** \brief performs LinkService specific operations to send a Nack
- */
- virtual void
- doSendNack(const lp::Nack& nack) = 0;
+ void
+ receivePacket(Transport::Packet&& packet);
protected: // upper interface to be invoked in subclass (receive path termination)
/** \brief delivers received Interest to forwarding
@@ -129,18 +159,28 @@
void
receiveNack(const lp::Nack& nack);
-public: // lower interface to be invoked by Transport
- /** \brief performs LinkService specific operations to receive a lower-layer packet
- */
- void
- receivePacket(Transport::Packet&& packet);
-
protected: // lower interface to be invoked in subclass (send path termination)
/** \brief sends a lower-layer packet via Transport
*/
void
sendPacket(Transport::Packet&& packet);
+private: // upper interface to be overridden in subclass (send path entrypoint)
+ /** \brief performs LinkService specific operations to send an Interest
+ */
+ virtual void
+ doSendInterest(const Interest& interest) = 0;
+
+ /** \brief performs LinkService specific operations to send a Data
+ */
+ virtual void
+ doSendData(const Data& data) = 0;
+
+ /** \brief performs LinkService specific operations to send a Nack
+ */
+ virtual void
+ doSendNack(const lp::Nack& nack) = 0;
+
private: // lower interface to be overridden in subclass
virtual void
doReceivePacket(Transport::Packet&& packet) = 0;
@@ -148,7 +188,7 @@
private:
LpFace* m_face;
Transport* m_transport;
- NetworkLayerCounters* m_counters; // TODO#3177 change into NetCounters
+ NetworkLayerCounters* m_oldCounters; // old counters from LpFaceWrapper
};
inline const LpFace*
@@ -169,6 +209,12 @@
return m_transport;
}
+inline const LinkService::Counters&
+LinkService::getCounters() const
+{
+ return *this;
+}
+
inline void
LinkService::receivePacket(Transport::Packet&& packet)
{
diff --git a/daemon/face/transport.cpp b/daemon/face/transport.cpp
index 1b7832e..0c4a4c6 100644
--- a/daemon/face/transport.cpp
+++ b/daemon/face/transport.cpp
@@ -65,7 +65,7 @@
, m_linkType(ndn::nfd::LINK_TYPE_NONE)
, m_mtu(MTU_INVALID)
, m_state(TransportState::UP)
- , m_counters(nullptr)
+ , m_oldCounters(nullptr)
{
}
@@ -81,7 +81,7 @@
m_face = &face;
m_service = &service;
- m_counters = &m_face->getMutableCounters();
+ m_oldCounters = &m_face->getMutableCounters();
}
void
@@ -109,8 +109,11 @@
return;
}
- // TODO#3177 increment LpPacket counter
- m_counters->getNOutBytes() += packet.packet.size();
+ if (state == TransportState::UP) {
+ ++this->nOutPackets;
+ this->nOutBytes += packet.packet.size();
+ m_oldCounters->getNOutBytes() += packet.packet.size();
+ }
this->doSend(std::move(packet));
}
@@ -121,8 +124,9 @@
BOOST_ASSERT(this->getMtu() == MTU_UNLIMITED ||
packet.packet.size() <= static_cast<size_t>(this->getMtu()));
- // TODO#3177 increment LpPacket counter
- m_counters->getNInBytes() += packet.packet.size();
+ ++this->nInPackets;
+ this->nInBytes += packet.packet.size();
+ m_oldCounters->getNInBytes() += packet.packet.size();
m_service->receivePacket(std::move(packet));
}
diff --git a/daemon/face/transport.hpp b/daemon/face/transport.hpp
index d069a0e..b0d10f4 100644
--- a/daemon/face/transport.hpp
+++ b/daemon/face/transport.hpp
@@ -51,6 +51,46 @@
std::ostream&
operator<<(std::ostream& os, TransportState state);
+/** \brief counters provided by Transport
+ * \note The type name 'TransportCounters' is implementation detail.
+ * Use 'Transport::Counters' in public API.
+ */
+class TransportCounters
+{
+public:
+ /** \brief count of incoming packets
+ *
+ * A 'packet' typically means a top-level TLV block.
+ * For a datagram-based transport, an incoming packet that cannot be parsed as TLV
+ * would not be counted.
+ */
+ PacketCounter nInPackets;
+
+ /** \brief count of outgoing packets
+ *
+ * A 'packet' typically means a top-level TLV block.
+ * This counter is incremented only if transport is UP.
+ */
+ PacketCounter nOutPackets;
+
+ /** \brief total incoming bytes
+ *
+ * This counter includes headers imposed by NFD (such as NDNLP),
+ * but excludes overhead of underlying protocol (such as IP header).
+ * For a datagram-based transport, an incoming packet that cannot be parsed as TLV
+ * would not be counted.
+ */
+ ByteCounter nInBytes;
+
+ /** \brief total outgoing bytes
+ *
+ * This counter includes headers imposed by NFD (such as NDNLP),
+ * but excludes overhead of underlying protocol (such as IP header).
+ * This counter is increased only if transport is UP.
+ */
+ ByteCounter nOutBytes;
+};
+
/** \brief indicates the transport has no limit on payload size
*/
const ssize_t MTU_UNLIMITED = -1;
@@ -62,7 +102,7 @@
/** \brief the lower part of an LpFace
* \sa LpFace
*/
-class Transport : noncopyable
+class Transport : protected virtual TransportCounters, noncopyable
{
public:
/** \brief identifies an endpoint on the link
@@ -93,6 +133,10 @@
EndpointId remoteEndpoint;
};
+ /** \brief counters provided by Transport
+ */
+ typedef TransportCounters Counters;
+
/** \brief constructor
*
* Transport constructor initializes static properties to invalid values.
@@ -128,6 +172,9 @@
LinkService*
getLinkService();
+ virtual const Counters&
+ getCounters() const;
+
public: // upper interface
/** \brief request the transport to be closed
*
@@ -270,7 +317,7 @@
ndn::nfd::LinkType m_linkType;
ssize_t m_mtu;
TransportState m_state;
- LinkLayerCounters* m_counters; // TODO#3177 change into LinkCounters
+ LinkLayerCounters* m_oldCounters; // TODO#3177 change into LinkCounters
};
inline const LpFace*
@@ -291,6 +338,12 @@
return m_service;
}
+inline const Transport::Counters&
+Transport::getCounters() const
+{
+ return *this;
+}
+
inline FaceUri
Transport::getLocalUri() const
{
diff --git a/daemon/face/websocket-transport.cpp b/daemon/face/websocket-transport.cpp
index cf3da37..6423330 100644
--- a/daemon/face/websocket-transport.cpp
+++ b/daemon/face/websocket-transport.cpp
@@ -106,6 +106,8 @@
{
NFD_LOG_FACE_TRACE(__func__);
+ ++this->nOutPings;
+
websocketpp::lib::error_code error;
m_server.ping(m_handle, "NFD-WebSocket", error);
if (error)
@@ -118,6 +120,8 @@
WebSocketTransport::handlePong()
{
NFD_LOG_FACE_TRACE(__func__);
+
+ ++this->nInPongs;
}
void
diff --git a/daemon/face/websocket-transport.hpp b/daemon/face/websocket-transport.hpp
index 91a99c1..08542c0 100644
--- a/daemon/face/websocket-transport.hpp
+++ b/daemon/face/websocket-transport.hpp
@@ -33,16 +33,39 @@
namespace nfd {
namespace face {
-/**
- * \brief A Transport that communicates on a WebSocket connection
+/** \brief counters provided by WebSocketTransport
+ * \note The type name 'WebSocketTransportCounters' is implementation detail.
+ * Use 'WebSocketTransport::Counters' in public API.
*/
-class WebSocketTransport DECL_FINAL : public Transport
+class WebSocketTransportCounters : public virtual Transport::Counters
{
public:
+ /** \brief count of outgoing Pings
+ */
+ PacketCounter nOutPings;
+
+ /** \brief count of incoming Pongs
+ */
+ PacketCounter nInPongs;
+};
+
+/** \brief A Transport that communicates on a WebSocket connection
+ */
+class WebSocketTransport DECL_FINAL : public Transport
+ , protected virtual WebSocketTransportCounters
+{
+public:
+ /** \brief counters provided by WebSocketTransport
+ */
+ typedef WebSocketTransportCounters Counters;
+
WebSocketTransport(websocketpp::connection_hdl hdl,
websocket::Server& server,
time::milliseconds pingInterval);
+ virtual const Counters&
+ getCounters() const DECL_OVERRIDE;
+
/** \brief Translates a message into a Block
* and delivers it to the link service
*/
@@ -82,6 +105,12 @@
scheduler::ScopedEventId m_pingEventId;
};
+inline const WebSocketTransport::Counters&
+WebSocketTransport::getCounters() const
+{
+ return *this;
+}
+
} // namespace face
} // namespace nfd
diff --git a/tests/core/counter.t.cpp b/tests/core/counter.t.cpp
new file mode 100644
index 0000000..310e589
--- /dev/null
+++ b/tests/core/counter.t.cpp
@@ -0,0 +1,87 @@
+/* -*- 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/>.
+ */
+
+#include "core/counter.hpp"
+
+#include "tests/test-common.hpp"
+
+namespace nfd {
+namespace tests {
+
+BOOST_FIXTURE_TEST_SUITE(TestCounter, BaseFixture)
+
+BOOST_AUTO_TEST_CASE(PacketCnt)
+{
+ PacketCounter counter;
+
+ uint64_t observation = counter; // implicit conversion
+ BOOST_CHECK_EQUAL(observation, 0);
+
+ ++counter;
+ BOOST_CHECK_EQUAL(counter, 1);
+ ++counter;
+ ++counter;
+ BOOST_CHECK_EQUAL(counter, 3);
+
+ counter.set(2);
+ BOOST_CHECK_EQUAL(counter, 2);
+}
+
+BOOST_AUTO_TEST_CASE(ByteCnt)
+{
+ ByteCounter counter;
+
+ uint64_t observation = counter; // implicit conversion
+ BOOST_CHECK_EQUAL(observation, 0);
+
+ counter += 20;
+ BOOST_CHECK_EQUAL(counter, 20);
+ counter += 80;
+ counter += 90;
+ BOOST_CHECK_EQUAL(counter, 190);
+
+ counter.set(21);
+ BOOST_CHECK_EQUAL(counter, 21);
+}
+
+BOOST_AUTO_TEST_CASE(SizeCnt)
+{
+ std::vector<int> v;
+ SizeCounter<std::vector<int>> counter(v);
+
+ size_t observation = counter; // implicit conversion
+ BOOST_CHECK_EQUAL(observation, 0);
+
+ v.resize(249);
+ BOOST_CHECK_EQUAL(counter, 249);
+
+ v.resize(98);
+ BOOST_CHECK_EQUAL(counter, 98);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestCounter
+
+} // namespace tests
+} // namespace nfd
diff --git a/tests/daemon/face/dummy-transport.hpp b/tests/daemon/face/dummy-transport.hpp
index 0e76d47..6d1451c 100644
--- a/tests/daemon/face/dummy-transport.hpp
+++ b/tests/daemon/face/dummy-transport.hpp
@@ -43,7 +43,8 @@
const std::string& remoteUri = "dummy://",
ndn::nfd::FaceScope scope = ndn::nfd::FACE_SCOPE_NON_LOCAL,
ndn::nfd::FacePersistency persistency = ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
- ndn::nfd::LinkType linkType = ndn::nfd::LINK_TYPE_POINT_TO_POINT)
+ ndn::nfd::LinkType linkType = ndn::nfd::LINK_TYPE_POINT_TO_POINT,
+ ssize_t mtu = MTU_UNLIMITED)
: isClosed(false)
{
this->setLocalUri(FaceUri(localUri));
@@ -51,7 +52,7 @@
this->setScope(scope);
this->setPersistency(persistency);
this->setLinkType(linkType);
- this->setMtu(MTU_UNLIMITED);
+ this->setMtu(mtu);
}
void
diff --git a/tests/daemon/face/face-counters.t.cpp b/tests/daemon/face/face-counters.t.cpp
index 2d56113..949ac5b 100644
--- a/tests/daemon/face/face-counters.t.cpp
+++ b/tests/daemon/face/face-counters.t.cpp
@@ -33,34 +33,6 @@
BOOST_FIXTURE_TEST_SUITE(FaceFaceCounters, BaseFixture)
-BOOST_AUTO_TEST_CASE(PacketCnt)
-{
- PacketCounter counter;
-
- uint64_t observation = counter;//implicit convertible
- BOOST_CHECK_EQUAL(observation, 0);
-
- ++counter;
- BOOST_CHECK_EQUAL(static_cast<int>(counter), 1);
- ++counter;
- ++counter;
- BOOST_CHECK_EQUAL(static_cast<int>(counter), 3);
-}
-
-BOOST_AUTO_TEST_CASE(ByteCnt)
-{
- ByteCounter counter;
-
- uint64_t observation = counter;//implicit convertible
- BOOST_CHECK_EQUAL(observation, 0);
-
- counter += 20;
- BOOST_CHECK_EQUAL(static_cast<int>(counter), 20);
- counter += 80;
- counter += 90;
- BOOST_CHECK_EQUAL(static_cast<int>(counter), 190);
-}
-
BOOST_AUTO_TEST_CASE(Counters)
{
DummyFace face;
diff --git a/tests/daemon/face/transport.t.cpp b/tests/daemon/face/transport.t.cpp
new file mode 100644
index 0000000..ae6a9c1
--- /dev/null
+++ b/tests/daemon/face/transport.t.cpp
@@ -0,0 +1,256 @@
+/* -*- 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/>.
+ */
+
+#include "face/transport.hpp"
+#include "face/lp-face.hpp"
+#include "dummy-transport.hpp"
+#include "dummy-receive-link-service.hpp"
+#include "transport-properties.hpp"
+
+#include <boost/mpl/empty_sequence.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/joint_view.hpp>
+#include <boost/mpl/map.hpp>
+#include <boost/mpl/set.hpp>
+#include <boost/mpl/transform_view.hpp>
+
+#include "tests/test-common.hpp"
+
+namespace nfd {
+namespace face {
+namespace tests {
+
+using namespace nfd::tests;
+namespace ip = boost::asio::ip;
+
+BOOST_AUTO_TEST_SUITE(Face)
+
+class DummyTransportFixture : public BaseFixture
+{
+public:
+ DummyTransportFixture()
+ : transport(nullptr)
+ , sentPackets(nullptr)
+ , receivedPackets(nullptr)
+ {
+ // Constructor does not initialize the fixture,
+ // so that test case may specify different parameters to DummyTransport constructor.
+ }
+
+ void
+ initialize(unique_ptr<DummyTransport> transport = make_unique<DummyTransport>())
+ {
+ this->face = make_unique<LpFace>(make_unique<DummyReceiveLinkService>(), std::move(transport));
+ this->transport = static_cast<DummyTransport*>(face->getTransport());
+ this->sentPackets = &this->transport->sentPackets;
+ this->receivedPackets = &static_cast<DummyReceiveLinkService*>(face->getLinkService())->receivedPackets;
+ }
+
+public:
+ unique_ptr<LpFace> face;
+ DummyTransport* transport;
+ std::vector<Transport::Packet>* sentPackets;
+ std::vector<Transport::Packet>* receivedPackets;
+};
+
+BOOST_FIXTURE_TEST_SUITE(TestTransport, DummyTransportFixture)
+
+BOOST_AUTO_TEST_CASE(DummyTransportStaticProperties)
+{
+ this->initialize();
+ checkStaticPropertiesInitialized(*transport);
+}
+
+BOOST_AUTO_TEST_SUITE(StateTransition)
+
+namespace mpl = boost::mpl;
+
+/** \brief a macro to declare a TransportState as a integral constant
+ */
+#define TRANSPORT_STATE_C(X) mpl::int_<static_cast<int>(TransportState::X)>
+
+/** \brief a map from every TransportState to a valid state transition sequence
+ * for entering this state from UP
+ */
+typedef mpl::map<
+ mpl::pair<TRANSPORT_STATE_C(UP),
+ mpl::vector<>>,
+ mpl::pair<TRANSPORT_STATE_C(DOWN),
+ mpl::vector<
+ TRANSPORT_STATE_C(DOWN)
+ >>,
+ mpl::pair<TRANSPORT_STATE_C(CLOSING),
+ mpl::vector<
+ TRANSPORT_STATE_C(CLOSING)
+ >>,
+ mpl::pair<TRANSPORT_STATE_C(FAILED),
+ mpl::vector<
+ TRANSPORT_STATE_C(FAILED)
+ >>,
+ mpl::pair<TRANSPORT_STATE_C(CLOSED),
+ mpl::vector<
+ TRANSPORT_STATE_C(CLOSING),
+ TRANSPORT_STATE_C(CLOSED)
+ >>
+> StateEntering;
+
+/** \brief a sequence of all valid TransportStates
+ */
+typedef mpl::fold<StateEntering,
+ mpl::vector<>,
+ mpl::push_back<mpl::_1, mpl::first<mpl::_2>>
+>::type States;
+
+/** \brief a set of all valid state transitions
+ */
+typedef mpl::set<
+ mpl::pair<TRANSPORT_STATE_C(UP), TRANSPORT_STATE_C(DOWN)>,
+ mpl::pair<TRANSPORT_STATE_C(DOWN), TRANSPORT_STATE_C(UP)>,
+ mpl::pair<TRANSPORT_STATE_C(UP), TRANSPORT_STATE_C(CLOSING)>,
+ mpl::pair<TRANSPORT_STATE_C(UP), TRANSPORT_STATE_C(FAILED)>,
+ mpl::pair<TRANSPORT_STATE_C(DOWN), TRANSPORT_STATE_C(CLOSING)>,
+ mpl::pair<TRANSPORT_STATE_C(DOWN), TRANSPORT_STATE_C(FAILED)>,
+ mpl::pair<TRANSPORT_STATE_C(CLOSING), TRANSPORT_STATE_C(CLOSED)>,
+ mpl::pair<TRANSPORT_STATE_C(FAILED), TRANSPORT_STATE_C(CLOSED)>
+> ValidStateTransitions;
+
+/** \brief a metafunction class to generate a sequence of all state transitions
+ * from a specified state
+ */
+struct StateTransitionsFrom
+{
+ template<typename FROM>
+ struct apply
+ {
+ typedef typename mpl::fold<
+ States,
+ mpl::vector<>,
+ mpl::push_back<mpl::_1, mpl::pair<FROM, mpl::_2>>
+ >::type type;
+ };
+};
+
+/** \brief a sequence of all state transitions
+ */
+typedef mpl::fold<
+ States,
+ mpl::empty_sequence,
+ mpl::joint_view<mpl::_1, mpl::apply<StateTransitionsFrom, mpl::protect<mpl::_1>>::type>
+>::type AllStateTransitions;
+
+#undef TRANSPORT_STATE_C
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(SetState, T, AllStateTransitions)
+{
+ this->initialize();
+
+ TransportState from = static_cast<TransportState>(T::first::value);
+ TransportState to = static_cast<TransportState>(T::second::value);
+ BOOST_TEST_MESSAGE("SetState " << from << " -> " << to);
+
+ // enter from state
+ typedef typename mpl::at<StateEntering, mpl::int_<T::first::value>>::type Steps;
+ mpl::for_each<Steps>(
+ [this] (int state) { transport->setState(static_cast<TransportState>(state)); });
+ BOOST_REQUIRE_EQUAL(transport->getState(), from);
+
+ bool hasSignal = false;
+ this->transport->afterStateChange.connect(
+ [from, to, &hasSignal] (TransportState oldState, TransportState newState) {
+ hasSignal = true;
+ BOOST_CHECK_EQUAL(oldState, from);
+ BOOST_CHECK_EQUAL(newState, to);
+ });
+
+ // do transition
+ bool isValid = from == to ||
+ mpl::has_key<ValidStateTransitions,
+ mpl::pair<mpl::int_<T::first::value>, mpl::int_<T::second::value>>
+ >::value;
+ if (isValid) {
+ BOOST_REQUIRE_NO_THROW(transport->setState(to));
+ BOOST_CHECK_EQUAL(hasSignal, from != to);
+ }
+ else {
+ BOOST_CHECK_THROW(this->transport->setState(to), std::runtime_error);
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END() // StateTransition
+
+BOOST_AUTO_TEST_CASE(Send)
+{
+ this->initialize();
+
+ Block pkt1 = ndn::encoding::makeStringBlock(300, "Lorem ipsum dolor sit amet,");
+ transport->send(Transport::Packet(Block(pkt1)));
+
+ Block pkt2 = ndn::encoding::makeStringBlock(301, "consectetur adipiscing elit,");
+ transport->send(Transport::Packet(Block(pkt2)));
+
+ transport->setState(TransportState::DOWN);
+ Block pkt3 = ndn::encoding::makeStringBlock(302, "sed do eiusmod tempor incididunt ");
+ transport->send(Transport::Packet(Block(pkt3)));
+
+ transport->setState(TransportState::CLOSING);
+ Block pkt4 = ndn::encoding::makeStringBlock(303, "ut labore et dolore magna aliqua.");
+ transport->send(Transport::Packet(Block(pkt4)));
+
+ BOOST_CHECK_EQUAL(transport->getCounters().nOutPackets, 2);
+ BOOST_CHECK_EQUAL(transport->getCounters().nOutBytes, pkt1.size() + pkt2.size());
+ BOOST_REQUIRE_EQUAL(sentPackets->size(), 3);
+ BOOST_CHECK(sentPackets->at(0).packet == pkt1);
+ BOOST_CHECK(sentPackets->at(1).packet == pkt2);
+ BOOST_CHECK(sentPackets->at(2).packet == pkt3);
+}
+
+BOOST_AUTO_TEST_CASE(Receive)
+{
+ this->initialize();
+
+ Block pkt1 = ndn::encoding::makeStringBlock(300, "Lorem ipsum dolor sit amet,");
+ transport->receivePacket(pkt1);
+
+ Block pkt2 = ndn::encoding::makeStringBlock(301, "consectetur adipiscing elit,");
+ transport->receivePacket(pkt2);
+
+ transport->setState(TransportState::DOWN);
+ Block pkt3 = ndn::encoding::makeStringBlock(302, "sed do eiusmod tempor incididunt ");
+ transport->receivePacket(pkt3);
+
+ BOOST_CHECK_EQUAL(transport->getCounters().nInPackets, 3);
+ BOOST_CHECK_EQUAL(transport->getCounters().nInBytes, pkt1.size() + pkt2.size() + pkt3.size());
+ BOOST_REQUIRE_EQUAL(receivedPackets->size(), 3);
+ BOOST_CHECK(receivedPackets->at(0).packet == pkt1);
+ BOOST_CHECK(receivedPackets->at(1).packet == pkt2);
+ BOOST_CHECK(receivedPackets->at(2).packet == pkt3);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestTransport
+BOOST_AUTO_TEST_SUITE_END() // Face
+
+} // namespace tests
+} // namespace face
+} // namespace nfd
diff --git a/tests/daemon/face/websocket-transport.t.cpp b/tests/daemon/face/websocket-transport.t.cpp
index f4115bc..8c295ba 100644
--- a/tests/daemon/face/websocket-transport.t.cpp
+++ b/tests/daemon/face/websocket-transport.t.cpp
@@ -234,6 +234,8 @@
BOOST_CHECK_EQUAL(limitedIo.run(2, // clientHandlePing, serverHandlePong
time::milliseconds(1500)), LimitedIo::EXCEED_OPS);
BOOST_CHECK_EQUAL(transport->getState(), TransportState::UP);
+ BOOST_CHECK_EQUAL(transport->getCounters().nOutPings, 1);
+ BOOST_CHECK_EQUAL(transport->getCounters().nInPongs, 1);
this->clientShouldPong = false;
BOOST_CHECK_EQUAL(limitedIo.run(2, // clientHandlePing, serverHandlePongTimeout
@@ -241,6 +243,8 @@
BOOST_CHECK_MESSAGE(transport->getState() == TransportState::FAILED ||
transport->getState() == TransportState::CLOSED,
"expect FAILED or CLOSED state, actual state=" << transport->getState());
+ BOOST_CHECK_EQUAL(transport->getCounters().nOutPings, 2);
+ BOOST_CHECK_EQUAL(transport->getCounters().nInPongs, 1);
}
BOOST_AUTO_TEST_CASE(Send)