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