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