blob: 2afa8fda03de08aa072f07afeb08d6a5fa4c1225 [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
Davide Pesaventocf7db2f2019-03-24 23:17:28 -040029#include "tests/test-common.hpp"
Davide Pesavento1d12d2f2019-03-22 12:44:14 -040030#include "tests/key-chain-fixture.hpp"
Davide Pesaventocf7db2f2019-03-24 23:17:28 -040031#include "tests/daemon/global-io-fixture.hpp"
Davide Pesaventoe1bdc082018-10-11 21:20:23 -040032
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000033#include <ndn-cxx/util/dummy-client-face.hpp>
34
35namespace nfd {
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000036namespace tests {
37
Davide Pesavento8a05c7f2019-02-28 02:26:19 -050038using rib::Route;
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000039
Davide Pesaventocf7db2f2019-03-24 23:17:28 -040040class RibManagerSlAnnounceFixture : public GlobalIoTimeFixture, public KeyChainFixture
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000041{
42public:
43 using SlAnnounceResult = RibManager::SlAnnounceResult;
44
45 RibManagerSlAnnounceFixture()
Davide Pesaventoe1bdc082018-10-11 21:20:23 -040046 : m_face(g_io, m_keyChain)
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000047 , m_nfdController(m_face, m_keyChain)
48 , m_dispatcher(m_face, m_keyChain)
49 , m_fibUpdater(rib, m_nfdController)
50 , m_trustedSigner(m_keyChain.createIdentity("/trusted", ndn::RsaKeyParams()))
51 , m_untrustedSigner(m_keyChain.createIdentity("/untrusted", ndn::RsaKeyParams()))
52 {
Davide Pesavento8a05c7f2019-02-28 02:26:19 -050053 rib.mockFibResponse = [] (const auto&) { return true; };
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000054 rib.wantMockFibResponseOnce = false;
55
56 // Face, Controller, Dispatcher are irrelevant to SlAnnounce functions but required by
57 // RibManager construction, so they are private. RibManager is a pointer to avoid code style
58 // rule 1.4 violation.
Davide Pesavento0a71dd32019-03-17 20:36:18 -040059 manager = make_unique<RibManager>(rib, m_face, m_keyChain, m_nfdController, m_dispatcher);
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000060
61 loadTrustSchema();
62 }
63
64 template<typename ...T>
65 ndn::PrefixAnnouncement
Davide Pesavento8a05c7f2019-02-28 02:26:19 -050066 makeTrustedAnn(T&&... args)
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000067 {
Davide Pesavento8a05c7f2019-02-28 02:26:19 -050068 return signPrefixAnn(makePrefixAnn(std::forward<T>(args)...), m_keyChain, m_trustedSigner);
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000069 }
70
71 template<typename ...T>
72 ndn::PrefixAnnouncement
Davide Pesavento8a05c7f2019-02-28 02:26:19 -050073 makeUntrustedAnn(T&&... args)
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000074 {
Davide Pesavento8a05c7f2019-02-28 02:26:19 -050075 return signPrefixAnn(makePrefixAnn(std::forward<T>(args)...), m_keyChain, m_untrustedSigner);
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000076 }
77
78 /** \brief Invoke manager->slAnnounce and wait for result.
79 */
80 SlAnnounceResult
81 slAnnounceSync(const ndn::PrefixAnnouncement& pa, uint64_t faceId, time::milliseconds maxLifetime)
82 {
83 optional<SlAnnounceResult> result;
84 manager->slAnnounce(pa, faceId, maxLifetime,
85 [&] (RibManager::SlAnnounceResult res) {
86 BOOST_CHECK(!result);
87 result = res;
88 });
89
Davide Pesaventoe1bdc082018-10-11 21:20:23 -040090 g_io.poll();
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000091 BOOST_CHECK(result);
92 return result.value_or(SlAnnounceResult::ERROR);
93 }
94
95 /** \brief Invoke manager->slRenew and wait for result.
96 */
97 SlAnnounceResult
98 slRenewSync(const Name& name, uint64_t faceId, time::milliseconds maxLifetime)
99 {
100 optional<SlAnnounceResult> result;
101 manager->slRenew(name, faceId, maxLifetime,
102 [&] (RibManager::SlAnnounceResult res) {
103 BOOST_CHECK(!result);
104 result = res;
105 });
106
Davide Pesaventoe1bdc082018-10-11 21:20:23 -0400107 g_io.poll();
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000108 BOOST_CHECK(result);
109 return result.value_or(SlAnnounceResult::ERROR);
110 }
111
112 /** \brief Invoke manager->slFindAnn and wait for result.
113 */
114 optional<ndn::PrefixAnnouncement>
115 slFindAnnSync(const Name& name)
116 {
117 optional<optional<ndn::PrefixAnnouncement>> result;
118 manager->slFindAnn(name,
119 [&] (optional<ndn::PrefixAnnouncement> found) {
120 BOOST_CHECK(!result);
121 result = found;
122 });
123
Davide Pesaventoe1bdc082018-10-11 21:20:23 -0400124 g_io.poll();
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000125 BOOST_CHECK(result);
126 return result.value_or(nullopt);
127 }
128
129 /** \brief Lookup a route with PREFIXANN origin.
130 */
131 Route*
132 findAnnRoute(const Name& name, uint64_t faceId)
133 {
134 Route routeQuery;
135 routeQuery.faceId = faceId;
136 routeQuery.origin = ndn::nfd::ROUTE_ORIGIN_PREFIXANN;
137 return rib.find(name, routeQuery);
138 }
139
140private:
141 /** \brief Prepare a trust schema and load as localhop_security.
142 *
143 * Test case may revert this operation with ribManager->disableLocalhop().
144 */
145 void
146 loadTrustSchema()
147 {
148 ConfigSection section;
149 section.put("rule.id", "PA");
150 section.put("rule.for", "data");
151 section.put("rule.checker.type", "customized");
152 section.put("rule.checker.sig-type", "rsa-sha256");
153 section.put("rule.checker.key-locator.type", "name");
154 section.put("rule.checker.key-locator.name", "/trusted");
155 section.put("rule.checker.key-locator.relation", "is-prefix-of");
156 section.put("trust-anchor.type", "base64");
157 section.put("trust-anchor.base64-string", getIdentityCertificateBase64("/trusted"));
158 manager->enableLocalhop(section, "trust-schema.section");
159 }
160
161public:
Davide Pesavento8a05c7f2019-02-28 02:26:19 -0500162 rib::Rib rib;
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000163 unique_ptr<RibManager> manager;
164
165private:
166 ndn::util::DummyClientFace m_face;
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000167 ndn::nfd::Controller m_nfdController;
Davide Pesavento78ddcab2019-02-28 22:00:03 -0500168 Dispatcher m_dispatcher;
Davide Pesavento8a05c7f2019-02-28 02:26:19 -0500169 rib::FibUpdater m_fibUpdater;
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000170
171 ndn::security::SigningInfo m_trustedSigner;
172 ndn::security::SigningInfo m_untrustedSigner;
173};
174
Davide Pesavento8a05c7f2019-02-28 02:26:19 -0500175BOOST_AUTO_TEST_SUITE(Mgmt)
176BOOST_AUTO_TEST_SUITE(TestRibManager)
177BOOST_FIXTURE_TEST_SUITE(SlAnnounce, RibManagerSlAnnounceFixture)
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000178
179BOOST_AUTO_TEST_CASE(AnnounceUnconfigured)
180{
181 manager->disableLocalhop();
182 auto pa = makeTrustedAnn("/fMXN7UeB", 1_h);
183 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 3275, 1_h), SlAnnounceResult::VALIDATION_FAILURE);
184
185 BOOST_CHECK(findAnnRoute("/fMXN7UeB", 3275) == nullptr);
186}
187
188BOOST_AUTO_TEST_CASE(AnnounceValidationError)
189{
190 auto pa = makeUntrustedAnn("/1nzAe0Y4", 1_h);
191 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 2959, 1_h), SlAnnounceResult::VALIDATION_FAILURE);
192
193 BOOST_CHECK(findAnnRoute("/1nzAe0Y4", 2959) == nullptr);
194}
195
196BOOST_AUTO_TEST_CASE(AnnounceInsert_AnnLifetime)
197{
198 auto pa = makeTrustedAnn("/EHJYmJz9", 1_h);
199 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 1641, 2_h), SlAnnounceResult::OK);
200
201 Route* route = findAnnRoute("/EHJYmJz9", 1641);
202 BOOST_REQUIRE(route != nullptr);
203 BOOST_CHECK_EQUAL(route->annExpires, time::steady_clock::now() + 1_h);
204 BOOST_CHECK_EQUAL(route->expires.value(), time::steady_clock::now() + 1_h);
205}
206
207BOOST_AUTO_TEST_CASE(AnnounceInsert_ArgLifetime)
208{
209 auto pa = makeTrustedAnn("/BU9Fec9E", 2_h);
210 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 1282, 1_h), SlAnnounceResult::OK);
211
212 Route* route = findAnnRoute("/BU9Fec9E", 1282);
213 BOOST_REQUIRE(route != nullptr);
214 BOOST_CHECK_EQUAL(route->annExpires, time::steady_clock::now() + 2_h);
215 BOOST_CHECK_EQUAL(route->expires.value(), time::steady_clock::now() + 1_h);
216}
217
218BOOST_AUTO_TEST_CASE(AnnounceReplace)
219{
220 auto pa = makeTrustedAnn("/HsBFGvL3", 1_h);
221 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 2813, 1_h), SlAnnounceResult::OK);
222
223 pa = makeTrustedAnn("/HsBFGvL3", 2_h);
224 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 2813, 2_h), SlAnnounceResult::OK);
225
226 Route* route = findAnnRoute("/HsBFGvL3", 2813);
227 BOOST_REQUIRE(route != nullptr);
228 BOOST_CHECK_EQUAL(route->annExpires, time::steady_clock::now() + 2_h);
229 BOOST_CHECK_EQUAL(route->expires.value(), time::steady_clock::now() + 2_h);
230}
231
232BOOST_AUTO_TEST_CASE(AnnounceExpired)
233{
234 auto pa = makeTrustedAnn("/awrVv6V7", 1_h, std::make_pair(-3_h, -1_h));
235 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 9087, 1_h), SlAnnounceResult::EXPIRED);
236
237 BOOST_CHECK(findAnnRoute("/awrVv6V7", 9087) == nullptr);
238}
239
240BOOST_AUTO_TEST_CASE(RenewNotFound)
241{
242 BOOST_CHECK_EQUAL(slRenewSync("IAYigN73", 1070, 1_h), SlAnnounceResult::NOT_FOUND);
243
244 BOOST_CHECK(findAnnRoute("/IAYigN73", 1070) == nullptr);
245}
246
247BOOST_AUTO_TEST_CASE(RenewProlong_ArgLifetime)
248{
249 auto pa = makeTrustedAnn("/P2IYFqtr", 4_h);
250 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 4506, 2_h), SlAnnounceResult::OK);
251 advanceClocks(1_h); // Route has 1_h remaining lifetime
252
Teng Lianga4e6ec32018-10-21 09:25:00 -0700253 BOOST_CHECK_EQUAL(slRenewSync("/P2IYFqtr/2321", 4506, 2_h), SlAnnounceResult::OK);
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000254
255 Route* route = findAnnRoute("/P2IYFqtr", 4506);
256 BOOST_REQUIRE(route != nullptr);
257 BOOST_CHECK_EQUAL(route->annExpires, time::steady_clock::now() + 3_h);
258 BOOST_CHECK_EQUAL(route->expires.value(), time::steady_clock::now() + 2_h); // set by slRenew
259}
260
261BOOST_AUTO_TEST_CASE(RenewProlong_AnnLifetime)
262{
263 auto pa = makeTrustedAnn("/be01Yiba", 4_h);
264 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 1589, 2_h), SlAnnounceResult::OK);
265 advanceClocks(1_h); // Route has 1_h remaining lifetime
266
Teng Lianga4e6ec32018-10-21 09:25:00 -0700267 BOOST_CHECK_EQUAL(slRenewSync("/be01Yiba/4324", 1589, 5_h), SlAnnounceResult::OK);
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000268
269 Route* route = findAnnRoute("/be01Yiba", 1589);
270 BOOST_REQUIRE(route != nullptr);
271 BOOST_CHECK_EQUAL(route->annExpires, time::steady_clock::now() + 3_h);
272 BOOST_CHECK_EQUAL(route->expires.value(), time::steady_clock::now() + 3_h); // capped by annExpires
273}
274
275BOOST_AUTO_TEST_CASE(RenewShorten)
276{
277 auto pa = makeTrustedAnn("/5XCHYCAd", 4_h);
278 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 3851, 4_h), SlAnnounceResult::OK);
279 advanceClocks(1_h); // Route has 3_h remaining lifetime
280
Teng Lianga4e6ec32018-10-21 09:25:00 -0700281 BOOST_CHECK_EQUAL(slRenewSync("/5XCHYCAd/98934", 3851, 1_h), SlAnnounceResult::OK);
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000282
283 Route* route = findAnnRoute("/5XCHYCAd", 3851);
284 BOOST_REQUIRE(route != nullptr);
285 BOOST_CHECK_EQUAL(route->annExpires, time::steady_clock::now() + 3_h);
286 BOOST_CHECK_EQUAL(route->expires.value(), time::steady_clock::now() + 1_h); // set by slRenew
287}
288
289BOOST_AUTO_TEST_CASE(RenewShorten_Zero)
290{
291 auto pa = makeTrustedAnn("/cdQ7KPNw", 4_h);
292 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 8031, 4_h), SlAnnounceResult::OK);
293 advanceClocks(1_h); // Route has 3_h remaining lifetime
294
Teng Lianga4e6ec32018-10-21 09:25:00 -0700295 BOOST_CHECK_EQUAL(slRenewSync("/cdQ7KPNw/8023", 8031, 0_s), SlAnnounceResult::EXPIRED);
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000296
297 BOOST_CHECK(findAnnRoute("/cdQ7KPNw", 8031) == nullptr);
298}
299
300BOOST_AUTO_TEST_CASE(FindExisting)
301{
302 auto pa = makeTrustedAnn("/JHugsjjr", 1_h);
303 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 2363, 1_h), SlAnnounceResult::OK);
304
305 auto found = slFindAnnSync("/JHugsjjr");
306 BOOST_REQUIRE(found);
307 BOOST_CHECK_EQUAL(found->getAnnouncedName(), "/JHugsjjr");
308 BOOST_CHECK(found->getData());
309
310 auto found2 = slFindAnnSync("/JHugsjjr/StvXhKR5");
311 BOOST_CHECK(found == found2);
312}
313
314BOOST_AUTO_TEST_CASE(FindNew)
315{
316 Route route;
317 route.faceId = 1367;
318 route.origin = ndn::nfd::ROUTE_ORIGIN_APP;
319 rib.insert("/dLY1pRhR", route);
320
321 auto pa = slFindAnnSync("/dLY1pRhR/3qNK9Ngn");
322 BOOST_REQUIRE(pa);
323 BOOST_CHECK_EQUAL(pa->getAnnouncedName(), "/dLY1pRhR");
324}
325
326BOOST_AUTO_TEST_CASE(FindNone)
327{
328 auto pa = slFindAnnSync("/2YNeYuV2");
329 BOOST_CHECK(!pa);
330}
331
Davide Pesavento8a05c7f2019-02-28 02:26:19 -0500332BOOST_AUTO_TEST_SUITE_END() // SlAnnounce
333BOOST_AUTO_TEST_SUITE_END() // TestRibManager
334BOOST_AUTO_TEST_SUITE_END() // Mgmt
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000335
336} // namespace tests
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000337} // namespace nfd