blob: cfe423223a23df300d9861e38dc67a1359856aa8 [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"
32
33#include "tests/test-common.hpp"
34#include "../face/dummy-face.hpp"
35
36#include <ndn-cpp-dev/encoding/tlv.hpp>
37
38namespace nfd {
39namespace tests {
40
41static inline uint64_t
42readNonNegativeIntegerType(const Block& block,
43 uint32_t type)
44{
45 if (block.type() == type)
46 {
47 return readNonNegativeInteger(block);
48 }
49 std::stringstream error;
50 error << "Expected type " << type << " got " << block.type();
51 throw ndn::Tlv::Error(error.str());
52}
53
54static inline uint64_t
55checkedReadNonNegativeIntegerType(Block::element_const_iterator& i,
56 Block::element_const_iterator end,
57 uint32_t type)
58{
59 if (i != end)
60 {
61 const Block& block = *i;
62 ++i;
63 return readNonNegativeIntegerType(block, type);
64 }
65 std::stringstream error;
66 error << "Unexpected end of Block while attempting to read type #"
67 << type;
68 throw ndn::Tlv::Error(error.str());
69}
70
71class FibEnumerationPublisherFixture : public BaseFixture
72{
73public:
74
75 FibEnumerationPublisherFixture()
76 : m_nameTree(1024)
77 , m_fib(m_nameTree)
78 , m_face(make_shared<InternalFace>())
79 , m_publisher(m_fib, m_face, "/localhost/nfd/FibEnumerationPublisherFixture")
80 , m_finished(false)
81 {
82
83 }
84
85 virtual
86 ~FibEnumerationPublisherFixture()
87 {
88
89 }
90
91 bool
92 hasNextHopWithCost(const fib::NextHopList& nextHops,
93 FaceId faceId,
94 uint64_t cost)
95 {
96 for (fib::NextHopList::const_iterator i = nextHops.begin();
97 i != nextHops.end();
98 ++i)
99 {
100 if (i->getFace()->getId() == faceId && i->getCost() == cost)
101 {
102 return true;
103 }
104 }
105 return false;
106 }
107
108 bool
109 entryHasPrefix(const shared_ptr<fib::Entry> entry, const Name& prefix)
110 {
111 return entry->getPrefix() == prefix;
112 }
113
114 void
115 validateFibEntry(const Block& entry)
116 {
117 entry.parse();
118
119 Block::element_const_iterator i = entry.elements_begin();
120 BOOST_REQUIRE(i != entry.elements_end());
121
122
123 BOOST_REQUIRE(i->type() == ndn::Tlv::Name);
124 Name prefix(*i);
125 ++i;
126
127 std::set<shared_ptr<fib::Entry> >::const_iterator referenceIter =
128 std::find_if(m_referenceEntries.begin(), m_referenceEntries.end(),
129 boost::bind(&FibEnumerationPublisherFixture::entryHasPrefix,
130 this, _1, prefix));
131
132 BOOST_REQUIRE(referenceIter != m_referenceEntries.end());
133
134 const shared_ptr<fib::Entry>& reference = *referenceIter;
135 BOOST_REQUIRE_EQUAL(prefix, reference->getPrefix());
136
137 // 0 or more next hop records
138 size_t nRecords = 0;
139 const fib::NextHopList& referenceNextHops = reference->getNextHops();
140 for (; i != entry.elements_end(); ++i)
141 {
142 const ndn::Block& nextHopRecord = *i;
143 BOOST_REQUIRE(nextHopRecord.type() == ndn::tlv::nfd::NextHopRecord);
144 nextHopRecord.parse();
145
146 Block::element_const_iterator j = nextHopRecord.elements_begin();
147
148 FaceId faceId =
149 checkedReadNonNegativeIntegerType(j,
150 entry.elements_end(),
151 ndn::tlv::nfd::FaceId);
152
153 uint64_t cost =
154 checkedReadNonNegativeIntegerType(j,
155 entry.elements_end(),
156 ndn::tlv::nfd::Cost);
157
158 BOOST_REQUIRE(hasNextHopWithCost(referenceNextHops, faceId, cost));
159
160 BOOST_REQUIRE(j == nextHopRecord.elements_end());
161 nRecords++;
162 }
163 BOOST_REQUIRE_EQUAL(nRecords, referenceNextHops.size());
164
165 BOOST_REQUIRE(i == entry.elements_end());
166 m_referenceEntries.erase(referenceIter);
167 }
168
169 void
170 decodeFibEntryBlock(const Data& data)
171 {
172 Block payload = data.getContent();
173
174 m_buffer.appendByteArray(payload.value(), payload.value_size());
175
Alexander Afanasyevefea8fe2014-03-23 00:00:35 -0700176 BOOST_CHECK_NO_THROW(data.getName()[-1].toSegment());
Steve DiBenedetto6214e562014-03-15 16:27:04 -0600177 if (data.getFinalBlockId() != data.getName()[-1])
178 {
179 return;
180 }
181
182 // wrap the FIB Entry blocks in a single Content TLV for easy parsing
183 m_buffer.prependVarNumber(m_buffer.size());
184 m_buffer.prependVarNumber(ndn::Tlv::Content);
185
186 ndn::Block parser(m_buffer.buf(), m_buffer.size());
187 parser.parse();
188
189 BOOST_REQUIRE_EQUAL(parser.elements_size(), m_referenceEntries.size());
190
191 for (Block::element_const_iterator i = parser.elements_begin();
192 i != parser.elements_end();
193 ++i)
194 {
195 if (i->type() != ndn::tlv::nfd::FibEntry)
196 {
197 BOOST_FAIL("expected fib entry, got type #" << i->type());
198 }
199
200 validateFibEntry(*i);
201 }
202 m_finished = true;
203 }
204
205protected:
206 NameTree m_nameTree;
207 Fib m_fib;
208 shared_ptr<InternalFace> m_face;
209 FibEnumerationPublisher m_publisher;
210 ndn::EncodingBuffer m_buffer;
211 std::set<shared_ptr<fib::Entry> > m_referenceEntries;
212
213protected:
214 bool m_finished;
215};
216
217} // namespace tests
218} // namespace nfd
219
220#endif // NFD_TESTS_MGMT_FIB_ENUMERATION_PUBLISHER_COMMON_HPP