blob: eba8064798686b7bbfebc1b94bc2a97d5f62f3b3 [file] [log] [blame]
Ashlesh Gawande85998a12017-12-07 22:22:13 -06001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2014-2019, The University of Memphis,
4 * Regents of the University of California,
5 * Arizona Board of Regents.
6 *
7 * This file is part of NLSR (Named-data Link State Routing).
8 * See AUTHORS.md for complete list of NLSR authors and contributors.
9 *
10 * NLSR is free software: you can redistribute it and/or modify it under the terms
11 * of the GNU General Public License as published by the Free Software Foundation,
12 * either version 3 of the License, or (at your option) any later version.
13 *
14 * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
15 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 * PURPOSE. See the GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
20 **/
21
22#include "communication/sync-logic-handler.hpp"
23#include "../test-common.hpp"
24#include "common.hpp"
25#include "nlsr.hpp"
26#include "lsa.hpp"
27
28#include <ndn-cxx/util/dummy-client-face.hpp>
29
30namespace nlsr {
31namespace test {
32
33using std::shared_ptr;
34
35template<int32_t Protocol>
36class SyncLogicFixture : public UnitTestTimeFixture
37{
38public:
39 SyncLogicFixture()
40 : face(m_ioService, m_keyChain)
41 , conf(face)
42 , confProcessor(conf, Protocol)
43 , testIsLsaNew([] (const ndn::Name& name, const Lsa::Type& lsaType,
44 const uint64_t sequenceNumber) {
45 return true;
46 })
47 , sync(face, testIsLsaNew, conf)
48 , updateNamePrefix(this->conf.getLsaPrefix().toUri() +
49 this->conf.getSiteName().toUri() +
50 "/%C1.Router/other-router/")
51 {
52 addIdentity(conf.getRouterPrefix());
53 }
54
55 void
56 receiveUpdate(const std::string& prefix, uint64_t seqNo)
57 {
58 this->advanceClocks(ndn::time::milliseconds(1), 10);
59 face.sentInterests.clear();
60
61 if (Protocol == SYNC_PROTOCOL_CHRONOSYNC) {
62 std::vector<chronosync::MissingDataInfo> updates;
63 updates.push_back({ndn::Name(prefix).appendNumber(1), 0, seqNo});
64 sync.m_syncLogic->onChronoSyncUpdate(updates);
65 }
66 else {
67 std::vector<psync::MissingDataInfo> updates;
68 updates.push_back({ndn::Name(prefix), 0, seqNo});
69 sync.m_syncLogic->onPSyncUpdate(updates);
70 }
71
72 this->advanceClocks(ndn::time::milliseconds(1), 10);
73 }
74
75public:
76 ndn::util::DummyClientFace face;
77 ConfParameter conf;
78 DummyConfFileProcessor confProcessor;
79 SyncLogicHandler::IsLsaNew testIsLsaNew;
80 SyncLogicHandler sync;
81
82 const std::string updateNamePrefix;
83 const std::vector<Lsa::Type> lsaTypes = {Lsa::Type::NAME, Lsa::Type::ADJACENCY,
84 Lsa::Type::COORDINATE};
85};
86
87using mpl_::int_;
88using Protocols = boost::mpl::vector<int_<SYNC_PROTOCOL_CHRONOSYNC>,
89 int_<SYNC_PROTOCOL_PSYNC>>;
90
91BOOST_AUTO_TEST_SUITE(TestSyncLogicHandler)
92
93/* Tests that when SyncLogicHandler receives an LSA of either Name or
94 Adjacency type that appears to be newer, it will emit to its signal
95 with those LSA details.
96 */
97BOOST_FIXTURE_TEST_CASE_TEMPLATE(UpdateForOtherLS, T, Protocols, SyncLogicFixture<T::value>)
98{
99 std::vector<Lsa::Type> lsaTypes = {Lsa::Type::NAME, Lsa::Type::ADJACENCY};
100
101 uint64_t syncSeqNo = 1;
102
103 for (const Lsa::Type& lsaType : lsaTypes) {
104 std::string updateName = this->updateNamePrefix + std::to_string(lsaType);
105
106 // Actual testing done here -- signal function callback
107 ndn::util::signal::ScopedConnection connection = this->sync.onNewLsa->connect(
108 [&] (const ndn::Name& routerName, const uint64_t& sequenceNumber) {
109 BOOST_CHECK_EQUAL(ndn::Name{updateName}, routerName);
110 BOOST_CHECK_EQUAL(sequenceNumber, syncSeqNo);
111 });
112
113 this->receiveUpdate(updateName, syncSeqNo);
114 }
115}
116
117/* Tests that when SyncLogicHandler in HR mode receives an LSA of
118 either Coordinate or Name type that appears to be newer, it will
119 emit to its signal with those LSA details.
120 */
121BOOST_FIXTURE_TEST_CASE_TEMPLATE(UpdateForOtherHR, T, Protocols, SyncLogicFixture<T::value>)
122{
123 this->conf.setHyperbolicState(HYPERBOLIC_STATE_ON);
124
125 uint64_t syncSeqNo = 1;
126 std::vector<Lsa::Type> lsaTypes = {Lsa::Type::NAME, Lsa::Type::COORDINATE};
127
128 for (const Lsa::Type& lsaType : lsaTypes) {
129 std::string updateName = this->updateNamePrefix + std::to_string(lsaType);
130
131 ndn::util::signal::ScopedConnection connection = this->sync.onNewLsa->connect(
132 [&] (const ndn::Name& routerName, const uint64_t& sequenceNumber) {
133 BOOST_CHECK_EQUAL(ndn::Name{updateName}, routerName);
134 BOOST_CHECK_EQUAL(sequenceNumber, syncSeqNo);
135 });
136
137 this->receiveUpdate(updateName, syncSeqNo);
138 }
139}
140
141/* Tests that when SyncLogicHandler in HR-dry mode receives an LSA of
142 any type that appears to be newer, it will emit to its signal with
143 those LSA details.
144 */
145BOOST_FIXTURE_TEST_CASE_TEMPLATE(UpdateForOtherHRDry, T, Protocols, SyncLogicFixture<T::value>)
146{
147 this->conf.setHyperbolicState(HYPERBOLIC_STATE_DRY_RUN);
148
149 uint64_t syncSeqNo = 1;
150
151 for (const Lsa::Type& lsaType : this->lsaTypes) {
152 std::string updateName = this->updateNamePrefix + std::to_string(lsaType);
153
154 ndn::util::signal::ScopedConnection connection = this->sync.onNewLsa->connect(
155 [&] (const ndn::Name& routerName, const uint64_t& sequenceNumber) {
156 BOOST_CHECK_EQUAL(ndn::Name{updateName}, routerName);
157 BOOST_CHECK_EQUAL(sequenceNumber, syncSeqNo);
158 });
159
160 this->receiveUpdate(updateName, syncSeqNo);
161 }
162}
163
164/* Tests that when SyncLogicHandler receives an update for an LSA with
165 details matching this router's details, it will *not* emit to its
166 signal those LSA details.
167 */
168BOOST_FIXTURE_TEST_CASE_TEMPLATE(NoUpdateForSelf, T, Protocols, SyncLogicFixture<T::value>)
169{
170 const uint64_t sequenceNumber = 1;
171
172 for (const Lsa::Type& lsaType : this->lsaTypes) {
173 // To ensure that we get correctly-separated components, create
174 // and modify a Name to hand off.
175 ndn::Name updateName = ndn::Name{this->conf.getLsaPrefix()};
176 updateName.append(this->conf.getSiteName())
177 .append(this->conf.getRouterName())
178 .append(std::to_string(lsaType));
179
180 ndn::util::signal::ScopedConnection connection = this->sync.onNewLsa->connect(
181 [&] (const ndn::Name& routerName, const uint64_t& sequenceNumber) {
182 BOOST_FAIL("Updates for self should not be emitted!");
183 });
184
185 this->receiveUpdate(updateName.toUri(), sequenceNumber);
186 }
187}
188
189/* Tests that when SyncLogicHandler receives an update for an LSA with
190 details that do not match the expected format, it will *not* emit
191 to its signal those LSA details.
192 */
193BOOST_FIXTURE_TEST_CASE_TEMPLATE(MalformedUpdate, T, Protocols, SyncLogicFixture<T::value>)
194{
195 const uint64_t sequenceNumber = 1;
196
197 for (const Lsa::Type& lsaType : this->lsaTypes) {
198 ndn::Name updateName{this->conf.getSiteName()};
199 updateName.append(this->conf.getRouterName()).append(std::to_string(lsaType));
200
201 ndn::util::signal::ScopedConnection connection = this->sync.onNewLsa->connect(
202 [&] (const ndn::Name& routerName, const uint64_t& sequenceNumber) {
203 BOOST_FAIL("Malformed updates should not be emitted!");
204 });
205
206 this->receiveUpdate(updateName.toUri(), sequenceNumber);
207 }
208}
209
210/* Tests that when SyncLogicHandler receives an update for an LSA with
211 details that do not appear to be new, it will *not* emit to its
212 signal those LSA details.
213 */
214BOOST_FIXTURE_TEST_CASE_TEMPLATE(LsaNotNew, T, Protocols, SyncLogicFixture<T::value>)
215{
216 auto testLsaAlwaysFalse = [] (const ndn::Name& routerName, const Lsa::Type& lsaType,
217 const uint64_t& sequenceNumber) {
218 return false;
219 };
220
221 const uint64_t sequenceNumber = 1;
222 SyncLogicHandler sync{this->face, testLsaAlwaysFalse, this->conf};
223 ndn::util::signal::ScopedConnection connection = sync.onNewLsa->connect(
224 [&] (const ndn::Name& routerName, const uint64_t& sequenceNumber) {
225 BOOST_FAIL("An update for an LSA with non-new sequence number should not emit!");
226 });
227
228 std::string updateName = this->updateNamePrefix + std::to_string(Lsa::Type::NAME);
229
230 this->receiveUpdate(updateName, sequenceNumber);
231}
232
233/* Tests that SyncLogicHandler successfully concatenates configured
234 variables together to form the necessary prefixes to advertise
235 through ChronoSync.
236 */
237BOOST_FIXTURE_TEST_CASE_TEMPLATE(UpdatePrefix, T, Protocols, SyncLogicFixture<T::value>)
238{
239 ndn::Name expectedPrefix = this->conf.getLsaPrefix();
240 expectedPrefix.append(this->conf.getSiteName());
241 expectedPrefix.append(this->conf.getRouterName());
242
243 this->sync.buildUpdatePrefix();
244
245 BOOST_CHECK_EQUAL(this->sync.m_nameLsaUserPrefix,
246 ndn::Name(expectedPrefix).append(std::to_string(Lsa::Type::NAME)));
247 BOOST_CHECK_EQUAL(this->sync.m_adjLsaUserPrefix,
248 ndn::Name(expectedPrefix).append(std::to_string(Lsa::Type::ADJACENCY)));
249 BOOST_CHECK_EQUAL(this->sync.m_coorLsaUserPrefix,
250 ndn::Name(expectedPrefix).append(std::to_string(Lsa::Type::COORDINATE)));
251}
252
253/* Tests that SyncLogicHandler's socket will be created when
254 Nlsr is initialized, preventing use of sync before the
255 socket is created.
256
257 NB: This test is as much an Nlsr class test as a
258 SyncLogicHandler class test, but it rides the line and ends up here.
259 */
260BOOST_FIXTURE_TEST_CASE_TEMPLATE(createSyncLogicOnInitialization, T, Protocols,
261 SyncLogicFixture<T::value>) // Bug #2649
262{
263 Nlsr nlsr(this->face, this->m_keyChain, this->conf);
264
265 // Make sure an adjacency LSA has not been built yet
266 ndn::Name key = ndn::Name(this->conf.getRouterPrefix()).append(std::to_string(Lsa::Type::ADJACENCY));
267 AdjLsa* lsa = nlsr.m_lsdb.findAdjLsa(key);
268 BOOST_REQUIRE(lsa == nullptr);
269
270 // Publish a routing update before an Adjacency LSA is built
271 BOOST_CHECK_NO_THROW(nlsr.m_lsdb.getSyncLogicHandler()
272 .publishRoutingUpdate(Lsa::Type::ADJACENCY, 0));
273}
274
275BOOST_AUTO_TEST_SUITE_END()
276
277} // namespace test
278} // namespace nlsr