blob: bc398caa7835c2ae5ca28b7038d3ec17e3e34048 [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
30#ifdef HAVE_LIBPCAP
31#include "face/ethernet-factory.hpp"
32#endif // HAVE_LIBPCAP
Junxiao Shib8590312016-12-29 21:22:25 +000033#include "face/udp-factory.hpp"
34#ifdef HAVE_UNIX_SOCKETS
35#include "face/unix-stream-factory.hpp"
36#endif // HAVE_UNIX_SOCKETS
37#ifdef HAVE_WEBSOCKET
38#include "face/websocket-factory.hpp"
39#endif // HAVE_WEBSOCKET
40
41#include "tests/test-common.hpp"
42
43namespace nfd {
44namespace face {
45namespace tests {
46
47using namespace nfd::tests;
48
Junxiao Shi38b24c72017-01-05 02:59:31 +000049BOOST_AUTO_TEST_SUITE(Face)
50BOOST_FIXTURE_TEST_SUITE(TestFaceSystem, FaceSystemFixture)
51
52BOOST_AUTO_TEST_SUITE(ProcessConfig)
53
54class DummyProtocolFactory : public ProtocolFactory
Junxiao Shib8590312016-12-29 21:22:25 +000055{
56public:
Junxiao Shi38b24c72017-01-05 02:59:31 +000057 void
58 processConfig(OptionalConfigSection configSection,
59 FaceSystem::ConfigContext& context) override
Junxiao Shib8590312016-12-29 21:22:25 +000060 {
Junxiao Shi38b24c72017-01-05 02:59:31 +000061 processConfigHistory.push_back({configSection, context.isDryRun});
62 if (!context.isDryRun) {
63 this->providedSchemes = this->newProvidedSchemes;
64 }
Junxiao Shib8590312016-12-29 21:22:25 +000065 }
66
67 void
Junxiao Shi38b24c72017-01-05 02:59:31 +000068 createFace(const FaceUri& uri,
69 ndn::nfd::FacePersistency persistency,
70 bool wantLocalFieldsEnabled,
71 const FaceCreatedCallback& onCreated,
72 const FaceCreationFailedCallback& onFailure) override
Junxiao Shib8590312016-12-29 21:22:25 +000073 {
Junxiao Shi38b24c72017-01-05 02:59:31 +000074 BOOST_FAIL("createFace should not be called");
Junxiao Shib8590312016-12-29 21:22:25 +000075 }
76
Junxiao Shi38b24c72017-01-05 02:59:31 +000077 std::vector<shared_ptr<const Channel>>
78 getChannels() const override
79 {
80 BOOST_FAIL("getChannels should not be called");
81 return {};
82 }
83
84public:
85 struct ProcessConfigArgs
86 {
87 OptionalConfigSection configSection;
88 bool isDryRun;
89 };
90 std::vector<ProcessConfigArgs> processConfigHistory;
91
92 std::set<std::string> newProvidedSchemes;
Junxiao Shib8590312016-12-29 21:22:25 +000093};
94
Junxiao Shi38b24c72017-01-05 02:59:31 +000095BOOST_AUTO_TEST_CASE(Normal)
96{
97 auto f1 = make_shared<DummyProtocolFactory>();
98 auto f2 = make_shared<DummyProtocolFactory>();
99 faceSystem.m_factories["f1"] = f1;
100 faceSystem.m_factories["f2"] = f2;
101
102 const std::string CONFIG = R"CONFIG(
103 face_system
104 {
105 f1
106 {
107 key v1
108 }
109 f2
110 {
111 key v2
112 }
113 }
114 )CONFIG";
115
116 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
117 BOOST_REQUIRE_EQUAL(f1->processConfigHistory.size(), 1);
118 BOOST_CHECK_EQUAL(f1->processConfigHistory.back().isDryRun, true);
119 BOOST_CHECK_EQUAL(f1->processConfigHistory.back().configSection->get<std::string>("key"), "v1");
120 BOOST_REQUIRE_EQUAL(f2->processConfigHistory.size(), 1);
121 BOOST_CHECK_EQUAL(f2->processConfigHistory.back().isDryRun, true);
122 BOOST_CHECK_EQUAL(f2->processConfigHistory.back().configSection->get<std::string>("key"), "v2");
123
124 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
125 BOOST_REQUIRE_EQUAL(f1->processConfigHistory.size(), 2);
126 BOOST_CHECK_EQUAL(f1->processConfigHistory.back().isDryRun, false);
127 BOOST_CHECK_EQUAL(f1->processConfigHistory.back().configSection->get<std::string>("key"), "v1");
128 BOOST_REQUIRE_EQUAL(f2->processConfigHistory.size(), 2);
129 BOOST_CHECK_EQUAL(f2->processConfigHistory.back().isDryRun, false);
130 BOOST_CHECK_EQUAL(f2->processConfigHistory.back().configSection->get<std::string>("key"), "v2");
131}
132
133BOOST_AUTO_TEST_CASE(OmittedSection)
134{
135 auto f1 = make_shared<DummyProtocolFactory>();
136 auto f2 = make_shared<DummyProtocolFactory>();
137 faceSystem.m_factories["f1"] = f1;
138 faceSystem.m_factories["f2"] = f2;
139
140 const std::string CONFIG = R"CONFIG(
141 face_system
142 {
143 f1
144 {
145 }
146 }
147 )CONFIG";
148
149 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
150 BOOST_REQUIRE_EQUAL(f1->processConfigHistory.size(), 1);
151 BOOST_CHECK_EQUAL(f1->processConfigHistory.back().isDryRun, true);
152 BOOST_REQUIRE_EQUAL(f2->processConfigHistory.size(), 1);
153 BOOST_CHECK_EQUAL(f2->processConfigHistory.back().isDryRun, true);
154 BOOST_CHECK(!f2->processConfigHistory.back().configSection);
155
156 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
157 BOOST_REQUIRE_EQUAL(f1->processConfigHistory.size(), 2);
158 BOOST_CHECK_EQUAL(f1->processConfigHistory.back().isDryRun, false);
159 BOOST_REQUIRE_EQUAL(f2->processConfigHistory.size(), 2);
160 BOOST_CHECK_EQUAL(f2->processConfigHistory.back().isDryRun, false);
161 BOOST_CHECK(!f2->processConfigHistory.back().configSection);
162}
163
164BOOST_AUTO_TEST_CASE(UnknownSection)
165{
166 const std::string CONFIG = R"CONFIG(
167 face_system
168 {
169 f0
170 {
171 }
172 }
173 )CONFIG";
174
175 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
176 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
177}
178
179BOOST_AUTO_TEST_CASE(ChangeProvidedSchemes)
180{
181 auto f1 = make_shared<DummyProtocolFactory>();
182 faceSystem.m_factories["f1"] = f1;
183
184 const std::string CONFIG = R"CONFIG(
185 face_system
186 {
187 f1
188 {
189 }
190 }
191 )CONFIG";
192
193 f1->newProvidedSchemes.insert("s1");
194 f1->newProvidedSchemes.insert("s2");
195 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
196 BOOST_CHECK(faceSystem.getFactoryByScheme("f1") == nullptr);
197 BOOST_CHECK_EQUAL(faceSystem.getFactoryByScheme("s1"), f1.get());
198 BOOST_CHECK_EQUAL(faceSystem.getFactoryByScheme("s2"), f1.get());
199
200 f1->newProvidedSchemes.erase("s2");
201 f1->newProvidedSchemes.insert("s3");
202 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
203 BOOST_CHECK(faceSystem.getFactoryByScheme("f1") == nullptr);
204 BOOST_CHECK_EQUAL(faceSystem.getFactoryByScheme("s1"), f1.get());
205 BOOST_CHECK(faceSystem.getFactoryByScheme("s2") == nullptr);
206 BOOST_CHECK_EQUAL(faceSystem.getFactoryByScheme("s3"), f1.get());
207}
208
209BOOST_AUTO_TEST_SUITE_END() // ProcessConfig
210
211///\todo #3904 move Config* to *Factory test suite
Junxiao Shib8590312016-12-29 21:22:25 +0000212
Junxiao Shib8590312016-12-29 21:22:25 +0000213BOOST_AUTO_TEST_SUITE(ConfigUdp)
214
215BOOST_AUTO_TEST_CASE(Normal)
216{
217 SKIP_IF_NOT_SUPERUSER();
218
219 const std::string CONFIG = R"CONFIG(
220 face_system
221 {
222 udp
223 {
224 port 6363
225 enable_v4 yes
226 enable_v6 yes
227 idle_timeout 30
228 keep_alive_interval 25
229 mcast yes
230 mcast_port 56363
231 mcast_group 224.0.23.170
232 }
233 }
234 )CONFIG";
235
236 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
237 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
238
Junxiao Shi38b24c72017-01-05 02:59:31 +0000239 auto& factory = this->getFactoryByScheme<UdpFactory>("udp");
240 BOOST_CHECK_EQUAL(factory.getChannels().size(), 2);
Junxiao Shib8590312016-12-29 21:22:25 +0000241}
242
243BOOST_AUTO_TEST_CASE(BadIdleTimeout)
244{
245 const std::string CONFIG = R"CONFIG(
246 face_system
247 {
248 udp
249 {
250 idle_timeout hello
251 }
252 }
253 )CONFIG";
254
255 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
256 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
257}
258
259BOOST_AUTO_TEST_CASE(BadMcast)
260{
261 const std::string CONFIG = R"CONFIG(
262 face_system
263 {
264 udp
265 {
266 mcast hello
267 }
268 }
269 )CONFIG";
270
271 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
272 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
273}
274
275BOOST_AUTO_TEST_CASE(BadMcastGroup)
276{
277 const std::string CONFIG = R"CONFIG(
278 face_system
279 {
280 udp
281 {
282 mcast no
283 mcast_port 50
284 mcast_group hello
285 }
286 }
287 )CONFIG";
288
289 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
290 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
291}
292
293BOOST_AUTO_TEST_CASE(BadMcastGroupV6)
294{
295 const std::string CONFIG = R"CONFIG(
296 face_system
297 {
298 udp
299 {
300 mcast no
301 mcast_port 50
302 mcast_group ::1
303 }
304 }
305 )CONFIG";
306
307 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
308 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
309}
310
311BOOST_AUTO_TEST_CASE(ChannelsDisabled)
312{
313 const std::string CONFIG = R"CONFIG(
314 face_system
315 {
316 udp
317 {
318 port 6363
319 enable_v4 no
320 enable_v6 no
321 idle_timeout 30
322 keep_alive_interval 25
323 mcast yes
324 mcast_port 56363
325 mcast_group 224.0.23.170
326 }
327 }
328 )CONFIG";
329
330 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
331 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
332}
333
334BOOST_AUTO_TEST_CASE(ConflictingMcast)
335{
336 const std::string CONFIG = R"CONFIG(
337 face_system
338 {
339 udp
340 {
341 port 6363
342 enable_v4 no
343 enable_v6 yes
344 idle_timeout 30
345 keep_alive_interval 25
346 mcast yes
347 mcast_port 56363
348 mcast_group 224.0.23.170
349 }
350 }
351 )CONFIG";
352
353 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
354 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
355}
356
357BOOST_AUTO_TEST_CASE(UnknownOption)
358{
359 const std::string CONFIG = R"CONFIG(
360 face_system
361 {
362 udp
363 {
364 hello
365 }
366 }
367 )CONFIG";
368
369 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
370 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
371}
372
373BOOST_AUTO_TEST_CASE(MulticastReinit)
374{
375 SKIP_IF_NOT_SUPERUSER();
376
377 const std::string CONFIG_WITH_MCAST = R"CONFIG(
378 face_system
379 {
380 udp
381 {
382 mcast yes
383 }
384 }
385 )CONFIG";
386
387 BOOST_CHECK_NO_THROW(parseConfig(CONFIG_WITH_MCAST, false));
388
Junxiao Shi38b24c72017-01-05 02:59:31 +0000389 auto& factory = this->getFactoryByScheme<UdpFactory>("udp");
Junxiao Shib8590312016-12-29 21:22:25 +0000390
Junxiao Shi38b24c72017-01-05 02:59:31 +0000391 if (factory.getMulticastFaces().empty()) {
Junxiao Shib8590312016-12-29 21:22:25 +0000392 BOOST_WARN_MESSAGE(false, "skipping assertions that require at least one UDP multicast face");
393 return;
394 }
395
396 const std::string CONFIG_WITHOUT_MCAST = R"CONFIG(
397 face_system
398 {
399 udp
400 {
401 mcast no
402 }
403 }
404 )CONFIG";
405
406 BOOST_CHECK_NO_THROW(parseConfig(CONFIG_WITHOUT_MCAST, false));
407 BOOST_REQUIRE_NO_THROW(g_io.poll());
Junxiao Shi38b24c72017-01-05 02:59:31 +0000408 BOOST_CHECK_EQUAL(factory.getMulticastFaces().size(), 0);
Junxiao Shib8590312016-12-29 21:22:25 +0000409}
410BOOST_AUTO_TEST_SUITE_END() // ConfigUdp
411
412#ifdef HAVE_LIBPCAP
413BOOST_AUTO_TEST_SUITE(ConfigEther)
414
415BOOST_AUTO_TEST_CASE(Normal)
416{
417 SKIP_IF_NOT_SUPERUSER();
418
419 const std::string CONFIG = R"CONFIG(
420 face_system
421 {
422 ether
423 {
424 mcast yes
425 mcast_group 01:00:5E:00:17:AA
426 whitelist
427 {
428 *
429 }
430 blacklist
431 {
432 }
433 }
434 }
435 )CONFIG";
436
437 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
438 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
439
Junxiao Shi38b24c72017-01-05 02:59:31 +0000440 auto& factory = this->getFactoryByScheme<EthernetFactory>("ether");
441 BOOST_CHECK_EQUAL(factory.getChannels().size(), 0);
Junxiao Shib8590312016-12-29 21:22:25 +0000442}
443
444BOOST_AUTO_TEST_CASE(BadMcast)
445{
446 const std::string CONFIG = R"CONFIG(
447 face_system
448 {
449 ether
450 {
451 mcast hello
452 }
453 }
454 )CONFIG";
455
456 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
457 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
458}
459
460BOOST_AUTO_TEST_CASE(BadMcastGroup)
461{
462 const std::string CONFIG = R"CONFIG(
463 face_system
464 {
465 ether
466 {
467 mcast yes
468 mcast_group
469 }
470 }
471 )CONFIG";
472
473 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
474 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
475}
476
477BOOST_AUTO_TEST_CASE(UnknownOption)
478{
479 const std::string CONFIG = R"CONFIG(
480 face_system
481 {
482 ether
483 {
484 hello
485 }
486 }
487 )CONFIG";
488
489 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
490 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
491}
492
493BOOST_AUTO_TEST_CASE(MulticastReinit)
494{
495 SKIP_IF_NOT_SUPERUSER();
496
497 const std::string CONFIG_WITH_MCAST = R"CONFIG(
498 face_system
499 {
500 ether
501 {
502 mcast yes
503 }
504 }
505 )CONFIG";
506
507 BOOST_CHECK_NO_THROW(parseConfig(CONFIG_WITH_MCAST, false));
508
Junxiao Shi38b24c72017-01-05 02:59:31 +0000509 auto& factory = this->getFactoryByScheme<EthernetFactory>("ether");
Junxiao Shib8590312016-12-29 21:22:25 +0000510
Junxiao Shi38b24c72017-01-05 02:59:31 +0000511 if (factory.getMulticastFaces().empty()) {
Junxiao Shib8590312016-12-29 21:22:25 +0000512 BOOST_WARN_MESSAGE(false, "skipping assertions that require at least one Ethernet multicast face");
513 return;
514 }
515
516 const std::string CONFIG_WITHOUT_MCAST = R"CONFIG(
517 face_system
518 {
519 ether
520 {
521 mcast no
522 }
523 }
524 )CONFIG";
525
526 BOOST_CHECK_NO_THROW(parseConfig(CONFIG_WITHOUT_MCAST, false));
527 BOOST_REQUIRE_NO_THROW(g_io.poll());
Junxiao Shi38b24c72017-01-05 02:59:31 +0000528 BOOST_CHECK_EQUAL(factory.getMulticastFaces().size(), 0);
Junxiao Shib8590312016-12-29 21:22:25 +0000529}
530
531BOOST_AUTO_TEST_SUITE_END() // ConfigEther
532#endif // HAVE_LIBPCAP
533
534#ifdef HAVE_WEBSOCKET
535BOOST_AUTO_TEST_SUITE(ConfigWebSocket)
536
537BOOST_AUTO_TEST_CASE(Normal)
538{
539 const std::string CONFIG = R"CONFIG(
540 face_system
541 {
542 websocket
543 {
544 listen yes
545 port 9696
546 enable_v4 yes
547 enable_v6 yes
548 }
549 }
550 )CONFIG";
551
552 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
553 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
554
Junxiao Shi38b24c72017-01-05 02:59:31 +0000555 auto& factory = this->getFactoryByScheme<WebSocketFactory>("websocket");
556 BOOST_CHECK_EQUAL(factory.getChannels().size(), 1);
Junxiao Shib8590312016-12-29 21:22:25 +0000557}
558
559BOOST_AUTO_TEST_CASE(ChannelsDisabled)
560{
561 const std::string CONFIG = R"CONFIG(
562 face_system
563 {
564 websocket
565 {
566 listen yes
567 port 9696
568 enable_v4 no
569 enable_v6 no
570 }
571 }
572 )CONFIG";
573
574 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
575 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
576}
577
578BOOST_AUTO_TEST_CASE(Ipv4ChannelDisabled)
579{
580 const std::string CONFIG = R"CONFIG(
581 face_system
582 {
583 websocket
584 {
585 listen yes
586 port 9696
587 enable_v4 no
588 enable_v6 yes
589 }
590 }
591 )CONFIG";
592
593 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
594 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
595}
596
597BOOST_AUTO_TEST_SUITE_END() // ConfigWebSocket
598#endif // HAVE_WEBSOCKET
599
600BOOST_AUTO_TEST_SUITE_END() // TestFaceSystem
601BOOST_AUTO_TEST_SUITE_END() // Mgmt
602
603} // namespace tests
604} // namespace face
605} // namespace nfd