blob: 01ff7670a9daca7c81e7af55ffb65d721066c40c [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shi2bea5c42017-08-14 20:10:32 +00002/*
Davide Pesavento0f830802018-01-16 23:58:58 -05003 * Copyright (c) 2013-2018 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
Davide Pesavento7e780642018-11-24 15:51:34 -050022#include "ndn-cxx/mgmt/nfd/controller.hpp"
23#include "ndn-cxx/mgmt/nfd/control-response.hpp"
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070024
Davide Pesavento7e780642018-11-24 15:51:34 -050025#include "tests/boost-test.hpp"
26#include "tests/make-interest-data.hpp"
27#include "tests/unit/mgmt/nfd/controller-fixture.hpp"
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070028
29namespace ndn {
30namespace nfd {
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070031namespace tests {
32
Junxiao Shi85d90832016-08-04 03:19:46 +000033using namespace ndn::tests;
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070034
Junxiao Shi7357ef22016-09-07 02:39:37 +000035BOOST_AUTO_TEST_SUITE(Mgmt)
36BOOST_AUTO_TEST_SUITE(Nfd)
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
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +000046 void
47 respond(const ControlResponse& responsePayload)
48 {
49 auto responseData = makeData(face.sentInterests.at(0).getName());
50 responseData->setContent(responsePayload.wireEncode());
51 face.receive(*responseData);
Davide Pesavento0f830802018-01-16 23:58:58 -050052 this->advanceClocks(1_ms);
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +000053 }
54
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070055private:
56 void
Junxiao Shi034c1882016-06-24 18:06:51 +000057 succeed(const ControlParameters& parameters)
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070058 {
Junxiao Shi034c1882016-06-24 18:06:51 +000059 succeeds.push_back(parameters);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070060 }
61
62protected:
Junxiao Shi034c1882016-06-24 18:06:51 +000063 Controller::CommandSucceedCallback succeedCallback;
64 std::vector<ControlParameters> succeeds;
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070065};
66
Junxiao Shi600f7112016-07-16 11:57:18 +000067// This test suite focuses on ControlCommand functionality of Controller.
68// Individual commands are tested in nfd-control-command.t.cpp
69// StatusDataset functionality is tested in nfd-status-dataset.t.cpp
Junxiao Shi7357ef22016-09-07 02:39:37 +000070BOOST_FIXTURE_TEST_SUITE(TestController, CommandFixture)
Junxiao Shib1990df2015-11-05 00:14:44 +000071
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +000072static ControlParameters
73makeFaceCreateResponse()
74{
75 ControlParameters resp;
76 resp.setFaceId(22)
77 .setUri("tcp4://192.0.2.1:6363")
78 .setLocalUri("tcp4://192.0.2.2:10847")
79 .setFacePersistency(ndn::nfd::FacePersistency::FACE_PERSISTENCY_PERSISTENT)
Eric Newberryd567aab2018-01-27 16:38:24 -070080 .setFlags(0x7);
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +000081 return resp;
82}
83
Junxiao Shi600f7112016-07-16 11:57:18 +000084BOOST_AUTO_TEST_CASE(Success)
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070085{
86 ControlParameters parameters;
Junxiao Shi5de006b2014-10-26 20:20:52 -070087 parameters.setUri("tcp4://192.0.2.1:6363");
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070088
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +000089 controller.start<FaceCreateCommand>(parameters, succeedCallback, commandFailCallback);
Davide Pesavento0f830802018-01-16 23:58:58 -050090 this->advanceClocks(1_ms);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070091
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -080092 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
93 const Interest& requestInterest = face.sentInterests[0];
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070094
95 FaceCreateCommand command;
Junxiao Shi5de006b2014-10-26 20:20:52 -070096 BOOST_CHECK(Name("/localhost/nfd/faces/create").isPrefixOf(requestInterest.getName()));
97 // 9 components: ndn:/localhost/nfd/faces/create/<parameters>/<signed Interest x4>
Junxiao Shi6a90f372014-10-13 20:29:30 -070098 BOOST_REQUIRE_EQUAL(requestInterest.getName().size(), 9);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070099 ControlParameters request;
100 // 4th component: <parameters>
Junxiao Shi6a90f372014-10-13 20:29:30 -0700101 BOOST_REQUIRE_NO_THROW(request.wireDecode(requestInterest.getName().at(4).blockFromValue()));
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700102 BOOST_CHECK_NO_THROW(command.validateRequest(request));
103 BOOST_CHECK_EQUAL(request.getUri(), parameters.getUri());
Junxiao Shi415b17c2014-11-12 00:43:25 -0700104 BOOST_CHECK_EQUAL(requestInterest.getInterestLifetime(), CommandOptions::DEFAULT_TIMEOUT);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700105
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000106 ControlParameters responseBody = makeFaceCreateResponse();
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700107 ControlResponse responsePayload(201, "created");
108 responsePayload.setBody(responseBody.wireEncode());
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000109 this->respond(responsePayload);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700110
Junxiao Shi034c1882016-06-24 18:06:51 +0000111 BOOST_CHECK_EQUAL(failCodes.size(), 0);
112 BOOST_REQUIRE_EQUAL(succeeds.size(), 1);
113 BOOST_CHECK_EQUAL(succeeds.back().getUri(), responseBody.getUri());
114 BOOST_CHECK_EQUAL(succeeds.back().getFaceId(), responseBody.getFaceId());
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700115}
116
Junxiao Shi600f7112016-07-16 11:57:18 +0000117BOOST_AUTO_TEST_CASE(SuccessNoCallback)
118{
119 ControlParameters parameters;
120 parameters.setUri("tcp4://192.0.2.1:6363");
121
Junxiao Shie7c7f152016-08-20 22:36:22 +0000122 controller.start<FaceCreateCommand>(parameters, nullptr, commandFailCallback);
Davide Pesavento0f830802018-01-16 23:58:58 -0500123 this->advanceClocks(1_ms);
Junxiao Shi600f7112016-07-16 11:57:18 +0000124
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000125 ControlParameters responseBody = makeFaceCreateResponse();
Junxiao Shi600f7112016-07-16 11:57:18 +0000126 ControlResponse responsePayload(201, "created");
127 responsePayload.setBody(responseBody.wireEncode());
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000128 this->respond(responsePayload);
Junxiao Shi600f7112016-07-16 11:57:18 +0000129
130 BOOST_CHECK_EQUAL(failCodes.size(), 0);
131}
132
133BOOST_AUTO_TEST_CASE(OptionsPrefix)
134{
135 ControlParameters parameters;
136 parameters.setName("/ndn/com/example");
137 parameters.setFaceId(400);
138
139 CommandOptions options;
140 options.setPrefix("/localhop/net/example/router1/nfd");
141
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000142 controller.start<RibRegisterCommand>(parameters, succeedCallback, commandFailCallback, options);
Davide Pesavento0f830802018-01-16 23:58:58 -0500143 this->advanceClocks(1_ms);
Junxiao Shi600f7112016-07-16 11:57:18 +0000144
145 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
146 const Interest& requestInterest = face.sentInterests[0];
147
148 FaceCreateCommand command;
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000149 BOOST_CHECK(Name("/localhop/net/example/router1/nfd/rib/register").isPrefixOf(requestInterest.getName()));
Junxiao Shi600f7112016-07-16 11:57:18 +0000150}
151
152BOOST_AUTO_TEST_CASE(InvalidRequest)
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700153{
154 ControlParameters parameters;
155 parameters.setName("ndn:/should-not-have-this-field");
156 // Uri is missing
157
158 BOOST_CHECK_THROW(controller.start<FaceCreateCommand>(
Junxiao Shie7c7f152016-08-20 22:36:22 +0000159 parameters, succeedCallback, commandFailCallback),
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700160 ControlCommand::ArgumentError);
161}
162
Junxiao Shi54f727d2016-08-08 20:29:11 +0000163BOOST_AUTO_TEST_CASE(ValidationFailure)
164{
165 this->setValidationResult(false);
166
167 ControlParameters parameters;
168 parameters.setUri("tcp4://192.0.2.1:6363");
169
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000170 controller.start<FaceCreateCommand>(parameters, succeedCallback, commandFailCallback);
Davide Pesavento0f830802018-01-16 23:58:58 -0500171 this->advanceClocks(1_ms);
Junxiao Shi54f727d2016-08-08 20:29:11 +0000172
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000173 ControlParameters responseBody = makeFaceCreateResponse();
Junxiao Shi54f727d2016-08-08 20:29:11 +0000174 ControlResponse responsePayload(201, "created");
175 responsePayload.setBody(responseBody.wireEncode());
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000176 this->respond(responsePayload);
Junxiao Shi54f727d2016-08-08 20:29:11 +0000177
178 BOOST_CHECK_EQUAL(succeeds.size(), 0);
179 BOOST_REQUIRE_EQUAL(failCodes.size(), 1);
180 BOOST_CHECK_EQUAL(failCodes.back(), Controller::ERROR_VALIDATION);
181}
182
Junxiao Shi600f7112016-07-16 11:57:18 +0000183BOOST_AUTO_TEST_CASE(ErrorCode)
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700184{
185 ControlParameters parameters;
Junxiao Shi5de006b2014-10-26 20:20:52 -0700186 parameters.setUri("tcp4://192.0.2.1:6363");
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700187
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000188 controller.start<FaceCreateCommand>(parameters, succeedCallback, commandFailCallback);
Davide Pesavento0f830802018-01-16 23:58:58 -0500189 this->advanceClocks(1_ms);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700190
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700191 ControlResponse responsePayload(401, "Not Authenticated");
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000192 this->respond(responsePayload);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700193
Junxiao Shi034c1882016-06-24 18:06:51 +0000194 BOOST_CHECK_EQUAL(succeeds.size(), 0);
195 BOOST_REQUIRE_EQUAL(failCodes.size(), 1);
196 BOOST_CHECK_EQUAL(failCodes.back(), 401);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700197}
198
Junxiao Shi600f7112016-07-16 11:57:18 +0000199BOOST_AUTO_TEST_CASE(InvalidResponse)
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700200{
201 ControlParameters parameters;
Junxiao Shi5de006b2014-10-26 20:20:52 -0700202 parameters.setUri("tcp4://192.0.2.1:6363");
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700203
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000204 controller.start<FaceCreateCommand>(parameters, succeedCallback, commandFailCallback);
Davide Pesavento0f830802018-01-16 23:58:58 -0500205 this->advanceClocks(1_ms);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700206
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000207 ControlParameters responseBody = makeFaceCreateResponse();
208 responseBody.unsetFaceId() // FaceId is missing
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700209 .setName("ndn:/should-not-have-this-field");
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700210 ControlResponse responsePayload(201, "created");
211 responsePayload.setBody(responseBody.wireEncode());
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000212 this->respond(responsePayload);
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);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700216}
217
Junxiao Shi600f7112016-07-16 11:57:18 +0000218BOOST_AUTO_TEST_CASE(Nack)
Junxiao Shib1990df2015-11-05 00:14:44 +0000219{
220 ControlParameters parameters;
221 parameters.setUri("tcp4://192.0.2.1:6363");
222
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000223 controller.start<FaceCreateCommand>(parameters, succeedCallback, commandFailCallback);
Davide Pesavento0f830802018-01-16 23:58:58 -0500224 this->advanceClocks(1_ms);
Junxiao Shib1990df2015-11-05 00:14:44 +0000225
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800226 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
227 const Interest& requestInterest = face.sentInterests[0];
Junxiao Shib1990df2015-11-05 00:14:44 +0000228
Junxiao Shi034c1882016-06-24 18:06:51 +0000229 auto responseNack = makeNack(requestInterest, lp::NackReason::NO_ROUTE);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800230 face.receive(responseNack);
Davide Pesavento0f830802018-01-16 23:58:58 -0500231 this->advanceClocks(1_ms);
Junxiao Shib1990df2015-11-05 00:14:44 +0000232
Junxiao Shi034c1882016-06-24 18:06:51 +0000233 BOOST_REQUIRE_EQUAL(failCodes.size(), 1);
234 BOOST_CHECK_EQUAL(failCodes.back(), Controller::ERROR_NACK);
Junxiao Shib1990df2015-11-05 00:14:44 +0000235}
236
Junxiao Shi600f7112016-07-16 11:57:18 +0000237BOOST_AUTO_TEST_CASE(Timeout)
Junxiao Shi5de006b2014-10-26 20:20:52 -0700238{
239 ControlParameters parameters;
240 parameters.setUri("tcp4://192.0.2.1:6363");
241
242 CommandOptions options;
Davide Pesavento0f830802018-01-16 23:58:58 -0500243 options.setTimeout(50_ms);
Junxiao Shi5de006b2014-10-26 20:20:52 -0700244
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000245 controller.start<FaceCreateCommand>(parameters, succeedCallback, commandFailCallback, options);
Davide Pesavento0f830802018-01-16 23:58:58 -0500246 this->advanceClocks(1_ms); // express Interest
247 this->advanceClocks(51_ms); // timeout
Junxiao Shi5de006b2014-10-26 20:20:52 -0700248
Junxiao Shi034c1882016-06-24 18:06:51 +0000249 BOOST_REQUIRE_EQUAL(failCodes.size(), 1);
250 BOOST_CHECK_EQUAL(failCodes.back(), Controller::ERROR_TIMEOUT);
Junxiao Shi5de006b2014-10-26 20:20:52 -0700251}
252
Junxiao Shi600f7112016-07-16 11:57:18 +0000253BOOST_AUTO_TEST_CASE(FailureNoCallback)
254{
255 ControlParameters parameters;
256 parameters.setUri("tcp4://192.0.2.1:6363");
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700257
Junxiao Shi600f7112016-07-16 11:57:18 +0000258 CommandOptions options;
Davide Pesavento0f830802018-01-16 23:58:58 -0500259 options.setTimeout(50_ms);
Junxiao Shi600f7112016-07-16 11:57:18 +0000260
261 controller.start<FaceCreateCommand>(parameters, succeedCallback, nullptr, options);
Davide Pesavento0f830802018-01-16 23:58:58 -0500262 this->advanceClocks(1_ms); // express Interest
263 this->advanceClocks(51_ms); // timeout
Junxiao Shi600f7112016-07-16 11:57:18 +0000264
265 BOOST_CHECK_EQUAL(succeeds.size(), 0);
266}
267
Junxiao Shi7357ef22016-09-07 02:39:37 +0000268BOOST_AUTO_TEST_SUITE_END() // TestController
269BOOST_AUTO_TEST_SUITE_END() // Nfd
270BOOST_AUTO_TEST_SUITE_END() // Mgmt
Junxiao Shi034c1882016-06-24 18:06:51 +0000271
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700272} // namespace tests
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700273} // namespace nfd
274} // namespace ndn