blob: 826ebc448c2a0cbc257daa2fc692eca8028e0bdf [file] [log] [blame]
Junxiao Shib8590312016-12-29 21:22:25 +00001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Junxiao Shi38b24c72017-01-05 02:59:31 +00003 * Copyright (c) 2014-2017, Regents of the University of California,
Junxiao Shib8590312016-12-29 21:22:25 +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
26#include "face/face-system.hpp"
Junxiao Shi38b24c72017-01-05 02:59:31 +000027#include "face-system-fixture.hpp"
Junxiao Shib8590312016-12-29 21:22:25 +000028
29// ProtocolFactory includes, sorted alphabetically
Junxiao Shib8590312016-12-29 21:22:25 +000030#include "face/udp-factory.hpp"
Junxiao Shib8590312016-12-29 21:22:25 +000031#ifdef HAVE_WEBSOCKET
32#include "face/websocket-factory.hpp"
33#endif // HAVE_WEBSOCKET
34
35#include "tests/test-common.hpp"
36
37namespace nfd {
38namespace face {
39namespace tests {
40
41using namespace nfd::tests;
42
Junxiao Shi38b24c72017-01-05 02:59:31 +000043BOOST_AUTO_TEST_SUITE(Face)
44BOOST_FIXTURE_TEST_SUITE(TestFaceSystem, FaceSystemFixture)
45
46BOOST_AUTO_TEST_SUITE(ProcessConfig)
47
48class DummyProtocolFactory : public ProtocolFactory
Junxiao Shib8590312016-12-29 21:22:25 +000049{
50public:
Junxiao Shi38b24c72017-01-05 02:59:31 +000051 void
52 processConfig(OptionalConfigSection configSection,
53 FaceSystem::ConfigContext& context) override
Junxiao Shib8590312016-12-29 21:22:25 +000054 {
Junxiao Shi38b24c72017-01-05 02:59:31 +000055 processConfigHistory.push_back({configSection, context.isDryRun});
56 if (!context.isDryRun) {
57 this->providedSchemes = this->newProvidedSchemes;
58 }
Junxiao Shib8590312016-12-29 21:22:25 +000059 }
60
61 void
Junxiao Shi38b24c72017-01-05 02:59:31 +000062 createFace(const FaceUri& uri,
63 ndn::nfd::FacePersistency persistency,
64 bool wantLocalFieldsEnabled,
65 const FaceCreatedCallback& onCreated,
66 const FaceCreationFailedCallback& onFailure) override
Junxiao Shib8590312016-12-29 21:22:25 +000067 {
Junxiao Shi38b24c72017-01-05 02:59:31 +000068 BOOST_FAIL("createFace should not be called");
Junxiao Shib8590312016-12-29 21:22:25 +000069 }
70
Junxiao Shi38b24c72017-01-05 02:59:31 +000071 std::vector<shared_ptr<const Channel>>
72 getChannels() const override
73 {
74 BOOST_FAIL("getChannels should not be called");
75 return {};
76 }
77
78public:
79 struct ProcessConfigArgs
80 {
81 OptionalConfigSection configSection;
82 bool isDryRun;
83 };
84 std::vector<ProcessConfigArgs> processConfigHistory;
85
86 std::set<std::string> newProvidedSchemes;
Junxiao Shib8590312016-12-29 21:22:25 +000087};
88
Junxiao Shi38b24c72017-01-05 02:59:31 +000089BOOST_AUTO_TEST_CASE(Normal)
90{
91 auto f1 = make_shared<DummyProtocolFactory>();
92 auto f2 = make_shared<DummyProtocolFactory>();
93 faceSystem.m_factories["f1"] = f1;
94 faceSystem.m_factories["f2"] = f2;
95
96 const std::string CONFIG = R"CONFIG(
97 face_system
98 {
99 f1
100 {
101 key v1
102 }
103 f2
104 {
105 key v2
106 }
107 }
108 )CONFIG";
109
110 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
111 BOOST_REQUIRE_EQUAL(f1->processConfigHistory.size(), 1);
112 BOOST_CHECK_EQUAL(f1->processConfigHistory.back().isDryRun, true);
113 BOOST_CHECK_EQUAL(f1->processConfigHistory.back().configSection->get<std::string>("key"), "v1");
114 BOOST_REQUIRE_EQUAL(f2->processConfigHistory.size(), 1);
115 BOOST_CHECK_EQUAL(f2->processConfigHistory.back().isDryRun, true);
116 BOOST_CHECK_EQUAL(f2->processConfigHistory.back().configSection->get<std::string>("key"), "v2");
117
118 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
119 BOOST_REQUIRE_EQUAL(f1->processConfigHistory.size(), 2);
120 BOOST_CHECK_EQUAL(f1->processConfigHistory.back().isDryRun, false);
121 BOOST_CHECK_EQUAL(f1->processConfigHistory.back().configSection->get<std::string>("key"), "v1");
122 BOOST_REQUIRE_EQUAL(f2->processConfigHistory.size(), 2);
123 BOOST_CHECK_EQUAL(f2->processConfigHistory.back().isDryRun, false);
124 BOOST_CHECK_EQUAL(f2->processConfigHistory.back().configSection->get<std::string>("key"), "v2");
125}
126
127BOOST_AUTO_TEST_CASE(OmittedSection)
128{
129 auto f1 = make_shared<DummyProtocolFactory>();
130 auto f2 = make_shared<DummyProtocolFactory>();
131 faceSystem.m_factories["f1"] = f1;
132 faceSystem.m_factories["f2"] = f2;
133
134 const std::string CONFIG = R"CONFIG(
135 face_system
136 {
137 f1
138 {
139 }
140 }
141 )CONFIG";
142
143 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
144 BOOST_REQUIRE_EQUAL(f1->processConfigHistory.size(), 1);
145 BOOST_CHECK_EQUAL(f1->processConfigHistory.back().isDryRun, true);
146 BOOST_REQUIRE_EQUAL(f2->processConfigHistory.size(), 1);
147 BOOST_CHECK_EQUAL(f2->processConfigHistory.back().isDryRun, true);
148 BOOST_CHECK(!f2->processConfigHistory.back().configSection);
149
150 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
151 BOOST_REQUIRE_EQUAL(f1->processConfigHistory.size(), 2);
152 BOOST_CHECK_EQUAL(f1->processConfigHistory.back().isDryRun, false);
153 BOOST_REQUIRE_EQUAL(f2->processConfigHistory.size(), 2);
154 BOOST_CHECK_EQUAL(f2->processConfigHistory.back().isDryRun, false);
155 BOOST_CHECK(!f2->processConfigHistory.back().configSection);
156}
157
158BOOST_AUTO_TEST_CASE(UnknownSection)
159{
160 const std::string CONFIG = R"CONFIG(
161 face_system
162 {
163 f0
164 {
165 }
166 }
167 )CONFIG";
168
169 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
170 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
171}
172
173BOOST_AUTO_TEST_CASE(ChangeProvidedSchemes)
174{
175 auto f1 = make_shared<DummyProtocolFactory>();
176 faceSystem.m_factories["f1"] = f1;
177
178 const std::string CONFIG = R"CONFIG(
179 face_system
180 {
181 f1
182 {
183 }
184 }
185 )CONFIG";
186
187 f1->newProvidedSchemes.insert("s1");
188 f1->newProvidedSchemes.insert("s2");
189 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
190 BOOST_CHECK(faceSystem.getFactoryByScheme("f1") == nullptr);
191 BOOST_CHECK_EQUAL(faceSystem.getFactoryByScheme("s1"), f1.get());
192 BOOST_CHECK_EQUAL(faceSystem.getFactoryByScheme("s2"), f1.get());
193
194 f1->newProvidedSchemes.erase("s2");
195 f1->newProvidedSchemes.insert("s3");
196 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
197 BOOST_CHECK(faceSystem.getFactoryByScheme("f1") == nullptr);
198 BOOST_CHECK_EQUAL(faceSystem.getFactoryByScheme("s1"), f1.get());
199 BOOST_CHECK(faceSystem.getFactoryByScheme("s2") == nullptr);
200 BOOST_CHECK_EQUAL(faceSystem.getFactoryByScheme("s3"), f1.get());
201}
202
203BOOST_AUTO_TEST_SUITE_END() // ProcessConfig
204
205///\todo #3904 move Config* to *Factory test suite
Junxiao Shib8590312016-12-29 21:22:25 +0000206
Junxiao Shib8590312016-12-29 21:22:25 +0000207BOOST_AUTO_TEST_SUITE(ConfigUdp)
208
209BOOST_AUTO_TEST_CASE(Normal)
210{
211 SKIP_IF_NOT_SUPERUSER();
212
213 const std::string CONFIG = R"CONFIG(
214 face_system
215 {
216 udp
217 {
218 port 6363
219 enable_v4 yes
220 enable_v6 yes
221 idle_timeout 30
222 keep_alive_interval 25
223 mcast yes
224 mcast_port 56363
225 mcast_group 224.0.23.170
226 }
227 }
228 )CONFIG";
229
230 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
231 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
232
Junxiao Shi38b24c72017-01-05 02:59:31 +0000233 auto& factory = this->getFactoryByScheme<UdpFactory>("udp");
234 BOOST_CHECK_EQUAL(factory.getChannels().size(), 2);
Junxiao Shib8590312016-12-29 21:22:25 +0000235}
236
237BOOST_AUTO_TEST_CASE(BadIdleTimeout)
238{
239 const std::string CONFIG = R"CONFIG(
240 face_system
241 {
242 udp
243 {
244 idle_timeout hello
245 }
246 }
247 )CONFIG";
248
249 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
250 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
251}
252
253BOOST_AUTO_TEST_CASE(BadMcast)
254{
255 const std::string CONFIG = R"CONFIG(
256 face_system
257 {
258 udp
259 {
260 mcast hello
261 }
262 }
263 )CONFIG";
264
265 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
266 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
267}
268
269BOOST_AUTO_TEST_CASE(BadMcastGroup)
270{
271 const std::string CONFIG = R"CONFIG(
272 face_system
273 {
274 udp
275 {
276 mcast no
277 mcast_port 50
278 mcast_group hello
279 }
280 }
281 )CONFIG";
282
283 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
284 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
285}
286
287BOOST_AUTO_TEST_CASE(BadMcastGroupV6)
288{
289 const std::string CONFIG = R"CONFIG(
290 face_system
291 {
292 udp
293 {
294 mcast no
295 mcast_port 50
296 mcast_group ::1
297 }
298 }
299 )CONFIG";
300
301 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
302 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
303}
304
305BOOST_AUTO_TEST_CASE(ChannelsDisabled)
306{
307 const std::string CONFIG = R"CONFIG(
308 face_system
309 {
310 udp
311 {
312 port 6363
313 enable_v4 no
314 enable_v6 no
315 idle_timeout 30
316 keep_alive_interval 25
317 mcast yes
318 mcast_port 56363
319 mcast_group 224.0.23.170
320 }
321 }
322 )CONFIG";
323
324 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
325 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
326}
327
328BOOST_AUTO_TEST_CASE(ConflictingMcast)
329{
330 const std::string CONFIG = R"CONFIG(
331 face_system
332 {
333 udp
334 {
335 port 6363
336 enable_v4 no
337 enable_v6 yes
338 idle_timeout 30
339 keep_alive_interval 25
340 mcast yes
341 mcast_port 56363
342 mcast_group 224.0.23.170
343 }
344 }
345 )CONFIG";
346
347 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
348 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
349}
350
351BOOST_AUTO_TEST_CASE(UnknownOption)
352{
353 const std::string CONFIG = R"CONFIG(
354 face_system
355 {
356 udp
357 {
358 hello
359 }
360 }
361 )CONFIG";
362
363 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
364 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
365}
366
367BOOST_AUTO_TEST_CASE(MulticastReinit)
368{
369 SKIP_IF_NOT_SUPERUSER();
370
371 const std::string CONFIG_WITH_MCAST = R"CONFIG(
372 face_system
373 {
374 udp
375 {
376 mcast yes
377 }
378 }
379 )CONFIG";
380
381 BOOST_CHECK_NO_THROW(parseConfig(CONFIG_WITH_MCAST, false));
382
Junxiao Shi38b24c72017-01-05 02:59:31 +0000383 auto& factory = this->getFactoryByScheme<UdpFactory>("udp");
Junxiao Shib8590312016-12-29 21:22:25 +0000384
Junxiao Shi38b24c72017-01-05 02:59:31 +0000385 if (factory.getMulticastFaces().empty()) {
Junxiao Shib8590312016-12-29 21:22:25 +0000386 BOOST_WARN_MESSAGE(false, "skipping assertions that require at least one UDP multicast face");
387 return;
388 }
389
390 const std::string CONFIG_WITHOUT_MCAST = R"CONFIG(
391 face_system
392 {
393 udp
394 {
395 mcast no
396 }
397 }
398 )CONFIG";
399
400 BOOST_CHECK_NO_THROW(parseConfig(CONFIG_WITHOUT_MCAST, false));
401 BOOST_REQUIRE_NO_THROW(g_io.poll());
Junxiao Shi38b24c72017-01-05 02:59:31 +0000402 BOOST_CHECK_EQUAL(factory.getMulticastFaces().size(), 0);
Junxiao Shib8590312016-12-29 21:22:25 +0000403}
404BOOST_AUTO_TEST_SUITE_END() // ConfigUdp
405
Junxiao Shib8590312016-12-29 21:22:25 +0000406#ifdef HAVE_WEBSOCKET
407BOOST_AUTO_TEST_SUITE(ConfigWebSocket)
408
409BOOST_AUTO_TEST_CASE(Normal)
410{
411 const std::string CONFIG = R"CONFIG(
412 face_system
413 {
414 websocket
415 {
416 listen yes
417 port 9696
418 enable_v4 yes
419 enable_v6 yes
420 }
421 }
422 )CONFIG";
423
424 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
425 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
426
Junxiao Shi38b24c72017-01-05 02:59:31 +0000427 auto& factory = this->getFactoryByScheme<WebSocketFactory>("websocket");
428 BOOST_CHECK_EQUAL(factory.getChannels().size(), 1);
Junxiao Shib8590312016-12-29 21:22:25 +0000429}
430
431BOOST_AUTO_TEST_CASE(ChannelsDisabled)
432{
433 const std::string CONFIG = R"CONFIG(
434 face_system
435 {
436 websocket
437 {
438 listen yes
439 port 9696
440 enable_v4 no
441 enable_v6 no
442 }
443 }
444 )CONFIG";
445
446 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
447 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
448}
449
450BOOST_AUTO_TEST_CASE(Ipv4ChannelDisabled)
451{
452 const std::string CONFIG = R"CONFIG(
453 face_system
454 {
455 websocket
456 {
457 listen yes
458 port 9696
459 enable_v4 no
460 enable_v6 yes
461 }
462 }
463 )CONFIG";
464
465 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
466 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
467}
468
469BOOST_AUTO_TEST_SUITE_END() // ConfigWebSocket
470#endif // HAVE_WEBSOCKET
471
472BOOST_AUTO_TEST_SUITE_END() // TestFaceSystem
473BOOST_AUTO_TEST_SUITE_END() // Mgmt
474
475} // namespace tests
476} // namespace face
477} // namespace nfd