blob: c7808d3c5fe63d4e514636edab20939b1783f932 [file] [log] [blame]
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +00001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2014-2018, Regents of the University of California,
4 * 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/rib-manager.hpp"
27
28#include "tests/identity-management-fixture.hpp"
Davide Pesaventoe1bdc082018-10-11 21:20:23 -040029
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000030#include <ndn-cxx/util/dummy-client-face.hpp>
31
32namespace nfd {
33namespace rib {
34namespace tests {
35
36using namespace nfd::tests;
37
38class RibManagerSlAnnounceFixture : public IdentityManagementTimeFixture
39{
40public:
41 using SlAnnounceResult = RibManager::SlAnnounceResult;
42
43 RibManagerSlAnnounceFixture()
Davide Pesaventoe1bdc082018-10-11 21:20:23 -040044 : m_face(g_io, m_keyChain)
45 , m_scheduler(g_io)
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000046 , m_nfdController(m_face, m_keyChain)
47 , m_dispatcher(m_face, m_keyChain)
48 , m_fibUpdater(rib, m_nfdController)
49 , m_trustedSigner(m_keyChain.createIdentity("/trusted", ndn::RsaKeyParams()))
50 , m_untrustedSigner(m_keyChain.createIdentity("/untrusted", ndn::RsaKeyParams()))
51 {
Davide Pesaventoe1bdc082018-10-11 21:20:23 -040052 rib.mockFibResponse = [] (const RibUpdateBatch&) { return true; };
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000053 rib.wantMockFibResponseOnce = false;
54
55 // Face, Controller, Dispatcher are irrelevant to SlAnnounce functions but required by
56 // RibManager construction, so they are private. RibManager is a pointer to avoid code style
57 // rule 1.4 violation.
Davide Pesaventoe1bdc082018-10-11 21:20:23 -040058 manager = make_unique<RibManager>(rib, m_face, m_keyChain, m_nfdController, m_dispatcher, m_scheduler);
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000059
60 loadTrustSchema();
61 }
62
63 template<typename ...T>
64 ndn::PrefixAnnouncement
65 makeTrustedAnn(const T&... args)
66 {
67 return signPrefixAnn(makePrefixAnn(args...), m_keyChain, m_trustedSigner);
68 }
69
70 template<typename ...T>
71 ndn::PrefixAnnouncement
72 makeUntrustedAnn(const T&... args)
73 {
74 return signPrefixAnn(makePrefixAnn(args...), m_keyChain, m_untrustedSigner);
75 }
76
77 /** \brief Invoke manager->slAnnounce and wait for result.
78 */
79 SlAnnounceResult
80 slAnnounceSync(const ndn::PrefixAnnouncement& pa, uint64_t faceId, time::milliseconds maxLifetime)
81 {
82 optional<SlAnnounceResult> result;
83 manager->slAnnounce(pa, faceId, maxLifetime,
84 [&] (RibManager::SlAnnounceResult res) {
85 BOOST_CHECK(!result);
86 result = res;
87 });
88
Davide Pesaventoe1bdc082018-10-11 21:20:23 -040089 g_io.poll();
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000090 BOOST_CHECK(result);
91 return result.value_or(SlAnnounceResult::ERROR);
92 }
93
94 /** \brief Invoke manager->slRenew and wait for result.
95 */
96 SlAnnounceResult
97 slRenewSync(const Name& name, uint64_t faceId, time::milliseconds maxLifetime)
98 {
99 optional<SlAnnounceResult> result;
100 manager->slRenew(name, faceId, maxLifetime,
101 [&] (RibManager::SlAnnounceResult res) {
102 BOOST_CHECK(!result);
103 result = res;
104 });
105
Davide Pesaventoe1bdc082018-10-11 21:20:23 -0400106 g_io.poll();
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000107 BOOST_CHECK(result);
108 return result.value_or(SlAnnounceResult::ERROR);
109 }
110
111 /** \brief Invoke manager->slFindAnn and wait for result.
112 */
113 optional<ndn::PrefixAnnouncement>
114 slFindAnnSync(const Name& name)
115 {
116 optional<optional<ndn::PrefixAnnouncement>> result;
117 manager->slFindAnn(name,
118 [&] (optional<ndn::PrefixAnnouncement> found) {
119 BOOST_CHECK(!result);
120 result = found;
121 });
122
Davide Pesaventoe1bdc082018-10-11 21:20:23 -0400123 g_io.poll();
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000124 BOOST_CHECK(result);
125 return result.value_or(nullopt);
126 }
127
128 /** \brief Lookup a route with PREFIXANN origin.
129 */
130 Route*
131 findAnnRoute(const Name& name, uint64_t faceId)
132 {
133 Route routeQuery;
134 routeQuery.faceId = faceId;
135 routeQuery.origin = ndn::nfd::ROUTE_ORIGIN_PREFIXANN;
136 return rib.find(name, routeQuery);
137 }
138
139private:
140 /** \brief Prepare a trust schema and load as localhop_security.
141 *
142 * Test case may revert this operation with ribManager->disableLocalhop().
143 */
144 void
145 loadTrustSchema()
146 {
147 ConfigSection section;
148 section.put("rule.id", "PA");
149 section.put("rule.for", "data");
150 section.put("rule.checker.type", "customized");
151 section.put("rule.checker.sig-type", "rsa-sha256");
152 section.put("rule.checker.key-locator.type", "name");
153 section.put("rule.checker.key-locator.name", "/trusted");
154 section.put("rule.checker.key-locator.relation", "is-prefix-of");
155 section.put("trust-anchor.type", "base64");
156 section.put("trust-anchor.base64-string", getIdentityCertificateBase64("/trusted"));
157 manager->enableLocalhop(section, "trust-schema.section");
158 }
159
160public:
161 Rib rib;
162 unique_ptr<RibManager> manager;
163
164private:
165 ndn::util::DummyClientFace m_face;
Davide Pesaventoe1bdc082018-10-11 21:20:23 -0400166 ndn::util::Scheduler m_scheduler;
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000167 ndn::nfd::Controller m_nfdController;
168 ndn::mgmt::Dispatcher m_dispatcher;
169 FibUpdater m_fibUpdater;
170
171 ndn::security::SigningInfo m_trustedSigner;
172 ndn::security::SigningInfo m_untrustedSigner;
173};
174
175BOOST_FIXTURE_TEST_SUITE(TestSlAnnounce, RibManagerSlAnnounceFixture)
176
177BOOST_AUTO_TEST_CASE(AnnounceUnconfigured)
178{
179 manager->disableLocalhop();
180 auto pa = makeTrustedAnn("/fMXN7UeB", 1_h);
181 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 3275, 1_h), SlAnnounceResult::VALIDATION_FAILURE);
182
183 BOOST_CHECK(findAnnRoute("/fMXN7UeB", 3275) == nullptr);
184}
185
186BOOST_AUTO_TEST_CASE(AnnounceValidationError)
187{
188 auto pa = makeUntrustedAnn("/1nzAe0Y4", 1_h);
189 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 2959, 1_h), SlAnnounceResult::VALIDATION_FAILURE);
190
191 BOOST_CHECK(findAnnRoute("/1nzAe0Y4", 2959) == nullptr);
192}
193
194BOOST_AUTO_TEST_CASE(AnnounceInsert_AnnLifetime)
195{
196 auto pa = makeTrustedAnn("/EHJYmJz9", 1_h);
197 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 1641, 2_h), SlAnnounceResult::OK);
198
199 Route* route = findAnnRoute("/EHJYmJz9", 1641);
200 BOOST_REQUIRE(route != nullptr);
201 BOOST_CHECK_EQUAL(route->annExpires, time::steady_clock::now() + 1_h);
202 BOOST_CHECK_EQUAL(route->expires.value(), time::steady_clock::now() + 1_h);
203}
204
205BOOST_AUTO_TEST_CASE(AnnounceInsert_ArgLifetime)
206{
207 auto pa = makeTrustedAnn("/BU9Fec9E", 2_h);
208 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 1282, 1_h), SlAnnounceResult::OK);
209
210 Route* route = findAnnRoute("/BU9Fec9E", 1282);
211 BOOST_REQUIRE(route != nullptr);
212 BOOST_CHECK_EQUAL(route->annExpires, time::steady_clock::now() + 2_h);
213 BOOST_CHECK_EQUAL(route->expires.value(), time::steady_clock::now() + 1_h);
214}
215
216BOOST_AUTO_TEST_CASE(AnnounceReplace)
217{
218 auto pa = makeTrustedAnn("/HsBFGvL3", 1_h);
219 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 2813, 1_h), SlAnnounceResult::OK);
220
221 pa = makeTrustedAnn("/HsBFGvL3", 2_h);
222 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 2813, 2_h), SlAnnounceResult::OK);
223
224 Route* route = findAnnRoute("/HsBFGvL3", 2813);
225 BOOST_REQUIRE(route != nullptr);
226 BOOST_CHECK_EQUAL(route->annExpires, time::steady_clock::now() + 2_h);
227 BOOST_CHECK_EQUAL(route->expires.value(), time::steady_clock::now() + 2_h);
228}
229
230BOOST_AUTO_TEST_CASE(AnnounceExpired)
231{
232 auto pa = makeTrustedAnn("/awrVv6V7", 1_h, std::make_pair(-3_h, -1_h));
233 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 9087, 1_h), SlAnnounceResult::EXPIRED);
234
235 BOOST_CHECK(findAnnRoute("/awrVv6V7", 9087) == nullptr);
236}
237
238BOOST_AUTO_TEST_CASE(RenewNotFound)
239{
240 BOOST_CHECK_EQUAL(slRenewSync("IAYigN73", 1070, 1_h), SlAnnounceResult::NOT_FOUND);
241
242 BOOST_CHECK(findAnnRoute("/IAYigN73", 1070) == nullptr);
243}
244
245BOOST_AUTO_TEST_CASE(RenewProlong_ArgLifetime)
246{
247 auto pa = makeTrustedAnn("/P2IYFqtr", 4_h);
248 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 4506, 2_h), SlAnnounceResult::OK);
249 advanceClocks(1_h); // Route has 1_h remaining lifetime
250
251 BOOST_CHECK_EQUAL(slRenewSync("/P2IYFqtr", 4506, 2_h), SlAnnounceResult::OK);
252
253 Route* route = findAnnRoute("/P2IYFqtr", 4506);
254 BOOST_REQUIRE(route != nullptr);
255 BOOST_CHECK_EQUAL(route->annExpires, time::steady_clock::now() + 3_h);
256 BOOST_CHECK_EQUAL(route->expires.value(), time::steady_clock::now() + 2_h); // set by slRenew
257}
258
259BOOST_AUTO_TEST_CASE(RenewProlong_AnnLifetime)
260{
261 auto pa = makeTrustedAnn("/be01Yiba", 4_h);
262 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 1589, 2_h), SlAnnounceResult::OK);
263 advanceClocks(1_h); // Route has 1_h remaining lifetime
264
265 BOOST_CHECK_EQUAL(slRenewSync("/be01Yiba", 1589, 5_h), SlAnnounceResult::OK);
266
267 Route* route = findAnnRoute("/be01Yiba", 1589);
268 BOOST_REQUIRE(route != nullptr);
269 BOOST_CHECK_EQUAL(route->annExpires, time::steady_clock::now() + 3_h);
270 BOOST_CHECK_EQUAL(route->expires.value(), time::steady_clock::now() + 3_h); // capped by annExpires
271}
272
273BOOST_AUTO_TEST_CASE(RenewShorten)
274{
275 auto pa = makeTrustedAnn("/5XCHYCAd", 4_h);
276 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 3851, 4_h), SlAnnounceResult::OK);
277 advanceClocks(1_h); // Route has 3_h remaining lifetime
278
279 BOOST_CHECK_EQUAL(slRenewSync("/5XCHYCAd", 3851, 1_h), SlAnnounceResult::OK);
280
281 Route* route = findAnnRoute("/5XCHYCAd", 3851);
282 BOOST_REQUIRE(route != nullptr);
283 BOOST_CHECK_EQUAL(route->annExpires, time::steady_clock::now() + 3_h);
284 BOOST_CHECK_EQUAL(route->expires.value(), time::steady_clock::now() + 1_h); // set by slRenew
285}
286
287BOOST_AUTO_TEST_CASE(RenewShorten_Zero)
288{
289 auto pa = makeTrustedAnn("/cdQ7KPNw", 4_h);
290 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 8031, 4_h), SlAnnounceResult::OK);
291 advanceClocks(1_h); // Route has 3_h remaining lifetime
292
293 BOOST_CHECK_EQUAL(slRenewSync("/cdQ7KPNw", 8031, 0_s), SlAnnounceResult::EXPIRED);
294
295 BOOST_CHECK(findAnnRoute("/cdQ7KPNw", 8031) == nullptr);
296}
297
298BOOST_AUTO_TEST_CASE(FindExisting)
299{
300 auto pa = makeTrustedAnn("/JHugsjjr", 1_h);
301 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 2363, 1_h), SlAnnounceResult::OK);
302
303 auto found = slFindAnnSync("/JHugsjjr");
304 BOOST_REQUIRE(found);
305 BOOST_CHECK_EQUAL(found->getAnnouncedName(), "/JHugsjjr");
306 BOOST_CHECK(found->getData());
307
308 auto found2 = slFindAnnSync("/JHugsjjr/StvXhKR5");
309 BOOST_CHECK(found == found2);
310}
311
312BOOST_AUTO_TEST_CASE(FindNew)
313{
314 Route route;
315 route.faceId = 1367;
316 route.origin = ndn::nfd::ROUTE_ORIGIN_APP;
317 rib.insert("/dLY1pRhR", route);
318
319 auto pa = slFindAnnSync("/dLY1pRhR/3qNK9Ngn");
320 BOOST_REQUIRE(pa);
321 BOOST_CHECK_EQUAL(pa->getAnnouncedName(), "/dLY1pRhR");
322}
323
324BOOST_AUTO_TEST_CASE(FindNone)
325{
326 auto pa = slFindAnnSync("/2YNeYuV2");
327 BOOST_CHECK(!pa);
328}
329
330BOOST_AUTO_TEST_SUITE_END() // TestSlAnnounce
331
332} // namespace tests
333} // namespace rib
334} // namespace nfd