blob: e27d4a3e75754781a64d5a6e068eff5b27d0a35e [file] [log] [blame]
Junxiao Shi034c1882016-06-24 18:06:51 +00001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2013-2016 Regents of the University of California.
4 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20 */
21
22#include "management/nfd-status-dataset.hpp"
23#include "management/nfd-controller.hpp"
24
25#include "nfd-controller-fixture.hpp"
26#include "../make-interest-data.hpp"
27
28namespace ndn {
29namespace nfd {
30namespace tests {
31
32using ndn::util::makeData;
33using ndn::util::signData;
34
35BOOST_AUTO_TEST_SUITE(Management)
36
37class ControllerStatusDatasetFixture : public ControllerFixture
38{
39protected:
40 /** \brief send one WireEncodable as Data reply
41 * \param prefix dataset prefix without version and segment
42 * \param payload payload block
43 * \note payload must fit in one Data
44 */
45 template<typename T>
46 void
47 sendDataset(const Name& prefix, const T& payload)
48 {
49 BOOST_CONCEPT_ASSERT((WireEncodable<T>));
50
51 auto data = this->prepareDatasetReply(prefix);
52 data->setContent(payload.wireEncode());
53 face.receive(*signData(data));
54 }
55
56 /** \brief send two WireEncodables as Data reply
57 * \param prefix dataset prefix without version and segment
58 * \param payload1 first vector item
59 * \param payload2 second vector item
60 * \note all payloads must fit in one Data
61 */
62 template<typename T1, typename T2>
63 void
64 sendDataset(const Name& prefix, const T1& payload1, const T2& payload2)
65 {
66 // The test suite allows up to two items, and put them in the same Data packet,
67 // because this test suite focuses on Controller::fetch<StatusDataset>,
68 // and is not intended to cover SegmentFetcher behavior.
69
70 BOOST_CONCEPT_ASSERT((WireEncodable<T1>));
71 BOOST_CONCEPT_ASSERT((WireEncodable<T2>));
72
73 ndn::encoding::EncodingBuffer buffer;
74 payload2.wireEncode(buffer);
75 payload1.wireEncode(buffer);
76
77 auto data = this->prepareDatasetReply(prefix);
78 data->setContent(buffer.buf(), buffer.size());
79 face.receive(*signData(data));
80 }
81
82private:
83 shared_ptr<Data>
84 prepareDatasetReply(const Name& prefix)
85 {
86 Name name = prefix;
87 name.appendVersion().appendSegment(0);
88
89 // These warnings assist in debugging a `hasResult` check failure.
90 // They usually indicate a misspelled prefix or incorrect timing in the test case.
91 if (face.sentInterests.size() < 1) {
92 BOOST_WARN_MESSAGE(false, "no Interest expressed");
93 }
94 else {
95 BOOST_WARN_MESSAGE(face.sentInterests.back().getName().isPrefixOf(name),
96 "last Interest " << face.sentInterests.back().getName() <<
97 " cannot be satisfied by this Data " << name);
98 }
99
100 auto data = make_shared<Data>(name);
101 data->setFinalBlockId(data->getName()[-1]);
102 return data;
103 }
104};
105
106BOOST_FIXTURE_TEST_SUITE(TestNfdStatusDataset, ControllerStatusDatasetFixture)
107
108BOOST_AUTO_TEST_SUITE(Failures)
109
110BOOST_AUTO_TEST_CASE(Timeout)
111{
112 CommandOptions options;
113 options.setTimeout(time::milliseconds(3000));
114 controller.fetch<FaceDataset>(
115 [] (const std::vector<FaceStatus>& result) { BOOST_FAIL("fetchDataset should not succeed"); },
116 failCallback,
117 options);
118 this->advanceClocks(time::milliseconds(500), 7);
119
120 BOOST_REQUIRE_EQUAL(failCodes.size(), 1);
121 BOOST_CHECK_EQUAL(failCodes.back(), Controller::ERROR_TIMEOUT);
122}
123
124BOOST_AUTO_TEST_CASE(DataHasNoSegment)
125{
126 controller.fetch<FaceDataset>(
127 [] (const std::vector<FaceStatus>& result) { BOOST_FAIL("fetchDataset should not succeed"); },
128 failCallback);
129 this->advanceClocks(time::milliseconds(500));
130
131 face.receive(*makeData("/localhost/nfd/faces/list/%FD%00"));
132 this->advanceClocks(time::milliseconds(500));
133
134 BOOST_REQUIRE_EQUAL(failCodes.size(), 1);
135 BOOST_CHECK_EQUAL(failCodes.back(), Controller::ERROR_SERVER);
136}
137
138BOOST_AUTO_TEST_CASE(Nack)
139{
140 controller.fetch<FaceDataset>(
141 [] (const std::vector<FaceStatus>& result) { BOOST_FAIL("fetchDataset should not succeed"); },
142 failCallback);
143 this->advanceClocks(time::milliseconds(500));
144
145 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
146 face.receive(lp::Nack(face.sentInterests.back()));
147 this->advanceClocks(time::milliseconds(500));
148
149 BOOST_REQUIRE_EQUAL(failCodes.size(), 1);
150 BOOST_CHECK_EQUAL(failCodes.back(), Controller::ERROR_NACK);
151}
152
153BOOST_AUTO_TEST_CASE(ParseError1)
154{
155 controller.fetch<FaceDataset>(
156 [] (const std::vector<FaceStatus>& result) { BOOST_FAIL("fetchDataset should not succeed"); },
157 failCallback);
158 this->advanceClocks(time::milliseconds(500));
159
160 Name payload; // Name is not valid FaceStatus
161 this->sendDataset("/localhost/nfd/faces/list", payload);
162 this->advanceClocks(time::milliseconds(500));
163
164 BOOST_REQUIRE_EQUAL(failCodes.size(), 1);
165 BOOST_CHECK_EQUAL(failCodes.back(), Controller::ERROR_SERVER);
166}
167
168BOOST_AUTO_TEST_CASE(ParseError2)
169{
170 controller.fetch<FaceDataset>(
171 [] (const std::vector<FaceStatus>& result) { BOOST_FAIL("fetchDataset should not succeed"); },
172 failCallback);
173 this->advanceClocks(time::milliseconds(500));
174
175 FaceStatus payload1;
176 payload1.setFaceId(10930);
177 Name payload2; // Name is not valid FaceStatus
178 this->sendDataset("/localhost/nfd/faces/list", payload1, payload2);
179 this->advanceClocks(time::milliseconds(500));
180
181 BOOST_REQUIRE_EQUAL(failCodes.size(), 1);
182 BOOST_CHECK_EQUAL(failCodes.back(), Controller::ERROR_SERVER);
183}
184
185BOOST_AUTO_TEST_SUITE_END() // Failures
186
187BOOST_AUTO_TEST_SUITE(Datasets)
188
189BOOST_AUTO_TEST_CASE(StatusGeneral)
190{
191 bool hasResult = false;
192 controller.fetch<ForwarderGeneralStatusDataset>(
193 [&hasResult] (const ForwarderStatus& result) {
194 hasResult = true;
195 BOOST_CHECK_EQUAL(result.getNfdVersion(), "0.4.2");
196 },
197 failCallback);
198 this->advanceClocks(time::milliseconds(500));
199
200 ForwarderStatus payload;
201 payload.setNfdVersion("0.4.2");
202 this->sendDataset("/localhost/nfd/status/general", payload);
203 this->advanceClocks(time::milliseconds(500));
204
205 BOOST_CHECK(hasResult);
206 BOOST_CHECK_EQUAL(failCodes.size(), 0);
207}
208
209BOOST_AUTO_TEST_CASE(FaceList)
210{
211 bool hasResult = false;
212 controller.fetch<FaceDataset>(
213 [&hasResult] (const std::vector<FaceStatus>& result) {
214 hasResult = true;
215 BOOST_CHECK_EQUAL(result.size(), 2);
216 BOOST_CHECK_EQUAL(result.front().getFaceId(), 24485);
217 },
218 failCallback);
219 this->advanceClocks(time::milliseconds(500));
220
221 FaceStatus payload1;
222 payload1.setFaceId(24485);
223 FaceStatus payload2;
224 payload2.setFaceId(12987);
225 this->sendDataset("/localhost/nfd/faces/list", payload1, payload2);
226 this->advanceClocks(time::milliseconds(500));
227
228 BOOST_CHECK(hasResult);
229 BOOST_CHECK_EQUAL(failCodes.size(), 0);
230}
231
232BOOST_AUTO_TEST_CASE(FaceQuery)
233{
234 FaceQueryFilter filter;
235 filter.setUriScheme("udp4");
236 bool hasResult = false;
237 controller.fetch<FaceQueryDataset>(
238 filter,
239 [&hasResult] (const std::vector<FaceStatus>& result) {
240 hasResult = true;
241 BOOST_CHECK_EQUAL(result.size(), 1);
242 BOOST_CHECK_EQUAL(result.front().getFaceId(), 8795);
243 },
244 failCallback);
245 this->advanceClocks(time::milliseconds(500));
246
247 Name prefix("/localhost/nfd/faces/query");
248 prefix.append(filter.wireEncode());
249 FaceStatus payload;
250 payload.setFaceId(8795);
251 this->sendDataset(prefix, payload);
252 this->advanceClocks(time::milliseconds(500));
253
254 BOOST_CHECK(hasResult);
255 BOOST_CHECK_EQUAL(failCodes.size(), 0);
256}
257
258BOOST_AUTO_TEST_CASE(FaceQueryWithOptions)
259{
260 FaceQueryFilter filter;
261 filter.setUriScheme("udp4");
262 CommandOptions options;
263 options.setTimeout(time::milliseconds(3000));
264 bool hasResult = false;
265 controller.fetch<FaceQueryDataset>(
266 filter,
267 [&hasResult] (const std::vector<FaceStatus>& result) {
268 hasResult = true;
269 BOOST_CHECK_EQUAL(result.size(), 1);
270 BOOST_CHECK_EQUAL(result.front().getFaceId(), 14022);
271 },
272 failCallback,
273 options);
274 this->advanceClocks(time::milliseconds(500));
275
276 Name prefix("/localhost/nfd/faces/query");
277 prefix.append(filter.wireEncode());
278 FaceStatus payload;
279 payload.setFaceId(14022);
280 this->sendDataset(prefix, payload);
281 this->advanceClocks(time::milliseconds(500));
282
283 BOOST_CHECK(hasResult);
284 BOOST_CHECK_EQUAL(failCodes.size(), 0);
285}
286
Junxiao Shi1eacb972016-07-07 22:51:07 +0000287BOOST_AUTO_TEST_CASE(FaceChannels)
288{
289 bool hasResult = false;
290 controller.fetch<ChannelDataset>(
291 [&hasResult] (const std::vector<ChannelStatus>& result) {
292 hasResult = true;
293 BOOST_CHECK_EQUAL(result.size(), 2);
294 BOOST_CHECK_EQUAL(result.front().getLocalUri(), "tcp4://192.0.2.1:6363");
295 },
296 failCallback);
297 this->advanceClocks(time::milliseconds(500));
298
299 ChannelStatus payload1;
300 payload1.setLocalUri("tcp4://192.0.2.1:6363");
301 ChannelStatus payload2;
302 payload2.setLocalUri("udp4://192.0.2.1:6363");
303 this->sendDataset("/localhost/nfd/faces/channels", payload1, payload2);
304 this->advanceClocks(time::milliseconds(500));
305
306 BOOST_CHECK(hasResult);
307 BOOST_CHECK_EQUAL(failCodes.size(), 0);
308}
309
Junxiao Shi034c1882016-06-24 18:06:51 +0000310BOOST_AUTO_TEST_CASE(FibList)
311{
312 bool hasResult = false;
313 controller.fetch<FibDataset>(
314 [&hasResult] (const std::vector<FibEntry>& result) {
315 hasResult = true;
316 BOOST_CHECK_EQUAL(result.size(), 2);
317 BOOST_CHECK_EQUAL(result.front().getPrefix(), "/wYs7fzYcfG");
318 },
319 failCallback);
320 this->advanceClocks(time::milliseconds(500));
321
322 FibEntry payload1;
323 payload1.setPrefix("/wYs7fzYcfG");
324 FibEntry payload2;
325 payload2.setPrefix("/LKvmnzY5S");
326 this->sendDataset("/localhost/nfd/fib/list", payload1, payload2);
327 this->advanceClocks(time::milliseconds(500));
328
329 BOOST_CHECK(hasResult);
330 BOOST_CHECK_EQUAL(failCodes.size(), 0);
331}
332
333BOOST_AUTO_TEST_CASE(StrategyChoiceList)
334{
335 bool hasResult = false;
336 controller.fetch<StrategyChoiceDataset>(
337 [&hasResult] (const std::vector<StrategyChoice>& result) {
338 hasResult = true;
339 BOOST_CHECK_EQUAL(result.size(), 2);
340 BOOST_CHECK_EQUAL(result.front().getName(), "/8MLz6N3B");
341 },
342 failCallback);
343 this->advanceClocks(time::milliseconds(500));
344
345 StrategyChoice payload1;
346 payload1.setName("/8MLz6N3B");
347 StrategyChoice payload2;
348 payload2.setName("/svqcBu0YwU");
349 this->sendDataset("/localhost/nfd/strategy-choice/list", payload1, payload2);
350 this->advanceClocks(time::milliseconds(500));
351
352 BOOST_CHECK(hasResult);
353 BOOST_CHECK_EQUAL(failCodes.size(), 0);
354}
355
356BOOST_AUTO_TEST_CASE(RibList)
357{
358 bool hasResult = false;
359 controller.fetch<RibDataset>(
360 [&hasResult] (const std::vector<RibEntry>& result) {
361 hasResult = true;
362 BOOST_CHECK_EQUAL(result.size(), 2);
363 BOOST_CHECK_EQUAL(result.front().getName(), "/zXxBth97ee");
364 },
365 failCallback);
366 this->advanceClocks(time::milliseconds(500));
367
368 RibEntry payload1;
369 payload1.setName("/zXxBth97ee");
370 RibEntry payload2;
371 payload2.setName("/rJ8CvUpr4G");
372 this->sendDataset("/localhost/nfd/rib/list", payload1, payload2);
373 this->advanceClocks(time::milliseconds(500));
374
375 BOOST_CHECK(hasResult);
376 BOOST_CHECK_EQUAL(failCodes.size(), 0);
377}
378
379BOOST_AUTO_TEST_CASE(RibListWithOptions)
380{
381 CommandOptions options;
382 options.setPrefix("/localhop/nfd");
383 bool hasResult = false;
384 controller.fetch<RibDataset>(
385 [&hasResult] (const std::vector<RibEntry>& result) {
386 hasResult = true;
387 BOOST_CHECK_EQUAL(result.size(), 1);
388 BOOST_CHECK_EQUAL(result.front().getName(), "/e6L5K4ascd");
389 },
390 failCallback,
391 options);
392 this->advanceClocks(time::milliseconds(500));
393
394 RibEntry payload;
395 payload.setName("/e6L5K4ascd");
396 this->sendDataset("/localhop/nfd/rib/list", payload);
397 this->advanceClocks(time::milliseconds(500));
398
399 BOOST_CHECK(hasResult);
400 BOOST_CHECK_EQUAL(failCodes.size(), 0);
401}
402
403BOOST_AUTO_TEST_SUITE_END() // Datasets
404
405BOOST_AUTO_TEST_SUITE_END() // TestNfdStatusDataset
406BOOST_AUTO_TEST_SUITE_END() // Management
407
408} // namespace tests
409} // namespace nfd
410} // namespace ndn