mgmt: RibEntry equality operators and formatted output
This commit also changes the return type of getRoutes()
from std::list to std::vector, and adds setRoutes(),
hasExpirationPeriod() and unsetExpirationPeriod().
Change-Id: I53f0ea846067c9087fa72273fc131826884ce12f
Refs: #3903
diff --git a/src/mgmt/nfd/rib-entry.cpp b/src/mgmt/nfd/rib-entry.cpp
index ed7fd67..17b53d6 100644
--- a/src/mgmt/nfd/rib-entry.cpp
+++ b/src/mgmt/nfd/rib-entry.cpp
@@ -20,34 +20,24 @@
*/
#include "rib-entry.hpp"
-#include "encoding/tlv-nfd.hpp"
#include "encoding/block-helpers.hpp"
+#include "encoding/encoding-buffer.hpp"
+#include "encoding/tlv-nfd.hpp"
#include "util/concepts.hpp"
+#include <boost/range/adaptor/reversed.hpp>
+
namespace ndn {
namespace nfd {
-//BOOST_CONCEPT_ASSERT((boost::EqualityComparable<Route>));
-BOOST_CONCEPT_ASSERT((WireEncodable<Route>));
-BOOST_CONCEPT_ASSERT((WireDecodable<Route>));
-static_assert(std::is_base_of<tlv::Error, Route::Error>::value,
- "Route::Error must inherit from tlv::Error");
-
-//BOOST_CONCEPT_ASSERT((boost::EqualityComparable<RibEntry>));
-BOOST_CONCEPT_ASSERT((WireEncodable<RibEntry>));
-BOOST_CONCEPT_ASSERT((WireDecodable<RibEntry>));
-static_assert(std::is_base_of<tlv::Error, RibEntry::Error>::value,
- "RibEntry::Error must inherit from tlv::Error");
-
-const time::milliseconds Route::INFINITE_EXPIRATION_PERIOD(time::milliseconds::max());
+BOOST_CONCEPT_ASSERT((StatusDatasetItem<Route>));
+BOOST_CONCEPT_ASSERT((StatusDatasetItem<RibEntry>));
Route::Route()
: m_faceId(INVALID_FACE_ID)
, m_origin(0)
, m_cost(0)
, m_flags(ROUTE_FLAG_CHILD_INHERIT)
- , m_expirationPeriod(INFINITE_EXPIRATION_PERIOD)
- , m_hasInfiniteExpirationPeriod(true)
{
}
@@ -91,8 +81,18 @@
Route&
Route::setExpirationPeriod(time::milliseconds expirationPeriod)
{
+ if (expirationPeriod == time::milliseconds::max())
+ return unsetExpirationPeriod();
+
m_expirationPeriod = expirationPeriod;
- m_hasInfiniteExpirationPeriod = m_expirationPeriod == INFINITE_EXPIRATION_PERIOD;
+ m_wire.reset();
+ return *this;
+}
+
+Route&
+Route::unsetExpirationPeriod()
+{
+ m_expirationPeriod = nullopt;
m_wire.reset();
return *this;
}
@@ -103,10 +103,9 @@
{
size_t totalLength = 0;
- // Absence of an ExpirationPeriod signifies non-expiration
- if (!m_hasInfiniteExpirationPeriod) {
+ if (m_expirationPeriod) {
totalLength += prependNonNegativeIntegerBlock(block, ndn::tlv::nfd::ExpirationPeriod,
- static_cast<uint64_t>(m_expirationPeriod.count()));
+ static_cast<uint64_t>(m_expirationPeriod->count()));
}
totalLength += prependNonNegativeIntegerBlock(block, ndn::tlv::nfd::Flags, m_flags);
totalLength += prependNonNegativeIntegerBlock(block, ndn::tlv::nfd::Cost, m_cost);
@@ -141,25 +140,13 @@
}
void
-Route::wireDecode(const Block& wire)
+Route::wireDecode(const Block& block)
{
- m_faceId = 0;
- m_origin = 0;
- m_cost = 0;
- m_flags = 0;
- m_expirationPeriod = time::milliseconds::min();
-
- m_wire = wire;
-
- if (m_wire.type() != tlv::nfd::Route) {
- std::stringstream error;
- error << "Expected Route Block, but Block is of a different type: #"
- << m_wire.type();
- BOOST_THROW_EXCEPTION(Error(error.str()));
+ if (block.type() != tlv::nfd::Route) {
+ BOOST_THROW_EXCEPTION(Error("expecting Route, but Block has type " + to_string(block.type())));
}
-
+ m_wire = block;
m_wire.parse();
-
Block::element_const_iterator val = m_wire.elements_begin();
if (val != m_wire.elements_end() && val->type() == tlv::nfd::FaceId) {
@@ -167,7 +154,7 @@
++val;
}
else {
- BOOST_THROW_EXCEPTION(Error("Missing required FaceId field"));
+ BOOST_THROW_EXCEPTION(Error("missing required FaceId field"));
}
if (val != m_wire.elements_end() && val->type() == tlv::nfd::Origin) {
@@ -175,7 +162,7 @@
++val;
}
else {
- BOOST_THROW_EXCEPTION(Error("Missing required Origin field"));
+ BOOST_THROW_EXCEPTION(Error("missing required Origin field"));
}
if (val != m_wire.elements_end() && val->type() == tlv::nfd::Cost) {
@@ -183,7 +170,7 @@
++val;
}
else {
- BOOST_THROW_EXCEPTION(Error("Missing required Cost field"));
+ BOOST_THROW_EXCEPTION(Error("missing required Cost field"));
}
if (val != m_wire.elements_end() && val->type() == tlv::nfd::Flags) {
@@ -191,38 +178,50 @@
++val;
}
else {
- BOOST_THROW_EXCEPTION(Error("Missing required Flags field"));
+ BOOST_THROW_EXCEPTION(Error("missing required Flags field"));
}
if (val != m_wire.elements_end() && val->type() == tlv::nfd::ExpirationPeriod) {
- m_expirationPeriod = time::milliseconds(readNonNegativeInteger(*val));
- m_hasInfiniteExpirationPeriod = false;
+ m_expirationPeriod.emplace(readNonNegativeInteger(*val));
+ ++val;
}
else {
- m_expirationPeriod = INFINITE_EXPIRATION_PERIOD;
- m_hasInfiniteExpirationPeriod = true;
+ m_expirationPeriod = nullopt;
}
}
+bool
+operator==(const Route& a, const Route& b)
+{
+ return a.getFaceId() == b.getFaceId() &&
+ a.getOrigin() == b.getOrigin() &&
+ a.getCost() == b.getCost() &&
+ a.getFlags() == b.getFlags() &&
+ a.getExpirationPeriod() == b.getExpirationPeriod();
+}
+
std::ostream&
operator<<(std::ostream& os, const Route& route)
{
os << "Route("
<< "FaceId: " << route.getFaceId() << ", "
<< "Origin: " << route.getOrigin() << ", "
- << "Cost: " << route.getCost() << ", "
- << "Flags: " << route.getFlags() << ", ";
+ << "Cost: " << route.getCost() << ", ";
- if (!route.hasInfiniteExpirationPeriod()) {
+ auto osFlags = os.flags();
+ // std::showbase doesn't work with number 0
+ os << "Flags: 0x" << std::noshowbase << std::noshowpos << std::nouppercase
+ << std::hex << route.getFlags() << ", ";
+ os.flags(osFlags);
+
+ if (route.hasExpirationPeriod()) {
os << "ExpirationPeriod: " << route.getExpirationPeriod();
}
else {
- os << "ExpirationPeriod: Infinity";
+ os << "ExpirationPeriod: infinite";
}
- os << ")";
-
- return os;
+ return os << ")";
}
////////////////////
@@ -264,12 +263,9 @@
{
size_t totalLength = 0;
- for (std::list<Route>::const_reverse_iterator it = m_routes.rbegin();
- it != m_routes.rend(); ++it)
- {
- totalLength += it->wireEncode(block);
- }
-
+ for (const auto& route : m_routes | boost::adaptors::reversed) {
+ totalLength += route.wireEncode(block);
+ }
totalLength += m_prefix.wireEncode(block);
totalLength += block.prependVarNumber(totalLength);
@@ -300,59 +296,72 @@
}
void
-RibEntry::wireDecode(const Block& wire)
+RibEntry::wireDecode(const Block& block)
{
- m_prefix.clear();
- m_routes.clear();
-
- m_wire = wire;
-
- if (m_wire.type() != tlv::nfd::RibEntry) {
- std::stringstream error;
- error << "Expected RibEntry Block, but Block is of a different type: #"
- << m_wire.type();
- BOOST_THROW_EXCEPTION(Error(error.str()));
+ if (block.type() != tlv::nfd::RibEntry) {
+ BOOST_THROW_EXCEPTION(Error("expecting RibEntry, but Block has type " + to_string(block.type())));
}
-
+ m_wire = block;
m_wire.parse();
-
Block::element_const_iterator val = m_wire.elements_begin();
- if (val != m_wire.elements_end() && val->type() == tlv::Name) {
- m_prefix.wireDecode(*val);
- ++val;
+ if (val == m_wire.elements_end()) {
+ BOOST_THROW_EXCEPTION(Error("unexpected end of RibEntry"));
}
- else {
- BOOST_THROW_EXCEPTION(Error("Missing required Name field"));
+ else if (val->type() != tlv::Name) {
+ BOOST_THROW_EXCEPTION(Error("expecting Name, but Block has type " + to_string(val->type())));
}
+ m_prefix.wireDecode(*val);
+ ++val;
+ m_routes.clear();
for (; val != m_wire.elements_end(); ++val) {
-
- if (val->type() == tlv::nfd::Route) {
- m_routes.push_back(Route(*val));
+ if (val->type() != tlv::nfd::Route) {
+ BOOST_THROW_EXCEPTION(Error("expecting Route, but Block has type " + to_string(val->type())));
}
- else {
- std::stringstream error;
- error << "Expected Route Block, but Block is of a different type: #"
- << m_wire.type();
- BOOST_THROW_EXCEPTION(Error(error.str()));
- }
+ m_routes.emplace_back(*val);
}
}
+bool
+operator==(const RibEntry& a, const RibEntry& b)
+{
+ const auto& aRoutes = a.getRoutes();
+ const auto& bRoutes = b.getRoutes();
+
+ if (a.getName() != b.getName() ||
+ aRoutes.size() != bRoutes.size())
+ return false;
+
+ std::vector<bool> matched(bRoutes.size(), false);
+ return std::all_of(aRoutes.begin(), aRoutes.end(),
+ [&] (const Route& route) {
+ for (size_t i = 0; i < bRoutes.size(); ++i) {
+ if (!matched[i] && bRoutes[i] == route) {
+ matched[i] = true;
+ return true;
+ }
+ }
+ return false;
+ });
+}
+
std::ostream&
operator<<(std::ostream& os, const RibEntry& entry)
{
- os << "RibEntry{\n"
- << " Name: " << entry.getName() << "\n";
+ os << "RibEntry(Prefix: " << entry.getName() << ",\n"
+ << " Routes: [";
- for (RibEntry::iterator it = entry.begin(); it != entry.end(); ++it) {
- os << " " << *it << "\n";
+ bool isFirst = true;
+ for (const auto& route : entry.getRoutes()) {
+ if (!isFirst)
+ os << ",\n ";
+ isFirst = false;
+ os << route;
}
+ os << "]\n";
- os << "}";
-
- return os;
+ return os << " )";
}
} // namespace nfd
diff --git a/src/mgmt/nfd/rib-entry.hpp b/src/mgmt/nfd/rib-entry.hpp
index b0d7289..0c2071d 100644
--- a/src/mgmt/nfd/rib-entry.hpp
+++ b/src/mgmt/nfd/rib-entry.hpp
@@ -23,30 +23,21 @@
#define NDN_MGMT_NFD_RIB_ENTRY_HPP
#include "rib-flags.hpp"
+#include "../../encoding/block.hpp"
#include "../../name.hpp"
#include "../../util/time.hpp"
-#include <list>
-
namespace ndn {
namespace nfd {
/**
- * @ingroup management
- *
- * @brief Data abstraction for Route
+ * \ingroup management
+ * \brief represents a route in a RibEntry
*
* A route indicates the availability of content via a certain face and
* provides meta-information about the face.
*
- * Route := ROUTE-TYPE TLV-LENGTH
- * FaceId
- * Origin
- * Cost
- * Flags
- * ExpirationPeriod?
- *
- * @sa http://redmine.named-data.net/projects/nfd/wiki/RibMgmt
+ * \sa https://redmine.named-data.net/projects/nfd/wiki/RibMgmt#Route
*/
class Route : public RibFlagsTraits<Route>
{
@@ -108,22 +99,23 @@
Route&
setFlags(uint64_t flags);
- static const time::milliseconds INFINITE_EXPIRATION_PERIOD;
+ bool
+ hasExpirationPeriod() const
+ {
+ return !!m_expirationPeriod;
+ }
time::milliseconds
getExpirationPeriod() const
{
- return m_expirationPeriod;
+ return m_expirationPeriod ? *m_expirationPeriod : time::milliseconds::max();
}
Route&
setExpirationPeriod(time::milliseconds expirationPeriod);
- bool
- hasInfiniteExpirationPeriod() const
- {
- return m_hasInfiniteExpirationPeriod;
- }
+ Route&
+ unsetExpirationPeriod();
template<encoding::Tag TAG>
size_t
@@ -133,34 +125,38 @@
wireEncode() const;
void
- wireDecode(const Block& wire);
+ wireDecode(const Block& block);
private:
uint64_t m_faceId;
uint64_t m_origin;
uint64_t m_cost;
uint64_t m_flags;
- time::milliseconds m_expirationPeriod;
- bool m_hasInfiniteExpirationPeriod;
+ optional<time::milliseconds> m_expirationPeriod;
mutable Block m_wire;
};
+bool
+operator==(const Route& a, const Route& b);
+
+inline bool
+operator!=(const Route& a, const Route& b)
+{
+ return !(a == b);
+}
+
std::ostream&
operator<<(std::ostream& os, const Route& route);
+
/**
- * @ingroup management
+ * \ingroup management
+ * \brief represents an item in NFD RIB dataset
*
- * @brief Data abstraction for RIB entry
+ * A RIB entry contains one or more routes for a name prefix
*
- * A RIB entry contains one or more routes for the name prefix
- *
- * RibEntry := RIB-ENTRY-TYPE TLV-LENGTH
- * Name
- * Route+
- *
- * @sa http://redmine.named-data.net/projects/nfd/wiki/RibMgmt
+ * \sa https://redmine.named-data.net/projects/nfd/wiki/RibMgmt#RIB-Dataset
*/
class RibEntry
{
@@ -175,9 +171,6 @@
}
};
- typedef std::list<Route> RouteList;
- typedef RouteList::const_iterator iterator;
-
RibEntry();
explicit
@@ -192,12 +185,21 @@
RibEntry&
setName(const Name& prefix);
- const std::list<Route>&
+ const std::vector<Route>&
getRoutes() const
{
return m_routes;
}
+ template<typename InputIt>
+ RibEntry&
+ setRoutes(InputIt first, InputIt last)
+ {
+ m_routes.assign(first, last);
+ m_wire.reset();
+ return *this;
+ }
+
RibEntry&
addRoute(const Route& route);
@@ -212,31 +214,22 @@
wireEncode() const;
void
- wireDecode(const Block& wire);
-
- iterator
- begin() const;
-
- iterator
- end() const;
+ wireDecode(const Block& block);
private:
Name m_prefix;
- RouteList m_routes;
+ std::vector<Route> m_routes;
mutable Block m_wire;
};
-inline RibEntry::iterator
-RibEntry::begin() const
-{
- return m_routes.begin();
-}
+bool
+operator==(const RibEntry& a, const RibEntry& b);
-inline RibEntry::iterator
-RibEntry::end() const
+inline bool
+operator!=(const RibEntry& a, const RibEntry& b)
{
- return m_routes.end();
+ return !(a == b);
}
std::ostream&
diff --git a/src/mgmt/nfd/rib-flags.hpp b/src/mgmt/nfd/rib-flags.hpp
index 158048f..ebc2b9e 100644
--- a/src/mgmt/nfd/rib-flags.hpp
+++ b/src/mgmt/nfd/rib-flags.hpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2013-2016 Regents of the University of California.
+ * Copyright (c) 2013-2017 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -29,10 +29,10 @@
/**
* \ingroup management
- * \brief implements getters to each RIB flag
+ * \brief defines getters for each route inheritance flag
*
- * \tparam T class containing a RibFlags field and implements
- * `RibFlags getFlags() const` method
+ * \tparam T class containing a RouteFlags field and implementing
+ * a `RouteFlags getFlags() const` member function
*/
template<typename T>
class RibFlagsTraits
@@ -49,6 +49,9 @@
{
return static_cast<const T*>(this)->getFlags() & ROUTE_FLAG_CAPTURE;
}
+
+protected:
+ RibFlagsTraits() = default;
};
} // namespace nfd
diff --git a/tests/unit-tests/mgmt/nfd/rib-entry.t.cpp b/tests/unit-tests/mgmt/nfd/rib-entry.t.cpp
index 415be29..cc3ed58 100644
--- a/tests/unit-tests/mgmt/nfd/rib-entry.t.cpp
+++ b/tests/unit-tests/mgmt/nfd/rib-entry.t.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2013-2016 Regents of the University of California.
+ * Copyright (c) 2013-2017 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -20,9 +20,9 @@
*/
#include "mgmt/nfd/rib-entry.hpp"
-#include "mgmt/nfd/control-command.hpp"
#include "boost-test.hpp"
+#include <boost/lexical_cast.hpp>
namespace ndn {
namespace nfd {
@@ -32,310 +32,182 @@
BOOST_AUTO_TEST_SUITE(Nfd)
BOOST_AUTO_TEST_SUITE(TestRibEntry)
-const uint8_t RouteData[] =
+static Route
+makeRoute()
{
- 0x81, 0x10, 0x69, 0x01, 0x01, 0x6f, 0x01, 0x80, 0x6a, 0x01, 0x64, 0x6c, 0x01, 0x02,
- 0x6d, 0x02, 0x27, 0x10
-};
+ return Route()
+ .setFaceId(1)
+ .setOrigin(128)
+ .setCost(100)
+ .setFlags(ndn::nfd::ROUTE_FLAG_CAPTURE);
+}
-const uint8_t RouteInfiniteExpirationPeriod[] =
+static RibEntry
+makeRibEntry()
{
- 0x81, 0x0C, 0x69, 0x01, 0x01, 0x6f, 0x01, 0x80, 0x6a, 0x01, 0x64, 0x6c, 0x01, 0x02
-};
-
-const uint8_t RibEntryData[] =
-{
- // Header + Name
- 0x80, 0x34, 0x07, 0x0e, 0x08, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f,
- 0x08, 0x05, 0x77, 0x6f, 0x72, 0x6c, 0x64,
- // Route
- 0x81, 0x10, 0x69, 0x01, 0x01, 0x6f, 0x01, 0x80, 0x6a, 0x01, 0x64, 0x6c, 0x01, 0x02,
- 0x6d, 0x02, 0x27, 0x10,
- // Route
- 0x81, 0x10, 0x69, 0x01, 0x02, 0x6f, 0x01, 0x00, 0x6a, 0x01, 0x20, 0x6c, 0x01, 0x01,
- 0x6d, 0x02, 0x13, 0x88
-};
-
-const uint8_t RibEntryInfiniteExpirationPeriod[] =
-{
- // Header + Name
- 0x80, 0x30, 0x07, 0x0e, 0x08, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f,
- 0x08, 0x05, 0x77, 0x6f, 0x72, 0x6c, 0x64,
- // Route
- 0x81, 0x10, 0x69, 0x01, 0x01, 0x6f, 0x01, 0x80, 0x6a, 0x01, 0x64, 0x6c, 0x01, 0x02,
- 0x6d, 0x02, 0x27, 0x10,
- // Route with no ExpirationPeriod
- 0x81, 0x0C, 0x69, 0x01, 0x02, 0x6f, 0x01, 0x00, 0x6a, 0x01, 0x20, 0x6c, 0x01, 0x01,
-};
+ return RibEntry()
+ .setName("/hello/world")
+ .addRoute(makeRoute()
+ .setExpirationPeriod(time::seconds(10)));
+}
BOOST_AUTO_TEST_CASE(RouteEncode)
{
- Route route;
- route.setFaceId(1);
- route.setOrigin(128);
- route.setCost(100);
- route.setFlags(ndn::nfd::ROUTE_FLAG_CAPTURE);
- route.setExpirationPeriod(time::milliseconds(10000));
+ Route route1 = makeRoute();
+ route1.setExpirationPeriod(time::seconds(10));
+ const Block& wire = route1.wireEncode();
- const Block& wire = route.wireEncode();
+ static const uint8_t expected[] = {
+ 0x81, 0x10, 0x69, 0x01, 0x01, 0x6f, 0x01, 0x80, 0x6a, 0x01, 0x64, 0x6c, 0x01, 0x02,
+ 0x6d, 0x02, 0x27, 0x10
+ };
+ BOOST_CHECK_EQUAL_COLLECTIONS(expected, expected + sizeof(expected),
+ wire.begin(), wire.end());
- BOOST_REQUIRE_EQUAL_COLLECTIONS(RouteData,
- RouteData + sizeof(RouteData),
- wire.begin(), wire.end());
+ Route route2(wire);
+ BOOST_CHECK_EQUAL(route1, route2);
}
-BOOST_AUTO_TEST_CASE(RouteDecode)
+BOOST_AUTO_TEST_CASE(RouteNoExpirationPeriodEncode)
{
- Route route;
+ Route route1 = makeRoute();
+ const Block& wire = route1.wireEncode();
- BOOST_REQUIRE_NO_THROW(route.wireDecode(Block(RouteData, sizeof(RouteData))));
+ static const uint8_t expected[] = {
+ 0x81, 0x0C, 0x69, 0x01, 0x01, 0x6f, 0x01, 0x80, 0x6a, 0x01, 0x64, 0x6c, 0x01, 0x02
+ };
+ BOOST_CHECK_EQUAL_COLLECTIONS(expected, expected + sizeof(expected),
+ wire.begin(), wire.end());
- BOOST_REQUIRE_EQUAL(route.getFaceId(), 1);
- BOOST_REQUIRE_EQUAL(route.getOrigin(), 128);
- BOOST_REQUIRE_EQUAL(route.getCost(), 100);
- BOOST_REQUIRE_EQUAL(route.getFlags(), static_cast<uint64_t>(ndn::nfd::ROUTE_FLAG_CAPTURE));
- BOOST_REQUIRE_EQUAL(route.getExpirationPeriod(), time::milliseconds(10000));
- BOOST_REQUIRE_EQUAL(route.hasInfiniteExpirationPeriod(), false);
+ Route route2(wire);
+ BOOST_CHECK_EQUAL(route1, route2);
}
-BOOST_AUTO_TEST_CASE(RouteInfiniteExpirationPeriodEncode)
+BOOST_AUTO_TEST_CASE(RouteEquality)
{
- Route route;
- route.setFaceId(1);
- route.setOrigin(128);
- route.setCost(100);
- route.setFlags(ndn::nfd::ROUTE_FLAG_CAPTURE);
- route.setExpirationPeriod(Route::INFINITE_EXPIRATION_PERIOD);
+ Route route1, route2;
- const Block& wire = route.wireEncode();
+ route1 = makeRoute();
+ route2 = route1;
+ BOOST_CHECK_EQUAL(route1, route2);
- BOOST_REQUIRE_EQUAL_COLLECTIONS(RouteInfiniteExpirationPeriod,
- RouteInfiniteExpirationPeriod + sizeof(RouteInfiniteExpirationPeriod),
- wire.begin(), wire.end());
-}
+ route2.setFaceId(42);
+ BOOST_CHECK_NE(route1, route2);
-BOOST_AUTO_TEST_CASE(RouteInfiniteExpirationPeriodDecode)
-{
- Route route;
-
- BOOST_REQUIRE_NO_THROW(route.wireDecode(Block(RouteInfiniteExpirationPeriod,
- sizeof(RouteInfiniteExpirationPeriod))));
-
- BOOST_REQUIRE_EQUAL(route.getFaceId(), 1);
- BOOST_REQUIRE_EQUAL(route.getOrigin(), 128);
- BOOST_REQUIRE_EQUAL(route.getCost(), 100);
- BOOST_REQUIRE_EQUAL(route.getFlags(), static_cast<uint64_t>(ndn::nfd::ROUTE_FLAG_CAPTURE));
- BOOST_REQUIRE_EQUAL(route.getExpirationPeriod(), Route::INFINITE_EXPIRATION_PERIOD);
- BOOST_REQUIRE_EQUAL(route.hasInfiniteExpirationPeriod(), true);
-}
-
-BOOST_AUTO_TEST_CASE(RouteOutputStream)
-{
- Route route;
- route.setFaceId(1);
- route.setOrigin(128);
- route.setCost(100);
- route.setFlags(ndn::nfd::ROUTE_FLAG_CAPTURE);
- route.setExpirationPeriod(time::milliseconds(10000));
-
- std::ostringstream os;
- os << route;
-
- BOOST_CHECK_EQUAL(os.str(), "Route(FaceId: 1, Origin: 128, Cost: 100, "
- "Flags: 2, ExpirationPeriod: 10000 milliseconds)");
+ route2 = route1;
+ route2.setExpirationPeriod(time::minutes(1));
+ BOOST_CHECK_NE(route1, route2);
}
BOOST_AUTO_TEST_CASE(RibEntryEncode)
{
- RibEntry entry;
- entry.setName("/hello/world");
+ RibEntry entry1 = makeRibEntry();
+ entry1.addRoute(Route()
+ .setFaceId(2)
+ .setOrigin(0)
+ .setCost(32)
+ .setFlags(ndn::nfd::ROUTE_FLAG_CHILD_INHERIT)
+ .setExpirationPeriod(time::seconds(5)));
+ const Block& wire = entry1.wireEncode();
- Route route1;
- route1.setFaceId(1);
- route1.setOrigin(128);
- route1.setCost(100);
- route1.setFlags(ndn::nfd::ROUTE_FLAG_CAPTURE);
- route1.setExpirationPeriod(time::milliseconds(10000));
- entry.addRoute(route1);
-
- Route route2;
- route2.setFaceId(2);
- route2.setOrigin(0);
- route2.setCost(32);
- route2.setFlags(ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
- route2.setExpirationPeriod(time::milliseconds(5000));
- entry.addRoute(route2);
-
- const Block& wire = entry.wireEncode();
-
- BOOST_CHECK_EQUAL_COLLECTIONS(RibEntryData,
- RibEntryData + sizeof(RibEntryData),
+ static const uint8_t expected[] = {
+ 0x80, 0x34, 0x07, 0x0e, 0x08, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x08, 0x05, 0x77,
+ 0x6f, 0x72, 0x6c, 0x64, 0x81, 0x10, 0x69, 0x01, 0x01, 0x6f, 0x01, 0x80, 0x6a, 0x01,
+ 0x64, 0x6c, 0x01, 0x02, 0x6d, 0x02, 0x27, 0x10, 0x81, 0x10, 0x69, 0x01, 0x02, 0x6f,
+ 0x01, 0x00, 0x6a, 0x01, 0x20, 0x6c, 0x01, 0x01, 0x6d, 0x02, 0x13, 0x88
+ };
+ BOOST_CHECK_EQUAL_COLLECTIONS(expected, expected + sizeof(expected),
wire.begin(), wire.end());
+
+ RibEntry entry2(wire);
+ BOOST_CHECK_EQUAL(entry1, entry2);
}
-BOOST_AUTO_TEST_CASE(RibEntryDecode)
-{
- RibEntry entry;
- BOOST_REQUIRE_NO_THROW(entry.wireDecode(Block(RibEntryData,
- sizeof(RibEntryData))));
-
- BOOST_CHECK_EQUAL(entry.getName(), "/hello/world");
- BOOST_CHECK_EQUAL(entry.getRoutes().size(), 2);
-
- std::list<Route> routes = entry.getRoutes();
-
- std::list<Route>::const_iterator it = routes.begin();
- BOOST_CHECK_EQUAL(it->getFaceId(), 1);
- BOOST_CHECK_EQUAL(it->getOrigin(), 128);
- BOOST_CHECK_EQUAL(it->getCost(), 100);
- BOOST_CHECK_EQUAL(it->getFlags(), static_cast<uint64_t>(ndn::nfd::ROUTE_FLAG_CAPTURE));
- BOOST_CHECK_EQUAL(it->getExpirationPeriod(), time::milliseconds(10000));
- BOOST_CHECK_EQUAL(it->hasInfiniteExpirationPeriod(), false);
-
- ++it;
- BOOST_CHECK_EQUAL(it->getFaceId(), 2);
- BOOST_CHECK_EQUAL(it->getOrigin(), 0);
- BOOST_CHECK_EQUAL(it->getCost(), 32);
- BOOST_CHECK_EQUAL(it->getFlags(), static_cast<uint64_t>(ndn::nfd::ROUTE_FLAG_CHILD_INHERIT));
- BOOST_CHECK_EQUAL(it->getExpirationPeriod(), time::milliseconds(5000));
- BOOST_CHECK_EQUAL(it->hasInfiniteExpirationPeriod(), false);
-}
-
-BOOST_AUTO_TEST_CASE(RibEntryInfiniteExpirationPeriodEncode)
+BOOST_AUTO_TEST_CASE(RibEntryClearRoutes)
{
RibEntry entry;
entry.setName("/hello/world");
+ BOOST_CHECK_EQUAL(entry.getRoutes().size(), 0);
Route route1;
- route1.setFaceId(1);
- route1.setOrigin(128);
- route1.setCost(100);
- route1.setFlags(ndn::nfd::ROUTE_FLAG_CAPTURE);
- route1.setExpirationPeriod(time::milliseconds(10000));
- entry.addRoute(route1);
-
- Route route2;
- route2.setFaceId(2);
- route2.setOrigin(0);
- route2.setCost(32);
- route2.setFlags(ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
- route2.setExpirationPeriod(Route::INFINITE_EXPIRATION_PERIOD);
- entry.addRoute(route2);
-
- const Block& wire = entry.wireEncode();
-
- BOOST_CHECK_EQUAL_COLLECTIONS(RibEntryInfiniteExpirationPeriod,
- RibEntryInfiniteExpirationPeriod +
- sizeof(RibEntryInfiniteExpirationPeriod),
- wire.begin(), wire.end());
-}
-
-BOOST_AUTO_TEST_CASE(RibEntryInfiniteExpirationPeriodDecode)
-{
- RibEntry entry;
- BOOST_REQUIRE_NO_THROW(entry.wireDecode(Block(RibEntryInfiniteExpirationPeriod,
- sizeof(RibEntryInfiniteExpirationPeriod))));
-
- BOOST_CHECK_EQUAL(entry.getName(), "/hello/world");
- BOOST_CHECK_EQUAL(entry.getRoutes().size(), 2);
-
- std::list<Route> routes = entry.getRoutes();
-
- std::list<Route>::const_iterator it = routes.begin();
- BOOST_CHECK_EQUAL(it->getFaceId(), 1);
- BOOST_CHECK_EQUAL(it->getOrigin(), 128);
- BOOST_CHECK_EQUAL(it->getCost(), 100);
- BOOST_CHECK_EQUAL(it->getFlags(), static_cast<uint64_t>(ndn::nfd::ROUTE_FLAG_CAPTURE));
- BOOST_CHECK_EQUAL(it->getExpirationPeriod(), time::milliseconds(10000));
- BOOST_CHECK_EQUAL(it->hasInfiniteExpirationPeriod(), false);
-
- ++it;
- BOOST_CHECK_EQUAL(it->getFaceId(), 2);
- BOOST_CHECK_EQUAL(it->getOrigin(), 0);
- BOOST_CHECK_EQUAL(it->getCost(), 32);
- BOOST_CHECK_EQUAL(it->getFlags(), static_cast<uint64_t>(ndn::nfd::ROUTE_FLAG_CHILD_INHERIT));
- BOOST_CHECK_EQUAL(it->getExpirationPeriod(), Route::INFINITE_EXPIRATION_PERIOD);
- BOOST_CHECK_EQUAL(it->hasInfiniteExpirationPeriod(), true);
-}
-
-BOOST_AUTO_TEST_CASE(RibEntryClear)
-{
- RibEntry entry;
- entry.setName("/hello/world");
-
- Route route1;
- route1.setFaceId(1);
- route1.setOrigin(128);
- route1.setCost(100);
- route1.setFlags(ndn::nfd::ROUTE_FLAG_CAPTURE);
- route1.setExpirationPeriod(time::milliseconds(10000));
+ route1.setFaceId(42);
entry.addRoute(route1);
BOOST_REQUIRE_EQUAL(entry.getRoutes().size(), 1);
-
- std::list<Route> routes = entry.getRoutes();
-
- std::list<Route>::const_iterator it = routes.begin();
- BOOST_CHECK_EQUAL(it->getFaceId(), 1);
- BOOST_CHECK_EQUAL(it->getOrigin(), 128);
- BOOST_CHECK_EQUAL(it->getCost(), 100);
- BOOST_CHECK_EQUAL(it->getFlags(), static_cast<uint64_t>(ndn::nfd::ROUTE_FLAG_CAPTURE));
- BOOST_CHECK_EQUAL(it->getExpirationPeriod(), time::milliseconds(10000));
- BOOST_CHECK_EQUAL(it->hasInfiniteExpirationPeriod(), false);
+ BOOST_CHECK_EQUAL(entry.getRoutes().front(), route1);
entry.clearRoutes();
BOOST_CHECK_EQUAL(entry.getRoutes().size(), 0);
-
- Route route2;
- route2.setFaceId(2);
- route2.setOrigin(0);
- route2.setCost(32);
- route2.setFlags(ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
- route2.setExpirationPeriod(Route::INFINITE_EXPIRATION_PERIOD);
- entry.addRoute(route2);
- BOOST_REQUIRE_EQUAL(entry.getRoutes().size(), 1);
-
- routes = entry.getRoutes();
-
- it = routes.begin();
- BOOST_CHECK_EQUAL(it->getFaceId(), 2);
- BOOST_CHECK_EQUAL(it->getOrigin(), 0);
- BOOST_CHECK_EQUAL(it->getCost(), 32);
- BOOST_CHECK_EQUAL(it->getFlags(), static_cast<uint64_t>(ndn::nfd::ROUTE_FLAG_CHILD_INHERIT));
- BOOST_CHECK_EQUAL(it->getExpirationPeriod(), Route::INFINITE_EXPIRATION_PERIOD);
- BOOST_CHECK_EQUAL(it->hasInfiniteExpirationPeriod(), true);
}
-BOOST_AUTO_TEST_CASE(RibEntryOutputStream)
+BOOST_AUTO_TEST_CASE(RibEntryEquality)
{
+ RibEntry entry1, entry2;
+ BOOST_CHECK_EQUAL(entry1, entry2);
+
+ entry1 = entry2 = makeRibEntry();
+ BOOST_CHECK_EQUAL(entry1, entry2);
+ BOOST_CHECK_EQUAL(entry2, entry1);
+
+ entry2.setName("/different/name");
+ BOOST_CHECK_NE(entry1, entry2);
+
+ entry2 = entry1;
+ std::vector<Route> empty;
+ entry2.setRoutes(empty.begin(), empty.end());
+ BOOST_CHECK_NE(entry1, entry2);
+ BOOST_CHECK_NE(entry2, entry1);
+
+ entry2 = entry1;
+ auto r1 = Route()
+ .setFaceId(1)
+ .setCost(1000);
+ entry1.addRoute(r1);
+ BOOST_CHECK_NE(entry1, entry2);
+ BOOST_CHECK_NE(entry2, entry1);
+
+ auto r42 = Route()
+ .setFaceId(42)
+ .setCost(42);
+ entry1.addRoute(r42);
+ entry2.addRoute(r42)
+ .addRoute(r1);
+ BOOST_CHECK_EQUAL(entry1, entry2); // order of Routes is irrelevant
+ BOOST_CHECK_EQUAL(entry2, entry1);
+
+ entry1 = entry2 = makeRibEntry();
+ entry1.addRoute(r1)
+ .addRoute(r42);
+ entry2.addRoute(r42)
+ .addRoute(r42);
+ BOOST_CHECK_NE(entry1, entry2); // match each Route at most once
+ BOOST_CHECK_NE(entry2, entry1);
+}
+
+BOOST_AUTO_TEST_CASE(Print)
+{
+ Route route;
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(route),
+ "Route(FaceId: 0, Origin: 0, Cost: 0, Flags: 0x1, ExpirationPeriod: infinite)");
+
RibEntry entry;
- entry.setName("/hello/world");
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(entry),
+ "RibEntry(Prefix: /,\n"
+ " Routes: []\n"
+ " )");
- Route route1;
- route1.setFaceId(1);
- route1.setOrigin(128);
- route1.setCost(100);
- route1.setFlags(ndn::nfd::ROUTE_FLAG_CAPTURE);
- route1.setExpirationPeriod(time::milliseconds(10000));
- entry.addRoute(route1);
-
- Route route2;
- route2.setFaceId(2);
- route2.setOrigin(0);
- route2.setCost(32);
- route2.setFlags(ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);
- route2.setExpirationPeriod(Route::INFINITE_EXPIRATION_PERIOD);
- entry.addRoute(route2);
-
- std::ostringstream os;
- os << entry;
-
- BOOST_CHECK_EQUAL(os.str(), "RibEntry{\n"
- " Name: /hello/world\n"
- " Route(FaceId: 1, Origin: 128, Cost: 100, "
- "Flags: 2, ExpirationPeriod: 10000 milliseconds)\n"
- " Route(FaceId: 2, Origin: 0, Cost: 32, "
- "Flags: 1, ExpirationPeriod: Infinity)\n"
- "}");
+ entry = makeRibEntry();
+ entry.addRoute(Route()
+ .setFaceId(2)
+ .setOrigin(0)
+ .setCost(32)
+ .setFlags(ndn::nfd::ROUTE_FLAG_CHILD_INHERIT));
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(entry),
+ "RibEntry(Prefix: /hello/world,\n"
+ " Routes: [Route(FaceId: 1, Origin: 128, Cost: 100, Flags: 0x2, "
+ "ExpirationPeriod: 10000 milliseconds),\n"
+ " Route(FaceId: 2, Origin: 0, Cost: 32, Flags: 0x1, "
+ "ExpirationPeriod: infinite)]\n"
+ " )");
}
BOOST_AUTO_TEST_SUITE_END() // TestRibEntry