blob: ea3ca1011eb22c1aa1fc4401edfff329ee05fb8e [file] [log] [blame]
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +00001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
Davide Pesavento8a05c7f2019-02-28 02:26:19 -05003 * Copyright (c) 2014-2019, Regents of the University of California,
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +00004 * 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
Davide Pesavento8a05c7f2019-02-28 02:26:19 -050026#include "mgmt/rib-manager.hpp"
27#include "rib/fib-updater.hpp"
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000028
29#include "tests/identity-management-fixture.hpp"
Davide Pesaventoe1bdc082018-10-11 21:20:23 -040030
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000031#include <ndn-cxx/util/dummy-client-face.hpp>
32
33namespace nfd {
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000034namespace tests {
35
Davide Pesavento8a05c7f2019-02-28 02:26:19 -050036using rib::Route;
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000037
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)
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000045 , m_nfdController(m_face, m_keyChain)
46 , m_dispatcher(m_face, m_keyChain)
47 , m_fibUpdater(rib, m_nfdController)
48 , m_trustedSigner(m_keyChain.createIdentity("/trusted", ndn::RsaKeyParams()))
49 , m_untrustedSigner(m_keyChain.createIdentity("/untrusted", ndn::RsaKeyParams()))
50 {
Davide Pesavento8a05c7f2019-02-28 02:26:19 -050051 rib.mockFibResponse = [] (const auto&) { return true; };
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000052 rib.wantMockFibResponseOnce = false;
53
54 // Face, Controller, Dispatcher are irrelevant to SlAnnounce functions but required by
55 // RibManager construction, so they are private. RibManager is a pointer to avoid code style
56 // rule 1.4 violation.
Davide Pesavento0a71dd32019-03-17 20:36:18 -040057 manager = make_unique<RibManager>(rib, m_face, m_keyChain, m_nfdController, m_dispatcher);
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000058
59 loadTrustSchema();
60 }
61
62 template<typename ...T>
63 ndn::PrefixAnnouncement
Davide Pesavento8a05c7f2019-02-28 02:26:19 -050064 makeTrustedAnn(T&&... args)
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000065 {
Davide Pesavento8a05c7f2019-02-28 02:26:19 -050066 return signPrefixAnn(makePrefixAnn(std::forward<T>(args)...), m_keyChain, m_trustedSigner);
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000067 }
68
69 template<typename ...T>
70 ndn::PrefixAnnouncement
Davide Pesavento8a05c7f2019-02-28 02:26:19 -050071 makeUntrustedAnn(T&&... args)
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000072 {
Davide Pesavento8a05c7f2019-02-28 02:26:19 -050073 return signPrefixAnn(makePrefixAnn(std::forward<T>(args)...), m_keyChain, m_untrustedSigner);
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000074 }
75
76 /** \brief Invoke manager->slAnnounce and wait for result.
77 */
78 SlAnnounceResult
79 slAnnounceSync(const ndn::PrefixAnnouncement& pa, uint64_t faceId, time::milliseconds maxLifetime)
80 {
81 optional<SlAnnounceResult> result;
82 manager->slAnnounce(pa, faceId, maxLifetime,
83 [&] (RibManager::SlAnnounceResult res) {
84 BOOST_CHECK(!result);
85 result = res;
86 });
87
Davide Pesaventoe1bdc082018-10-11 21:20:23 -040088 g_io.poll();
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000089 BOOST_CHECK(result);
90 return result.value_or(SlAnnounceResult::ERROR);
91 }
92
93 /** \brief Invoke manager->slRenew and wait for result.
94 */
95 SlAnnounceResult
96 slRenewSync(const Name& name, uint64_t faceId, time::milliseconds maxLifetime)
97 {
98 optional<SlAnnounceResult> result;
99 manager->slRenew(name, faceId, maxLifetime,
100 [&] (RibManager::SlAnnounceResult res) {
101 BOOST_CHECK(!result);
102 result = res;
103 });
104
Davide Pesaventoe1bdc082018-10-11 21:20:23 -0400105 g_io.poll();
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000106 BOOST_CHECK(result);
107 return result.value_or(SlAnnounceResult::ERROR);
108 }
109
110 /** \brief Invoke manager->slFindAnn and wait for result.
111 */
112 optional<ndn::PrefixAnnouncement>
113 slFindAnnSync(const Name& name)
114 {
115 optional<optional<ndn::PrefixAnnouncement>> result;
116 manager->slFindAnn(name,
117 [&] (optional<ndn::PrefixAnnouncement> found) {
118 BOOST_CHECK(!result);
119 result = found;
120 });
121
Davide Pesaventoe1bdc082018-10-11 21:20:23 -0400122 g_io.poll();
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000123 BOOST_CHECK(result);
124 return result.value_or(nullopt);
125 }
126
127 /** \brief Lookup a route with PREFIXANN origin.
128 */
129 Route*
130 findAnnRoute(const Name& name, uint64_t faceId)
131 {
132 Route routeQuery;
133 routeQuery.faceId = faceId;
134 routeQuery.origin = ndn::nfd::ROUTE_ORIGIN_PREFIXANN;
135 return rib.find(name, routeQuery);
136 }
137
138private:
139 /** \brief Prepare a trust schema and load as localhop_security.
140 *
141 * Test case may revert this operation with ribManager->disableLocalhop().
142 */
143 void
144 loadTrustSchema()
145 {
146 ConfigSection section;
147 section.put("rule.id", "PA");
148 section.put("rule.for", "data");
149 section.put("rule.checker.type", "customized");
150 section.put("rule.checker.sig-type", "rsa-sha256");
151 section.put("rule.checker.key-locator.type", "name");
152 section.put("rule.checker.key-locator.name", "/trusted");
153 section.put("rule.checker.key-locator.relation", "is-prefix-of");
154 section.put("trust-anchor.type", "base64");
155 section.put("trust-anchor.base64-string", getIdentityCertificateBase64("/trusted"));
156 manager->enableLocalhop(section, "trust-schema.section");
157 }
158
159public:
Davide Pesavento8a05c7f2019-02-28 02:26:19 -0500160 rib::Rib rib;
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000161 unique_ptr<RibManager> manager;
162
163private:
164 ndn::util::DummyClientFace m_face;
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000165 ndn::nfd::Controller m_nfdController;
Davide Pesavento78ddcab2019-02-28 22:00:03 -0500166 Dispatcher m_dispatcher;
Davide Pesavento8a05c7f2019-02-28 02:26:19 -0500167 rib::FibUpdater m_fibUpdater;
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000168
169 ndn::security::SigningInfo m_trustedSigner;
170 ndn::security::SigningInfo m_untrustedSigner;
171};
172
Davide Pesavento8a05c7f2019-02-28 02:26:19 -0500173BOOST_AUTO_TEST_SUITE(Mgmt)
174BOOST_AUTO_TEST_SUITE(TestRibManager)
175BOOST_FIXTURE_TEST_SUITE(SlAnnounce, RibManagerSlAnnounceFixture)
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000176
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
Teng Lianga4e6ec32018-10-21 09:25:00 -0700251 BOOST_CHECK_EQUAL(slRenewSync("/P2IYFqtr/2321", 4506, 2_h), SlAnnounceResult::OK);
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000252
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
Teng Lianga4e6ec32018-10-21 09:25:00 -0700265 BOOST_CHECK_EQUAL(slRenewSync("/be01Yiba/4324", 1589, 5_h), SlAnnounceResult::OK);
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000266
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
Teng Lianga4e6ec32018-10-21 09:25:00 -0700279 BOOST_CHECK_EQUAL(slRenewSync("/5XCHYCAd/98934", 3851, 1_h), SlAnnounceResult::OK);
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000280
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
Teng Lianga4e6ec32018-10-21 09:25:00 -0700293 BOOST_CHECK_EQUAL(slRenewSync("/cdQ7KPNw/8023", 8031, 0_s), SlAnnounceResult::EXPIRED);
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000294
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
Davide Pesavento8a05c7f2019-02-28 02:26:19 -0500330BOOST_AUTO_TEST_SUITE_END() // SlAnnounce
331BOOST_AUTO_TEST_SUITE_END() // TestRibManager
332BOOST_AUTO_TEST_SUITE_END() // Mgmt
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000333
334} // namespace tests
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000335} // namespace nfd