blob: 9f9150bc80e92606990944b16271c7229b86933a [file] [log] [blame]
Steve DiBenedetto6214e562014-03-15 16:27:04 -06001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Vince Lehman5144f822014-07-23 15:12:56 -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 * The University of Memphis
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -070010 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Vince Lehman5144f822014-07-23 15:12:56 -070024 */
Steve DiBenedetto6214e562014-03-15 16:27:04 -060025
Alexander Afanasyev613e2a92014-04-15 13:36:58 -070026#ifndef NFD_TESTS_NFD_MGMT_FIB_ENUMERATION_PUBLISHER_COMMON_HPP
27#define NFD_TESTS_NFD_MGMT_FIB_ENUMERATION_PUBLISHER_COMMON_HPP
Steve DiBenedetto6214e562014-03-15 16:27:04 -060028
29#include "mgmt/fib-enumeration-publisher.hpp"
30
31#include "mgmt/app-face.hpp"
32#include "mgmt/internal-face.hpp"
Davide Pesavento52a18f92014-04-10 00:55:01 +020033#include "table/fib.hpp"
34#include "table/name-tree.hpp"
Steve DiBenedetto6214e562014-03-15 16:27:04 -060035
36#include "tests/test-common.hpp"
37#include "../face/dummy-face.hpp"
38
Alexander Afanasyev4a771362014-04-24 21:29:33 -070039#include <ndn-cxx/encoding/tlv.hpp>
Steve DiBenedetto6214e562014-03-15 16:27:04 -060040
41namespace nfd {
42namespace tests {
43
44static inline uint64_t
45readNonNegativeIntegerType(const Block& block,
46 uint32_t type)
47{
48 if (block.type() == type)
49 {
50 return readNonNegativeInteger(block);
51 }
52 std::stringstream error;
53 error << "Expected type " << type << " got " << block.type();
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -070054 BOOST_THROW_EXCEPTION(tlv::Error(error.str()));
Steve DiBenedetto6214e562014-03-15 16:27:04 -060055}
56
57static inline uint64_t
58checkedReadNonNegativeIntegerType(Block::element_const_iterator& i,
59 Block::element_const_iterator end,
60 uint32_t type)
61{
62 if (i != end)
63 {
64 const Block& block = *i;
65 ++i;
66 return readNonNegativeIntegerType(block, type);
67 }
68 std::stringstream error;
69 error << "Unexpected end of Block while attempting to read type #"
70 << type;
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -070071 BOOST_THROW_EXCEPTION(tlv::Error(error.str()));
Steve DiBenedetto6214e562014-03-15 16:27:04 -060072}
73
74class FibEnumerationPublisherFixture : public BaseFixture
75{
76public:
77
78 FibEnumerationPublisherFixture()
Haowei Yuanf52dac72014-03-24 23:35:03 -050079 : m_fib(m_nameTree)
Steve DiBenedetto6214e562014-03-15 16:27:04 -060080 , m_face(make_shared<InternalFace>())
Vince Lehman5144f822014-07-23 15:12:56 -070081 , m_publisher(m_fib, *m_face, "/localhost/nfd/FibEnumerationPublisherFixture", m_keyChain)
Steve DiBenedetto6214e562014-03-15 16:27:04 -060082 , m_finished(false)
83 {
Steve DiBenedetto6214e562014-03-15 16:27:04 -060084 }
85
86 virtual
87 ~FibEnumerationPublisherFixture()
88 {
Steve DiBenedetto6214e562014-03-15 16:27:04 -060089 }
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
Junxiao Shi67f11ac2014-10-19 09:29:13 -0700123 BOOST_REQUIRE(i->type() == tlv::Name);
Steve DiBenedetto6214e562014-03-15 16:27:04 -0600124 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(),
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700129 bind(&FibEnumerationPublisherFixture::entryHasPrefix,
130 this, _1, prefix));
Steve DiBenedetto6214e562014-03-15 16:27:04 -0600131
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());
Junxiao Shi67f11ac2014-10-19 09:29:13 -0700184 m_buffer.prependVarNumber(tlv::Content);
Steve DiBenedetto6214e562014-03-15 16:27:04 -0600185
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;
Vince Lehman5144f822014-07-23 15:12:56 -0700212 ndn::KeyChain m_keyChain;
Steve DiBenedetto6214e562014-03-15 16:27:04 -0600213
214protected:
215 bool m_finished;
216};
217
218} // namespace tests
219} // namespace nfd
220
Alexander Afanasyev613e2a92014-04-15 13:36:58 -0700221#endif // NFD_TESTS_NFD_MGMT_FIB_ENUMERATION_PUBLISHER_COMMON_HPP