blob: 7507c5de3b9f68ab03fba4e72c5a2aa5d25b3d6d [file] [log] [blame]
Steve DiBenedetto6214e562014-03-15 16:27:04 -06001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -07003 * Copyright (c) 2014 Regents of the University of California,
4 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology
9 *
10 * This file is part of NFD (Named Data Networking Forwarding Daemon).
11 * See AUTHORS.md for complete list of NFD authors and contributors.
12 *
13 * NFD is free software: you can redistribute it and/or modify it under the terms
14 * of the GNU General Public License as published by the Free Software Foundation,
15 * either version 3 of the License, or (at your option) any later version.
16 *
17 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
18 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
19 * PURPOSE. See the GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along with
22 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
23 **/
Steve DiBenedetto6214e562014-03-15 16:27:04 -060024
25#ifndef NFD_TESTS_MGMT_FIB_ENUMERATION_PUBLISHER_COMMON_HPP
26#define NFD_TESTS_MGMT_FIB_ENUMERATION_PUBLISHER_COMMON_HPP
27
28#include "mgmt/fib-enumeration-publisher.hpp"
29
30#include "mgmt/app-face.hpp"
31#include "mgmt/internal-face.hpp"
Davide Pesavento52a18f92014-04-10 00:55:01 +020032#include "table/fib.hpp"
33#include "table/name-tree.hpp"
Steve DiBenedetto6214e562014-03-15 16:27:04 -060034
35#include "tests/test-common.hpp"
36#include "../face/dummy-face.hpp"
37
38#include <ndn-cpp-dev/encoding/tlv.hpp>
39
40namespace nfd {
41namespace tests {
42
43static inline uint64_t
44readNonNegativeIntegerType(const Block& block,
45 uint32_t type)
46{
47 if (block.type() == type)
48 {
49 return readNonNegativeInteger(block);
50 }
51 std::stringstream error;
52 error << "Expected type " << type << " got " << block.type();
53 throw ndn::Tlv::Error(error.str());
54}
55
56static inline uint64_t
57checkedReadNonNegativeIntegerType(Block::element_const_iterator& i,
58 Block::element_const_iterator end,
59 uint32_t type)
60{
61 if (i != end)
62 {
63 const Block& block = *i;
64 ++i;
65 return readNonNegativeIntegerType(block, type);
66 }
67 std::stringstream error;
68 error << "Unexpected end of Block while attempting to read type #"
69 << type;
70 throw ndn::Tlv::Error(error.str());
71}
72
73class FibEnumerationPublisherFixture : public BaseFixture
74{
75public:
76
77 FibEnumerationPublisherFixture()
Haowei Yuanf52dac72014-03-24 23:35:03 -050078 : m_fib(m_nameTree)
Steve DiBenedetto6214e562014-03-15 16:27:04 -060079 , m_face(make_shared<InternalFace>())
80 , m_publisher(m_fib, m_face, "/localhost/nfd/FibEnumerationPublisherFixture")
81 , m_finished(false)
82 {
Steve DiBenedetto6214e562014-03-15 16:27:04 -060083 }
84
85 virtual
86 ~FibEnumerationPublisherFixture()
87 {
Steve DiBenedetto6214e562014-03-15 16:27:04 -060088 }
89
90 bool
91 hasNextHopWithCost(const fib::NextHopList& nextHops,
92 FaceId faceId,
93 uint64_t cost)
94 {
95 for (fib::NextHopList::const_iterator i = nextHops.begin();
96 i != nextHops.end();
97 ++i)
98 {
99 if (i->getFace()->getId() == faceId && i->getCost() == cost)
100 {
101 return true;
102 }
103 }
104 return false;
105 }
106
107 bool
108 entryHasPrefix(const shared_ptr<fib::Entry> entry, const Name& prefix)
109 {
110 return entry->getPrefix() == prefix;
111 }
112
113 void
114 validateFibEntry(const Block& entry)
115 {
116 entry.parse();
117
118 Block::element_const_iterator i = entry.elements_begin();
119 BOOST_REQUIRE(i != entry.elements_end());
120
121
122 BOOST_REQUIRE(i->type() == ndn::Tlv::Name);
123 Name prefix(*i);
124 ++i;
125
126 std::set<shared_ptr<fib::Entry> >::const_iterator referenceIter =
127 std::find_if(m_referenceEntries.begin(), m_referenceEntries.end(),
128 boost::bind(&FibEnumerationPublisherFixture::entryHasPrefix,
129 this, _1, prefix));
130
131 BOOST_REQUIRE(referenceIter != m_referenceEntries.end());
132
133 const shared_ptr<fib::Entry>& reference = *referenceIter;
134 BOOST_REQUIRE_EQUAL(prefix, reference->getPrefix());
135
136 // 0 or more next hop records
137 size_t nRecords = 0;
138 const fib::NextHopList& referenceNextHops = reference->getNextHops();
139 for (; i != entry.elements_end(); ++i)
140 {
141 const ndn::Block& nextHopRecord = *i;
142 BOOST_REQUIRE(nextHopRecord.type() == ndn::tlv::nfd::NextHopRecord);
143 nextHopRecord.parse();
144
145 Block::element_const_iterator j = nextHopRecord.elements_begin();
146
147 FaceId faceId =
148 checkedReadNonNegativeIntegerType(j,
149 entry.elements_end(),
150 ndn::tlv::nfd::FaceId);
151
152 uint64_t cost =
153 checkedReadNonNegativeIntegerType(j,
154 entry.elements_end(),
155 ndn::tlv::nfd::Cost);
156
157 BOOST_REQUIRE(hasNextHopWithCost(referenceNextHops, faceId, cost));
158
159 BOOST_REQUIRE(j == nextHopRecord.elements_end());
160 nRecords++;
161 }
162 BOOST_REQUIRE_EQUAL(nRecords, referenceNextHops.size());
163
164 BOOST_REQUIRE(i == entry.elements_end());
165 m_referenceEntries.erase(referenceIter);
166 }
167
168 void
169 decodeFibEntryBlock(const Data& data)
170 {
171 Block payload = data.getContent();
172
173 m_buffer.appendByteArray(payload.value(), payload.value_size());
174
Alexander Afanasyevefea8fe2014-03-23 00:00:35 -0700175 BOOST_CHECK_NO_THROW(data.getName()[-1].toSegment());
Steve DiBenedetto6214e562014-03-15 16:27:04 -0600176 if (data.getFinalBlockId() != data.getName()[-1])
177 {
178 return;
179 }
180
181 // wrap the FIB Entry blocks in a single Content TLV for easy parsing
182 m_buffer.prependVarNumber(m_buffer.size());
183 m_buffer.prependVarNumber(ndn::Tlv::Content);
184
185 ndn::Block parser(m_buffer.buf(), m_buffer.size());
186 parser.parse();
187
188 BOOST_REQUIRE_EQUAL(parser.elements_size(), m_referenceEntries.size());
189
190 for (Block::element_const_iterator i = parser.elements_begin();
191 i != parser.elements_end();
192 ++i)
193 {
194 if (i->type() != ndn::tlv::nfd::FibEntry)
195 {
196 BOOST_FAIL("expected fib entry, got type #" << i->type());
197 }
198
199 validateFibEntry(*i);
200 }
201 m_finished = true;
202 }
203
204protected:
205 NameTree m_nameTree;
206 Fib m_fib;
207 shared_ptr<InternalFace> m_face;
208 FibEnumerationPublisher m_publisher;
209 ndn::EncodingBuffer m_buffer;
210 std::set<shared_ptr<fib::Entry> > m_referenceEntries;
211
212protected:
213 bool m_finished;
214};
215
216} // namespace tests
217} // namespace nfd
218
219#endif // NFD_TESTS_MGMT_FIB_ENUMERATION_PUBLISHER_COMMON_HPP