blob: aff0beec0023840bc698ed544bfdfe589ac5bf68 [file] [log] [blame]
Yanbiao Li6704a4a2015-08-19 16:30:16 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shi332783b2018-02-04 23:52:46 +00002/*
Davide Pesavento1d2d3372025-01-14 12:04:12 -05003 * Copyright (c) 2014-2025, Regents of the University of California,
Yanbiao Li6704a4a2015-08-19 16:30:16 -07004 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis.
10 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
24 */
25
26#include "mgmt/strategy-choice-manager.hpp"
Yanbiao Li6704a4a2015-08-19 16:30:16 -070027#include "table/strategy-choice.hpp"
Junxiao Shia49a1ab2016-07-15 18:24:36 +000028
Davide Pesavento78ddcab2019-02-28 22:00:03 -050029#include "manager-common-fixture.hpp"
30#include "tests/daemon/fw/dummy-strategy.hpp"
Davide Pesavento28181322018-11-08 16:44:50 -050031
Junxiao Shi25c6ce42016-09-09 13:49:59 +000032#include <ndn-cxx/mgmt/nfd/strategy-choice.hpp>
Yanbiao Li6704a4a2015-08-19 16:30:16 -070033
Davide Pesaventoe422f9e2022-06-03 01:30:23 -040034namespace nfd::tests {
Yanbiao Li6704a4a2015-08-19 16:30:16 -070035
Davide Pesavento78ddcab2019-02-28 22:00:03 -050036class StrategyChoiceManagerFixture : public ManagerFixtureWithAuthenticator
Yanbiao Li6704a4a2015-08-19 16:30:16 -070037{
38public:
39 StrategyChoiceManagerFixture()
Junxiao Shi7d30d852017-01-22 03:29:26 +000040 : sc(m_forwarder.getStrategyChoice())
41 , manager(sc, m_dispatcher, *m_authenticator)
Eric Newberry358414d2021-03-21 20:56:42 -070042 , strategyNameP(Name("/strategy-choice-manager-P").appendVersion(2))
Yanbiao Li6704a4a2015-08-19 16:30:16 -070043 {
Junxiao Shi7d30d852017-01-22 03:29:26 +000044 VersionedDummyStrategy<2>::registerAs(strategyNameP);
45
Junxiao Shi9ddf1b52016-08-22 03:58:55 +000046 setTopPrefix();
Yanbiao Lidf846e52016-01-30 21:53:47 -080047 setPrivilege("strategy-choice");
Yanbiao Li6704a4a2015-08-19 16:30:16 -070048 }
49
50public:
Junxiao Shi7d30d852017-01-22 03:29:26 +000051 /** \return whether exact-match StrategyChoice entry exists
52 */
53 bool
54 hasEntry(const Name& name) const
Yanbiao Li6704a4a2015-08-19 16:30:16 -070055 {
Junxiao Shi7d30d852017-01-22 03:29:26 +000056 return sc.get(name).first;
Yanbiao Li6704a4a2015-08-19 16:30:16 -070057 }
58
Junxiao Shi7d30d852017-01-22 03:29:26 +000059 /** \return strategy instance name from an exact-match StrategyChoice entry
60 */
61 Name
62 getInstanceName(const Name& name) const
Yanbiao Li6704a4a2015-08-19 16:30:16 -070063 {
Davide Pesaventoa3a7a4e2022-05-29 16:06:22 -040064 auto [hasEntry, instanceName] = sc.get(name);
65 return hasEntry ? instanceName : Name("/no-StrategyChoice-entry-at").append(name);
Yanbiao Li6704a4a2015-08-19 16:30:16 -070066 }
67
68protected:
Davide Pesavento1d2d3372025-01-14 12:04:12 -050069 static inline const Name SET_SC_REQUEST = Name("/localhost/nfd")
70 .append(ndn::nfd::StrategyChoiceSetCommand::getName());
71 static inline const Name UNSET_SC_REQUEST = Name("/localhost/nfd")
72 .append(ndn::nfd::StrategyChoiceUnsetCommand::getName());
73
Junxiao Shi7d30d852017-01-22 03:29:26 +000074 StrategyChoice& sc;
75 StrategyChoiceManager manager;
76
77 const Name strategyNameP;
Yanbiao Li6704a4a2015-08-19 16:30:16 -070078};
79
Davide Pesavento97210d52016-10-14 15:45:48 +020080BOOST_AUTO_TEST_SUITE(Mgmt)
81BOOST_FIXTURE_TEST_SUITE(TestStrategyChoiceManager, StrategyChoiceManagerFixture)
Yanbiao Li6704a4a2015-08-19 16:30:16 -070082
Junxiao Shi7d30d852017-01-22 03:29:26 +000083BOOST_AUTO_TEST_CASE(SetSuccess)
Yanbiao Li6704a4a2015-08-19 16:30:16 -070084{
Junxiao Shi7d30d852017-01-22 03:29:26 +000085 ControlParameters reqParams;
86 reqParams.setName("/A")
87 .setStrategy(strategyNameP.getPrefix(-1)); // use unversioned strategy name in request
Davide Pesavento1d2d3372025-01-14 12:04:12 -050088 auto req = makeControlCommandRequest(SET_SC_REQUEST, reqParams);
Junxiao Shi7d30d852017-01-22 03:29:26 +000089 receiveInterest(req);
Yanbiao Li6704a4a2015-08-19 16:30:16 -070090
Junxiao Shi7d30d852017-01-22 03:29:26 +000091 ControlParameters expectedParams;
92 expectedParams.setName("/A")
93 .setStrategy(strategyNameP); // response should have versioned strategy name
Davide Pesavento4296fe32025-01-14 23:00:41 -050094 ControlResponse expectedResp = makeResponse(200, "OK", expectedParams);
Junxiao Shi8a1f1702017-07-03 00:05:08 +000095 BOOST_CHECK_EQUAL(checkResponse(0, req.getName(), expectedResp),
Yanbiao Li6704a4a2015-08-19 16:30:16 -070096 CheckResponseResult::OK);
97
Junxiao Shi7d30d852017-01-22 03:29:26 +000098 BOOST_CHECK_EQUAL(getInstanceName("/A"), strategyNameP);
Yanbiao Li6704a4a2015-08-19 16:30:16 -070099
Junxiao Shi7d30d852017-01-22 03:29:26 +0000100 // Strategy versioning and parameters are not tested here because they are covered by
101 // Table/TestStrategyChoice test suite.
Yanbiao Li6704a4a2015-08-19 16:30:16 -0700102}
103
Junxiao Shi7d30d852017-01-22 03:29:26 +0000104BOOST_AUTO_TEST_CASE(SetUnknownStrategy)
Yanbiao Li6704a4a2015-08-19 16:30:16 -0700105{
Junxiao Shi7d30d852017-01-22 03:29:26 +0000106 ControlParameters reqParams;
107 reqParams.setName("/A")
108 .setStrategy("/strategy-choice-manager-unknown");
Davide Pesavento1d2d3372025-01-14 12:04:12 -0500109 auto req = makeControlCommandRequest(SET_SC_REQUEST, reqParams);
Junxiao Shi7d30d852017-01-22 03:29:26 +0000110 receiveInterest(req);
Yanbiao Li6704a4a2015-08-19 16:30:16 -0700111
Junxiao Shi7d30d852017-01-22 03:29:26 +0000112 ControlResponse expectedResp;
113 expectedResp.setCode(404)
114 .setText("Strategy not registered");
Junxiao Shi8a1f1702017-07-03 00:05:08 +0000115 BOOST_CHECK_EQUAL(checkResponse(0, req.getName(), expectedResp),
Yanbiao Li6704a4a2015-08-19 16:30:16 -0700116 CheckResponseResult::OK);
Yanbiao Li6704a4a2015-08-19 16:30:16 -0700117
Junxiao Shi7d30d852017-01-22 03:29:26 +0000118 BOOST_CHECK_EQUAL(hasEntry("/A"), false);
119}
120
Junxiao Shi332783b2018-02-04 23:52:46 +0000121BOOST_AUTO_TEST_CASE(SetNameTooLong)
122{
123 Name prefix;
Davide Pesavento2cae8ca2019-04-18 20:48:05 -0400124 while (prefix.size() <= NameTree::getMaxDepth()) {
Junxiao Shi332783b2018-02-04 23:52:46 +0000125 prefix.append("A");
126 }
127 ControlParameters reqParams;
128 reqParams.setName(prefix)
129 .setStrategy(strategyNameP);
Davide Pesavento1d2d3372025-01-14 12:04:12 -0500130 auto req = makeControlCommandRequest(SET_SC_REQUEST, reqParams);
Junxiao Shi332783b2018-02-04 23:52:46 +0000131 receiveInterest(req);
132
133 ControlResponse expectedResp;
134 expectedResp.setCode(414)
135 .setText("Prefix has too many components (limit is " +
Davide Pesavento2c9d2ca2024-01-27 16:36:51 -0500136 std::to_string(NameTree::getMaxDepth()) + ")");
Junxiao Shi332783b2018-02-04 23:52:46 +0000137 BOOST_CHECK_EQUAL(checkResponse(0, req.getName(), expectedResp),
138 CheckResponseResult::OK);
139
140 BOOST_CHECK_EQUAL(hasEntry(prefix), false);
141}
142
Junxiao Shi7d30d852017-01-22 03:29:26 +0000143BOOST_AUTO_TEST_CASE(UnsetSuccess)
144{
145 auto insertRes = sc.insert("/A", strategyNameP);
Davide Pesavento4296fe32025-01-14 23:00:41 -0500146 BOOST_TEST_REQUIRE(insertRes);
Junxiao Shi7d30d852017-01-22 03:29:26 +0000147
148 ControlParameters reqParams;
149 reqParams.setName("/A");
Davide Pesavento1d2d3372025-01-14 12:04:12 -0500150 auto req = makeControlCommandRequest(UNSET_SC_REQUEST, reqParams);
Junxiao Shi7d30d852017-01-22 03:29:26 +0000151 receiveInterest(req);
152
153 ControlParameters expectedParams(reqParams);
Davide Pesavento4296fe32025-01-14 23:00:41 -0500154 ControlResponse expectedResp = makeResponse(200, "OK", expectedParams);
Junxiao Shi8a1f1702017-07-03 00:05:08 +0000155 BOOST_CHECK_EQUAL(checkResponse(0, req.getName(), expectedResp),
Yanbiao Li6704a4a2015-08-19 16:30:16 -0700156 CheckResponseResult::OK);
Junxiao Shi7d30d852017-01-22 03:29:26 +0000157
158 BOOST_CHECK_EQUAL(hasEntry("/A"), false);
Yanbiao Li6704a4a2015-08-19 16:30:16 -0700159}
160
Junxiao Shi7d30d852017-01-22 03:29:26 +0000161BOOST_AUTO_TEST_CASE(UnsetNoop)
Yanbiao Li6704a4a2015-08-19 16:30:16 -0700162{
Junxiao Shi7d30d852017-01-22 03:29:26 +0000163 ControlParameters reqParams;
164 reqParams.setName("/A");
Davide Pesavento1d2d3372025-01-14 12:04:12 -0500165 auto req = makeControlCommandRequest(UNSET_SC_REQUEST, reqParams);
Junxiao Shi7d30d852017-01-22 03:29:26 +0000166 receiveInterest(req);
Yanbiao Li6704a4a2015-08-19 16:30:16 -0700167
Junxiao Shi7d30d852017-01-22 03:29:26 +0000168 ControlParameters expectedParams(reqParams);
Davide Pesavento4296fe32025-01-14 23:00:41 -0500169 ControlResponse expectedResp = makeResponse(200, "OK", expectedParams);
Junxiao Shi8a1f1702017-07-03 00:05:08 +0000170 BOOST_CHECK_EQUAL(checkResponse(0, req.getName(), expectedResp),
Junxiao Shi7d30d852017-01-22 03:29:26 +0000171 CheckResponseResult::OK);
Yanbiao Li6704a4a2015-08-19 16:30:16 -0700172
Junxiao Shi7d30d852017-01-22 03:29:26 +0000173 BOOST_CHECK_EQUAL(hasEntry("/A"), false);
Yanbiao Li6704a4a2015-08-19 16:30:16 -0700174}
175
Junxiao Shi7d30d852017-01-22 03:29:26 +0000176BOOST_AUTO_TEST_CASE(UnsetRootForbidden)
Yanbiao Li6704a4a2015-08-19 16:30:16 -0700177{
Junxiao Shi7d30d852017-01-22 03:29:26 +0000178 ControlParameters reqParams;
179 reqParams.setName("/");
Davide Pesavento1d2d3372025-01-14 12:04:12 -0500180 auto req = makeControlCommandRequest(UNSET_SC_REQUEST, reqParams);
Junxiao Shi7d30d852017-01-22 03:29:26 +0000181 receiveInterest(req);
182
183 ControlResponse expectedResp;
184 expectedResp.setCode(400)
185 .setText("failed in validating parameters");
Junxiao Shi8a1f1702017-07-03 00:05:08 +0000186 BOOST_CHECK_EQUAL(checkResponse(0, req.getName(), expectedResp),
Junxiao Shi7d30d852017-01-22 03:29:26 +0000187 CheckResponseResult::OK);
188
189 BOOST_CHECK_EQUAL(hasEntry("/"), true);
Yanbiao Li6704a4a2015-08-19 16:30:16 -0700190}
191
Davide Pesavento97210d52016-10-14 15:45:48 +0200192BOOST_AUTO_TEST_CASE(StrategyChoiceDataset)
Yanbiao Li6704a4a2015-08-19 16:30:16 -0700193{
Junxiao Shi7d30d852017-01-22 03:29:26 +0000194 std::map<Name, Name> expected; // namespace => strategy instance name
Davide Pesavento4296fe32025-01-14 23:00:41 -0500195 for (const auto& entry : sc) {
Junxiao Shi7d30d852017-01-22 03:29:26 +0000196 expected[entry.getPrefix()] = entry.getStrategyInstanceName();
Yanbiao Li6704a4a2015-08-19 16:30:16 -0700197 }
198
Davide Pesavento28181322018-11-08 16:44:50 -0500199 for (size_t i = expected.size(); i < 1024; ++i) {
Junxiao Shi7d30d852017-01-22 03:29:26 +0000200 Name name("/SC");
201 name.appendNumber(i);
202 Name strategy = DummyStrategy::getStrategyName(i);
203
204 auto insertRes = sc.insert(name, strategy);
Davide Pesavento4296fe32025-01-14 23:00:41 -0500205 BOOST_TEST(insertRes);
Junxiao Shi7d30d852017-01-22 03:29:26 +0000206 expected[name] = strategy;
Yanbiao Li6704a4a2015-08-19 16:30:16 -0700207 }
Yanbiao Li6704a4a2015-08-19 16:30:16 -0700208
Davide Pesavento28181322018-11-08 16:44:50 -0500209 receiveInterest(Interest("/localhost/nfd/strategy-choice/list").setCanBePrefix(true));
210
Junxiao Shi7d30d852017-01-22 03:29:26 +0000211 Block dataset = concatenateResponses();
212 dataset.parse();
213 BOOST_CHECK_EQUAL(dataset.elements_size(), expected.size());
Yanbiao Li6704a4a2015-08-19 16:30:16 -0700214
Davide Pesavento4296fe32025-01-14 23:00:41 -0500215 for (const auto& el : dataset.elements()) {
216 ndn::nfd::StrategyChoice record(el);
Davide Pesaventod7083a52023-10-19 17:51:16 -0400217 BOOST_TEST_INFO_SCOPE(record);
Junxiao Shi7d30d852017-01-22 03:29:26 +0000218 auto found = expected.find(record.getName());
219 if (found == expected.end()) {
220 BOOST_ERROR("record has unexpected namespace " << record.getName());
221 }
222 else {
Davide Pesaventod7083a52023-10-19 17:51:16 -0400223 BOOST_TEST(record.getStrategy() == found->second);
Junxiao Shi7d30d852017-01-22 03:29:26 +0000224 expected.erase(found);
225 }
Yanbiao Li6704a4a2015-08-19 16:30:16 -0700226 }
227
Junxiao Shi7d30d852017-01-22 03:29:26 +0000228 for (const auto& pair : expected) {
229 BOOST_ERROR("record for " << pair.first << " is missing");
230 }
Yanbiao Li6704a4a2015-08-19 16:30:16 -0700231}
232
233BOOST_AUTO_TEST_SUITE_END() // TestStrategyChoiceManager
234BOOST_AUTO_TEST_SUITE_END() // Mgmt
235
Davide Pesaventoe422f9e2022-06-03 01:30:23 -0400236} // namespace nfd::tests