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