blob: 052b89c8cd7b90f487d5a1f37b9cb539f97c1fa8 [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
Eric Newberry42602412016-08-27 09:33:18 -070087class UdpFaceConnectToSelf // face that will cause afterCreateFaceFailure to be invoked
88 // fails because remote endpoint is prohibited
Yanbiao Li73860e32015-08-19 16:30:16 -070089{
90public:
91 ControlParameters
92 getParameters()
93 {
94 return ControlParameters()
95 .setUri("udp4://0.0.0.0:16363"); // cannot connect to self
96 }
97};
98
99
100class UdpFacePersistent
101{
102public:
103 ControlParameters
104 getParameters()
105 {
106 return ControlParameters()
107 .setUri("udp4://127.0.0.1:26363")
108 .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT);
109 }
110};
111
112class UdpFacePermanent
113{
114public:
115 ControlParameters
116 getParameters()
117 {
118 return ControlParameters()
119 .setUri("udp4://127.0.0.1:26363")
120 .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERMANENT);
121 }
122};
123
124class Success
125{
126public:
127 ControlResponse
128 getExpected()
129 {
130 return ControlResponse()
131 .setCode(200)
132 .setText("OK");
133 }
134};
135
136template<int CODE>
137class Failure
138{
139public:
140 ControlResponse
141 getExpected()
142 {
143 return ControlResponse()
144 .setCode(CODE)
145 .setText("Error"); // error description should not be checked
146 }
147};
148
149namespace mpl = boost::mpl;
150
Eric Newberry42602412016-08-27 09:33:18 -0700151// pairs of CreateCommand and Success/Failure status
152typedef mpl::vector<mpl::pair<TcpFaceOnDemand, Failure<406>>,
Yanbiao Li73860e32015-08-19 16:30:16 -0700153 mpl::pair<TcpFacePersistent, Success>,
Eric Newberry42602412016-08-27 09:33:18 -0700154 mpl::pair<TcpFacePermanent, Failure<406>>,
155 mpl::pair<UdpFaceOnDemand, Failure<406>>,
Yanbiao Li73860e32015-08-19 16:30:16 -0700156 mpl::pair<UdpFacePersistent, Success>,
157 mpl::pair<UdpFacePermanent, Success>,
Eric Newberry42602412016-08-27 09:33:18 -0700158 mpl::pair<UdpFaceConnectToSelf, Failure<406>>> Faces;
Yanbiao Li73860e32015-08-19 16:30:16 -0700159
Eric Newberry42602412016-08-27 09:33:18 -0700160BOOST_FIXTURE_TEST_CASE_TEMPLATE(NewFace, T, Faces, FaceManagerCommandFixture)
Yanbiao Li73860e32015-08-19 16:30:16 -0700161{
162 typedef typename T::first FaceType;
163 typedef typename T::second CreateResult;
164
165 Name commandName("/localhost/nfd/faces");
166 commandName.append("create");
167 commandName.append(FaceType().getParameters().wireEncode());
Junxiao Shib84e6742016-07-19 13:16:22 +0000168 auto command = makeInterest(commandName);
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000169 m_keyChain.sign(*command);
Yanbiao Li73860e32015-08-19 16:30:16 -0700170
171 bool hasCallbackFired = false;
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000172 this->node1.face.onSendData.connect([this, command, &hasCallbackFired] (const Data& response) {
Eric Newberry42602412016-08-27 09:33:18 -0700173 if (!command->getName().isPrefixOf(response.getName())) {
174 return;
175 }
Yanbiao Li73860e32015-08-19 16:30:16 -0700176
Eric Newberry42602412016-08-27 09:33:18 -0700177 ControlResponse actual(response.getContent().blockFromValue());
178 ControlResponse expected(CreateResult().getExpected());
179 BOOST_CHECK_EQUAL(expected.getCode(), actual.getCode());
180 BOOST_TEST_MESSAGE(actual.getText());
Yanbiao Li73860e32015-08-19 16:30:16 -0700181
Eric Newberry42602412016-08-27 09:33:18 -0700182 if (actual.getBody().hasWire()) {
183 ControlParameters expectedParams(FaceType().getParameters());
184 ControlParameters actualParams(actual.getBody());
Yanbiao Li73860e32015-08-19 16:30:16 -0700185
Eric Newberry42602412016-08-27 09:33:18 -0700186 BOOST_CHECK(actualParams.hasFaceId());
187 BOOST_CHECK_EQUAL(expectedParams.getFacePersistency(), actualParams.getFacePersistency());
188
189 if (actual.getCode() != 200) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700190 BOOST_CHECK_EQUAL(expectedParams.getUri(), actualParams.getUri());
Yanbiao Li73860e32015-08-19 16:30:16 -0700191 }
Eric Newberry42602412016-08-27 09:33:18 -0700192 }
193 hasCallbackFired = true;
194 });
Yanbiao Li73860e32015-08-19 16:30:16 -0700195
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000196 this->node1.face.receive(*command);
Junxiao Shib84e6742016-07-19 13:16:22 +0000197 this->advanceClocks(time::milliseconds(1), 5);
Yanbiao Li73860e32015-08-19 16:30:16 -0700198
199 BOOST_CHECK(hasCallbackFired);
200}
201
202
203typedef mpl::vector<// mpl::pair<mpl::pair<TcpFacePersistent, TcpFacePermanent>, TcpFacePermanent>, // no need to check now
204 // mpl::pair<mpl::pair<TcpFacePermanent, TcpFacePersistent>, TcpFacePermanent>, // no need to check now
205 mpl::pair<mpl::pair<UdpFacePersistent, UdpFacePermanent>, UdpFacePermanent>,
206 mpl::pair<mpl::pair<UdpFacePermanent, UdpFacePersistent>, UdpFacePermanent>> FaceTransitions;
207
208
Eric Newberry42602412016-08-27 09:33:18 -0700209BOOST_FIXTURE_TEST_CASE_TEMPLATE(ExistingFace, T, FaceTransitions, FaceManagerCommandFixture)
Yanbiao Li73860e32015-08-19 16:30:16 -0700210{
211 typedef typename T::first::first FaceType1;
212 typedef typename T::first::second FaceType2;
213 typedef typename T::second FinalFaceType;
214
215 {
216 // create face
217
218 Name commandName("/localhost/nfd/faces");
219 commandName.append("create");
220 commandName.append(FaceType1().getParameters().wireEncode());
Junxiao Shib84e6742016-07-19 13:16:22 +0000221 auto command = makeInterest(commandName);
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000222 m_keyChain.sign(*command);
Yanbiao Li73860e32015-08-19 16:30:16 -0700223
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000224 this->node1.face.receive(*command);
Junxiao Shib84e6742016-07-19 13:16:22 +0000225 this->advanceClocks(time::milliseconds(1), 5);
Yanbiao Li73860e32015-08-19 16:30:16 -0700226 }
227
228 //
229 {
230 // re-create face (= change face persistency)
231
232 Name commandName("/localhost/nfd/faces");
233 commandName.append("create");
234 commandName.append(FaceType2().getParameters().wireEncode());
Junxiao Shib84e6742016-07-19 13:16:22 +0000235 auto command = makeInterest(commandName);
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000236 m_keyChain.sign(*command);
Yanbiao Li73860e32015-08-19 16:30:16 -0700237
238 bool hasCallbackFired = false;
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000239 this->node1.face.onSendData.connect([this, command, &hasCallbackFired] (const Data& response) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700240 if (!command->getName().isPrefixOf(response.getName())) {
241 return;
242 }
243
244 ControlResponse actual(response.getContent().blockFromValue());
245 BOOST_REQUIRE_EQUAL(actual.getCode(), 200);
246
247 ControlParameters expectedParams(FinalFaceType().getParameters());
248 ControlParameters actualParams(actual.getBody());
Eric Newberry42602412016-08-27 09:33:18 -0700249 BOOST_REQUIRE(!actualParams.hasUri()); // Uri parameter is only included on command failure
Yanbiao Li73860e32015-08-19 16:30:16 -0700250 BOOST_CHECK_EQUAL(expectedParams.getFacePersistency(), actualParams.getFacePersistency());
251
252 hasCallbackFired = true;
253 });
254
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000255 this->node1.face.receive(*command);
Junxiao Shib84e6742016-07-19 13:16:22 +0000256 this->advanceClocks(time::milliseconds(1), 5);
Yanbiao Li73860e32015-08-19 16:30:16 -0700257
258 BOOST_CHECK(hasCallbackFired);
259 }
260}
261
262
263class UdpFace
264{
265public:
266 ControlParameters
267 getParameters()
268 {
269 return ControlParameters()
270 .setUri("udp4://127.0.0.1:16363")
271 .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT);
272 }
273};
274
275
276// Note that the transitions from on-demand TcpFace are intentionally not tested.
277// On-demand TcpFace has a remote endpoint with a randomized port number. Normal face
278// creation operations will not need to create a face toward a remote port not listened by
279// a channel.
280
281typedef mpl::vector<mpl::pair<UdpFace, UdpFacePersistent>,
282 mpl::pair<UdpFace, UdpFacePermanent>> OnDemandFaceTransitions;
283
284// need a slightly different logic to test transitions from OnDemand state
Eric Newberry42602412016-08-27 09:33:18 -0700285BOOST_FIXTURE_TEST_CASE_TEMPLATE(ExistingFaceOnDemand, T, OnDemandFaceTransitions, FaceManagerCommandFixture)
Yanbiao Li73860e32015-08-19 16:30:16 -0700286{
287 typedef typename T::first OtherNodeFace;
288 typedef typename T::second FaceType;
289
290 {
291 // create on-demand face
292
293 Name commandName("/localhost/nfd/faces");
294 commandName.append("create");
295 commandName.append(OtherNodeFace().getParameters().wireEncode());
Junxiao Shib84e6742016-07-19 13:16:22 +0000296 auto command = makeInterest(commandName);
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000297 m_keyChain.sign(*command);
Yanbiao Li73860e32015-08-19 16:30:16 -0700298
299 ndn::util::signal::ScopedConnection connection =
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000300 this->node2.face.onSendData.connect([this, command] (const Data& response) {
Eric Newberry42602412016-08-27 09:33:18 -0700301 if (!command->getName().isPrefixOf(response.getName())) {
302 return;
303 }
Yanbiao Li73860e32015-08-19 16:30:16 -0700304
Eric Newberry42602412016-08-27 09:33:18 -0700305 ControlResponse controlResponse(response.getContent().blockFromValue());
306 BOOST_REQUIRE_EQUAL(controlResponse.getText(), "OK");
307 BOOST_REQUIRE_EQUAL(controlResponse.getCode(), 200);
308 BOOST_REQUIRE(!ControlParameters(controlResponse.getBody()).hasUri());
309 uint64_t faceId = ControlParameters(controlResponse.getBody()).getFaceId();
310 auto face = this->node2.faceTable.get(static_cast<FaceId>(faceId));
Yanbiao Li73860e32015-08-19 16:30:16 -0700311
Eric Newberry42602412016-08-27 09:33:18 -0700312 // to force creation of on-demand face
313 auto dummyInterest = make_shared<Interest>("/hello/world");
314 face->sendInterest(*dummyInterest);
315 });
Yanbiao Li73860e32015-08-19 16:30:16 -0700316
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000317 this->node2.face.receive(*command);
Junxiao Shib84e6742016-07-19 13:16:22 +0000318 this->advanceClocks(time::milliseconds(1), 5); // let node2 process command and send Interest
319 std::this_thread::sleep_for(std::chrono::milliseconds(100)); // allow wallclock time for socket IO
320 this->advanceClocks(time::milliseconds(1), 5); // let node1 accept Interest and create on-demand face
Yanbiao Li73860e32015-08-19 16:30:16 -0700321 }
322
323 // make sure there is on-demand face
Yanbiao Li73860e32015-08-19 16:30:16 -0700324 FaceUri onDemandFaceUri(FaceType().getParameters().getUri());
Junxiao Shib84e6742016-07-19 13:16:22 +0000325 const Face* foundFace = nullptr;
326 for (const Face& face : this->node1.faceTable) {
327 if (face.getRemoteUri() == onDemandFaceUri) {
328 foundFace = &face;
Yanbiao Li73860e32015-08-19 16:30:16 -0700329 break;
330 }
331 }
Junxiao Shib84e6742016-07-19 13:16:22 +0000332 BOOST_REQUIRE_MESSAGE(foundFace != nullptr, "on-demand face is not created");
Yanbiao Li73860e32015-08-19 16:30:16 -0700333
334 //
335 {
336 // re-create face (= change face persistency)
337
338 Name commandName("/localhost/nfd/faces");
339 commandName.append("create");
340 commandName.append(FaceType().getParameters().wireEncode());
Junxiao Shib84e6742016-07-19 13:16:22 +0000341 auto command = makeInterest(commandName);
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000342 m_keyChain.sign(*command);
Yanbiao Li73860e32015-08-19 16:30:16 -0700343
344 bool hasCallbackFired = false;
Junxiao Shib84e6742016-07-19 13:16:22 +0000345 this->node1.face.onSendData.connect(
346 [this, command, &hasCallbackFired, foundFace] (const Data& response) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700347 if (!command->getName().isPrefixOf(response.getName())) {
348 return;
349 }
350
351 ControlResponse actual(response.getContent().blockFromValue());
352 BOOST_REQUIRE_EQUAL(actual.getCode(), 200);
353
354 ControlParameters expectedParams(FaceType().getParameters());
355 ControlParameters actualParams(actual.getBody());
Eric Newberry42602412016-08-27 09:33:18 -0700356 BOOST_REQUIRE(!actualParams.hasUri());
Junxiao Shib84e6742016-07-19 13:16:22 +0000357 BOOST_CHECK_EQUAL(actualParams.getFacePersistency(), expectedParams.getFacePersistency());
358 BOOST_CHECK_EQUAL(actualParams.getFaceId(), foundFace->getId());
359 BOOST_CHECK_EQUAL(foundFace->getPersistency(), expectedParams.getFacePersistency());
Yanbiao Li73860e32015-08-19 16:30:16 -0700360
361 hasCallbackFired = true;
362 });
363
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000364 this->node1.face.receive(*command);
Junxiao Shib84e6742016-07-19 13:16:22 +0000365 this->advanceClocks(time::milliseconds(1), 5);
Yanbiao Li73860e32015-08-19 16:30:16 -0700366
367 BOOST_CHECK(hasCallbackFired);
368 }
369}
370
371BOOST_AUTO_TEST_SUITE_END() // CreateFace
372BOOST_AUTO_TEST_SUITE_END() // TestFaceManager
373BOOST_AUTO_TEST_SUITE_END() // Mgmt
374
Weiwei Liuf5aee942016-03-19 07:00:42 +0000375} // namespace tests
376} // namespace nfd