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