blob: df1f97f2961c62844a750e3925602e02dd7ef782 [file] [log] [blame]
Eric Newberryb5aa7f52016-09-03 20:36:12 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2014-2016, 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.
10 *
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/>.
24 */
25
26#include "face-manager-command-fixture.hpp"
27#include "nfd-manager-common-fixture.hpp"
Junxiao Shicbc8e942016-09-06 03:17:45 +000028#include <ndn-cxx/lp/tags.hpp>
Eric Newberryb5aa7f52016-09-03 20:36:12 -070029
30namespace nfd {
31namespace tests {
32
33BOOST_AUTO_TEST_SUITE(Mgmt)
34BOOST_AUTO_TEST_SUITE(TestFaceManager)
35
36class FaceManagerUpdateFixture : public FaceManagerCommandFixture
37{
38public:
39 FaceManagerUpdateFixture()
40 : faceId(0)
41 {
42 }
43
44 ~FaceManagerUpdateFixture()
45 {
46 destroyFace();
47 }
48
49 void
50 createFace(const std::string& uri = "tcp4://127.0.0.1:26363",
51 ndn::nfd::FacePersistency persistency = ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
52 bool enableLocalFields = false)
53 {
54 ControlParameters params;
55 params.setUri(uri);
56 params.setFacePersistency(persistency);
57 params.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, enableLocalFields);
58
59 Name commandName("/localhost/nfd/faces/create");
60 commandName.append(params.wireEncode());
61 auto command = makeInterest(commandName);
62 m_keyChain.sign(*command);
63
64 bool hasCallbackFired = false;
65 signal::ScopedConnection connection = this->node1.face.onSendData.connect(
66 [this, command, &hasCallbackFired] (const Data& response) {
67 if (!command->getName().isPrefixOf(response.getName())) {
68 return;
69 }
70
71 ControlResponse create(response.getContent().blockFromValue());
72 BOOST_REQUIRE_EQUAL(create.getCode(), 200);
73
74 if (create.getBody().hasWire()) {
75 ControlParameters faceParams(create.getBody());
76 BOOST_REQUIRE(faceParams.hasFaceId());
77 this->faceId = faceParams.getFaceId();
78 }
79 else {
80 BOOST_FAIL("Face creation failed");
81 }
82
83 hasCallbackFired = true;
84 });
85
86 this->node1.face.receive(*command);
87 this->advanceClocks(time::milliseconds(1), 5);
88
89 BOOST_REQUIRE(hasCallbackFired);
90 }
91
92 void
93 updateFace(const ControlParameters& requestParams,
94 bool isSelfUpdating,
95 const function<void(const ControlResponse& resp)>& checkResp)
96 {
97 Name commandName("/localhost/nfd/faces/update");
98 commandName.append(requestParams.wireEncode());
99 auto command = makeInterest(commandName);
100 if (isSelfUpdating) {
101 // Attach IncomingFaceIdTag to interest
102 command->setTag(make_shared<lp::IncomingFaceIdTag>(faceId));
103 }
104 m_keyChain.sign(*command);
105
106 bool hasCallbackFired = false;
107 signal::ScopedConnection connection = this->node1.face.onSendData.connect(
108 [this, command, &hasCallbackFired, &checkResp] (const Data& response) {
109 if (!command->getName().isPrefixOf(response.getName())) {
110 return;
111 }
112
113 ControlResponse actual(response.getContent().blockFromValue());
114 checkResp(actual);
115
116 hasCallbackFired = true;
117 });
118
119 this->node1.face.receive(*command);
120 this->advanceClocks(time::milliseconds(1), 5);
121
122 BOOST_CHECK(hasCallbackFired);
123 }
124
125private:
126 void
127 destroyFace()
128 {
129 if (faceId == 0) {
130 return;
131 }
132
133 ControlParameters params;
134 params.setFaceId(faceId);
135
136 Name commandName("/localhost/nfd/faces/destroy");
137 commandName.append(params.wireEncode());
138 auto command = makeInterest(commandName);
139 m_keyChain.sign(*command);
140
141 bool hasCallbackFired = false;
142 signal::ScopedConnection connection = this->node1.face.onSendData.connect(
143 [this, command, &hasCallbackFired] (const Data& response) {
144 if (!command->getName().isPrefixOf(response.getName())) {
145 return;
146 }
147
148 ControlResponse destroy(response.getContent().blockFromValue());
149 BOOST_CHECK_EQUAL(destroy.getCode(), 200);
150
151 faceId = 0;
152 hasCallbackFired = true;
153 });
154
155 this->node1.face.receive(*command);
156 this->advanceClocks(time::milliseconds(1), 5);
157
158 BOOST_CHECK(hasCallbackFired);
159 }
160
161public:
162 FaceId faceId;
163};
164
165BOOST_FIXTURE_TEST_SUITE(UpdateFace, FaceManagerUpdateFixture)
166
167BOOST_AUTO_TEST_CASE(FaceDoesNotExist)
168{
169 ControlParameters requestParams;
170 requestParams.setFaceId(65535);
171
172 updateFace(requestParams, false, [] (const ControlResponse& actual) {
173 ControlResponse expected(404, "Specified face does not exist");
174 BOOST_CHECK_EQUAL(actual.getCode(), expected.getCode());
175 BOOST_TEST_MESSAGE(actual.getText());
176 });
177}
178
179// TODO #3232: Expected failure until FacePersistency updating implemented
180BOOST_AUTO_TEST_CASE(UpdatePersistency)
181{
182 createFace();
183
184 ControlParameters requestParams;
185 requestParams.setFaceId(faceId);
186 requestParams.setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERMANENT);
187
188 updateFace(requestParams, false, [] (const ControlResponse& actual) {
189 ControlResponse expected(409, "Invalid fields specified");
190 BOOST_CHECK_EQUAL(actual.getCode(), expected.getCode());
191 BOOST_TEST_MESSAGE(actual.getText());
192
193 if (actual.getBody().hasWire()) {
194 ControlParameters actualParams(actual.getBody());
195
196 BOOST_REQUIRE(actualParams.hasFacePersistency());
197 BOOST_CHECK_EQUAL(actualParams.getFacePersistency(), ndn::nfd::FACE_PERSISTENCY_PERMANENT);
198 }
199 else {
200 BOOST_ERROR("Response does not contain ControlParameters");
201 }
202 });
203}
204
205class TcpLocalFieldsEnable
206{
207public:
208 std::string
209 getUri()
210 {
211 return "tcp4://127.0.0.1:26363";
212 }
213
214 boost::asio::ip::address_v4
215 getIpAddress()
216 {
217 return boost::asio::ip::address_v4::from_string("127.0.0.1");
218 }
219
220 ndn::nfd::FacePersistency
221 getPersistency()
222 {
223 return ndn::nfd::FACE_PERSISTENCY_PERSISTENT;
224 }
225
226 bool
227 getInitLocalFieldsEnabled()
228 {
229 return false;
230 }
231
232 bool
233 getLocalFieldsEnabled()
234 {
235 return true;
236 }
237
238 bool
239 getLocalFieldsEnabledMask()
240 {
241 return true;
242 }
243
244 bool
245 shouldHaveWire()
246 {
247 return false;
248 }
249};
250
251class TcpLocalFieldsDisable
252{
253public:
254 std::string
255 getUri()
256 {
257 return "tcp4://127.0.0.1:26363";
258 }
259
260 ndn::nfd::FacePersistency
261 getPersistency()
262 {
263 return ndn::nfd::FACE_PERSISTENCY_PERSISTENT;
264 }
265
266 bool
267 getInitLocalFieldsEnabled()
268 {
269 return true;
270 }
271
272 bool
273 getLocalFieldsEnabled()
274 {
275 return false;
276 }
277
278 bool
279 getLocalFieldsEnabledMask()
280 {
281 return true;
282 }
283
284 bool
285 shouldHaveWire()
286 {
287 return false;
288 }
289};
290
291// UDP faces are non-local by definition
292class UdpLocalFieldsEnable
293{
294public:
295 std::string
296 getUri()
297 {
298 return "udp4://127.0.0.1:26363";
299 }
300
301 ndn::nfd::FacePersistency
302 getPersistency()
303 {
304 return ndn::nfd::FACE_PERSISTENCY_PERSISTENT;
305 }
306
307 bool
308 getInitLocalFieldsEnabled()
309 {
310 return false;
311 }
312
313 bool
314 getLocalFieldsEnabled()
315 {
316 return true;
317 }
318
319 bool
320 getLocalFieldsEnabledMask()
321 {
322 return true;
323 }
324
325 bool
326 shouldHaveWire()
327 {
328 return true;
329 }
330};
331
332// UDP faces are non-local by definition
333// In this test case, attempt to disable local fields on face with local fields already disabled
334class UdpLocalFieldsDisable
335{
336public:
337 std::string
338 getUri()
339 {
340 return "udp4://127.0.0.1:26363";
341 }
342
343 ndn::nfd::FacePersistency
344 getPersistency()
345 {
346 return ndn::nfd::FACE_PERSISTENCY_PERSISTENT;
347 }
348
349 bool
350 getInitLocalFieldsEnabled()
351 {
352 return false;
353 }
354
355 bool
356 getLocalFieldsEnabled()
357 {
358 return false;
359 }
360
361 bool
362 getLocalFieldsEnabledMask()
363 {
364 return true;
365 }
366
367 bool
368 shouldHaveWire()
369 {
370 return false;
371 }
372};
373
374// In this test case, set Flags to enable local fields on non-local face, but exclude local fields
375// from Mask. This test case will pass as no action is taken due to the missing Mask bit.
376class UdpLocalFieldsEnableNoMaskBit
377{
378public:
379 std::string
380 getUri()
381 {
382 return "udp4://127.0.0.1:26363";
383 }
384
385 ndn::nfd::FacePersistency
386 getPersistency()
387 {
388 return ndn::nfd::FACE_PERSISTENCY_PERSISTENT;
389 }
390
391 bool
392 getInitLocalFieldsEnabled()
393 {
394 return false;
395 }
396
397 bool
398 getLocalFieldsEnabled()
399 {
400 return true;
401 }
402
403 bool
404 getLocalFieldsEnabledMask()
405 {
406 return false;
407 }
408
409 bool
410 shouldHaveWire()
411 {
412 return false;
413 }
414};
415
416namespace mpl = boost::mpl;
417
418typedef mpl::vector<mpl::pair<TcpLocalFieldsEnable, CommandSuccess>,
419 mpl::pair<TcpLocalFieldsDisable, CommandSuccess>,
420 mpl::pair<UdpLocalFieldsEnable, CommandFailure<409>>,
421 mpl::pair<UdpLocalFieldsDisable, CommandSuccess>,
422 mpl::pair<UdpLocalFieldsEnableNoMaskBit, CommandSuccess>> LocalFieldFaces;
423
424BOOST_AUTO_TEST_CASE_TEMPLATE(UpdateLocalFields, T, LocalFieldFaces)
425{
426 typedef typename T::first TestType;
427 typedef typename T::second ResultType;
428
429 createFace(TestType().getUri(), TestType().getPersistency(), TestType().getInitLocalFieldsEnabled());
430
431 ControlParameters requestParams;
432 requestParams.setFaceId(faceId);
433 requestParams.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, TestType().getLocalFieldsEnabled());
434 if (!TestType().getLocalFieldsEnabledMask()) {
435 requestParams.unsetFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED);
436 }
437
438 updateFace(requestParams, false, [] (const ControlResponse& actual) {
439 ControlResponse expected(ResultType().getExpected().getCode(), "");
440 BOOST_CHECK_EQUAL(actual.getCode(), expected.getCode());
441 BOOST_TEST_MESSAGE(actual.getText());
442
443 if (TestType().shouldHaveWire() && actual.getBody().hasWire()) {
444 ControlParameters actualParams(actual.getBody());
445
446 BOOST_CHECK(!actualParams.hasFacePersistency());
447 BOOST_CHECK(actualParams.hasFlags());
448 BOOST_CHECK(actualParams.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED));
449 BOOST_CHECK(actualParams.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED));
450 }
451 });
452}
453
454BOOST_AUTO_TEST_CASE(UpdateLocalFieldsEnableDisable)
455{
456 createFace();
457
458 ControlParameters enableParams;
459 enableParams.setFaceId(faceId);
460 enableParams.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, true);
461
462 ControlParameters disableParams;
463 disableParams.setFaceId(faceId);
464 disableParams.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, false);
465
466 updateFace(enableParams, false, [] (const ControlResponse& actual) {
467 ControlResponse expected(200, "OK");
468 BOOST_CHECK_EQUAL(actual.getCode(), expected.getCode());
469 BOOST_TEST_MESSAGE(actual.getText());
470
471 if (actual.getBody().hasWire()) {
472 ControlParameters actualParams(actual.getBody());
473
474 BOOST_CHECK(actualParams.hasFaceId());
475 BOOST_CHECK(actualParams.hasFacePersistency());
476 BOOST_REQUIRE(actualParams.hasFlags());
477 // Check if flags indicate local fields enabled
478 BOOST_CHECK(actualParams.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED));
479 }
480 else {
481 BOOST_ERROR("Enable: Response does not contain ControlParameters");
482 }
483 });
484
485 updateFace(disableParams, false, [] (const ControlResponse& actual) {
486 ControlResponse expected(200, "OK");
487 BOOST_CHECK_EQUAL(actual.getCode(), expected.getCode());
488 BOOST_TEST_MESSAGE(actual.getText());
489
490 if (actual.getBody().hasWire()) {
491 ControlParameters actualParams(actual.getBody());
492
493 BOOST_CHECK(actualParams.hasFaceId());
494 BOOST_CHECK(actualParams.hasFacePersistency());
495 BOOST_REQUIRE(actualParams.hasFlags());
496 // Check if flags indicate local fields disabled
497 BOOST_CHECK(!actualParams.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED));
498 }
499 else {
500 BOOST_ERROR("Disable: Response does not contain ControlParameters");
501 }
502 });
503}
504
505BOOST_AUTO_TEST_CASE(SelfUpdating)
506{
507 createFace();
508
509 // Send a command that does nothing (will return 200) and does not contain a FaceId
510 ControlParameters sentParams;
511
512 updateFace(sentParams, true, [] (const ControlResponse& actual) {
513 ControlResponse expected(200, "OK");
514 BOOST_REQUIRE_EQUAL(actual.getCode(), expected.getCode());
515 BOOST_TEST_MESSAGE(actual.getText());
516 });
517}
518
519BOOST_AUTO_TEST_SUITE_END() // UpdateFace
520BOOST_AUTO_TEST_SUITE_END() // TestFaceManager
521BOOST_AUTO_TEST_SUITE_END() // Mgmt
522
523} // namespace tests
524} // namespace nfd