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