blob: 423499aff31e1e229938d29d5f627157a8b24dc5 [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 Shi8c2ab2e2017-05-05 20:26:34 +00003 * Copyright (c) 2013-2017 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
Junxiao Shi7357ef22016-09-07 02:39:37 +000022#include "mgmt/nfd/controller.hpp"
23#include "mgmt/nfd/control-response.hpp"
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070024
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070025#include <boost/tuple/tuple.hpp>
26
Junxiao Shi7357ef22016-09-07 02:39:37 +000027#include "controller-fixture.hpp"
28#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 Shi7357ef22016-09-07 02:39:37 +000036BOOST_AUTO_TEST_SUITE(Mgmt)
37BOOST_AUTO_TEST_SUITE(Nfd)
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070038
Junxiao Shi034c1882016-06-24 18:06:51 +000039class CommandFixture : public ControllerFixture
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070040{
41protected:
42 CommandFixture()
Junxiao Shi034c1882016-06-24 18:06:51 +000043 : succeedCallback(bind(&CommandFixture::succeed, this, _1))
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070044 {
45 }
46
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +000047 void
48 respond(const ControlResponse& responsePayload)
49 {
50 auto responseData = makeData(face.sentInterests.at(0).getName());
51 responseData->setContent(responsePayload.wireEncode());
52 face.receive(*responseData);
53 this->advanceClocks(time::milliseconds(1));
54 }
55
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070056private:
57 void
Junxiao Shi034c1882016-06-24 18:06:51 +000058 succeed(const ControlParameters& parameters)
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070059 {
Junxiao Shi034c1882016-06-24 18:06:51 +000060 succeeds.push_back(parameters);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070061 }
62
63protected:
Junxiao Shi034c1882016-06-24 18:06:51 +000064 Controller::CommandSucceedCallback succeedCallback;
65 std::vector<ControlParameters> succeeds;
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070066};
67
Junxiao Shi600f7112016-07-16 11:57:18 +000068// This test suite focuses on ControlCommand functionality of Controller.
69// Individual commands are tested in nfd-control-command.t.cpp
70// StatusDataset functionality is tested in nfd-status-dataset.t.cpp
Junxiao Shi7357ef22016-09-07 02:39:37 +000071BOOST_FIXTURE_TEST_SUITE(TestController, CommandFixture)
Junxiao Shib1990df2015-11-05 00:14:44 +000072
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +000073static ControlParameters
74makeFaceCreateResponse()
75{
76 ControlParameters resp;
77 resp.setFaceId(22)
78 .setUri("tcp4://192.0.2.1:6363")
79 .setLocalUri("tcp4://192.0.2.2:10847")
80 .setFacePersistency(ndn::nfd::FacePersistency::FACE_PERSISTENCY_PERSISTENT)
81 .setFlags(0x7);
82 return resp;
83}
84
Junxiao Shi600f7112016-07-16 11:57:18 +000085BOOST_AUTO_TEST_CASE(Success)
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070086{
87 ControlParameters parameters;
Junxiao Shi5de006b2014-10-26 20:20:52 -070088 parameters.setUri("tcp4://192.0.2.1:6363");
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070089
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +000090 controller.start<FaceCreateCommand>(parameters, succeedCallback, commandFailCallback);
Junxiao Shi600f7112016-07-16 11:57:18 +000091 this->advanceClocks(time::milliseconds(1));
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070092
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -080093 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
94 const Interest& requestInterest = face.sentInterests[0];
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070095
96 FaceCreateCommand command;
Junxiao Shi5de006b2014-10-26 20:20:52 -070097 BOOST_CHECK(Name("/localhost/nfd/faces/create").isPrefixOf(requestInterest.getName()));
98 // 9 components: ndn:/localhost/nfd/faces/create/<parameters>/<signed Interest x4>
Junxiao Shi6a90f372014-10-13 20:29:30 -070099 BOOST_REQUIRE_EQUAL(requestInterest.getName().size(), 9);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700100 ControlParameters request;
101 // 4th component: <parameters>
Junxiao Shi6a90f372014-10-13 20:29:30 -0700102 BOOST_REQUIRE_NO_THROW(request.wireDecode(requestInterest.getName().at(4).blockFromValue()));
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700103 BOOST_CHECK_NO_THROW(command.validateRequest(request));
104 BOOST_CHECK_EQUAL(request.getUri(), parameters.getUri());
Junxiao Shi415b17c2014-11-12 00:43:25 -0700105 BOOST_CHECK_EQUAL(requestInterest.getInterestLifetime(), CommandOptions::DEFAULT_TIMEOUT);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700106
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000107 ControlParameters responseBody = makeFaceCreateResponse();
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700108 ControlResponse responsePayload(201, "created");
109 responsePayload.setBody(responseBody.wireEncode());
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000110 this->respond(responsePayload);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700111
Junxiao Shi034c1882016-06-24 18:06:51 +0000112 BOOST_CHECK_EQUAL(failCodes.size(), 0);
113 BOOST_REQUIRE_EQUAL(succeeds.size(), 1);
114 BOOST_CHECK_EQUAL(succeeds.back().getUri(), responseBody.getUri());
115 BOOST_CHECK_EQUAL(succeeds.back().getFaceId(), responseBody.getFaceId());
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700116}
117
Junxiao Shi600f7112016-07-16 11:57:18 +0000118BOOST_AUTO_TEST_CASE(SuccessNoCallback)
119{
120 ControlParameters parameters;
121 parameters.setUri("tcp4://192.0.2.1:6363");
122
Junxiao Shie7c7f152016-08-20 22:36:22 +0000123 controller.start<FaceCreateCommand>(parameters, nullptr, commandFailCallback);
Junxiao Shi600f7112016-07-16 11:57:18 +0000124 this->advanceClocks(time::milliseconds(1));
125
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000126 ControlParameters responseBody = makeFaceCreateResponse();
Junxiao Shi600f7112016-07-16 11:57:18 +0000127 ControlResponse responsePayload(201, "created");
128 responsePayload.setBody(responseBody.wireEncode());
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000129 this->respond(responsePayload);
Junxiao Shi600f7112016-07-16 11:57:18 +0000130
131 BOOST_CHECK_EQUAL(failCodes.size(), 0);
132}
133
134BOOST_AUTO_TEST_CASE(OptionsPrefix)
135{
136 ControlParameters parameters;
137 parameters.setName("/ndn/com/example");
138 parameters.setFaceId(400);
139
140 CommandOptions options;
141 options.setPrefix("/localhop/net/example/router1/nfd");
142
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000143 controller.start<RibRegisterCommand>(parameters, succeedCallback, commandFailCallback, options);
Junxiao Shi600f7112016-07-16 11:57:18 +0000144 this->advanceClocks(time::milliseconds(1));
145
146 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
147 const Interest& requestInterest = face.sentInterests[0];
148
149 FaceCreateCommand command;
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000150 BOOST_CHECK(Name("/localhop/net/example/router1/nfd/rib/register").isPrefixOf(requestInterest.getName()));
Junxiao Shi600f7112016-07-16 11:57:18 +0000151}
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
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000171 controller.start<FaceCreateCommand>(parameters, succeedCallback, commandFailCallback);
Junxiao Shi54f727d2016-08-08 20:29:11 +0000172 this->advanceClocks(time::milliseconds(1));
173
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000174 ControlParameters responseBody = makeFaceCreateResponse();
Junxiao Shi54f727d2016-08-08 20:29:11 +0000175 ControlResponse responsePayload(201, "created");
176 responsePayload.setBody(responseBody.wireEncode());
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000177 this->respond(responsePayload);
Junxiao Shi54f727d2016-08-08 20:29:11 +0000178
179 BOOST_CHECK_EQUAL(succeeds.size(), 0);
180 BOOST_REQUIRE_EQUAL(failCodes.size(), 1);
181 BOOST_CHECK_EQUAL(failCodes.back(), Controller::ERROR_VALIDATION);
182}
183
Junxiao Shi600f7112016-07-16 11:57:18 +0000184BOOST_AUTO_TEST_CASE(ErrorCode)
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700185{
186 ControlParameters parameters;
Junxiao Shi5de006b2014-10-26 20:20:52 -0700187 parameters.setUri("tcp4://192.0.2.1:6363");
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700188
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000189 controller.start<FaceCreateCommand>(parameters, succeedCallback, commandFailCallback);
Junxiao Shi600f7112016-07-16 11:57:18 +0000190 this->advanceClocks(time::milliseconds(1));
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700191
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700192 ControlResponse responsePayload(401, "Not Authenticated");
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000193 this->respond(responsePayload);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700194
Junxiao Shi034c1882016-06-24 18:06:51 +0000195 BOOST_CHECK_EQUAL(succeeds.size(), 0);
196 BOOST_REQUIRE_EQUAL(failCodes.size(), 1);
197 BOOST_CHECK_EQUAL(failCodes.back(), 401);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700198}
199
Junxiao Shi600f7112016-07-16 11:57:18 +0000200BOOST_AUTO_TEST_CASE(InvalidResponse)
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700201{
202 ControlParameters parameters;
Junxiao Shi5de006b2014-10-26 20:20:52 -0700203 parameters.setUri("tcp4://192.0.2.1:6363");
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700204
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000205 controller.start<FaceCreateCommand>(parameters, succeedCallback, commandFailCallback);
Junxiao Shi600f7112016-07-16 11:57:18 +0000206 this->advanceClocks(time::milliseconds(1));
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700207
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000208 ControlParameters responseBody = makeFaceCreateResponse();
209 responseBody.unsetFaceId() // FaceId is missing
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700210 .setName("ndn:/should-not-have-this-field");
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700211 ControlResponse responsePayload(201, "created");
212 responsePayload.setBody(responseBody.wireEncode());
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000213 this->respond(responsePayload);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700214
Junxiao Shi034c1882016-06-24 18:06:51 +0000215 BOOST_CHECK_EQUAL(succeeds.size(), 0);
216 BOOST_REQUIRE_EQUAL(failCodes.size(), 1);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700217}
218
Junxiao Shi600f7112016-07-16 11:57:18 +0000219BOOST_AUTO_TEST_CASE(Nack)
Junxiao Shib1990df2015-11-05 00:14:44 +0000220{
221 ControlParameters parameters;
222 parameters.setUri("tcp4://192.0.2.1:6363");
223
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000224 controller.start<FaceCreateCommand>(parameters, succeedCallback, commandFailCallback);
Junxiao Shi600f7112016-07-16 11:57:18 +0000225 this->advanceClocks(time::milliseconds(1));
Junxiao Shib1990df2015-11-05 00:14:44 +0000226
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800227 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
228 const Interest& requestInterest = face.sentInterests[0];
Junxiao Shib1990df2015-11-05 00:14:44 +0000229
Junxiao Shi034c1882016-06-24 18:06:51 +0000230 auto responseNack = makeNack(requestInterest, lp::NackReason::NO_ROUTE);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800231 face.receive(responseNack);
Junxiao Shi600f7112016-07-16 11:57:18 +0000232 this->advanceClocks(time::milliseconds(1));
Junxiao Shib1990df2015-11-05 00:14:44 +0000233
Junxiao Shi034c1882016-06-24 18:06:51 +0000234 BOOST_REQUIRE_EQUAL(failCodes.size(), 1);
235 BOOST_CHECK_EQUAL(failCodes.back(), Controller::ERROR_NACK);
Junxiao Shib1990df2015-11-05 00:14:44 +0000236}
237
Junxiao Shi600f7112016-07-16 11:57:18 +0000238BOOST_AUTO_TEST_CASE(Timeout)
Junxiao Shi5de006b2014-10-26 20:20:52 -0700239{
240 ControlParameters parameters;
241 parameters.setUri("tcp4://192.0.2.1:6363");
242
243 CommandOptions options;
244 options.setTimeout(time::milliseconds(50));
245
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000246 controller.start<FaceCreateCommand>(parameters, succeedCallback, commandFailCallback, options);
247 this->advanceClocks(time::milliseconds(1)); // express Interest
248 this->advanceClocks(time::milliseconds(51)); // timeout
Junxiao Shi5de006b2014-10-26 20:20:52 -0700249
Junxiao Shi034c1882016-06-24 18:06:51 +0000250 BOOST_REQUIRE_EQUAL(failCodes.size(), 1);
251 BOOST_CHECK_EQUAL(failCodes.back(), Controller::ERROR_TIMEOUT);
Junxiao Shi5de006b2014-10-26 20:20:52 -0700252}
253
Junxiao Shi600f7112016-07-16 11:57:18 +0000254BOOST_AUTO_TEST_CASE(FailureNoCallback)
255{
256 ControlParameters parameters;
257 parameters.setUri("tcp4://192.0.2.1:6363");
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700258
Junxiao Shi600f7112016-07-16 11:57:18 +0000259 CommandOptions options;
260 options.setTimeout(time::milliseconds(50));
261
262 controller.start<FaceCreateCommand>(parameters, succeedCallback, nullptr, options);
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000263 this->advanceClocks(time::milliseconds(1)); // express Interest
264 this->advanceClocks(time::milliseconds(51)); // timeout
Junxiao Shi600f7112016-07-16 11:57:18 +0000265
266 BOOST_CHECK_EQUAL(succeeds.size(), 0);
267}
268
Junxiao Shi7357ef22016-09-07 02:39:37 +0000269BOOST_AUTO_TEST_SUITE_END() // TestController
270BOOST_AUTO_TEST_SUITE_END() // Nfd
271BOOST_AUTO_TEST_SUITE_END() // Mgmt
Junxiao Shi034c1882016-06-24 18:06:51 +0000272
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700273} // namespace tests
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700274} // namespace nfd
275} // namespace ndn