blob: 86943223bac4ab25d246c6a94cf2258d95a59e55 [file] [log] [blame]
Junxiao Shia7f9a292016-11-22 16:31:38 +00001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2014-2016, Regents of the University of California,
4 * 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/** \file
27 * This test suite tests localhost and localhop scope control in strategies.
28 */
29
30// Strategies implementing namespace-based scope control, sorted alphabetically.
31#include "fw/access-strategy.hpp"
Junxiao Shie21b3f32016-11-24 14:13:46 +000032#include "fw/best-route-strategy.hpp"
Junxiao Shia7f9a292016-11-22 16:31:38 +000033#include "fw/best-route-strategy2.hpp"
Junxiao Shie21b3f32016-11-24 14:13:46 +000034#include "fw/multicast-strategy.hpp"
35#include "fw/ncc-strategy.hpp"
Junxiao Shia7f9a292016-11-22 16:31:38 +000036
37#include "tests/test-common.hpp"
38#include "tests/limited-io.hpp"
Junxiao Shie21b3f32016-11-24 14:13:46 +000039#include "install-strategy.hpp"
Junxiao Shia7f9a292016-11-22 16:31:38 +000040#include "strategy-tester.hpp"
41#include "tests/daemon/face/dummy-face.hpp"
42#include <boost/mpl/copy_if.hpp>
43#include <boost/mpl/vector.hpp>
44
45namespace nfd {
46namespace fw {
47namespace tests {
48
49using namespace nfd::tests;
50
51template<typename S>
52class StrategyScopeControlFixture : public UnitTestTimeFixture
53{
54public:
55 StrategyScopeControlFixture()
56 : limitedIo(this)
57 , nStrategyActions(0)
Junxiao Shie21b3f32016-11-24 14:13:46 +000058 , strategy(choose<StrategyTester<S>>(forwarder))
Junxiao Shia7f9a292016-11-22 16:31:38 +000059 , fib(forwarder.getFib())
60 , pit(forwarder.getPit())
61 , nonLocalFace1(make_shared<DummyFace>("dummy://1", "dummy://1", ndn::nfd::FACE_SCOPE_NON_LOCAL))
62 , nonLocalFace2(make_shared<DummyFace>("dummy://2", "dummy://2", ndn::nfd::FACE_SCOPE_NON_LOCAL))
63 , localFace3(make_shared<DummyFace>("dummy://3", "dummy://3", ndn::nfd::FACE_SCOPE_LOCAL))
64 , localFace4(make_shared<DummyFace>("dummy://4", "dummy://4", ndn::nfd::FACE_SCOPE_LOCAL))
65 {
66 this->strategy.afterAction.connect([this] {
67 limitedIo.afterOp();
68 ++nStrategyActions;
69 });
70
71 forwarder.addFace(nonLocalFace1);
72 forwarder.addFace(nonLocalFace2);
73 forwarder.addFace(localFace3);
74 forwarder.addFace(localFace4);
75 }
76
77 /** \brief execute f and wait for a number of strategy actions
78 * \note The actions may occur either during f() invocation or afterwards.
79 */
80 void
81 waitForStrategyAction(const std::function<void()>& f, int nExpectedActions = 1)
82 {
83 nStrategyActions = 0;
84 f();
85 if (nStrategyActions < nExpectedActions) {
86 BOOST_REQUIRE_EQUAL(limitedIo.run(nExpectedActions - nStrategyActions, LimitedIo::UNLIMITED_TIME),
87 LimitedIo::EXCEED_OPS);
88 }
Junxiao Shie21b3f32016-11-24 14:13:46 +000089 // A correctly implemented strategy is required to invoke reject pending Interest action
90 // if it decides to not forward an Interest. If a test case is stuck in an endless loop within
91 // this function, check that rejectPendingInterest is invoked under proper condition.
Junxiao Shia7f9a292016-11-22 16:31:38 +000092 }
93
94public:
95 LimitedIo limitedIo;
96 int nStrategyActions;
97
98 Forwarder forwarder;
Junxiao Shie21b3f32016-11-24 14:13:46 +000099 StrategyTester<S>& strategy;
Junxiao Shia7f9a292016-11-22 16:31:38 +0000100 Fib& fib;
101 Pit& pit;
102
103 shared_ptr<Face> nonLocalFace1;
104 shared_ptr<Face> nonLocalFace2;
105 shared_ptr<Face> localFace3;
106 shared_ptr<Face> localFace4;
107};
108
109BOOST_AUTO_TEST_SUITE(Fw)
110BOOST_AUTO_TEST_SUITE(TestStrategyScopeControl)
111
Junxiao Shie21b3f32016-11-24 14:13:46 +0000112template<typename S, bool WillSendNackNoRoute, bool CanProcessNack>
113class Test
Junxiao Shia7f9a292016-11-22 16:31:38 +0000114{
115public:
Junxiao Shie21b3f32016-11-24 14:13:46 +0000116 using Strategy = S;
Junxiao Shia7f9a292016-11-22 16:31:38 +0000117
118 static bool
119 willSendNackNoRoute()
120 {
Junxiao Shie21b3f32016-11-24 14:13:46 +0000121 return WillSendNackNoRoute;
Junxiao Shia7f9a292016-11-22 16:31:38 +0000122 }
123
124 static bool
125 canProcessNack()
126 {
Junxiao Shie21b3f32016-11-24 14:13:46 +0000127 return CanProcessNack;
Junxiao Shia7f9a292016-11-22 16:31:38 +0000128 }
129};
130
131using Tests = boost::mpl::vector<
Junxiao Shie21b3f32016-11-24 14:13:46 +0000132 Test<AccessStrategy, false, false>,
133 Test<BestRouteStrategy, false, false>,
134 Test<BestRouteStrategy2, true, true>,
135 Test<MulticastStrategy, false, false>,
136 Test<NccStrategy, false, false>
Junxiao Shia7f9a292016-11-22 16:31:38 +0000137>;
138
139BOOST_FIXTURE_TEST_CASE_TEMPLATE(LocalhostInterestToLocal,
Junxiao Shie21b3f32016-11-24 14:13:46 +0000140 T, Tests, StrategyScopeControlFixture<typename T::Strategy>)
Junxiao Shia7f9a292016-11-22 16:31:38 +0000141{
142 fib::Entry* fibEntry = this->fib.insert("/localhost/A").first;
143 fibEntry->addNextHop(*this->localFace4, 10);
144
145 shared_ptr<Interest> interest = makeInterest("/localhost/A/1");
146 shared_ptr<pit::Entry> pitEntry = this->pit.insert(*interest).first;
147 pitEntry->insertOrUpdateInRecord(*this->localFace3, *interest);
148
149 this->waitForStrategyAction(
150 [&] { this->strategy.afterReceiveInterest(*this->localFace3, *interest, pitEntry); });
151
152 BOOST_CHECK_EQUAL(this->strategy.sendInterestHistory.size(), 1);
153 BOOST_CHECK_EQUAL(this->strategy.rejectPendingInterestHistory.size(), 0);
154 BOOST_CHECK_EQUAL(this->strategy.sendNackHistory.size(), 0);
155}
156
157BOOST_FIXTURE_TEST_CASE_TEMPLATE(LocalhostInterestToNonLocal,
Junxiao Shie21b3f32016-11-24 14:13:46 +0000158 T, Tests, StrategyScopeControlFixture<typename T::Strategy>)
Junxiao Shia7f9a292016-11-22 16:31:38 +0000159{
160 fib::Entry* fibEntry = this->fib.insert("/localhost/A").first;
161 fibEntry->addNextHop(*this->nonLocalFace2, 10);
162
163 shared_ptr<Interest> interest = makeInterest("/localhost/A/1");
164 shared_ptr<pit::Entry> pitEntry = this->pit.insert(*interest).first;
165 pitEntry->insertOrUpdateInRecord(*this->localFace3, *interest);
166
167 this->waitForStrategyAction(
168 [&] { this->strategy.afterReceiveInterest(*this->localFace3, *interest, pitEntry); },
169 1 + T::willSendNackNoRoute());
170
171 BOOST_CHECK_EQUAL(this->strategy.sendInterestHistory.size(), 0);
172 BOOST_CHECK_EQUAL(this->strategy.rejectPendingInterestHistory.size(), 1);
173 if (T::willSendNackNoRoute()) {
174 BOOST_REQUIRE_EQUAL(this->strategy.sendNackHistory.size(), 1);
175 BOOST_CHECK_EQUAL(this->strategy.sendNackHistory.back().header.getReason(), lp::NackReason::NO_ROUTE);
176 }
177}
178
179BOOST_FIXTURE_TEST_CASE_TEMPLATE(LocalhostInterestToLocalAndNonLocal,
Junxiao Shie21b3f32016-11-24 14:13:46 +0000180 T, Tests, StrategyScopeControlFixture<typename T::Strategy>)
Junxiao Shia7f9a292016-11-22 16:31:38 +0000181{
182 fib::Entry* fibEntry = this->fib.insert("/localhost/A").first;
183 fibEntry->addNextHop(*this->nonLocalFace2, 10);
184 fibEntry->addNextHop(*this->localFace4, 20);
185
186 shared_ptr<Interest> interest = makeInterest("/localhost/A/1");
187 shared_ptr<pit::Entry> pitEntry = this->pit.insert(*interest).first;
188 pitEntry->insertOrUpdateInRecord(*this->localFace3, *interest);
189
190 this->waitForStrategyAction(
191 [&] { this->strategy.afterReceiveInterest(*this->localFace3, *interest, pitEntry); });
192
193 BOOST_REQUIRE_EQUAL(this->strategy.sendInterestHistory.size(), 1);
194 BOOST_CHECK_EQUAL(this->strategy.sendInterestHistory.back().outFaceId, this->localFace4->getId());
195 BOOST_CHECK_EQUAL(this->strategy.rejectPendingInterestHistory.size(), 0);
196 BOOST_CHECK_EQUAL(this->strategy.sendNackHistory.size(), 0);
197}
198
199BOOST_FIXTURE_TEST_CASE_TEMPLATE(LocalhopInterestToNonLocal,
Junxiao Shie21b3f32016-11-24 14:13:46 +0000200 T, Tests, StrategyScopeControlFixture<typename T::Strategy>)
Junxiao Shia7f9a292016-11-22 16:31:38 +0000201{
202 fib::Entry* fibEntry = this->fib.insert("/localhop/A").first;
203 fibEntry->addNextHop(*this->nonLocalFace2, 10);
204
205 shared_ptr<Interest> interest = makeInterest("/localhop/A/1");
206 shared_ptr<pit::Entry> pitEntry = this->pit.insert(*interest).first;
207 pitEntry->insertOrUpdateInRecord(*this->nonLocalFace1, *interest);
208
209 this->waitForStrategyAction(
210 [&] { this->strategy.afterReceiveInterest(*this->nonLocalFace1, *interest, pitEntry); },
211 1 + T::willSendNackNoRoute());
212
213 BOOST_CHECK_EQUAL(this->strategy.sendInterestHistory.size(), 0);
214 BOOST_CHECK_EQUAL(this->strategy.rejectPendingInterestHistory.size(), 1);
215 if (T::willSendNackNoRoute()) {
216 BOOST_REQUIRE_EQUAL(this->strategy.sendNackHistory.size(), 1);
217 BOOST_CHECK_EQUAL(this->strategy.sendNackHistory.back().header.getReason(), lp::NackReason::NO_ROUTE);
218 }
219}
220
221BOOST_FIXTURE_TEST_CASE_TEMPLATE(LocalhopInterestToNonLocalAndLocal,
Junxiao Shie21b3f32016-11-24 14:13:46 +0000222 T, Tests, StrategyScopeControlFixture<typename T::Strategy>)
Junxiao Shia7f9a292016-11-22 16:31:38 +0000223{
224 fib::Entry* fibEntry = this->fib.insert("/localhop/A").first;
225 fibEntry->addNextHop(*this->nonLocalFace2, 10);
226 fibEntry->addNextHop(*this->localFace4, 20);
227
228 shared_ptr<Interest> interest = makeInterest("/localhop/A/1");
229 shared_ptr<pit::Entry> pitEntry = this->pit.insert(*interest).first;
230 pitEntry->insertOrUpdateInRecord(*this->nonLocalFace1, *interest);
231
232 this->waitForStrategyAction(
233 [&] { this->strategy.afterReceiveInterest(*this->nonLocalFace1, *interest, pitEntry); });
234
235 BOOST_REQUIRE_EQUAL(this->strategy.sendInterestHistory.size(), 1);
236 BOOST_CHECK_EQUAL(this->strategy.sendInterestHistory.back().outFaceId, this->localFace4->getId());
237 BOOST_CHECK_EQUAL(this->strategy.rejectPendingInterestHistory.size(), 0);
238 BOOST_CHECK_EQUAL(this->strategy.sendNackHistory.size(), 0);
239}
240
241BOOST_FIXTURE_TEST_CASE_TEMPLATE(LocalhostNackToNonLocal,
Junxiao Shie21b3f32016-11-24 14:13:46 +0000242 T, Tests, StrategyScopeControlFixture<typename T::Strategy>)
Junxiao Shia7f9a292016-11-22 16:31:38 +0000243{
244 fib::Entry* fibEntry = this->fib.insert("/localhost/A").first;
245 fibEntry->addNextHop(*this->localFace4, 10);
246 fibEntry->addNextHop(*this->nonLocalFace2, 20);
247
248 shared_ptr<Interest> interest = makeInterest("/localhost/A/1", 1460);
249 shared_ptr<pit::Entry> pitEntry = this->pit.insert(*interest).first;
250 pitEntry->insertOrUpdateInRecord(*this->localFace3, *interest);
251 lp::Nack nack = makeNack("/localhost/A/1", 1460, lp::NackReason::NO_ROUTE);
252 pitEntry->insertOrUpdateOutRecord(*this->localFace4, *interest)->setIncomingNack(nack);
253
254 this->waitForStrategyAction(
255 [&] { this->strategy.afterReceiveNack(*this->localFace4, nack, pitEntry); },
256 T::canProcessNack());
257
258 BOOST_CHECK_EQUAL(this->strategy.sendInterestHistory.size(), 0);
259 BOOST_CHECK_EQUAL(this->strategy.rejectPendingInterestHistory.size(), 0);
260 if (T::canProcessNack()) {
261 BOOST_REQUIRE_EQUAL(this->strategy.sendNackHistory.size(), 1);
262 BOOST_CHECK_EQUAL(this->strategy.sendNackHistory.back().header.getReason(), lp::NackReason::NO_ROUTE);
263 }
264}
265
266BOOST_FIXTURE_TEST_CASE_TEMPLATE(LocalhopNackToNonLocal,
Junxiao Shie21b3f32016-11-24 14:13:46 +0000267 T, Tests, StrategyScopeControlFixture<typename T::Strategy>)
Junxiao Shia7f9a292016-11-22 16:31:38 +0000268{
269 fib::Entry* fibEntry = this->fib.insert("/localhop/A").first;
270 fibEntry->addNextHop(*this->localFace4, 10);
271 fibEntry->addNextHop(*this->nonLocalFace2, 20);
272
273 shared_ptr<Interest> interest = makeInterest("/localhop/A/1", 1377);
274 shared_ptr<pit::Entry> pitEntry = this->pit.insert(*interest).first;
275 pitEntry->insertOrUpdateInRecord(*this->nonLocalFace1, *interest);
276 lp::Nack nack = makeNack("/localhop/A/1", 1377, lp::NackReason::NO_ROUTE);
277 pitEntry->insertOrUpdateOutRecord(*this->localFace4, *interest)->setIncomingNack(nack);
278
279 this->waitForStrategyAction(
280 [&] { this->strategy.afterReceiveNack(*this->localFace4, nack, pitEntry); },
281 T::canProcessNack());
282
283 BOOST_CHECK_EQUAL(this->strategy.sendInterestHistory.size(), 0);
284 BOOST_CHECK_EQUAL(this->strategy.rejectPendingInterestHistory.size(), 0);
285 if (T::canProcessNack()) {
286 BOOST_REQUIRE_EQUAL(this->strategy.sendNackHistory.size(), 1);
287 BOOST_CHECK_EQUAL(this->strategy.sendNackHistory.back().header.getReason(), lp::NackReason::NO_ROUTE);
288 }
289}
290
291BOOST_AUTO_TEST_SUITE_END() // TestStrategyScopeControl
292BOOST_AUTO_TEST_SUITE_END() // Fw
293
294} // namespace tests
295} // namespace fw
296} // namespace nfd