blob: 13031fbe3469e92be045947a13f195eec744c5a4 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shi7b6b79d2014-03-26 20:59:35 -07002/**
Junxiao Shi034c1882016-06-24 18:06:51 +00003 * Copyright (c) 2013-2016 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070020 */
21
22#include "management/nfd-controller.hpp"
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070023#include "management/nfd-control-response.hpp"
24
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070025#include <boost/tuple/tuple.hpp>
26
Junxiao Shi034c1882016-06-24 18:06:51 +000027#include "nfd-controller-fixture.hpp"
Junxiao Shib1990df2015-11-05 00:14:44 +000028#include "../make-interest-data.hpp"
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070029
30namespace ndn {
31namespace nfd {
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070032namespace tests {
33
Junxiao Shi85d90832016-08-04 03:19:46 +000034using namespace ndn::tests;
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070035
Junxiao Shib1990df2015-11-05 00:14:44 +000036BOOST_AUTO_TEST_SUITE(Management)
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070037
Junxiao Shi034c1882016-06-24 18:06:51 +000038class CommandFixture : public ControllerFixture
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070039{
40protected:
41 CommandFixture()
Junxiao Shi034c1882016-06-24 18:06:51 +000042 : succeedCallback(bind(&CommandFixture::succeed, this, _1))
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070043 {
44 }
45
46private:
47 void
Junxiao Shi034c1882016-06-24 18:06:51 +000048 succeed(const ControlParameters& parameters)
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070049 {
Junxiao Shi034c1882016-06-24 18:06:51 +000050 succeeds.push_back(parameters);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070051 }
52
53protected:
Junxiao Shi034c1882016-06-24 18:06:51 +000054 Controller::CommandSucceedCallback succeedCallback;
55 std::vector<ControlParameters> succeeds;
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070056};
57
Junxiao Shi600f7112016-07-16 11:57:18 +000058// This test suite focuses on ControlCommand functionality of Controller.
59// Individual commands are tested in nfd-control-command.t.cpp
60// StatusDataset functionality is tested in nfd-status-dataset.t.cpp
Junxiao Shib1990df2015-11-05 00:14:44 +000061BOOST_FIXTURE_TEST_SUITE(TestNfdController, CommandFixture)
62
Junxiao Shi600f7112016-07-16 11:57:18 +000063BOOST_AUTO_TEST_CASE(Success)
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070064{
65 ControlParameters parameters;
Junxiao Shi5de006b2014-10-26 20:20:52 -070066 parameters.setUri("tcp4://192.0.2.1:6363");
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070067
68 BOOST_CHECK_NO_THROW(controller.start<FaceCreateCommand>(
Junxiao Shie7c7f152016-08-20 22:36:22 +000069 parameters, succeedCallback, commandFailCallback));
Junxiao Shi600f7112016-07-16 11:57:18 +000070 this->advanceClocks(time::milliseconds(1));
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070071
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -080072 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
73 const Interest& requestInterest = face.sentInterests[0];
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070074
75 FaceCreateCommand command;
Junxiao Shi5de006b2014-10-26 20:20:52 -070076 BOOST_CHECK(Name("/localhost/nfd/faces/create").isPrefixOf(requestInterest.getName()));
77 // 9 components: ndn:/localhost/nfd/faces/create/<parameters>/<signed Interest x4>
Junxiao Shi6a90f372014-10-13 20:29:30 -070078 BOOST_REQUIRE_EQUAL(requestInterest.getName().size(), 9);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070079 ControlParameters request;
80 // 4th component: <parameters>
Junxiao Shi6a90f372014-10-13 20:29:30 -070081 BOOST_REQUIRE_NO_THROW(request.wireDecode(requestInterest.getName().at(4).blockFromValue()));
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070082 BOOST_CHECK_NO_THROW(command.validateRequest(request));
83 BOOST_CHECK_EQUAL(request.getUri(), parameters.getUri());
Junxiao Shi415b17c2014-11-12 00:43:25 -070084 BOOST_CHECK_EQUAL(requestInterest.getInterestLifetime(), CommandOptions::DEFAULT_TIMEOUT);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070085
86 ControlParameters responseBody;
87 responseBody.setUri("tcp4://192.0.2.1:6363")
Yukai Tud93c5fc2015-08-25 11:37:16 +080088 .setFaceId(22)
89 .setFacePersistency(ndn::nfd::FacePersistency::FACE_PERSISTENCY_PERSISTENT);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070090 ControlResponse responsePayload(201, "created");
91 responsePayload.setBody(responseBody.wireEncode());
92
Junxiao Shi034c1882016-06-24 18:06:51 +000093 auto responseData = makeData(requestInterest.getName());
Junxiao Shib1990df2015-11-05 00:14:44 +000094 responseData->setContent(responsePayload.wireEncode());
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -080095 face.receive(*responseData);
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -080096
Junxiao Shi600f7112016-07-16 11:57:18 +000097 this->advanceClocks(time::milliseconds(1));
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070098
Junxiao Shi034c1882016-06-24 18:06:51 +000099 BOOST_CHECK_EQUAL(failCodes.size(), 0);
100 BOOST_REQUIRE_EQUAL(succeeds.size(), 1);
101 BOOST_CHECK_EQUAL(succeeds.back().getUri(), responseBody.getUri());
102 BOOST_CHECK_EQUAL(succeeds.back().getFaceId(), responseBody.getFaceId());
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700103}
104
Junxiao Shi600f7112016-07-16 11:57:18 +0000105BOOST_AUTO_TEST_CASE(SuccessNoCallback)
106{
107 ControlParameters parameters;
108 parameters.setUri("tcp4://192.0.2.1:6363");
109
Junxiao Shie7c7f152016-08-20 22:36:22 +0000110 controller.start<FaceCreateCommand>(parameters, nullptr, commandFailCallback);
Junxiao Shi600f7112016-07-16 11:57:18 +0000111 this->advanceClocks(time::milliseconds(1));
112
113 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
114 const Interest& requestInterest = face.sentInterests[0];
115
116 ControlParameters responseBody;
117 responseBody.setUri("tcp4://192.0.2.1:6363")
118 .setFaceId(22)
119 .setFacePersistency(ndn::nfd::FacePersistency::FACE_PERSISTENCY_PERSISTENT);
120 ControlResponse responsePayload(201, "created");
121 responsePayload.setBody(responseBody.wireEncode());
122
123 auto responseData = makeData(requestInterest.getName());
124 responseData->setContent(responsePayload.wireEncode());
125 face.receive(*responseData);
126
127 BOOST_CHECK_NO_THROW(this->advanceClocks(time::milliseconds(1)));
128
129 BOOST_CHECK_EQUAL(failCodes.size(), 0);
130}
131
132BOOST_AUTO_TEST_CASE(OptionsPrefix)
133{
134 ControlParameters parameters;
135 parameters.setName("/ndn/com/example");
136 parameters.setFaceId(400);
137
138 CommandOptions options;
139 options.setPrefix("/localhop/net/example/router1/nfd");
140
141 BOOST_CHECK_NO_THROW(controller.start<RibRegisterCommand>(
Junxiao Shie7c7f152016-08-20 22:36:22 +0000142 parameters, succeedCallback, commandFailCallback, options));
Junxiao Shi600f7112016-07-16 11:57:18 +0000143 this->advanceClocks(time::milliseconds(1));
144
145 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
146 const Interest& requestInterest = face.sentInterests[0];
147
148 FaceCreateCommand command;
149 BOOST_CHECK(Name("/localhop/net/example/router1/nfd/rib/register").isPrefixOf(
150 requestInterest.getName()));
151}
152
153BOOST_AUTO_TEST_CASE(InvalidRequest)
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700154{
155 ControlParameters parameters;
156 parameters.setName("ndn:/should-not-have-this-field");
157 // Uri is missing
158
159 BOOST_CHECK_THROW(controller.start<FaceCreateCommand>(
Junxiao Shie7c7f152016-08-20 22:36:22 +0000160 parameters, succeedCallback, commandFailCallback),
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700161 ControlCommand::ArgumentError);
162}
163
Junxiao Shi54f727d2016-08-08 20:29:11 +0000164BOOST_AUTO_TEST_CASE(ValidationFailure)
165{
166 this->setValidationResult(false);
167
168 ControlParameters parameters;
169 parameters.setUri("tcp4://192.0.2.1:6363");
170
171 BOOST_CHECK_NO_THROW(controller.start<FaceCreateCommand>(
Junxiao Shie7c7f152016-08-20 22:36:22 +0000172 parameters, succeedCallback, commandFailCallback));
Junxiao Shi54f727d2016-08-08 20:29:11 +0000173 this->advanceClocks(time::milliseconds(1));
174
175 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
176 const Interest& requestInterest = face.sentInterests[0];
177
178 ControlParameters responseBody;
179 responseBody.setUri("tcp4://192.0.2.1:6363")
180 .setFaceId(22)
181 .setFacePersistency(ndn::nfd::FacePersistency::FACE_PERSISTENCY_PERSISTENT);
182 ControlResponse responsePayload(201, "created");
183 responsePayload.setBody(responseBody.wireEncode());
184
185 auto responseData = makeData(requestInterest.getName());
186 responseData->setContent(responsePayload.wireEncode());
187 face.receive(*responseData);
188 this->advanceClocks(time::milliseconds(1));
189
190 BOOST_CHECK_EQUAL(succeeds.size(), 0);
191 BOOST_REQUIRE_EQUAL(failCodes.size(), 1);
192 BOOST_CHECK_EQUAL(failCodes.back(), Controller::ERROR_VALIDATION);
193}
194
Junxiao Shi600f7112016-07-16 11:57:18 +0000195BOOST_AUTO_TEST_CASE(ErrorCode)
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700196{
197 ControlParameters parameters;
Junxiao Shi5de006b2014-10-26 20:20:52 -0700198 parameters.setUri("tcp4://192.0.2.1:6363");
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700199
200 BOOST_CHECK_NO_THROW(controller.start<FaceCreateCommand>(
Junxiao Shie7c7f152016-08-20 22:36:22 +0000201 parameters, succeedCallback, commandFailCallback));
Junxiao Shi600f7112016-07-16 11:57:18 +0000202 this->advanceClocks(time::milliseconds(1));
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700203
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800204 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
205 const Interest& requestInterest = face.sentInterests[0];
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700206
207 ControlResponse responsePayload(401, "Not Authenticated");
208
Junxiao Shi034c1882016-06-24 18:06:51 +0000209 auto responseData = makeData(requestInterest.getName());
Junxiao Shib1990df2015-11-05 00:14:44 +0000210 responseData->setContent(responsePayload.wireEncode());
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800211 face.receive(*responseData);
Junxiao Shi600f7112016-07-16 11:57:18 +0000212 this->advanceClocks(time::milliseconds(1));
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700213
Junxiao Shi034c1882016-06-24 18:06:51 +0000214 BOOST_CHECK_EQUAL(succeeds.size(), 0);
215 BOOST_REQUIRE_EQUAL(failCodes.size(), 1);
216 BOOST_CHECK_EQUAL(failCodes.back(), 401);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700217}
218
Junxiao Shi600f7112016-07-16 11:57:18 +0000219BOOST_AUTO_TEST_CASE(InvalidResponse)
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700220{
221 ControlParameters parameters;
Junxiao Shi5de006b2014-10-26 20:20:52 -0700222 parameters.setUri("tcp4://192.0.2.1:6363");
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700223
224 BOOST_CHECK_NO_THROW(controller.start<FaceCreateCommand>(
Junxiao Shie7c7f152016-08-20 22:36:22 +0000225 parameters, succeedCallback, commandFailCallback));
Junxiao Shi600f7112016-07-16 11:57:18 +0000226 this->advanceClocks(time::milliseconds(1));
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700227
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800228 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
229 const Interest& requestInterest = face.sentInterests[0];
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700230
231 ControlParameters responseBody;
232 responseBody.setUri("tcp4://192.0.2.1:6363")
233 .setName("ndn:/should-not-have-this-field");
234 // FaceId is missing
235 ControlResponse responsePayload(201, "created");
236 responsePayload.setBody(responseBody.wireEncode());
237
Junxiao Shi034c1882016-06-24 18:06:51 +0000238 auto responseData = makeData(requestInterest.getName());
Junxiao Shib1990df2015-11-05 00:14:44 +0000239 responseData->setContent(responsePayload.wireEncode());
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800240 face.receive(*responseData);
Junxiao Shi600f7112016-07-16 11:57:18 +0000241 this->advanceClocks(time::milliseconds(1));
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700242
Junxiao Shi034c1882016-06-24 18:06:51 +0000243 BOOST_CHECK_EQUAL(succeeds.size(), 0);
244 BOOST_REQUIRE_EQUAL(failCodes.size(), 1);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700245}
246
Junxiao Shi600f7112016-07-16 11:57:18 +0000247BOOST_AUTO_TEST_CASE(Nack)
Junxiao Shib1990df2015-11-05 00:14:44 +0000248{
249 ControlParameters parameters;
250 parameters.setUri("tcp4://192.0.2.1:6363");
251
252 BOOST_CHECK_NO_THROW(controller.start<FaceCreateCommand>(
Junxiao Shie7c7f152016-08-20 22:36:22 +0000253 parameters, succeedCallback, commandFailCallback));
Junxiao Shi600f7112016-07-16 11:57:18 +0000254 this->advanceClocks(time::milliseconds(1));
Junxiao Shib1990df2015-11-05 00:14:44 +0000255
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800256 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
257 const Interest& requestInterest = face.sentInterests[0];
Junxiao Shib1990df2015-11-05 00:14:44 +0000258
Junxiao Shi034c1882016-06-24 18:06:51 +0000259 auto responseNack = makeNack(requestInterest, lp::NackReason::NO_ROUTE);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800260 face.receive(responseNack);
Junxiao Shi600f7112016-07-16 11:57:18 +0000261 this->advanceClocks(time::milliseconds(1));
Junxiao Shib1990df2015-11-05 00:14:44 +0000262
Junxiao Shi034c1882016-06-24 18:06:51 +0000263 BOOST_REQUIRE_EQUAL(failCodes.size(), 1);
264 BOOST_CHECK_EQUAL(failCodes.back(), Controller::ERROR_NACK);
Junxiao Shib1990df2015-11-05 00:14:44 +0000265}
266
Junxiao Shi600f7112016-07-16 11:57:18 +0000267BOOST_AUTO_TEST_CASE(Timeout)
Junxiao Shi5de006b2014-10-26 20:20:52 -0700268{
269 ControlParameters parameters;
270 parameters.setUri("tcp4://192.0.2.1:6363");
271
272 CommandOptions options;
273 options.setTimeout(time::milliseconds(50));
274
275 BOOST_CHECK_NO_THROW(controller.start<FaceCreateCommand>(
Junxiao Shie7c7f152016-08-20 22:36:22 +0000276 parameters, succeedCallback, commandFailCallback, options));
Junxiao Shi600f7112016-07-16 11:57:18 +0000277 this->advanceClocks(time::milliseconds(1), 101); // Face's PIT granularity is 100ms
Junxiao Shi5de006b2014-10-26 20:20:52 -0700278
Junxiao Shi034c1882016-06-24 18:06:51 +0000279 BOOST_REQUIRE_EQUAL(failCodes.size(), 1);
280 BOOST_CHECK_EQUAL(failCodes.back(), Controller::ERROR_TIMEOUT);
Junxiao Shi5de006b2014-10-26 20:20:52 -0700281}
282
Junxiao Shi600f7112016-07-16 11:57:18 +0000283BOOST_AUTO_TEST_CASE(FailureNoCallback)
284{
285 ControlParameters parameters;
286 parameters.setUri("tcp4://192.0.2.1:6363");
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700287
Junxiao Shi600f7112016-07-16 11:57:18 +0000288 CommandOptions options;
289 options.setTimeout(time::milliseconds(50));
290
291 controller.start<FaceCreateCommand>(parameters, succeedCallback, nullptr, options);
292 BOOST_CHECK_NO_THROW(this->advanceClocks(time::milliseconds(100), 10));
293 // timeout
294
295 BOOST_CHECK_EQUAL(succeeds.size(), 0);
296}
297
298BOOST_AUTO_TEST_SUITE_END() // TestNfdController
299BOOST_AUTO_TEST_SUITE_END() // Management
Junxiao Shi034c1882016-06-24 18:06:51 +0000300
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700301} // namespace tests
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700302} // namespace nfd
303} // namespace ndn