blob: 8be9d233c2a0aae0e211156b337f04957436d565 [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 Pesaventoaebf5d72024-12-26 16:04:12 -05003 * Copyright (c) 2013-2025 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"
Davide Pesaventoaebf5d72024-12-26 16:04:12 -050023#include "ndn-cxx/mgmt/nfd/control-command.hpp"
Davide Pesavento7e780642018-11-24 15:51:34 -050024#include "ndn-cxx/mgmt/nfd/control-response.hpp"
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070025
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050026#include "tests/test-common.hpp"
Davide Pesavento7e780642018-11-24 15:51:34 -050027#include "tests/unit/mgmt/nfd/controller-fixture.hpp"
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070028
Davide Pesavento47ce2ee2023-05-09 01:33:33 -040029namespace ndn::tests {
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070030
Davide Pesavento47ce2ee2023-05-09 01:33:33 -040031using namespace ndn::nfd;
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070032
Junxiao Shi7357ef22016-09-07 02:39:37 +000033BOOST_AUTO_TEST_SUITE(Mgmt)
34BOOST_AUTO_TEST_SUITE(Nfd)
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070035
Junxiao Shi034c1882016-06-24 18:06:51 +000036class CommandFixture : public ControllerFixture
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070037{
38protected:
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +000039 void
40 respond(const ControlResponse& responsePayload)
41 {
42 auto responseData = makeData(face.sentInterests.at(0).getName());
43 responseData->setContent(responsePayload.wireEncode());
44 face.receive(*responseData);
Davide Pesavento0f830802018-01-16 23:58:58 -050045 this->advanceClocks(1_ms);
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +000046 }
47
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070048protected:
Davide Pesavento09103432023-03-24 20:30:41 -040049 CommandSuccessCallback succeedCallback = [this] (const auto& params) {
Davide Pesavento2e481fc2021-07-02 18:20:03 -040050 succeeds.push_back(params);
51 };
Junxiao Shi034c1882016-06-24 18:06:51 +000052 std::vector<ControlParameters> succeeds;
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070053};
54
Junxiao Shi600f7112016-07-16 11:57:18 +000055// This test suite focuses on ControlCommand functionality of Controller.
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050056// Individual commands are tested in control-command.t.cpp
57// StatusDataset functionality is tested in status-dataset.t.cpp
Junxiao Shi7357ef22016-09-07 02:39:37 +000058BOOST_FIXTURE_TEST_SUITE(TestController, CommandFixture)
Junxiao Shib1990df2015-11-05 00:14:44 +000059
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +000060static ControlParameters
61makeFaceCreateResponse()
62{
63 ControlParameters resp;
64 resp.setFaceId(22)
65 .setUri("tcp4://192.0.2.1:6363")
66 .setLocalUri("tcp4://192.0.2.2:10847")
67 .setFacePersistency(ndn::nfd::FacePersistency::FACE_PERSISTENCY_PERSISTENT)
Eric Newberryd567aab2018-01-27 16:38:24 -070068 .setFlags(0x7);
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +000069 return resp;
70}
71
Junxiao Shi600f7112016-07-16 11:57:18 +000072BOOST_AUTO_TEST_CASE(Success)
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070073{
74 ControlParameters parameters;
Junxiao Shi5de006b2014-10-26 20:20:52 -070075 parameters.setUri("tcp4://192.0.2.1:6363");
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070076
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +000077 controller.start<FaceCreateCommand>(parameters, succeedCallback, commandFailCallback);
Davide Pesavento0f830802018-01-16 23:58:58 -050078 this->advanceClocks(1_ms);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070079
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -080080 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
81 const Interest& requestInterest = face.sentInterests[0];
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070082
Junxiao Shi5de006b2014-10-26 20:20:52 -070083 BOOST_CHECK(Name("/localhost/nfd/faces/create").isPrefixOf(requestInterest.getName()));
Davide Pesavento8fbffe42022-06-15 18:36:03 -040084 BOOST_CHECK(requestInterest.isSigned());
85 BOOST_CHECK(requestInterest.isParametersDigestValid());
Junxiao Shi415b17c2014-11-12 00:43:25 -070086 BOOST_CHECK_EQUAL(requestInterest.getInterestLifetime(), CommandOptions::DEFAULT_TIMEOUT);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070087
Davide Pesavento8fbffe42022-06-15 18:36:03 -040088 // 6 components: /localhost/nfd/faces/create/<parameters>/params-sha256=...
89 BOOST_REQUIRE_EQUAL(requestInterest.getName().size(), 6);
90 ControlParameters requestParams(requestInterest.getName()[4].blockFromValue());
Davide Pesaventoaebf5d72024-12-26 16:04:12 -050091 BOOST_CHECK_NO_THROW(FaceCreateCommand::validateRequest(requestParams));
Davide Pesavento8fbffe42022-06-15 18:36:03 -040092 BOOST_CHECK_EQUAL(requestParams.getUri(), parameters.getUri());
93
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +000094 ControlParameters responseBody = makeFaceCreateResponse();
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070095 ControlResponse responsePayload(201, "created");
96 responsePayload.setBody(responseBody.wireEncode());
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +000097 this->respond(responsePayload);
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);
Davide Pesavento0f830802018-01-16 23:58:58 -0500111 this->advanceClocks(1_ms);
Junxiao Shi600f7112016-07-16 11:57:18 +0000112
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000113 ControlParameters responseBody = makeFaceCreateResponse();
Junxiao Shi600f7112016-07-16 11:57:18 +0000114 ControlResponse responsePayload(201, "created");
115 responsePayload.setBody(responseBody.wireEncode());
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000116 this->respond(responsePayload);
Junxiao Shi600f7112016-07-16 11:57:18 +0000117
118 BOOST_CHECK_EQUAL(failCodes.size(), 0);
119}
120
121BOOST_AUTO_TEST_CASE(OptionsPrefix)
122{
123 ControlParameters parameters;
124 parameters.setName("/ndn/com/example");
125 parameters.setFaceId(400);
126
127 CommandOptions options;
128 options.setPrefix("/localhop/net/example/router1/nfd");
129
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000130 controller.start<RibRegisterCommand>(parameters, succeedCallback, commandFailCallback, options);
Davide Pesavento0f830802018-01-16 23:58:58 -0500131 this->advanceClocks(1_ms);
Junxiao Shi600f7112016-07-16 11:57:18 +0000132
133 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
Davide Pesaventoaebf5d72024-12-26 16:04:12 -0500134 const Interest& request = face.sentInterests[0];
Junxiao Shi600f7112016-07-16 11:57:18 +0000135
Davide Pesaventoaebf5d72024-12-26 16:04:12 -0500136 BOOST_CHECK(Name("/localhop/net/example/router1/nfd/rib/register").isPrefixOf(request.getName()));
137 BOOST_CHECK(request.isSigned());
138 BOOST_CHECK(request.isParametersDigestValid());
Junxiao Shi600f7112016-07-16 11:57:18 +0000139}
140
141BOOST_AUTO_TEST_CASE(InvalidRequest)
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700142{
143 ControlParameters parameters;
144 parameters.setName("ndn:/should-not-have-this-field");
145 // Uri is missing
146
Davide Pesavento8fbffe42022-06-15 18:36:03 -0400147 BOOST_CHECK_THROW(controller.start<FaceCreateCommand>(parameters, succeedCallback, commandFailCallback),
Davide Pesaventoaebf5d72024-12-26 16:04:12 -0500148 ArgumentError);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700149}
150
Junxiao Shi54f727d2016-08-08 20:29:11 +0000151BOOST_AUTO_TEST_CASE(ValidationFailure)
152{
153 this->setValidationResult(false);
154
155 ControlParameters parameters;
156 parameters.setUri("tcp4://192.0.2.1:6363");
157
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000158 controller.start<FaceCreateCommand>(parameters, succeedCallback, commandFailCallback);
Davide Pesavento0f830802018-01-16 23:58:58 -0500159 this->advanceClocks(1_ms);
Junxiao Shi54f727d2016-08-08 20:29:11 +0000160
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000161 ControlParameters responseBody = makeFaceCreateResponse();
Junxiao Shi54f727d2016-08-08 20:29:11 +0000162 ControlResponse responsePayload(201, "created");
163 responsePayload.setBody(responseBody.wireEncode());
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000164 this->respond(responsePayload);
Junxiao Shi54f727d2016-08-08 20:29:11 +0000165
166 BOOST_CHECK_EQUAL(succeeds.size(), 0);
167 BOOST_REQUIRE_EQUAL(failCodes.size(), 1);
168 BOOST_CHECK_EQUAL(failCodes.back(), Controller::ERROR_VALIDATION);
169}
170
Junxiao Shi600f7112016-07-16 11:57:18 +0000171BOOST_AUTO_TEST_CASE(ErrorCode)
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700172{
173 ControlParameters parameters;
Junxiao Shi5de006b2014-10-26 20:20:52 -0700174 parameters.setUri("tcp4://192.0.2.1:6363");
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700175
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000176 controller.start<FaceCreateCommand>(parameters, succeedCallback, commandFailCallback);
Davide Pesavento0f830802018-01-16 23:58:58 -0500177 this->advanceClocks(1_ms);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700178
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700179 ControlResponse responsePayload(401, "Not Authenticated");
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000180 this->respond(responsePayload);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700181
Junxiao Shi034c1882016-06-24 18:06:51 +0000182 BOOST_CHECK_EQUAL(succeeds.size(), 0);
183 BOOST_REQUIRE_EQUAL(failCodes.size(), 1);
184 BOOST_CHECK_EQUAL(failCodes.back(), 401);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700185}
186
Junxiao Shi600f7112016-07-16 11:57:18 +0000187BOOST_AUTO_TEST_CASE(InvalidResponse)
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700188{
189 ControlParameters parameters;
Junxiao Shi5de006b2014-10-26 20:20:52 -0700190 parameters.setUri("tcp4://192.0.2.1:6363");
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700191
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000192 controller.start<FaceCreateCommand>(parameters, succeedCallback, commandFailCallback);
Davide Pesavento0f830802018-01-16 23:58:58 -0500193 this->advanceClocks(1_ms);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700194
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000195 ControlParameters responseBody = makeFaceCreateResponse();
196 responseBody.unsetFaceId() // FaceId is missing
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700197 .setName("ndn:/should-not-have-this-field");
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700198 ControlResponse responsePayload(201, "created");
199 responsePayload.setBody(responseBody.wireEncode());
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000200 this->respond(responsePayload);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700201
Junxiao Shi034c1882016-06-24 18:06:51 +0000202 BOOST_CHECK_EQUAL(succeeds.size(), 0);
203 BOOST_REQUIRE_EQUAL(failCodes.size(), 1);
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700204}
205
Junxiao Shi600f7112016-07-16 11:57:18 +0000206BOOST_AUTO_TEST_CASE(Nack)
Junxiao Shib1990df2015-11-05 00:14:44 +0000207{
208 ControlParameters parameters;
209 parameters.setUri("tcp4://192.0.2.1:6363");
210
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000211 controller.start<FaceCreateCommand>(parameters, succeedCallback, commandFailCallback);
Davide Pesavento0f830802018-01-16 23:58:58 -0500212 this->advanceClocks(1_ms);
Junxiao Shib1990df2015-11-05 00:14:44 +0000213
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800214 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
215 const Interest& requestInterest = face.sentInterests[0];
Junxiao Shib1990df2015-11-05 00:14:44 +0000216
Junxiao Shi034c1882016-06-24 18:06:51 +0000217 auto responseNack = makeNack(requestInterest, lp::NackReason::NO_ROUTE);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800218 face.receive(responseNack);
Davide Pesavento0f830802018-01-16 23:58:58 -0500219 this->advanceClocks(1_ms);
Junxiao Shib1990df2015-11-05 00:14:44 +0000220
Junxiao Shi034c1882016-06-24 18:06:51 +0000221 BOOST_REQUIRE_EQUAL(failCodes.size(), 1);
222 BOOST_CHECK_EQUAL(failCodes.back(), Controller::ERROR_NACK);
Junxiao Shib1990df2015-11-05 00:14:44 +0000223}
224
Junxiao Shi600f7112016-07-16 11:57:18 +0000225BOOST_AUTO_TEST_CASE(Timeout)
Junxiao Shi5de006b2014-10-26 20:20:52 -0700226{
227 ControlParameters parameters;
228 parameters.setUri("tcp4://192.0.2.1:6363");
229
230 CommandOptions options;
Davide Pesavento0f830802018-01-16 23:58:58 -0500231 options.setTimeout(50_ms);
Junxiao Shi5de006b2014-10-26 20:20:52 -0700232
Junxiao Shi8c2ab2e2017-05-05 20:26:34 +0000233 controller.start<FaceCreateCommand>(parameters, succeedCallback, commandFailCallback, options);
Davide Pesavento0f830802018-01-16 23:58:58 -0500234 this->advanceClocks(1_ms); // express Interest
235 this->advanceClocks(51_ms); // timeout
Junxiao Shi5de006b2014-10-26 20:20:52 -0700236
Junxiao Shi034c1882016-06-24 18:06:51 +0000237 BOOST_REQUIRE_EQUAL(failCodes.size(), 1);
238 BOOST_CHECK_EQUAL(failCodes.back(), Controller::ERROR_TIMEOUT);
Junxiao Shi5de006b2014-10-26 20:20:52 -0700239}
240
Junxiao Shi600f7112016-07-16 11:57:18 +0000241BOOST_AUTO_TEST_CASE(FailureNoCallback)
242{
243 ControlParameters parameters;
244 parameters.setUri("tcp4://192.0.2.1:6363");
Junxiao Shi7b6b79d2014-03-26 20:59:35 -0700245
Junxiao Shi600f7112016-07-16 11:57:18 +0000246 CommandOptions options;
Davide Pesavento0f830802018-01-16 23:58:58 -0500247 options.setTimeout(50_ms);
Junxiao Shi600f7112016-07-16 11:57:18 +0000248
249 controller.start<FaceCreateCommand>(parameters, succeedCallback, nullptr, options);
Davide Pesavento0f830802018-01-16 23:58:58 -0500250 this->advanceClocks(1_ms); // express Interest
251 this->advanceClocks(51_ms); // timeout
Junxiao Shi600f7112016-07-16 11:57:18 +0000252
253 BOOST_CHECK_EQUAL(succeeds.size(), 0);
254}
255
Junxiao Shi7357ef22016-09-07 02:39:37 +0000256BOOST_AUTO_TEST_SUITE_END() // TestController
257BOOST_AUTO_TEST_SUITE_END() // Nfd
258BOOST_AUTO_TEST_SUITE_END() // Mgmt
Junxiao Shi034c1882016-06-24 18:06:51 +0000259
Davide Pesavento47ce2ee2023-05-09 01:33:33 -0400260} // namespace ndn::tests