blob: c691491a4eea332120bdc7e6e2744efe94444bd7 [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
123namespace mpl = boost::mpl;
124
Eric Newberry42602412016-08-27 09:33:18 -0700125// pairs of CreateCommand and Success/Failure status
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700126typedef mpl::vector<mpl::pair<TcpFaceOnDemand, CommandFailure<406>>,
127 mpl::pair<TcpFacePersistent, CommandSuccess>,
128 mpl::pair<TcpFacePermanent, CommandFailure<406>>,
129 mpl::pair<UdpFaceOnDemand, CommandFailure<406>>,
130 mpl::pair<UdpFacePersistent, CommandSuccess>,
131 mpl::pair<UdpFacePermanent, CommandSuccess>,
132 mpl::pair<UdpFaceConnectToSelf, CommandFailure<406>>> Faces;
Yanbiao Li73860e32015-08-19 16:30:16 -0700133
Eric Newberry42602412016-08-27 09:33:18 -0700134BOOST_FIXTURE_TEST_CASE_TEMPLATE(NewFace, T, Faces, FaceManagerCommandFixture)
Yanbiao Li73860e32015-08-19 16:30:16 -0700135{
136 typedef typename T::first FaceType;
137 typedef typename T::second CreateResult;
138
139 Name commandName("/localhost/nfd/faces");
140 commandName.append("create");
141 commandName.append(FaceType().getParameters().wireEncode());
Junxiao Shib84e6742016-07-19 13:16:22 +0000142 auto command = makeInterest(commandName);
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000143 m_keyChain.sign(*command);
Yanbiao Li73860e32015-08-19 16:30:16 -0700144
145 bool hasCallbackFired = false;
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000146 this->node1.face.onSendData.connect([this, command, &hasCallbackFired] (const Data& response) {
Eric Newberry42602412016-08-27 09:33:18 -0700147 if (!command->getName().isPrefixOf(response.getName())) {
148 return;
149 }
Yanbiao Li73860e32015-08-19 16:30:16 -0700150
Eric Newberry42602412016-08-27 09:33:18 -0700151 ControlResponse actual(response.getContent().blockFromValue());
152 ControlResponse expected(CreateResult().getExpected());
153 BOOST_CHECK_EQUAL(expected.getCode(), actual.getCode());
154 BOOST_TEST_MESSAGE(actual.getText());
Yanbiao Li73860e32015-08-19 16:30:16 -0700155
Eric Newberry42602412016-08-27 09:33:18 -0700156 if (actual.getBody().hasWire()) {
157 ControlParameters expectedParams(FaceType().getParameters());
158 ControlParameters actualParams(actual.getBody());
Yanbiao Li73860e32015-08-19 16:30:16 -0700159
Eric Newberry42602412016-08-27 09:33:18 -0700160 BOOST_CHECK(actualParams.hasFaceId());
161 BOOST_CHECK_EQUAL(expectedParams.getFacePersistency(), actualParams.getFacePersistency());
162
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700163 if (actual.getCode() == 200) {
164 if (expectedParams.hasFlags()) {
165 // TODO: #3731 check if Flags match
166 }
167 else {
168 // TODO: #3731 check if Flags at defaults
169 }
170 }
171 else {
Yanbiao Li73860e32015-08-19 16:30:16 -0700172 BOOST_CHECK_EQUAL(expectedParams.getUri(), actualParams.getUri());
Yanbiao Li73860e32015-08-19 16:30:16 -0700173 }
Eric Newberry42602412016-08-27 09:33:18 -0700174 }
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700175
176 if (actual.getCode() != 200) {
177 // ensure face not created
178 FaceUri uri(FaceType().getParameters().getUri());
179 auto& faceTable = this->node1.manager.m_faceTable;
180 BOOST_CHECK(std::none_of(faceTable.begin(), faceTable.end(), [uri] (Face& face) {
181 return face.getRemoteUri() == uri;
182 }));
183 }
184
Eric Newberry42602412016-08-27 09:33:18 -0700185 hasCallbackFired = true;
186 });
Yanbiao Li73860e32015-08-19 16:30:16 -0700187
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000188 this->node1.face.receive(*command);
Junxiao Shib84e6742016-07-19 13:16:22 +0000189 this->advanceClocks(time::milliseconds(1), 5);
Yanbiao Li73860e32015-08-19 16:30:16 -0700190
191 BOOST_CHECK(hasCallbackFired);
192}
193
194
195typedef mpl::vector<// mpl::pair<mpl::pair<TcpFacePersistent, TcpFacePermanent>, TcpFacePermanent>, // no need to check now
196 // mpl::pair<mpl::pair<TcpFacePermanent, TcpFacePersistent>, TcpFacePermanent>, // no need to check now
197 mpl::pair<mpl::pair<UdpFacePersistent, UdpFacePermanent>, UdpFacePermanent>,
198 mpl::pair<mpl::pair<UdpFacePermanent, UdpFacePersistent>, UdpFacePermanent>> FaceTransitions;
199
200
Eric Newberry42602412016-08-27 09:33:18 -0700201BOOST_FIXTURE_TEST_CASE_TEMPLATE(ExistingFace, T, FaceTransitions, FaceManagerCommandFixture)
Yanbiao Li73860e32015-08-19 16:30:16 -0700202{
203 typedef typename T::first::first FaceType1;
204 typedef typename T::first::second FaceType2;
205 typedef typename T::second FinalFaceType;
206
207 {
208 // create face
209
210 Name commandName("/localhost/nfd/faces");
211 commandName.append("create");
212 commandName.append(FaceType1().getParameters().wireEncode());
Junxiao Shib84e6742016-07-19 13:16:22 +0000213 auto command = makeInterest(commandName);
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000214 m_keyChain.sign(*command);
Yanbiao Li73860e32015-08-19 16:30:16 -0700215
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000216 this->node1.face.receive(*command);
Junxiao Shib84e6742016-07-19 13:16:22 +0000217 this->advanceClocks(time::milliseconds(1), 5);
Yanbiao Li73860e32015-08-19 16:30:16 -0700218 }
219
220 //
221 {
222 // re-create face (= change face persistency)
223
224 Name commandName("/localhost/nfd/faces");
225 commandName.append("create");
226 commandName.append(FaceType2().getParameters().wireEncode());
Junxiao Shib84e6742016-07-19 13:16:22 +0000227 auto command = makeInterest(commandName);
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000228 m_keyChain.sign(*command);
Yanbiao Li73860e32015-08-19 16:30:16 -0700229
230 bool hasCallbackFired = false;
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000231 this->node1.face.onSendData.connect([this, command, &hasCallbackFired] (const Data& response) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700232 if (!command->getName().isPrefixOf(response.getName())) {
233 return;
234 }
235
236 ControlResponse actual(response.getContent().blockFromValue());
237 BOOST_REQUIRE_EQUAL(actual.getCode(), 200);
238
239 ControlParameters expectedParams(FinalFaceType().getParameters());
240 ControlParameters actualParams(actual.getBody());
Eric Newberry42602412016-08-27 09:33:18 -0700241 BOOST_REQUIRE(!actualParams.hasUri()); // Uri parameter is only included on command failure
Yanbiao Li73860e32015-08-19 16:30:16 -0700242 BOOST_CHECK_EQUAL(expectedParams.getFacePersistency(), actualParams.getFacePersistency());
243
244 hasCallbackFired = true;
245 });
246
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000247 this->node1.face.receive(*command);
Junxiao Shib84e6742016-07-19 13:16:22 +0000248 this->advanceClocks(time::milliseconds(1), 5);
Yanbiao Li73860e32015-08-19 16:30:16 -0700249
250 BOOST_CHECK(hasCallbackFired);
251 }
252}
253
254
255class UdpFace
256{
257public:
258 ControlParameters
259 getParameters()
260 {
261 return ControlParameters()
262 .setUri("udp4://127.0.0.1:16363")
263 .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT);
264 }
265};
266
267
268// Note that the transitions from on-demand TcpFace are intentionally not tested.
269// On-demand TcpFace has a remote endpoint with a randomized port number. Normal face
270// creation operations will not need to create a face toward a remote port not listened by
271// a channel.
272
273typedef mpl::vector<mpl::pair<UdpFace, UdpFacePersistent>,
274 mpl::pair<UdpFace, UdpFacePermanent>> OnDemandFaceTransitions;
275
276// need a slightly different logic to test transitions from OnDemand state
Eric Newberry42602412016-08-27 09:33:18 -0700277BOOST_FIXTURE_TEST_CASE_TEMPLATE(ExistingFaceOnDemand, T, OnDemandFaceTransitions, FaceManagerCommandFixture)
Yanbiao Li73860e32015-08-19 16:30:16 -0700278{
279 typedef typename T::first OtherNodeFace;
280 typedef typename T::second FaceType;
281
282 {
283 // create on-demand face
284
285 Name commandName("/localhost/nfd/faces");
286 commandName.append("create");
287 commandName.append(OtherNodeFace().getParameters().wireEncode());
Junxiao Shib84e6742016-07-19 13:16:22 +0000288 auto command = makeInterest(commandName);
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000289 m_keyChain.sign(*command);
Yanbiao Li73860e32015-08-19 16:30:16 -0700290
291 ndn::util::signal::ScopedConnection connection =
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000292 this->node2.face.onSendData.connect([this, command] (const Data& response) {
Eric Newberry42602412016-08-27 09:33:18 -0700293 if (!command->getName().isPrefixOf(response.getName())) {
294 return;
295 }
Yanbiao Li73860e32015-08-19 16:30:16 -0700296
Eric Newberry42602412016-08-27 09:33:18 -0700297 ControlResponse controlResponse(response.getContent().blockFromValue());
298 BOOST_REQUIRE_EQUAL(controlResponse.getText(), "OK");
299 BOOST_REQUIRE_EQUAL(controlResponse.getCode(), 200);
300 BOOST_REQUIRE(!ControlParameters(controlResponse.getBody()).hasUri());
301 uint64_t faceId = ControlParameters(controlResponse.getBody()).getFaceId();
302 auto face = this->node2.faceTable.get(static_cast<FaceId>(faceId));
Yanbiao Li73860e32015-08-19 16:30:16 -0700303
Eric Newberry42602412016-08-27 09:33:18 -0700304 // to force creation of on-demand face
305 auto dummyInterest = make_shared<Interest>("/hello/world");
306 face->sendInterest(*dummyInterest);
307 });
Yanbiao Li73860e32015-08-19 16:30:16 -0700308
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000309 this->node2.face.receive(*command);
Junxiao Shib84e6742016-07-19 13:16:22 +0000310 this->advanceClocks(time::milliseconds(1), 5); // let node2 process command and send Interest
311 std::this_thread::sleep_for(std::chrono::milliseconds(100)); // allow wallclock time for socket IO
312 this->advanceClocks(time::milliseconds(1), 5); // let node1 accept Interest and create on-demand face
Yanbiao Li73860e32015-08-19 16:30:16 -0700313 }
314
315 // make sure there is on-demand face
Yanbiao Li73860e32015-08-19 16:30:16 -0700316 FaceUri onDemandFaceUri(FaceType().getParameters().getUri());
Junxiao Shib84e6742016-07-19 13:16:22 +0000317 const Face* foundFace = nullptr;
318 for (const Face& face : this->node1.faceTable) {
319 if (face.getRemoteUri() == onDemandFaceUri) {
320 foundFace = &face;
Yanbiao Li73860e32015-08-19 16:30:16 -0700321 break;
322 }
323 }
Junxiao Shib84e6742016-07-19 13:16:22 +0000324 BOOST_REQUIRE_MESSAGE(foundFace != nullptr, "on-demand face is not created");
Yanbiao Li73860e32015-08-19 16:30:16 -0700325
326 //
327 {
328 // re-create face (= change face persistency)
329
330 Name commandName("/localhost/nfd/faces");
331 commandName.append("create");
332 commandName.append(FaceType().getParameters().wireEncode());
Junxiao Shib84e6742016-07-19 13:16:22 +0000333 auto command = makeInterest(commandName);
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000334 m_keyChain.sign(*command);
Yanbiao Li73860e32015-08-19 16:30:16 -0700335
336 bool hasCallbackFired = false;
Junxiao Shib84e6742016-07-19 13:16:22 +0000337 this->node1.face.onSendData.connect(
338 [this, command, &hasCallbackFired, foundFace] (const Data& response) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700339 if (!command->getName().isPrefixOf(response.getName())) {
340 return;
341 }
342
343 ControlResponse actual(response.getContent().blockFromValue());
344 BOOST_REQUIRE_EQUAL(actual.getCode(), 200);
345
346 ControlParameters expectedParams(FaceType().getParameters());
347 ControlParameters actualParams(actual.getBody());
Eric Newberry42602412016-08-27 09:33:18 -0700348 BOOST_REQUIRE(!actualParams.hasUri());
Junxiao Shib84e6742016-07-19 13:16:22 +0000349 BOOST_CHECK_EQUAL(actualParams.getFacePersistency(), expectedParams.getFacePersistency());
350 BOOST_CHECK_EQUAL(actualParams.getFaceId(), foundFace->getId());
351 BOOST_CHECK_EQUAL(foundFace->getPersistency(), expectedParams.getFacePersistency());
Yanbiao Li73860e32015-08-19 16:30:16 -0700352
353 hasCallbackFired = true;
354 });
355
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000356 this->node1.face.receive(*command);
Junxiao Shib84e6742016-07-19 13:16:22 +0000357 this->advanceClocks(time::milliseconds(1), 5);
Yanbiao Li73860e32015-08-19 16:30:16 -0700358
359 BOOST_CHECK(hasCallbackFired);
360 }
361}
362
363BOOST_AUTO_TEST_SUITE_END() // CreateFace
364BOOST_AUTO_TEST_SUITE_END() // TestFaceManager
365BOOST_AUTO_TEST_SUITE_END() // Mgmt
366
Weiwei Liuf5aee942016-03-19 07:00:42 +0000367} // namespace tests
368} // namespace nfd