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