blob: f33c7aeee99cf0f893fe930b26a6cf4c640515d0 [file] [log] [blame]
Yanbiao Lid7c96362015-01-30 23:58:24 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesaventoe1bdc082018-10-11 21:20:23 -04002/*
3 * Copyright (c) 2014-2018, Regents of the University of California,
Yanbiao Lid7c96362015-01-30 23:58:24 -08004 * 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 "rib/auto-prefix-propagator.hpp"
27
Davide Pesaventoe1bdc082018-10-11 21:20:23 -040028#include "tests/identity-management-fixture.hpp"
29
Junxiao Shi16a3adf2017-05-26 17:38:51 +000030#include <ndn-cxx/security/pib/pib.hpp>
Yanbiao Lid7c96362015-01-30 23:58:24 -080031#include <ndn-cxx/util/dummy-client-face.hpp>
32
33namespace nfd {
34namespace rib {
35namespace tests {
36
Junxiao Shi221b6fe2016-07-14 18:21:56 +000037using namespace nfd::tests;
38
Yanbiao Lid7c96362015-01-30 23:58:24 -080039const Name TEST_LINK_LOCAL_NFD_PREFIX("/localhop/nfd");
40const time::milliseconds TEST_PREFIX_PROPAGATION_TIMEOUT(1000);
41
Davide Pesavento97210d52016-10-14 15:45:48 +020042class AutoPrefixPropagatorFixture : public IdentityManagementTimeFixture
Yanbiao Lid7c96362015-01-30 23:58:24 -080043{
44public:
45 AutoPrefixPropagatorFixture()
Davide Pesaventoe1bdc082018-10-11 21:20:23 -040046 : m_face(g_io, m_keyChain, {true, true})
47 , m_scheduler(g_io)
Junxiao Shi221b6fe2016-07-14 18:21:56 +000048 , m_controller(m_face, m_keyChain)
Davide Pesaventoe1bdc082018-10-11 21:20:23 -040049 , m_propagator(m_controller, m_keyChain, m_scheduler, m_rib)
Junxiao Shi221b6fe2016-07-14 18:21:56 +000050 , m_requests(m_face.sentInterests)
Yanbiao Lid7c96362015-01-30 23:58:24 -080051 , m_entries(m_propagator.m_propagatedEntries)
52 {
53 m_propagator.enable();
54 m_propagator.m_controlParameters
55 .setCost(15)
56 .setOrigin(ndn::nfd::ROUTE_ORIGIN_CLIENT)// set origin to client.
57 .setFaceId(0);// the remote hub will take the input face as the faceId.
58 m_propagator.m_commandOptions
59 .setPrefix(TEST_LINK_LOCAL_NFD_PREFIX)
60 .setTimeout(TEST_PREFIX_PROPAGATION_TIMEOUT);
61 }
62
63public: // helpers for test
64 bool
65 insertEntryToRib(const Name& name, const uint64_t& faceId = 0)
66 {
67 if (m_rib.find(name) != m_rib.end()) {
Davide Pesavento97210d52016-10-14 15:45:48 +020068 BOOST_TEST_MESSAGE("RIB entry already exists: " + name.toUri());
Yanbiao Lid7c96362015-01-30 23:58:24 -080069 return false;
70 }
71
72 Route route;
73 route.faceId = faceId;
74 m_rib.insert(name, route);
75 advanceClocks(time::milliseconds(1));
76
77 return m_rib.find(name) != m_rib.end(); // return whether afterInserEntry will be triggered
78 }
79
80 bool
81 eraseEntryFromRib(const Name& name)
82 {
83 if (m_rib.find(name) == m_rib.end()) {
Davide Pesavento97210d52016-10-14 15:45:48 +020084 BOOST_TEST_MESSAGE("RIB entry does not exist: " + name.toUri());
Yanbiao Lid7c96362015-01-30 23:58:24 -080085 return false;
86 }
87
88 std::vector<Route> routeList;
89 std::copy(m_rib.find(name)->second->begin(), m_rib.find(name)->second->end(),
90 std::back_inserter(routeList));
91 for (auto&& route : routeList) {
92 m_rib.erase(name, route);
93 }
94 advanceClocks(time::milliseconds(1));
95
96 return m_rib.find(name) == m_rib.end(); // return whether afterEraseEntry will be triggered
97 }
98
99 void
100 connectToHub()
101 {
102 insertEntryToRib("/localhop/nfd");
103 }
104
105 void
106 disconnectFromHub()
107 {
108 eraseEntryFromRib("/localhop/nfd");
109 }
110
111public: // helpers for check
112 enum class CheckRequestResult {
113 OK,
114 OUT_OF_BOUNDARY,
115 INVALID_N_COMPONENTS,
116 WRONG_COMMAND_PREFIX,
117 WRONG_VERB,
118 INVALID_PARAMETERS,
119 WRONG_REGISTERING_PREFIX
120 };
121
122 /**
123 * @brief check a request at specified index
124 *
125 * @param idx the index of the specified request in m_requests
126 * @param verb the expected verb of request
127 * @param registeringPrefix the expected registering prefix of request
128
129 * @retval OK the specified request has a valid name, the right verb, a valid ControlParameters
130 * and the right registering prefix
131 * @retval OUT_OF_BOUNDARY the specified index out of boundary
132 * @retval INVALID_N_COMPONENTS the number of components of the request name is invalid
133 * @retval WRONG_COMMAND_PREFIX the command prefix of the request is wrong
134 * @retval WRONG_VERB the command verb of the request is wrong
135 * @retval INVALID_PARAMETERS no valid parameters can be decoded from the request's name
136 * @retval WRONG_REGISTERING_PREFIX the registering prefix of the request is wrong
137 */
138 CheckRequestResult
139 checkRequest(size_t idx, const std::string& verb, const Name& registeringPrefix)
140 {
141 Name requestName;
142 try {
143 requestName = m_requests.at(idx).getName();
144 }
145 catch (const std::out_of_range&) {
146 return CheckRequestResult::OUT_OF_BOUNDARY;
147 }
148
149 if (requestName.size() < 5) {
150 return CheckRequestResult::INVALID_N_COMPONENTS;
151 }
152
153 if (requestName.getPrefix(2) != TEST_LINK_LOCAL_NFD_PREFIX) {
154 return CheckRequestResult::WRONG_COMMAND_PREFIX;
155 }
156
157 if (requestName.get(3) != Name::Component(verb)) {
158 return CheckRequestResult::WRONG_VERB;
159 }
160
161 ControlParameters parameters;
162 try {
163 parameters.wireDecode(requestName.get(4).blockFromValue());
164 }
165 catch (const tlv::Error&) {
166 return CheckRequestResult::INVALID_PARAMETERS;
167 }
168
169 if (parameters.getName() != registeringPrefix) {
170 return CheckRequestResult::WRONG_REGISTERING_PREFIX;
171 }
172
173 return CheckRequestResult::OK;
174 }
175
176protected:
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000177 ndn::util::DummyClientFace m_face;
Davide Pesaventoe1bdc082018-10-11 21:20:23 -0400178 ndn::util::Scheduler m_scheduler;
Junxiao Shi221b6fe2016-07-14 18:21:56 +0000179 ndn::nfd::Controller m_controller;
180 Rib m_rib;
181 AutoPrefixPropagator m_propagator;
182 std::vector<Interest>& m_requests; ///< store sent out requests
183 AutoPrefixPropagator::PropagatedEntryList& m_entries; ///< store propagated entries
Yanbiao Lid7c96362015-01-30 23:58:24 -0800184};
185
186std::ostream&
187operator<<(std::ostream &os, const AutoPrefixPropagatorFixture::CheckRequestResult& result)
188{
189 switch (result) {
190 case AutoPrefixPropagatorFixture::CheckRequestResult::OK:
191 os << "OK";
192 break;
193 case AutoPrefixPropagatorFixture::CheckRequestResult::OUT_OF_BOUNDARY:
194 os << "OUT_OF_BOUNDARY";
195 break;
196 case AutoPrefixPropagatorFixture::CheckRequestResult::INVALID_N_COMPONENTS:
197 os << "INVALID_N_COMPONENTS";
198 break;
199 case AutoPrefixPropagatorFixture::CheckRequestResult::WRONG_COMMAND_PREFIX:
200 os << "WRONG_COMMAND_PREFIX";
201 break;
202 case AutoPrefixPropagatorFixture::CheckRequestResult::WRONG_VERB:
203 os << "WRONG_VERB";
204 break;
205 case AutoPrefixPropagatorFixture::CheckRequestResult::INVALID_PARAMETERS:
206 os << "INVALID_PARAMETERS";
207 break;
208 case AutoPrefixPropagatorFixture::CheckRequestResult::WRONG_REGISTERING_PREFIX:
209 os << "WRONG_REGISTERING_PREFIX";
210 break;
211 default:
212 break;
213 }
214
215 return os;
216}
217
Yanbiao Lid7c96362015-01-30 23:58:24 -0800218BOOST_FIXTURE_TEST_SUITE(TestAutoPrefixPropagator, AutoPrefixPropagatorFixture)
219
220BOOST_AUTO_TEST_CASE(EnableDisable)
221{
222 connectToHub();
223 BOOST_REQUIRE(addIdentity("/test/A"));
224
225 auto testPropagateRevokeBasic = [this] () -> bool {
226 m_propagator.m_propagatedEntries.clear();
227
228 if (!insertEntryToRib("/test/A/app")) {
229 return false;
230 }
Davide Pesaventoe1bdc082018-10-11 21:20:23 -0400231 m_entries["/test/A"].succeed(m_scheduler, nullptr);
Yanbiao Lid7c96362015-01-30 23:58:24 -0800232 if (!eraseEntryFromRib("/test/A/app")) {
233 return false;
234 }
235 return true;
236 };
237
238 m_propagator.disable();
239 BOOST_REQUIRE(testPropagateRevokeBasic());
240 BOOST_CHECK(m_requests.empty());
241
242 m_propagator.enable();
243 BOOST_REQUIRE(testPropagateRevokeBasic());
244 BOOST_REQUIRE_EQUAL(m_requests.size(), 2);
245 BOOST_CHECK_EQUAL(checkRequest(0, "register", "/test/A"), CheckRequestResult::OK);
246 BOOST_CHECK_EQUAL(checkRequest(1, "unregister", "/test/A"), CheckRequestResult::OK);
247}
248
249BOOST_AUTO_TEST_CASE(LoadConfiguration)
250{
251 ConfigFile config;
252 config.addSectionHandler("auto_prefix_propagate",
253 bind(&AutoPrefixPropagator::loadConfig, &m_propagator, _1));
254
255 const std::string CONFIG_STRING =
256 "auto_prefix_propagate\n"
257 "{\n"
258 " cost 11\n"
259 " timeout 22\n"
260 " refresh_interval 33\n"
261 " base_retry_wait 44\n"
262 " max_retry_wait 55\n"
263 "}";
264 config.parse(CONFIG_STRING, true, "test-auto-prefix-propagator");
265
266 BOOST_CHECK_EQUAL(m_propagator.m_controlParameters.getCost(), 11);
267 BOOST_CHECK_EQUAL(m_propagator.m_controlParameters.getOrigin(), ndn::nfd::ROUTE_ORIGIN_CLIENT);
268 BOOST_CHECK_EQUAL(m_propagator.m_controlParameters.getFaceId(), 0);
269
270 BOOST_CHECK_EQUAL(m_propagator.m_commandOptions.getPrefix(), TEST_LINK_LOCAL_NFD_PREFIX);
271 BOOST_CHECK_EQUAL(m_propagator.m_commandOptions.getTimeout(), time::milliseconds(22));
272
273 BOOST_CHECK_EQUAL(m_propagator.m_refreshInterval, time::seconds(33));
274 BOOST_CHECK_EQUAL(m_propagator.m_baseRetryWait, time::seconds(44));
275 BOOST_CHECK_EQUAL(m_propagator.m_maxRetryWait, time::seconds(55));
276}
277
Yanbiao Lid7c96362015-01-30 23:58:24 -0800278BOOST_AUTO_TEST_CASE(GetPrefixPropagationParameters)
279{
280 BOOST_REQUIRE(addIdentity("/test/A"));
281 BOOST_REQUIRE(addIdentity("/test/A/B"));
282 BOOST_REQUIRE(addIdentity("/test/C/nrd"));
283
284 auto parameters1 = m_propagator.getPrefixPropagationParameters("/none/A/B/app");
285 auto parameters2 = m_propagator.getPrefixPropagationParameters("/test/A/B/app");
286 auto parameters3 = m_propagator.getPrefixPropagationParameters("/test/C/D/app");
287
288 BOOST_CHECK(!parameters1.isValid);
289
290 BOOST_CHECK(parameters2.isValid);
291 BOOST_CHECK_EQUAL(parameters2.parameters.getName(), "/test/A");
292 BOOST_CHECK_EQUAL(parameters2.options.getSigningInfo().getSignerName(), "/test/A");
293
294 BOOST_CHECK(parameters3.isValid);
295 BOOST_CHECK_EQUAL(parameters3.parameters.getName(), "/test/C");
296 BOOST_CHECK_EQUAL(parameters3.options.getSigningInfo().getSignerName(), "/test/C/nrd");
297}
298
299BOOST_AUTO_TEST_CASE(CheckCurrentPropagatedPrefix)
300{
301 BOOST_REQUIRE(addIdentity("/test/A"));
302 BOOST_REQUIRE(addIdentity("/test/B/nrd"));
303 BOOST_REQUIRE(addIdentity("/test/A/B"));
304
305 BOOST_CHECK(!m_propagator.doesCurrentPropagatedPrefixWork("/test/E")); // does not exist
306 BOOST_CHECK(!m_propagator.doesCurrentPropagatedPrefixWork("/test/A/B")); // has a better option
307 BOOST_CHECK(m_propagator.doesCurrentPropagatedPrefixWork("/test/A"));
308 BOOST_CHECK(m_propagator.doesCurrentPropagatedPrefixWork("/test/B"));
309}
310
311BOOST_AUTO_TEST_CASE(RedoPropagation)
312{
313 connectToHub();
314 BOOST_REQUIRE(addIdentity("/test/A"));
315 BOOST_REQUIRE(addIdentity("/test/B"));
316 BOOST_REQUIRE(addIdentity("/test/B/C"));
317 BOOST_REQUIRE(insertEntryToRib("/test/A/app"));
318 BOOST_REQUIRE(insertEntryToRib("/test/B/C/app"));
319 BOOST_REQUIRE(insertEntryToRib("/test/B/D/app"));
320
321 auto testRedoPropagation = [this] (const Name& signingIdentity) {
322 m_requests.clear();
323
324 m_entries[signingIdentity].setSigningIdentity(signingIdentity);
325
326 auto parameters = m_propagator.m_controlParameters;
327 auto options = m_propagator.m_commandOptions;
328 ndn::security::SigningInfo info(ndn::security::SigningInfo::SIGNER_TYPE_ID, signingIdentity);
329 m_propagator.redoPropagation(m_entries.find(signingIdentity),
330 parameters.setName(signingIdentity),
331 options.setSigningInfo(info),
332 time::seconds(0));
333 advanceClocks(time::milliseconds(1));
334 };
335
336 testRedoPropagation("/test/A"); // current propagated prefix still works
337 BOOST_REQUIRE_EQUAL(m_requests.size(), 1);
338 BOOST_CHECK_EQUAL(checkRequest(0, "register", "/test/A"), CheckRequestResult::OK);
339 BOOST_CHECK(m_entries.find("test/A") != m_entries.end());
340
Junxiao Shi16a3adf2017-05-26 17:38:51 +0000341 m_keyChain.deleteIdentity(m_keyChain.getPib().getIdentity("/test/B"));
Yanbiao Lid7c96362015-01-30 23:58:24 -0800342 testRedoPropagation("/test/B"); // signingIdentity no longer exists
343 BOOST_REQUIRE_EQUAL(m_requests.size(), 1);
344 BOOST_CHECK_EQUAL(checkRequest(0, "register", "/test/B/C"), CheckRequestResult::OK);
345 BOOST_CHECK(m_entries.find("/test/B") == m_entries.end());
346 BOOST_CHECK(m_entries.find("/test/B/C") != m_entries.end());
347
348 testRedoPropagation("/test/B"); // no alternative identity
349 BOOST_CHECK(m_requests.empty());
350 BOOST_CHECK(m_entries.find("/test/B") == m_entries.end());
351
Davide Pesaventoe1bdc082018-10-11 21:20:23 -0400352 m_entries["/test/B/C"].succeed(m_scheduler, nullptr);
Yanbiao Lid7c96362015-01-30 23:58:24 -0800353 testRedoPropagation("/test/B"); // alternative identity has been propagated
354 BOOST_CHECK(m_requests.empty());
355 BOOST_CHECK(m_entries.find("/test/B") == m_entries.end());
356
357 BOOST_REQUIRE(addIdentity("/test/B/"));
358 testRedoPropagation("/test/B/C"); // better option exists: /test/B
359 BOOST_REQUIRE_EQUAL(m_requests.size(), 1);
360 BOOST_CHECK_EQUAL(checkRequest(0, "register", "/test/B"), CheckRequestResult::OK);
361 BOOST_CHECK(m_entries.find("test/B/C") == m_entries.end());
362}
363
Yanbiao Lid7c96362015-01-30 23:58:24 -0800364BOOST_AUTO_TEST_SUITE(PropagateRevokeSemantics)
365
366BOOST_AUTO_TEST_CASE(Basic)
367{
368 connectToHub(); // ensure connectivity to the hub
369 BOOST_REQUIRE(addIdentity("/test/A"));
370
371 BOOST_REQUIRE(insertEntryToRib("/test/A/app")); // ensure afterInsertEntry signal emitted
Davide Pesaventoe1bdc082018-10-11 21:20:23 -0400372 m_entries["/test/A"].succeed(m_scheduler, nullptr); // ensure there is a valid entry inserted
Yanbiao Lid7c96362015-01-30 23:58:24 -0800373 BOOST_REQUIRE(eraseEntryFromRib("/test/A/app")); // ensure afterEraseEntry signal emitted
374
375 BOOST_REQUIRE_EQUAL(m_requests.size(), 2);
376 BOOST_CHECK_EQUAL(checkRequest(0, "register", "/test/A"), CheckRequestResult::OK);
377 BOOST_CHECK_EQUAL(checkRequest(1, "unregister", "/test/A"), CheckRequestResult::OK);
378}
379
380BOOST_AUTO_TEST_CASE(LocalPrefix)
381{
382 connectToHub();
383 BOOST_REQUIRE(addIdentity("/localhost/A"));
384
385 BOOST_REQUIRE(insertEntryToRib("/localhost/A/app"));
386 BOOST_CHECK(m_requests.empty());
387
Davide Pesaventoe1bdc082018-10-11 21:20:23 -0400388 m_propagator.m_propagatedEntries["/localhost/A"].succeed(m_scheduler, nullptr);
Yanbiao Lid7c96362015-01-30 23:58:24 -0800389 BOOST_REQUIRE(eraseEntryFromRib("/localhost/A/app"));
390 BOOST_CHECK(m_requests.empty());
391}
392
393BOOST_AUTO_TEST_CASE(InvalidPropagationParameters)
394{
395 connectToHub();
396
397 // no identity can be found
398 BOOST_CHECK(!m_propagator.getPrefixPropagationParameters("/test/A/app").isValid);
399
400 BOOST_REQUIRE(insertEntryToRib("/test/A/app"));
401 BOOST_CHECK(m_requests.empty());
402
Davide Pesaventoe1bdc082018-10-11 21:20:23 -0400403 m_entries["/test/A"].succeed(m_scheduler, nullptr);
Yanbiao Lid7c96362015-01-30 23:58:24 -0800404 BOOST_REQUIRE(eraseEntryFromRib("/test/A/app"));
405 BOOST_CHECK(m_requests.empty());
406}
407
408BOOST_AUTO_TEST_CASE(NoHubConnectivity)
409{
410 BOOST_REQUIRE(addIdentity("/test/A"));
411
412 BOOST_REQUIRE(insertEntryToRib("/test/A/app"));
413 BOOST_CHECK(m_requests.empty());
414
Davide Pesaventoe1bdc082018-10-11 21:20:23 -0400415 m_entries["/test/A"].succeed(m_scheduler, nullptr);
Yanbiao Lid7c96362015-01-30 23:58:24 -0800416 BOOST_REQUIRE(eraseEntryFromRib("/test/A/app"));
417 BOOST_CHECK(m_requests.empty());
418}
419
Yanbiao Li6db75f02016-01-16 12:25:23 +0800420BOOST_AUTO_TEST_CASE(ProcessSuspendedEntries)
421{
422 BOOST_REQUIRE(addIdentity("/test/A"));
423
424 BOOST_REQUIRE(insertEntryToRib("/test/A/app1"));
425 BOOST_REQUIRE(insertEntryToRib("/test/A/app2"));
426 BOOST_CHECK(m_requests.empty()); // no propagation because no hub is connected
427 BOOST_CHECK_EQUAL(m_entries.size(), 1); // /test/A was suspended
428
429 BOOST_REQUIRE(eraseEntryFromRib("/test/A/app2"));
430 BOOST_CHECK_EQUAL(m_entries.size(), 1); // /test/A was kept for app1
431
432 // repeat the scenario that leads to BUG 3362.
433 // ensure there is no improper assertion.
434 BOOST_REQUIRE(insertEntryToRib("/test/A/app2"));
435}
436
Yanbiao Lid7c96362015-01-30 23:58:24 -0800437BOOST_AUTO_TEST_CASE(PropagatedEntryExists)
438{
439 connectToHub();
440 BOOST_REQUIRE(addIdentity("/test/A"));
441 BOOST_REQUIRE(insertEntryToRib("/test/A/app1"));
442
443 m_requests.clear();
444 BOOST_REQUIRE(insertEntryToRib("/test/A/app2")); // /test/A has been propagated by /test/A/app1
445 BOOST_CHECK(m_requests.empty());
446}
447
448BOOST_AUTO_TEST_CASE(PropagatedEntryShouldKeep)
449{
450 connectToHub();
451 BOOST_REQUIRE(addIdentity("/test/A"));
452 BOOST_REQUIRE(insertEntryToRib("/test/A/app1"));
453 BOOST_REQUIRE(insertEntryToRib("/test/A/app2"));
454
455 m_requests.clear();
456 BOOST_REQUIRE(eraseEntryFromRib("/test/A/app2")); // /test/A should be kept for /test/A/app1
457 BOOST_CHECK(m_requests.empty());
458}
459
460BOOST_AUTO_TEST_CASE(BackOffRetryPolicy)
461{
462 m_propagator.m_commandOptions.setTimeout(time::milliseconds(1));
463 m_propagator.m_baseRetryWait = time::seconds(1);
464 m_propagator.m_maxRetryWait = time::seconds(2);
465
466 connectToHub();
467 BOOST_REQUIRE(addIdentity("/test/A"));
468 BOOST_REQUIRE(insertEntryToRib("/test/A/app"));
469
470 BOOST_REQUIRE_EQUAL(m_requests.size(), 1);
471 BOOST_CHECK_EQUAL(checkRequest(0, "register", "/test/A"), CheckRequestResult::OK);
472
Junxiao Shi0de23a22015-12-03 20:07:02 +0000473 advanceClocks(time::milliseconds(10), time::milliseconds(1050)); // wait for the 1st retry
Yanbiao Lid7c96362015-01-30 23:58:24 -0800474 BOOST_REQUIRE_EQUAL(m_requests.size(), 2);
475 BOOST_CHECK_EQUAL(checkRequest(1, "register", "/test/A"), CheckRequestResult::OK);
476
Junxiao Shi0de23a22015-12-03 20:07:02 +0000477 advanceClocks(time::milliseconds(10), time::milliseconds(2050)); // wait for the 2nd retry, 2 times
Yanbiao Lid7c96362015-01-30 23:58:24 -0800478 BOOST_REQUIRE_EQUAL(m_requests.size(), 3);
479 BOOST_CHECK_EQUAL(checkRequest(2, "register", "/test/A"), CheckRequestResult::OK);
480
Junxiao Shi0de23a22015-12-03 20:07:02 +0000481 advanceClocks(time::milliseconds(10), time::milliseconds(2050)); // wait for the 3rd retry, reach the upper bound
Yanbiao Lid7c96362015-01-30 23:58:24 -0800482 BOOST_REQUIRE_EQUAL(m_requests.size(), 4);
483 BOOST_CHECK_EQUAL(checkRequest(3, "register", "/test/A"), CheckRequestResult::OK);
484}
485
486BOOST_AUTO_TEST_SUITE_END() // PropagateRevokeSemantics
487
488BOOST_AUTO_TEST_SUITE(PropagatedEntryStateChanges)
489
490BOOST_AUTO_TEST_CASE(AfterRibInsert)
491{
492 BOOST_REQUIRE(addIdentity("/test/A"));
493
494 auto testAfterRibInsert = [this] (const Name& ribEntryPrefix) {
495 m_requests.clear();
496 m_propagator.m_propagatedEntries.clear(); // ensure entry does not exist
497
498 auto propagateParameters = m_propagator.getPrefixPropagationParameters(ribEntryPrefix);
499 m_propagator.afterRibInsert(propagateParameters.parameters, propagateParameters.options);
500 advanceClocks(time::milliseconds(1));
501 };
502
503 testAfterRibInsert("/test/A/app1");
504 BOOST_CHECK(m_requests.empty()); // no connectivity now
505 BOOST_CHECK(m_entries.find("/test/A") != m_entries.end());
506
507 connectToHub();
508 testAfterRibInsert("/test/A/app2");
509 BOOST_REQUIRE_EQUAL(m_requests.size(), 1);
510 BOOST_CHECK_EQUAL(checkRequest(0, "register", "/test/A"), CheckRequestResult::OK);
511 BOOST_CHECK(m_entries.find("/test/A") != m_entries.end());
512}
513
514BOOST_AUTO_TEST_CASE(AfterRibErase)
515{
516 BOOST_REQUIRE(addIdentity("/test/A"));
517
518 auto testAfterRibInsert = [this] (const Name& localUnregPrefix) {
519 m_requests.clear();
520
521 auto propagateParameters = m_propagator.getPrefixPropagationParameters(localUnregPrefix);
522 m_propagator.afterRibErase(propagateParameters.parameters.unsetCost(),
523 propagateParameters.options);
524 advanceClocks(time::milliseconds(1));
525 };
526
Davide Pesaventoe1bdc082018-10-11 21:20:23 -0400527 m_entries["/test/A"].succeed(m_scheduler, nullptr);
Yanbiao Lid7c96362015-01-30 23:58:24 -0800528 testAfterRibInsert("/test/A/app");
529 BOOST_CHECK(m_requests.empty()); // no connectivity
530 BOOST_CHECK(m_entries.find("/test/A") == m_entries.end()); // has been erased
531
532 connectToHub();
Davide Pesaventoe1bdc082018-10-11 21:20:23 -0400533 m_entries["/test/A"].fail(m_scheduler, nullptr);
Yanbiao Lid7c96362015-01-30 23:58:24 -0800534 testAfterRibInsert("/test/A/app");
535 BOOST_CHECK(m_requests.empty()); // previous propagation has not succeeded
536 BOOST_CHECK(m_entries.find("/test/A") == m_entries.end()); // has been erased
537
Davide Pesaventoe1bdc082018-10-11 21:20:23 -0400538 m_entries["/test/A"].succeed(m_scheduler, nullptr);
Yanbiao Lid7c96362015-01-30 23:58:24 -0800539 testAfterRibInsert("/test/A/app");
540 BOOST_REQUIRE_EQUAL(m_requests.size(), 1);
541 BOOST_CHECK_EQUAL(checkRequest(0, "unregister", "/test/A"), CheckRequestResult::OK);
542 BOOST_CHECK(m_entries.find("/test/A") == m_entries.end()); // has been erased
543}
544
545BOOST_AUTO_TEST_CASE(AfterHubConnectDisconnect)
546{
547 BOOST_REQUIRE(addIdentity("/test/A"));
548 BOOST_REQUIRE(addIdentity("/test/B"));
549 BOOST_REQUIRE(addIdentity("/test/C"));
550 BOOST_REQUIRE(insertEntryToRib("/test/A/app"));
551 BOOST_REQUIRE(insertEntryToRib("/test/B/app"));
552
553 // recorder the prefixes that will be propagated in order
554 std::vector<Name> propagatedPrefixes;
555
556 BOOST_CHECK(m_requests.empty()); // no request because there is no connectivity to the hub now
557 BOOST_REQUIRE_EQUAL(m_entries.size(), 2); // valid entries will be kept
558
559 connectToHub(); // 2 cached entries will be processed
560 for (auto&& entry : m_entries) {
561 propagatedPrefixes.push_back(entry.first);
562 }
563
564 BOOST_REQUIRE(insertEntryToRib("/test/C/app")); // will be processed directly
565 propagatedPrefixes.push_back("/test/C");
566 BOOST_REQUIRE_EQUAL(m_entries.size(), 3);
567
568 BOOST_REQUIRE(m_entries["/test/A"].isPropagating());
569 BOOST_REQUIRE(m_entries["/test/B"].isPropagating());
570 BOOST_REQUIRE(m_entries["/test/C"].isPropagating());
571
572 disconnectFromHub(); // all 3 entries are initialized
573 BOOST_CHECK(m_entries["/test/A"].isNew());
574 BOOST_CHECK(m_entries["/test/B"].isNew());
575 BOOST_CHECK(m_entries["/test/C"].isNew());
576
577 connectToHub(); // all 3 entries will be processed
578 for (auto&& entry : m_entries) {
579 propagatedPrefixes.push_back(entry.first);
580 }
581
582 BOOST_REQUIRE_EQUAL(m_requests.size(), 6);
583 BOOST_REQUIRE_EQUAL(propagatedPrefixes.size(), 6);
584 BOOST_CHECK_EQUAL(checkRequest(0, "register", propagatedPrefixes[0]), CheckRequestResult::OK);
585 BOOST_CHECK_EQUAL(checkRequest(1, "register", propagatedPrefixes[1]), CheckRequestResult::OK);
586 BOOST_CHECK_EQUAL(checkRequest(2, "register", propagatedPrefixes[2]), CheckRequestResult::OK);
587 BOOST_CHECK_EQUAL(checkRequest(3, "register", propagatedPrefixes[3]), CheckRequestResult::OK);
588 BOOST_CHECK_EQUAL(checkRequest(4, "register", propagatedPrefixes[4]), CheckRequestResult::OK);
589 BOOST_CHECK_EQUAL(checkRequest(5, "register", propagatedPrefixes[5]), CheckRequestResult::OK);
590}
591
592BOOST_AUTO_TEST_CASE(AfterPropagateSucceed)
593{
594 bool wasRefreshEventTriggered = false;
595 auto testAfterPropagateSucceed = [&] (const Name& ribEntryPrefix) {
596 m_requests.clear();
597 wasRefreshEventTriggered = false;
598
599 auto propagateParameters = m_propagator.getPrefixPropagationParameters(ribEntryPrefix);
600 m_propagator.afterPropagateSucceed(propagateParameters.parameters, propagateParameters.options,
601 [&]{ wasRefreshEventTriggered = true; });
602 advanceClocks(time::milliseconds(1));
603 };
604
605 BOOST_REQUIRE(addIdentity("/test/A"));
606 m_propagator.m_refreshInterval = time::seconds(0); // event will be executed at once
607 m_entries["/test/A"].startPropagation(); // set to be in PROPAGATING state
608
609 testAfterPropagateSucceed("/test/A/app"); // will trigger refresh event
610 BOOST_CHECK(wasRefreshEventTriggered);
611 BOOST_CHECK(m_requests.empty());
612
613 m_entries.erase(m_entries.find("/test/A")); // set to be in RELEASED state
614 testAfterPropagateSucceed("/test/A/app"); // will call startRevocation
615 BOOST_CHECK(!wasRefreshEventTriggered);
616 BOOST_REQUIRE_EQUAL(m_requests.size(), 1);
617 BOOST_CHECK_EQUAL(checkRequest(0, "unregister", "/test/A"), CheckRequestResult::OK);
618}
619
620BOOST_AUTO_TEST_CASE(AfterPropagateFail)
621{
622 bool wasRetryEventTriggered = false;
623 auto testAfterPropagateFail = [&] (const Name& ribEntryPrefix) {
624 m_requests.clear();
625 wasRetryEventTriggered = false;
626
627 auto propagateParameters = m_propagator.getPrefixPropagationParameters(ribEntryPrefix);
Junxiao Shi29b41282016-08-22 03:47:02 +0000628 m_propagator.afterPropagateFail(ndn::nfd::ControlResponse(400, "test"),
629 propagateParameters.parameters, propagateParameters.options,
630 time::seconds(0), [&] { wasRetryEventTriggered = true; });
Yanbiao Lid7c96362015-01-30 23:58:24 -0800631 advanceClocks(time::milliseconds(1));
632 };
633
634 BOOST_REQUIRE(addIdentity("/test/A"));
635 m_entries["/test/A"].startPropagation(); // set to be in PROPAGATING state
636
637 testAfterPropagateFail("/test/A/app"); // will trigger retry event
638 BOOST_CHECK(wasRetryEventTriggered);
639 BOOST_CHECK(m_requests.empty());
640
641 m_entries.erase(m_entries.find("/test/A")); // set to be in RELEASED state
642 testAfterPropagateFail("/test/A/app"); // will do nothing
643 BOOST_CHECK(!wasRetryEventTriggered);
644 BOOST_CHECK(m_requests.empty());
645}
646
647BOOST_AUTO_TEST_CASE(AfterRevokeSucceed)
648{
649 auto testAfterRevokeSucceed = [&] (const Name& ribEntryPrefix) {
650 m_requests.clear();
651 auto propagateParameters = m_propagator.getPrefixPropagationParameters(ribEntryPrefix);
652 m_propagator.afterRevokeSucceed(propagateParameters.parameters,
653 propagateParameters.options,
654 time::seconds(0));
655 advanceClocks(time::milliseconds(1));
656 };
657
658 BOOST_REQUIRE(addIdentity("/test/A"));
659
660 testAfterRevokeSucceed("/test/A/app"); // in RELEASED state
661 BOOST_CHECK(m_requests.empty());
662
Davide Pesaventoe1bdc082018-10-11 21:20:23 -0400663 m_entries["/test/A"].fail(m_scheduler, nullptr); // in PROPAGATE_FAIL state
Yanbiao Lid7c96362015-01-30 23:58:24 -0800664 testAfterRevokeSucceed("/test/A/app");
665 BOOST_CHECK(m_requests.empty());
666
Davide Pesaventoe1bdc082018-10-11 21:20:23 -0400667 m_entries["/test/A"].succeed(m_scheduler, nullptr); // in PROPAGATED state
Yanbiao Lid7c96362015-01-30 23:58:24 -0800668 testAfterRevokeSucceed("/test/A/app");
669 BOOST_REQUIRE_EQUAL(m_requests.size(), 1);
670 BOOST_CHECK_EQUAL(checkRequest(0, "register", "/test/A"), CheckRequestResult::OK);
671
672 m_entries["/test/A"].startPropagation(); // in PROPAGATING state
673 testAfterRevokeSucceed("/test/A/app");
674 BOOST_REQUIRE_EQUAL(m_requests.size(), 1);
675 BOOST_CHECK_EQUAL(checkRequest(0, "register", "/test/A"), CheckRequestResult::OK);
676}
677
678BOOST_AUTO_TEST_SUITE_END() // PropagatedEntryStateChanges
679
680BOOST_AUTO_TEST_SUITE_END() // TestAutoPrefixPropagator
Yanbiao Lid7c96362015-01-30 23:58:24 -0800681
682} // namespace tests
683} // namespace rib
684} // namespace nfd