blob: ed893885d19a7ad2b7a6c72f9845c57c5f5d4318 [file] [log] [blame]
Yanbiao Li73860e32015-08-19 16:30:16 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Weiwei Liuf5aee942016-03-19 07:00:42 +00003 * Copyright (c) 2014-2016, Regents of the University of California,
Yanbiao Li73860e32015-08-19 16:30:16 -07004 * 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
Eric Newberry42602412016-08-27 09:33:18 -070026#include "face-manager-command-fixture.hpp"
27#include "nfd-manager-common-fixture.hpp"
Junxiao Shib84e6742016-07-19 13:16:22 +000028
29#include <thread>
Yanbiao Li73860e32015-08-19 16:30:16 -070030
Yanbiao Li73860e32015-08-19 16:30:16 -070031namespace nfd {
32namespace tests {
33
Yanbiao Li73860e32015-08-19 16:30:16 -070034BOOST_AUTO_TEST_SUITE(Mgmt)
35BOOST_AUTO_TEST_SUITE(TestFaceManager)
36
37BOOST_FIXTURE_TEST_SUITE(CreateFace, BaseFixture)
38
Yanbiao Li73860e32015-08-19 16:30:16 -070039class TcpFaceOnDemand
40{
41public:
42 ControlParameters
43 getParameters()
44 {
45 return ControlParameters()
46 .setUri("tcp4://127.0.0.1:26363")
47 .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_ON_DEMAND);
48 }
49};
50
51class TcpFacePersistent
52{
53public:
54 ControlParameters
55 getParameters()
56 {
57 return ControlParameters()
58 .setUri("tcp4://127.0.0.1:26363")
59 .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT);
60 }
61};
62
63class TcpFacePermanent
64{
65public:
66 ControlParameters
67 getParameters()
68 {
69 return ControlParameters()
70 .setUri("tcp4://127.0.0.1:26363")
71 .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERMANENT);
72 }
73};
74
75class UdpFaceOnDemand
76{
77public:
78 ControlParameters
79 getParameters()
80 {
81 return ControlParameters()
82 .setUri("udp4://127.0.0.1:26363")
83 .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_ON_DEMAND);
84 }
85};
86
Yanbiao Li73860e32015-08-19 16:30:16 -070087class UdpFacePersistent
88{
89public:
90 ControlParameters
91 getParameters()
92 {
93 return ControlParameters()
94 .setUri("udp4://127.0.0.1:26363")
95 .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT);
96 }
97};
98
99class UdpFacePermanent
100{
101public:
102 ControlParameters
103 getParameters()
104 {
105 return ControlParameters()
106 .setUri("udp4://127.0.0.1:26363")
107 .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERMANENT);
108 }
109};
110
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700111class UdpFaceConnectToSelf // face that will cause afterCreateFaceFailure to be invoked
112 // fails because remote endpoint is prohibited
Yanbiao Li73860e32015-08-19 16:30:16 -0700113{
114public:
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700115 ControlParameters
116 getParameters()
Yanbiao Li73860e32015-08-19 16:30:16 -0700117 {
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700118 return ControlParameters()
119 .setUri("udp4://0.0.0.0:16363"); // cannot connect to self
Yanbiao Li73860e32015-08-19 16:30:16 -0700120 }
121};
122
Eric Newberryf40551a2016-09-05 15:41:16 -0700123class LocalTcpFaceLocalFieldsEnabled
124{
125public:
126 ControlParameters
127 getParameters()
128 {
129 return ControlParameters()
130 .setUri("tcp4://127.0.0.1:26363")
131 .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT)
132 .setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, true);
133 }
134};
135
136class LocalTcpFaceLocalFieldsDisabled
137{
138public:
139 ControlParameters
140 getParameters()
141 {
142 return ControlParameters()
143 .setUri("tcp4://127.0.0.1:26363")
144 .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT)
145 .setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, false);
146 }
147};
148
149class NonLocalUdpFaceLocalFieldsEnabled // won't work because non-local scope
150{
151public:
152 ControlParameters
153 getParameters()
154 {
155 return ControlParameters()
156 .setUri("udp4://127.0.0.1:26363")
157 .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT)
158 .setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, true);
159 }
160};
161
162class NonLocalUdpFaceLocalFieldsDisabled
163{
164public:
165 ControlParameters
166 getParameters()
167 {
168 return ControlParameters()
169 .setUri("udp4://127.0.0.1:26363")
170 .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT)
171 .setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, false);
172 }
173};
174
Yanbiao Li73860e32015-08-19 16:30:16 -0700175namespace mpl = boost::mpl;
176
Eric Newberry42602412016-08-27 09:33:18 -0700177// pairs of CreateCommand and Success/Failure status
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700178typedef mpl::vector<mpl::pair<TcpFaceOnDemand, CommandFailure<406>>,
179 mpl::pair<TcpFacePersistent, CommandSuccess>,
180 mpl::pair<TcpFacePermanent, CommandFailure<406>>,
181 mpl::pair<UdpFaceOnDemand, CommandFailure<406>>,
182 mpl::pair<UdpFacePersistent, CommandSuccess>,
183 mpl::pair<UdpFacePermanent, CommandSuccess>,
Eric Newberryf40551a2016-09-05 15:41:16 -0700184 mpl::pair<UdpFaceConnectToSelf, CommandFailure<406>>,
185 mpl::pair<LocalTcpFaceLocalFieldsEnabled, CommandSuccess>,
186 mpl::pair<LocalTcpFaceLocalFieldsDisabled, CommandSuccess>,
187 mpl::pair<NonLocalUdpFaceLocalFieldsEnabled, CommandFailure<406>>,
188 mpl::pair<NonLocalUdpFaceLocalFieldsDisabled, CommandSuccess>> Faces;
Yanbiao Li73860e32015-08-19 16:30:16 -0700189
Eric Newberry42602412016-08-27 09:33:18 -0700190BOOST_FIXTURE_TEST_CASE_TEMPLATE(NewFace, T, Faces, FaceManagerCommandFixture)
Yanbiao Li73860e32015-08-19 16:30:16 -0700191{
192 typedef typename T::first FaceType;
193 typedef typename T::second CreateResult;
194
195 Name commandName("/localhost/nfd/faces");
196 commandName.append("create");
197 commandName.append(FaceType().getParameters().wireEncode());
Junxiao Shib84e6742016-07-19 13:16:22 +0000198 auto command = makeInterest(commandName);
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000199 m_keyChain.sign(*command);
Yanbiao Li73860e32015-08-19 16:30:16 -0700200
201 bool hasCallbackFired = false;
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000202 this->node1.face.onSendData.connect([this, command, &hasCallbackFired] (const Data& response) {
Eric Newberry42602412016-08-27 09:33:18 -0700203 if (!command->getName().isPrefixOf(response.getName())) {
204 return;
205 }
Yanbiao Li73860e32015-08-19 16:30:16 -0700206
Eric Newberry42602412016-08-27 09:33:18 -0700207 ControlResponse actual(response.getContent().blockFromValue());
208 ControlResponse expected(CreateResult().getExpected());
209 BOOST_CHECK_EQUAL(expected.getCode(), actual.getCode());
210 BOOST_TEST_MESSAGE(actual.getText());
Yanbiao Li73860e32015-08-19 16:30:16 -0700211
Eric Newberry42602412016-08-27 09:33:18 -0700212 if (actual.getBody().hasWire()) {
213 ControlParameters expectedParams(FaceType().getParameters());
214 ControlParameters actualParams(actual.getBody());
Yanbiao Li73860e32015-08-19 16:30:16 -0700215
Eric Newberry42602412016-08-27 09:33:18 -0700216 BOOST_CHECK(actualParams.hasFaceId());
217 BOOST_CHECK_EQUAL(expectedParams.getFacePersistency(), actualParams.getFacePersistency());
218
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700219 if (actual.getCode() == 200) {
220 if (expectedParams.hasFlags()) {
Eric Newberryf40551a2016-09-05 15:41:16 -0700221 BOOST_CHECK_EQUAL(expectedParams.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED),
222 actualParams.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED));
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700223 }
224 else {
Eric Newberryf40551a2016-09-05 15:41:16 -0700225 // local fields are disabled by default
226 BOOST_CHECK_EQUAL(actualParams.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED), false);
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700227 }
228 }
229 else {
Yanbiao Li73860e32015-08-19 16:30:16 -0700230 BOOST_CHECK_EQUAL(expectedParams.getUri(), actualParams.getUri());
Yanbiao Li73860e32015-08-19 16:30:16 -0700231 }
Eric Newberry42602412016-08-27 09:33:18 -0700232 }
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700233
234 if (actual.getCode() != 200) {
235 // ensure face not created
236 FaceUri uri(FaceType().getParameters().getUri());
237 auto& faceTable = this->node1.manager.m_faceTable;
238 BOOST_CHECK(std::none_of(faceTable.begin(), faceTable.end(), [uri] (Face& face) {
239 return face.getRemoteUri() == uri;
240 }));
241 }
242
Eric Newberry42602412016-08-27 09:33:18 -0700243 hasCallbackFired = true;
244 });
Yanbiao Li73860e32015-08-19 16:30:16 -0700245
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000246 this->node1.face.receive(*command);
Junxiao Shib84e6742016-07-19 13:16:22 +0000247 this->advanceClocks(time::milliseconds(1), 5);
Yanbiao Li73860e32015-08-19 16:30:16 -0700248
249 BOOST_CHECK(hasCallbackFired);
250}
251
252
253typedef mpl::vector<// mpl::pair<mpl::pair<TcpFacePersistent, TcpFacePermanent>, TcpFacePermanent>, // no need to check now
Eric Newberryf40551a2016-09-05 15:41:16 -0700254 // mpl::pair<mpl::pair<TcpFacePermanent, TcpFacePersistent>, TcpFacePersistent>, // no need to check now
Yanbiao Li73860e32015-08-19 16:30:16 -0700255 mpl::pair<mpl::pair<UdpFacePersistent, UdpFacePermanent>, UdpFacePermanent>,
256 mpl::pair<mpl::pair<UdpFacePermanent, UdpFacePersistent>, UdpFacePermanent>> FaceTransitions;
257
258
Eric Newberry42602412016-08-27 09:33:18 -0700259BOOST_FIXTURE_TEST_CASE_TEMPLATE(ExistingFace, T, FaceTransitions, FaceManagerCommandFixture)
Yanbiao Li73860e32015-08-19 16:30:16 -0700260{
261 typedef typename T::first::first FaceType1;
262 typedef typename T::first::second FaceType2;
263 typedef typename T::second FinalFaceType;
264
265 {
266 // create face
267
268 Name commandName("/localhost/nfd/faces");
269 commandName.append("create");
270 commandName.append(FaceType1().getParameters().wireEncode());
Junxiao Shib84e6742016-07-19 13:16:22 +0000271 auto command = makeInterest(commandName);
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000272 m_keyChain.sign(*command);
Yanbiao Li73860e32015-08-19 16:30:16 -0700273
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000274 this->node1.face.receive(*command);
Junxiao Shib84e6742016-07-19 13:16:22 +0000275 this->advanceClocks(time::milliseconds(1), 5);
Yanbiao Li73860e32015-08-19 16:30:16 -0700276 }
277
278 //
279 {
280 // re-create face (= change face persistency)
281
282 Name commandName("/localhost/nfd/faces");
283 commandName.append("create");
284 commandName.append(FaceType2().getParameters().wireEncode());
Junxiao Shib84e6742016-07-19 13:16:22 +0000285 auto command = makeInterest(commandName);
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000286 m_keyChain.sign(*command);
Yanbiao Li73860e32015-08-19 16:30:16 -0700287
288 bool hasCallbackFired = false;
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000289 this->node1.face.onSendData.connect([this, command, &hasCallbackFired] (const Data& response) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700290 if (!command->getName().isPrefixOf(response.getName())) {
291 return;
292 }
293
294 ControlResponse actual(response.getContent().blockFromValue());
295 BOOST_REQUIRE_EQUAL(actual.getCode(), 200);
Eric Newberryf40551a2016-09-05 15:41:16 -0700296 BOOST_TEST_MESSAGE(actual.getText());
Yanbiao Li73860e32015-08-19 16:30:16 -0700297
298 ControlParameters expectedParams(FinalFaceType().getParameters());
299 ControlParameters actualParams(actual.getBody());
Eric Newberry42602412016-08-27 09:33:18 -0700300 BOOST_REQUIRE(!actualParams.hasUri()); // Uri parameter is only included on command failure
Yanbiao Li73860e32015-08-19 16:30:16 -0700301 BOOST_CHECK_EQUAL(expectedParams.getFacePersistency(), actualParams.getFacePersistency());
302
303 hasCallbackFired = true;
304 });
305
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000306 this->node1.face.receive(*command);
Junxiao Shib84e6742016-07-19 13:16:22 +0000307 this->advanceClocks(time::milliseconds(1), 5);
Yanbiao Li73860e32015-08-19 16:30:16 -0700308
309 BOOST_CHECK(hasCallbackFired);
310 }
311}
312
313
314class UdpFace
315{
316public:
317 ControlParameters
318 getParameters()
319 {
320 return ControlParameters()
321 .setUri("udp4://127.0.0.1:16363")
322 .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT);
323 }
324};
325
326
327// Note that the transitions from on-demand TcpFace are intentionally not tested.
328// On-demand TcpFace has a remote endpoint with a randomized port number. Normal face
329// creation operations will not need to create a face toward a remote port not listened by
330// a channel.
331
332typedef mpl::vector<mpl::pair<UdpFace, UdpFacePersistent>,
333 mpl::pair<UdpFace, UdpFacePermanent>> OnDemandFaceTransitions;
334
335// need a slightly different logic to test transitions from OnDemand state
Eric Newberry42602412016-08-27 09:33:18 -0700336BOOST_FIXTURE_TEST_CASE_TEMPLATE(ExistingFaceOnDemand, T, OnDemandFaceTransitions, FaceManagerCommandFixture)
Yanbiao Li73860e32015-08-19 16:30:16 -0700337{
338 typedef typename T::first OtherNodeFace;
339 typedef typename T::second FaceType;
340
341 {
342 // create on-demand face
343
344 Name commandName("/localhost/nfd/faces");
345 commandName.append("create");
346 commandName.append(OtherNodeFace().getParameters().wireEncode());
Junxiao Shib84e6742016-07-19 13:16:22 +0000347 auto command = makeInterest(commandName);
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000348 m_keyChain.sign(*command);
Yanbiao Li73860e32015-08-19 16:30:16 -0700349
350 ndn::util::signal::ScopedConnection connection =
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000351 this->node2.face.onSendData.connect([this, command] (const Data& response) {
Eric Newberry42602412016-08-27 09:33:18 -0700352 if (!command->getName().isPrefixOf(response.getName())) {
353 return;
354 }
Yanbiao Li73860e32015-08-19 16:30:16 -0700355
Eric Newberry42602412016-08-27 09:33:18 -0700356 ControlResponse controlResponse(response.getContent().blockFromValue());
357 BOOST_REQUIRE_EQUAL(controlResponse.getText(), "OK");
358 BOOST_REQUIRE_EQUAL(controlResponse.getCode(), 200);
359 BOOST_REQUIRE(!ControlParameters(controlResponse.getBody()).hasUri());
360 uint64_t faceId = ControlParameters(controlResponse.getBody()).getFaceId();
361 auto face = this->node2.faceTable.get(static_cast<FaceId>(faceId));
Yanbiao Li73860e32015-08-19 16:30:16 -0700362
Eric Newberry42602412016-08-27 09:33:18 -0700363 // to force creation of on-demand face
364 auto dummyInterest = make_shared<Interest>("/hello/world");
365 face->sendInterest(*dummyInterest);
366 });
Yanbiao Li73860e32015-08-19 16:30:16 -0700367
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000368 this->node2.face.receive(*command);
Junxiao Shib84e6742016-07-19 13:16:22 +0000369 this->advanceClocks(time::milliseconds(1), 5); // let node2 process command and send Interest
370 std::this_thread::sleep_for(std::chrono::milliseconds(100)); // allow wallclock time for socket IO
371 this->advanceClocks(time::milliseconds(1), 5); // let node1 accept Interest and create on-demand face
Yanbiao Li73860e32015-08-19 16:30:16 -0700372 }
373
374 // make sure there is on-demand face
Yanbiao Li73860e32015-08-19 16:30:16 -0700375 FaceUri onDemandFaceUri(FaceType().getParameters().getUri());
Junxiao Shib84e6742016-07-19 13:16:22 +0000376 const Face* foundFace = nullptr;
377 for (const Face& face : this->node1.faceTable) {
378 if (face.getRemoteUri() == onDemandFaceUri) {
379 foundFace = &face;
Yanbiao Li73860e32015-08-19 16:30:16 -0700380 break;
381 }
382 }
Junxiao Shib84e6742016-07-19 13:16:22 +0000383 BOOST_REQUIRE_MESSAGE(foundFace != nullptr, "on-demand face is not created");
Yanbiao Li73860e32015-08-19 16:30:16 -0700384
385 //
386 {
387 // re-create face (= change face persistency)
388
389 Name commandName("/localhost/nfd/faces");
390 commandName.append("create");
391 commandName.append(FaceType().getParameters().wireEncode());
Junxiao Shib84e6742016-07-19 13:16:22 +0000392 auto command = makeInterest(commandName);
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000393 m_keyChain.sign(*command);
Yanbiao Li73860e32015-08-19 16:30:16 -0700394
395 bool hasCallbackFired = false;
Junxiao Shib84e6742016-07-19 13:16:22 +0000396 this->node1.face.onSendData.connect(
397 [this, command, &hasCallbackFired, foundFace] (const Data& response) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700398 if (!command->getName().isPrefixOf(response.getName())) {
399 return;
400 }
401
402 ControlResponse actual(response.getContent().blockFromValue());
403 BOOST_REQUIRE_EQUAL(actual.getCode(), 200);
404
405 ControlParameters expectedParams(FaceType().getParameters());
406 ControlParameters actualParams(actual.getBody());
Eric Newberry42602412016-08-27 09:33:18 -0700407 BOOST_REQUIRE(!actualParams.hasUri());
Junxiao Shib84e6742016-07-19 13:16:22 +0000408 BOOST_CHECK_EQUAL(actualParams.getFacePersistency(), expectedParams.getFacePersistency());
409 BOOST_CHECK_EQUAL(actualParams.getFaceId(), foundFace->getId());
410 BOOST_CHECK_EQUAL(foundFace->getPersistency(), expectedParams.getFacePersistency());
Yanbiao Li73860e32015-08-19 16:30:16 -0700411
412 hasCallbackFired = true;
413 });
414
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000415 this->node1.face.receive(*command);
Junxiao Shib84e6742016-07-19 13:16:22 +0000416 this->advanceClocks(time::milliseconds(1), 5);
Yanbiao Li73860e32015-08-19 16:30:16 -0700417
418 BOOST_CHECK(hasCallbackFired);
419 }
420}
421
422BOOST_AUTO_TEST_SUITE_END() // CreateFace
423BOOST_AUTO_TEST_SUITE_END() // TestFaceManager
424BOOST_AUTO_TEST_SUITE_END() // Mgmt
425
Weiwei Liuf5aee942016-03-19 07:00:42 +0000426} // namespace tests
427} // namespace nfd