blob: 7aa54ac5d4d0c14a54949a297b8b1541fd71d53d [file] [log] [blame]
Yanbiao Li6704a4a2015-08-19 16:30:16 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Yanbiao Lidf846e52016-01-30 21:53:47 -08003 * Copyright (c) 2014-2016, 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
Davide Pesavento5f47aa62016-10-07 22:09:09 +020028#include "core/random.hpp"
Yanbiao Li6704a4a2015-08-19 16:30:16 -070029#include "face/face.hpp"
30#include "face/internal-face.hpp"
Davide Pesavento97210d52016-10-14 15:45:48 +020031#include "fw/strategy.hpp"
Yanbiao Li6704a4a2015-08-19 16:30:16 -070032#include "table/name-tree.hpp"
33#include "table/strategy-choice.hpp"
Junxiao Shia49a1ab2016-07-15 18:24:36 +000034
Davide Pesavento97210d52016-10-14 15:45:48 +020035#include "nfd-manager-common-fixture.hpp"
Yanbiao Li6704a4a2015-08-19 16:30:16 -070036#include "tests/daemon/face/dummy-face.hpp"
37#include "tests/daemon/fw/dummy-strategy.hpp"
Junxiao Shia49a1ab2016-07-15 18:24:36 +000038#include "tests/daemon/fw/install-strategy.hpp"
Yanbiao Li6704a4a2015-08-19 16:30:16 -070039
Junxiao Shi25c6ce42016-09-09 13:49:59 +000040#include <ndn-cxx/mgmt/nfd/strategy-choice.hpp>
Yanbiao Li6704a4a2015-08-19 16:30:16 -070041
42namespace nfd {
43namespace tests {
44
Yanbiao Lidf846e52016-01-30 21:53:47 -080045class StrategyChoiceManagerFixture : public NfdManagerCommonFixture
Yanbiao Li6704a4a2015-08-19 16:30:16 -070046{
47public:
48 StrategyChoiceManagerFixture()
49 : m_strategyChoice(m_forwarder.getStrategyChoice())
Junxiao Shi9ddf1b52016-08-22 03:58:55 +000050 , m_manager(m_strategyChoice, m_dispatcher, *m_authenticator)
Yanbiao Li6704a4a2015-08-19 16:30:16 -070051 {
Junxiao Shi9ddf1b52016-08-22 03:58:55 +000052 setTopPrefix();
Yanbiao Lidf846e52016-01-30 21:53:47 -080053 setPrivilege("strategy-choice");
Yanbiao Li6704a4a2015-08-19 16:30:16 -070054 }
55
56public:
57 void
Junxiao Shia49a1ab2016-07-15 18:24:36 +000058 installStrategy(const Name& strategyName)
Yanbiao Li6704a4a2015-08-19 16:30:16 -070059 {
Junxiao Shia49a1ab2016-07-15 18:24:36 +000060 install<DummyStrategy>(m_forwarder, strategyName);
Yanbiao Li6704a4a2015-08-19 16:30:16 -070061 }
62
63 const Name&
64 findStrategy(const Name& name)
65 {
66 return m_strategyChoice.findEffectiveStrategy(name).getName();
67 }
68
69 ControlParameters
70 makeParameters(const Name& name, const Name& strategy)
71 {
72 return ControlParameters().setName(name).setStrategy(strategy);
73 }
74
75protected:
76 StrategyChoice& m_strategyChoice;
77 StrategyChoiceManager m_manager;
78};
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
83BOOST_AUTO_TEST_CASE(SetStrategy)
84{
85 auto testSetStrategy = [this] (const ControlParameters& parameters) -> Name {
86 m_responses.clear();
87 auto command = makeControlCommandRequest("/localhost/nfd/strategy-choice/set", parameters);
88 receiveInterest(command);
89 return command->getName();
90 };
91
92 installStrategy("/localhost/nfd/strategy/test-strategy-a");
93 installStrategy("/localhost/nfd/strategy/test-strategy-c/%FD%01"); // version 1
94 installStrategy("/localhost/nfd/strategy/test-strategy-c/%FD%02"); // version 2
95
96 auto parametersA = makeParameters("test", "/localhost/nfd/strategy/test-strategy-a");
97 auto parametersB = makeParameters("test", "/localhost/nfd/strategy/test-strategy-b");
98 auto parametersC1 = makeParameters("test", "/localhost/nfd/strategy/test-strategy-c/%FD%01");
99 auto parametersC = makeParameters("test", "/localhost/nfd/strategy/test-strategy-c");
100
101 auto commandNameA = testSetStrategy(parametersA); // succeed
102 BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
103 BOOST_CHECK_EQUAL(checkResponse(0, commandNameA, makeResponse(200, "OK", parametersA)),
104 CheckResponseResult::OK);
105 BOOST_CHECK_EQUAL(findStrategy("/test"), "/localhost/nfd/strategy/test-strategy-a");
106
107 auto commandNameB = testSetStrategy(parametersB); // not installed
108 BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
109 BOOST_CHECK_EQUAL(checkResponse(0, commandNameB, ControlResponse(504, "Unsupported strategy")),
110 CheckResponseResult::OK);
111
112 auto commandNameC1 = testSetStrategy(parametersC1); // specified version
113 BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
114 BOOST_CHECK_EQUAL(checkResponse(0, commandNameC1, makeResponse(200, "OK", parametersC1)),
115 CheckResponseResult::OK);
116 BOOST_CHECK_EQUAL(findStrategy("/test"), "/localhost/nfd/strategy/test-strategy-c/%FD%01");
117
118 auto commandNameC = testSetStrategy(parametersC); // latest version
119 parametersC.setStrategy("/localhost/nfd/strategy/test-strategy-c/%FD%02"); // change to latest
120 BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
121 BOOST_CHECK_EQUAL(checkResponse(0, commandNameC, makeResponse(200, "OK", parametersC)),
122 CheckResponseResult::OK);
123 BOOST_CHECK_EQUAL(findStrategy("/test"), "/localhost/nfd/strategy/test-strategy-c/%FD%02");
124}
125
126BOOST_AUTO_TEST_CASE(UnsetStrategy)
127{
128 auto testUnsetStrategy = [this] (const ControlParameters& parameters) -> Name {
129 m_responses.clear();
130 auto command = makeControlCommandRequest("/localhost/nfd/strategy-choice/unset", parameters);
131 receiveInterest(command);
132 return command->getName();
133 };
134
135 installStrategy("/localhost/nfd/strategy/test-strategy-a");
136 installStrategy("/localhost/nfd/strategy/test-strategy-b");
137 installStrategy("/localhost/nfd/strategy/test-strategy-c");
138
139 BOOST_CHECK(m_strategyChoice.insert("ndn:/", "/localhost/nfd/strategy/test-strategy-a")); // root
140 BOOST_CHECK(m_strategyChoice.insert("/test", "/localhost/nfd/strategy/test-strategy-b")); // test
141 BOOST_CHECK_EQUAL(findStrategy("/"), "/localhost/nfd/strategy/test-strategy-a");
142
143 auto parametersRoot = ControlParameters().setName("ndn:/"); // root prefix
144 auto parametersNone = ControlParameters().setName("/none"); // no such entry
145 auto parametersTest = ControlParameters().setName("/test"); // has such entry
146
147 BOOST_CHECK_EQUAL(findStrategy("/"), "/localhost/nfd/strategy/test-strategy-a"); // root
148 auto commandRootName = testUnsetStrategy(parametersRoot);
149 auto expectedResponse = ControlResponse(400, "failed in validating parameters");
150 BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
151 BOOST_CHECK_EQUAL(checkResponse(0, commandRootName, expectedResponse), CheckResponseResult::OK);
152 BOOST_CHECK_EQUAL(findStrategy("/"), "/localhost/nfd/strategy/test-strategy-a"); // keep as root
153
154 BOOST_CHECK_EQUAL(findStrategy("/none"), "/localhost/nfd/strategy/test-strategy-a"); // root
155 auto commandNoneName = testUnsetStrategy(parametersNone);
156 BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
157 BOOST_CHECK_EQUAL(checkResponse(0, commandNoneName, makeResponse(200, "OK", parametersNone)),
158 CheckResponseResult::OK);
159 BOOST_CHECK_EQUAL(findStrategy("/none"), "/localhost/nfd/strategy/test-strategy-a"); // root
160
161 BOOST_CHECK_EQUAL(findStrategy("/test"), "/localhost/nfd/strategy/test-strategy-b"); // self
162 auto commandTestName = testUnsetStrategy(parametersTest);
163 BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
164 BOOST_CHECK_EQUAL(checkResponse(0, commandTestName, makeResponse(200, "OK", parametersTest)),
165 CheckResponseResult::OK);
166 BOOST_CHECK_EQUAL(findStrategy("/test"), "/localhost/nfd/strategy/test-strategy-a"); // parent
167}
168
169// @todo Remove when ndn::nfd::StrategyChoice implements operator!= and operator<<
170class StrategyChoice : public ndn::nfd::StrategyChoice
171{
172public:
173 StrategyChoice() = default;
174
175 StrategyChoice(const ndn::nfd::StrategyChoice& entry)
176 : ndn::nfd::StrategyChoice(entry)
177 {
178 }
179};
180
181bool
182operator!=(const StrategyChoice& left, const StrategyChoice& right)
183{
184 return left.getName() != right.getName() || left.getStrategy() != right.getStrategy();
185}
186
187std::ostream&
188operator<<(std::ostream &os, const StrategyChoice& entry)
189{
190 os << "[ " << entry.getName() << ", " << entry.getStrategy() << " ]";
191 return os;
192}
193
Davide Pesavento97210d52016-10-14 15:45:48 +0200194BOOST_AUTO_TEST_CASE(StrategyChoiceDataset)
Yanbiao Li6704a4a2015-08-19 16:30:16 -0700195{
196 size_t nPreInsertedStrategies = m_strategyChoice.size(); // the best-route strategy
197 std::set<Name> actualNames, actualStrategies;
Davide Pesavento97210d52016-10-14 15:45:48 +0200198 for (const auto& entry : m_strategyChoice) {
Yanbiao Li6704a4a2015-08-19 16:30:16 -0700199 actualNames.insert(entry.getPrefix());
200 actualStrategies.insert(entry.getStrategyName());
201 }
202
Davide Pesavento5f47aa62016-10-07 22:09:09 +0200203 std::uniform_int_distribution<uint64_t> dist;
Yanbiao Li6704a4a2015-08-19 16:30:16 -0700204 size_t nEntries = 1024;
205 for (size_t i = 0 ; i < nEntries ; i++) {
206 auto name = Name("test-name").appendSegment(i);
Davide Pesavento5f47aa62016-10-07 22:09:09 +0200207 auto strategy = Name("test-strategy").appendSegment(dist(getGlobalRng()));
Yanbiao Li6704a4a2015-08-19 16:30:16 -0700208 auto entry = ndn::nfd::StrategyChoice().setName(name).setStrategy(strategy);
209 actualNames.insert(name);
210 actualStrategies.insert(strategy);
211 installStrategy(strategy);
212 m_strategyChoice.insert(name, strategy);
213 }
214 nEntries += nPreInsertedStrategies;
215
216 receiveInterest(makeInterest("/localhost/nfd/strategy-choice/list"));
217
218 Block content;
219 BOOST_CHECK_NO_THROW(content = concatenateResponses());
220 BOOST_CHECK_NO_THROW(content.parse());
221 BOOST_CHECK_EQUAL(content.elements().size(), nEntries);
222
223 std::vector<StrategyChoice> receivedRecords, expectedRecords;
224 for (size_t idx = 0; idx < nEntries; ++idx) {
225 BOOST_TEST_MESSAGE("processing element: " << idx);
226
227 StrategyChoice decodedEntry;
228 BOOST_REQUIRE_NO_THROW(decodedEntry.wireDecode(content.elements()[idx]));
229 receivedRecords.push_back(decodedEntry);
230
231 actualNames.erase(decodedEntry.getName());
232 actualStrategies.erase(decodedEntry.getStrategy());
233
234 auto result = m_strategyChoice.get(decodedEntry.getName());
235 BOOST_REQUIRE(result.first);
236
237 auto record = StrategyChoice().setName(decodedEntry.getName()).setStrategy(result.second);
238 expectedRecords.push_back(record);
239 }
240
241 BOOST_CHECK_EQUAL(actualNames.size(), 0);
242 BOOST_CHECK_EQUAL(actualStrategies.size(), 0);
Yanbiao Li6704a4a2015-08-19 16:30:16 -0700243 BOOST_CHECK_EQUAL_COLLECTIONS(receivedRecords.begin(), receivedRecords.end(),
244 expectedRecords.begin(), expectedRecords.end());
245}
246
247BOOST_AUTO_TEST_SUITE_END() // TestStrategyChoiceManager
248BOOST_AUTO_TEST_SUITE_END() // Mgmt
249
250} // namespace tests
251} // namespace nfd