blob: 4d6b8a2537dc2a61c1988b5bba9a8711362edf1d [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
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
47private:
48 void
Junxiao Shi034c1882016-06-24 18:06:51 +000049 succeed(const ControlParameters& parameters)
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070050 {
Junxiao Shi034c1882016-06-24 18:06:51 +000051 succeeds.push_back(parameters);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070052 }
53
54protected:
Junxiao Shi034c1882016-06-24 18:06:51 +000055 Controller::CommandSucceedCallback succeedCallback;
56 std::vector<ControlParameters> succeeds;
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070057};
58
Junxiao Shi600f7112016-07-16 11:57:18 +000059// This test suite focuses on ControlCommand functionality of Controller.
60// Individual commands are tested in nfd-control-command.t.cpp
61// StatusDataset functionality is tested in nfd-status-dataset.t.cpp
Junxiao Shi7357ef22016-09-07 02:39:37 +000062BOOST_FIXTURE_TEST_SUITE(TestController, CommandFixture)
Junxiao Shib1990df2015-11-05 00:14:44 +000063
Junxiao Shi600f7112016-07-16 11:57:18 +000064BOOST_AUTO_TEST_CASE(Success)
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070065{
66 ControlParameters parameters;
Junxiao Shi5de006b2014-10-26 20:20:52 -070067 parameters.setUri("tcp4://192.0.2.1:6363");
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070068
69 BOOST_CHECK_NO_THROW(controller.start<FaceCreateCommand>(
Junxiao Shie7c7f152016-08-20 22:36:22 +000070 parameters, succeedCallback, commandFailCallback));
Junxiao Shi600f7112016-07-16 11:57:18 +000071 this->advanceClocks(time::milliseconds(1));
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070072
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -080073 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
74 const Interest& requestInterest = face.sentInterests[0];
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070075
76 FaceCreateCommand command;
Junxiao Shi5de006b2014-10-26 20:20:52 -070077 BOOST_CHECK(Name("/localhost/nfd/faces/create").isPrefixOf(requestInterest.getName()));
78 // 9 components: ndn:/localhost/nfd/faces/create/<parameters>/<signed Interest x4>
Junxiao Shi6a90f372014-10-13 20:29:30 -070079 BOOST_REQUIRE_EQUAL(requestInterest.getName().size(), 9);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070080 ControlParameters request;
81 // 4th component: <parameters>
Junxiao Shi6a90f372014-10-13 20:29:30 -070082 BOOST_REQUIRE_NO_THROW(request.wireDecode(requestInterest.getName().at(4).blockFromValue()));
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070083 BOOST_CHECK_NO_THROW(command.validateRequest(request));
84 BOOST_CHECK_EQUAL(request.getUri(), parameters.getUri());
Junxiao Shi415b17c2014-11-12 00:43:25 -070085 BOOST_CHECK_EQUAL(requestInterest.getInterestLifetime(), CommandOptions::DEFAULT_TIMEOUT);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070086
87 ControlParameters responseBody;
88 responseBody.setUri("tcp4://192.0.2.1:6363")
Yukai Tud93c5fc2015-08-25 11:37:16 +080089 .setFaceId(22)
90 .setFacePersistency(ndn::nfd::FacePersistency::FACE_PERSISTENCY_PERSISTENT);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070091 ControlResponse responsePayload(201, "created");
92 responsePayload.setBody(responseBody.wireEncode());
93
Junxiao Shi034c1882016-06-24 18:06:51 +000094 auto responseData = makeData(requestInterest.getName());
Junxiao Shib1990df2015-11-05 00:14:44 +000095 responseData->setContent(responsePayload.wireEncode());
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -080096 face.receive(*responseData);
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -080097
Junxiao Shi600f7112016-07-16 11:57:18 +000098 this->advanceClocks(time::milliseconds(1));
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070099
Junxiao Shi034c1882016-06-24 18:06:51 +0000100 BOOST_CHECK_EQUAL(failCodes.size(), 0);
101 BOOST_REQUIRE_EQUAL(succeeds.size(), 1);
102 BOOST_CHECK_EQUAL(succeeds.back().getUri(), responseBody.getUri());
103 BOOST_CHECK_EQUAL(succeeds.back().getFaceId(), responseBody.getFaceId());
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700104}
105
Junxiao Shi600f7112016-07-16 11:57:18 +0000106BOOST_AUTO_TEST_CASE(SuccessNoCallback)
107{
108 ControlParameters parameters;
109 parameters.setUri("tcp4://192.0.2.1:6363");
110
Junxiao Shie7c7f152016-08-20 22:36:22 +0000111 controller.start<FaceCreateCommand>(parameters, nullptr, commandFailCallback);
Junxiao Shi600f7112016-07-16 11:57:18 +0000112 this->advanceClocks(time::milliseconds(1));
113
114 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
115 const Interest& requestInterest = face.sentInterests[0];
116
117 ControlParameters responseBody;
118 responseBody.setUri("tcp4://192.0.2.1:6363")
119 .setFaceId(22)
120 .setFacePersistency(ndn::nfd::FacePersistency::FACE_PERSISTENCY_PERSISTENT);
121 ControlResponse responsePayload(201, "created");
122 responsePayload.setBody(responseBody.wireEncode());
123
124 auto responseData = makeData(requestInterest.getName());
125 responseData->setContent(responsePayload.wireEncode());
126 face.receive(*responseData);
127
128 BOOST_CHECK_NO_THROW(this->advanceClocks(time::milliseconds(1)));
129
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
142 BOOST_CHECK_NO_THROW(controller.start<RibRegisterCommand>(
Junxiao Shie7c7f152016-08-20 22:36:22 +0000143 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;
150 BOOST_CHECK(Name("/localhop/net/example/router1/nfd/rib/register").isPrefixOf(
151 requestInterest.getName()));
152}
153
154BOOST_AUTO_TEST_CASE(InvalidRequest)
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700155{
156 ControlParameters parameters;
157 parameters.setName("ndn:/should-not-have-this-field");
158 // Uri is missing
159
160 BOOST_CHECK_THROW(controller.start<FaceCreateCommand>(
Junxiao Shie7c7f152016-08-20 22:36:22 +0000161 parameters, succeedCallback, commandFailCallback),
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700162 ControlCommand::ArgumentError);
163}
164
Junxiao Shi54f727d2016-08-08 20:29:11 +0000165BOOST_AUTO_TEST_CASE(ValidationFailure)
166{
167 this->setValidationResult(false);
168
169 ControlParameters parameters;
170 parameters.setUri("tcp4://192.0.2.1:6363");
171
172 BOOST_CHECK_NO_THROW(controller.start<FaceCreateCommand>(
Junxiao Shie7c7f152016-08-20 22:36:22 +0000173 parameters, succeedCallback, commandFailCallback));
Junxiao Shi54f727d2016-08-08 20:29:11 +0000174 this->advanceClocks(time::milliseconds(1));
175
176 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
177 const Interest& requestInterest = face.sentInterests[0];
178
179 ControlParameters responseBody;
180 responseBody.setUri("tcp4://192.0.2.1:6363")
181 .setFaceId(22)
182 .setFacePersistency(ndn::nfd::FacePersistency::FACE_PERSISTENCY_PERSISTENT);
183 ControlResponse responsePayload(201, "created");
184 responsePayload.setBody(responseBody.wireEncode());
185
186 auto responseData = makeData(requestInterest.getName());
187 responseData->setContent(responsePayload.wireEncode());
188 face.receive(*responseData);
189 this->advanceClocks(time::milliseconds(1));
190
191 BOOST_CHECK_EQUAL(succeeds.size(), 0);
192 BOOST_REQUIRE_EQUAL(failCodes.size(), 1);
193 BOOST_CHECK_EQUAL(failCodes.back(), Controller::ERROR_VALIDATION);
194}
195
Junxiao Shi600f7112016-07-16 11:57:18 +0000196BOOST_AUTO_TEST_CASE(ErrorCode)
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700197{
198 ControlParameters parameters;
Junxiao Shi5de006b2014-10-26 20:20:52 -0700199 parameters.setUri("tcp4://192.0.2.1:6363");
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700200
201 BOOST_CHECK_NO_THROW(controller.start<FaceCreateCommand>(
Junxiao Shie7c7f152016-08-20 22:36:22 +0000202 parameters, succeedCallback, commandFailCallback));
Junxiao Shi600f7112016-07-16 11:57:18 +0000203 this->advanceClocks(time::milliseconds(1));
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700204
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800205 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
206 const Interest& requestInterest = face.sentInterests[0];
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700207
208 ControlResponse responsePayload(401, "Not Authenticated");
209
Junxiao Shi034c1882016-06-24 18:06:51 +0000210 auto responseData = makeData(requestInterest.getName());
Junxiao Shib1990df2015-11-05 00:14:44 +0000211 responseData->setContent(responsePayload.wireEncode());
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800212 face.receive(*responseData);
Junxiao Shi600f7112016-07-16 11:57:18 +0000213 this->advanceClocks(time::milliseconds(1));
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);
217 BOOST_CHECK_EQUAL(failCodes.back(), 401);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700218}
219
Junxiao Shi600f7112016-07-16 11:57:18 +0000220BOOST_AUTO_TEST_CASE(InvalidResponse)
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700221{
222 ControlParameters parameters;
Junxiao Shi5de006b2014-10-26 20:20:52 -0700223 parameters.setUri("tcp4://192.0.2.1:6363");
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700224
225 BOOST_CHECK_NO_THROW(controller.start<FaceCreateCommand>(
Junxiao Shie7c7f152016-08-20 22:36:22 +0000226 parameters, succeedCallback, commandFailCallback));
Junxiao Shi600f7112016-07-16 11:57:18 +0000227 this->advanceClocks(time::milliseconds(1));
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700228
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800229 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
230 const Interest& requestInterest = face.sentInterests[0];
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700231
232 ControlParameters responseBody;
233 responseBody.setUri("tcp4://192.0.2.1:6363")
234 .setName("ndn:/should-not-have-this-field");
235 // FaceId is missing
236 ControlResponse responsePayload(201, "created");
237 responsePayload.setBody(responseBody.wireEncode());
238
Junxiao Shi034c1882016-06-24 18:06:51 +0000239 auto responseData = makeData(requestInterest.getName());
Junxiao Shib1990df2015-11-05 00:14:44 +0000240 responseData->setContent(responsePayload.wireEncode());
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800241 face.receive(*responseData);
Junxiao Shi600f7112016-07-16 11:57:18 +0000242 this->advanceClocks(time::milliseconds(1));
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700243
Junxiao Shi034c1882016-06-24 18:06:51 +0000244 BOOST_CHECK_EQUAL(succeeds.size(), 0);
245 BOOST_REQUIRE_EQUAL(failCodes.size(), 1);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700246}
247
Junxiao Shi600f7112016-07-16 11:57:18 +0000248BOOST_AUTO_TEST_CASE(Nack)
Junxiao Shib1990df2015-11-05 00:14:44 +0000249{
250 ControlParameters parameters;
251 parameters.setUri("tcp4://192.0.2.1:6363");
252
253 BOOST_CHECK_NO_THROW(controller.start<FaceCreateCommand>(
Junxiao Shie7c7f152016-08-20 22:36:22 +0000254 parameters, succeedCallback, commandFailCallback));
Junxiao Shi600f7112016-07-16 11:57:18 +0000255 this->advanceClocks(time::milliseconds(1));
Junxiao Shib1990df2015-11-05 00:14:44 +0000256
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800257 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
258 const Interest& requestInterest = face.sentInterests[0];
Junxiao Shib1990df2015-11-05 00:14:44 +0000259
Junxiao Shi034c1882016-06-24 18:06:51 +0000260 auto responseNack = makeNack(requestInterest, lp::NackReason::NO_ROUTE);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800261 face.receive(responseNack);
Junxiao Shi600f7112016-07-16 11:57:18 +0000262 this->advanceClocks(time::milliseconds(1));
Junxiao Shib1990df2015-11-05 00:14:44 +0000263
Junxiao Shi034c1882016-06-24 18:06:51 +0000264 BOOST_REQUIRE_EQUAL(failCodes.size(), 1);
265 BOOST_CHECK_EQUAL(failCodes.back(), Controller::ERROR_NACK);
Junxiao Shib1990df2015-11-05 00:14:44 +0000266}
267
Junxiao Shi600f7112016-07-16 11:57:18 +0000268BOOST_AUTO_TEST_CASE(Timeout)
Junxiao Shi5de006b2014-10-26 20:20:52 -0700269{
270 ControlParameters parameters;
271 parameters.setUri("tcp4://192.0.2.1:6363");
272
273 CommandOptions options;
274 options.setTimeout(time::milliseconds(50));
275
276 BOOST_CHECK_NO_THROW(controller.start<FaceCreateCommand>(
Junxiao Shie7c7f152016-08-20 22:36:22 +0000277 parameters, succeedCallback, commandFailCallback, options));
Junxiao Shi600f7112016-07-16 11:57:18 +0000278 this->advanceClocks(time::milliseconds(1), 101); // Face's PIT granularity is 100ms
Junxiao Shi5de006b2014-10-26 20:20:52 -0700279
Junxiao Shi034c1882016-06-24 18:06:51 +0000280 BOOST_REQUIRE_EQUAL(failCodes.size(), 1);
281 BOOST_CHECK_EQUAL(failCodes.back(), Controller::ERROR_TIMEOUT);
Junxiao Shi5de006b2014-10-26 20:20:52 -0700282}
283
Junxiao Shi600f7112016-07-16 11:57:18 +0000284BOOST_AUTO_TEST_CASE(FailureNoCallback)
285{
286 ControlParameters parameters;
287 parameters.setUri("tcp4://192.0.2.1:6363");
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700288
Junxiao Shi600f7112016-07-16 11:57:18 +0000289 CommandOptions options;
290 options.setTimeout(time::milliseconds(50));
291
292 controller.start<FaceCreateCommand>(parameters, succeedCallback, nullptr, options);
293 BOOST_CHECK_NO_THROW(this->advanceClocks(time::milliseconds(100), 10));
294 // timeout
295
296 BOOST_CHECK_EQUAL(succeeds.size(), 0);
297}
298
Junxiao Shi7357ef22016-09-07 02:39:37 +0000299BOOST_AUTO_TEST_SUITE_END() // TestController
300BOOST_AUTO_TEST_SUITE_END() // Nfd
301BOOST_AUTO_TEST_SUITE_END() // Mgmt
Junxiao Shi034c1882016-06-24 18:06:51 +0000302
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700303} // namespace tests
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700304} // namespace nfd
305} // namespace ndn