blob: bcae7250d37b501d0f5075952cf4dc84bfe6c8da [file] [log] [blame]
Junxiao Shib8590312016-12-29 21:22:25 +00001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2014-2016, 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 "face/face-system.hpp"
27#include "fw/face-table.hpp"
28
29// ProtocolFactory includes, sorted alphabetically
30#ifdef HAVE_LIBPCAP
31#include "face/ethernet-factory.hpp"
32#endif // HAVE_LIBPCAP
33#include "face/tcp-factory.hpp"
34#include "face/udp-factory.hpp"
35#ifdef HAVE_UNIX_SOCKETS
36#include "face/unix-stream-factory.hpp"
37#endif // HAVE_UNIX_SOCKETS
38#ifdef HAVE_WEBSOCKET
39#include "face/websocket-factory.hpp"
40#endif // HAVE_WEBSOCKET
41
42#include "tests/test-common.hpp"
43
44namespace nfd {
45namespace face {
46namespace tests {
47
48using namespace nfd::tests;
49
50class FaceSystemFixture : public BaseFixture
51{
52public:
53 FaceSystemFixture()
54 : faceSystem(faceTable)
55 {
56 faceSystem.setConfigFile(configFile);
57 }
58
59 void
60 parseConfig(const std::string& text, bool isDryRun)
61 {
62 configFile.parse(text, isDryRun, "test-config");
63 }
64
65protected:
66 FaceTable faceTable;
67 FaceSystem faceSystem;
68 ConfigFile configFile;
69};
70
71BOOST_AUTO_TEST_SUITE(Face)
72BOOST_FIXTURE_TEST_SUITE(TestFaceSystem, FaceSystemFixture)
73
74#ifdef HAVE_UNIX_SOCKETS
75BOOST_AUTO_TEST_SUITE(ConfigUnix)
76
77BOOST_AUTO_TEST_CASE(Normal)
78{
79 const std::string CONFIG = R"CONFIG(
80 face_system
81 {
82 unix
83 {
84 path /tmp/nfd.sock
85 }
86 }
87 )CONFIG";
88
89 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
90 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
91
92 auto factory = dynamic_cast<UnixStreamFactory*>(faceSystem.getProtocolFactory("unix"));
93 BOOST_REQUIRE(factory != nullptr);
94 BOOST_CHECK_EQUAL(factory->getChannels().size(), 1);
95}
96
97BOOST_AUTO_TEST_CASE(UnknownOption)
98{
99 const std::string CONFIG = R"CONFIG(
100 face_system
101 {
102 unix
103 {
104 hello
105 }
106 }
107 )CONFIG";
108
109 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
110 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
111}
112
113BOOST_AUTO_TEST_SUITE_END() // ConfigUnix
114#endif // HAVE_UNIX_SOCKETS
115
116BOOST_AUTO_TEST_SUITE(ConfigTcp)
117
118BOOST_AUTO_TEST_CASE(Normal)
119{
120 const std::string CONFIG = R"CONFIG(
121 face_system
122 {
123 tcp
124 {
125 listen yes
126 port 16363
127 enable_v4 yes
128 enable_v6 yes
129 }
130 }
131 )CONFIG";
132
133 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
134 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
135
136 auto factory = dynamic_cast<TcpFactory*>(faceSystem.getProtocolFactory("tcp"));
137 BOOST_REQUIRE(factory != nullptr);
138 BOOST_CHECK_EQUAL(factory->getChannels().size(), 2);
139}
140
141BOOST_AUTO_TEST_CASE(BadListen)
142{
143 const std::string CONFIG = R"CONFIG(
144 face_system
145 {
146 tcp
147 {
148 listen hello
149 }
150 }
151 )CONFIG";
152
153 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
154 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
155}
156
157BOOST_AUTO_TEST_CASE(ChannelsDisabled)
158{
159 const std::string CONFIG = R"CONFIG(
160 face_system
161 {
162 tcp
163 {
164 port 6363
165 enable_v4 no
166 enable_v6 no
167 }
168 }
169 )CONFIG";
170
171 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
172 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
173}
174
175BOOST_AUTO_TEST_CASE(UnknownOption)
176{
177 const std::string CONFIG = R"CONFIG(
178 face_system
179 {
180 tcp
181 {
182 hello
183 }
184 }
185 )CONFIG";
186
187 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
188 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
189}
190
191BOOST_AUTO_TEST_SUITE_END() // ConfigTcp
192
193BOOST_AUTO_TEST_SUITE(ConfigUdp)
194
195BOOST_AUTO_TEST_CASE(Normal)
196{
197 SKIP_IF_NOT_SUPERUSER();
198
199 const std::string CONFIG = R"CONFIG(
200 face_system
201 {
202 udp
203 {
204 port 6363
205 enable_v4 yes
206 enable_v6 yes
207 idle_timeout 30
208 keep_alive_interval 25
209 mcast yes
210 mcast_port 56363
211 mcast_group 224.0.23.170
212 }
213 }
214 )CONFIG";
215
216 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
217 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
218
219 auto factory = dynamic_cast<UdpFactory*>(faceSystem.getProtocolFactory("udp"));
220 BOOST_REQUIRE(factory != nullptr);
221 BOOST_CHECK_EQUAL(factory->getChannels().size(), 2);
222}
223
224BOOST_AUTO_TEST_CASE(BadIdleTimeout)
225{
226 const std::string CONFIG = R"CONFIG(
227 face_system
228 {
229 udp
230 {
231 idle_timeout hello
232 }
233 }
234 )CONFIG";
235
236 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
237 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
238}
239
240BOOST_AUTO_TEST_CASE(BadMcast)
241{
242 const std::string CONFIG = R"CONFIG(
243 face_system
244 {
245 udp
246 {
247 mcast hello
248 }
249 }
250 )CONFIG";
251
252 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
253 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
254}
255
256BOOST_AUTO_TEST_CASE(BadMcastGroup)
257{
258 const std::string CONFIG = R"CONFIG(
259 face_system
260 {
261 udp
262 {
263 mcast no
264 mcast_port 50
265 mcast_group hello
266 }
267 }
268 )CONFIG";
269
270 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
271 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
272}
273
274BOOST_AUTO_TEST_CASE(BadMcastGroupV6)
275{
276 const std::string CONFIG = R"CONFIG(
277 face_system
278 {
279 udp
280 {
281 mcast no
282 mcast_port 50
283 mcast_group ::1
284 }
285 }
286 )CONFIG";
287
288 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
289 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
290}
291
292BOOST_AUTO_TEST_CASE(ChannelsDisabled)
293{
294 const std::string CONFIG = R"CONFIG(
295 face_system
296 {
297 udp
298 {
299 port 6363
300 enable_v4 no
301 enable_v6 no
302 idle_timeout 30
303 keep_alive_interval 25
304 mcast yes
305 mcast_port 56363
306 mcast_group 224.0.23.170
307 }
308 }
309 )CONFIG";
310
311 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
312 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
313}
314
315BOOST_AUTO_TEST_CASE(ConflictingMcast)
316{
317 const std::string CONFIG = R"CONFIG(
318 face_system
319 {
320 udp
321 {
322 port 6363
323 enable_v4 no
324 enable_v6 yes
325 idle_timeout 30
326 keep_alive_interval 25
327 mcast yes
328 mcast_port 56363
329 mcast_group 224.0.23.170
330 }
331 }
332 )CONFIG";
333
334 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
335 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
336}
337
338BOOST_AUTO_TEST_CASE(UnknownOption)
339{
340 const std::string CONFIG = R"CONFIG(
341 face_system
342 {
343 udp
344 {
345 hello
346 }
347 }
348 )CONFIG";
349
350 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
351 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
352}
353
354BOOST_AUTO_TEST_CASE(MulticastReinit)
355{
356 SKIP_IF_NOT_SUPERUSER();
357
358 const std::string CONFIG_WITH_MCAST = R"CONFIG(
359 face_system
360 {
361 udp
362 {
363 mcast yes
364 }
365 }
366 )CONFIG";
367
368 BOOST_CHECK_NO_THROW(parseConfig(CONFIG_WITH_MCAST, false));
369
370 auto factory = dynamic_cast<UdpFactory*>(faceSystem.getProtocolFactory("udp"));
371 BOOST_REQUIRE(factory != nullptr);
372
373 if (factory->getMulticastFaces().empty()) {
374 BOOST_WARN_MESSAGE(false, "skipping assertions that require at least one UDP multicast face");
375 return;
376 }
377
378 const std::string CONFIG_WITHOUT_MCAST = R"CONFIG(
379 face_system
380 {
381 udp
382 {
383 mcast no
384 }
385 }
386 )CONFIG";
387
388 BOOST_CHECK_NO_THROW(parseConfig(CONFIG_WITHOUT_MCAST, false));
389 BOOST_REQUIRE_NO_THROW(g_io.poll());
390 BOOST_CHECK_EQUAL(factory->getMulticastFaces().size(), 0);
391}
392BOOST_AUTO_TEST_SUITE_END() // ConfigUdp
393
394#ifdef HAVE_LIBPCAP
395BOOST_AUTO_TEST_SUITE(ConfigEther)
396
397BOOST_AUTO_TEST_CASE(Normal)
398{
399 SKIP_IF_NOT_SUPERUSER();
400
401 const std::string CONFIG = R"CONFIG(
402 face_system
403 {
404 ether
405 {
406 mcast yes
407 mcast_group 01:00:5E:00:17:AA
408 whitelist
409 {
410 *
411 }
412 blacklist
413 {
414 }
415 }
416 }
417 )CONFIG";
418
419 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
420 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
421
422 auto factory = dynamic_cast<EthernetFactory*>(faceSystem.getProtocolFactory("ether"));
423 BOOST_REQUIRE(factory != nullptr);
424 BOOST_CHECK_EQUAL(factory->getChannels().size(), 0);
425}
426
427BOOST_AUTO_TEST_CASE(BadMcast)
428{
429 const std::string CONFIG = R"CONFIG(
430 face_system
431 {
432 ether
433 {
434 mcast hello
435 }
436 }
437 )CONFIG";
438
439 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
440 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
441}
442
443BOOST_AUTO_TEST_CASE(BadMcastGroup)
444{
445 const std::string CONFIG = R"CONFIG(
446 face_system
447 {
448 ether
449 {
450 mcast yes
451 mcast_group
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(UnknownOption)
461{
462 const std::string CONFIG = R"CONFIG(
463 face_system
464 {
465 ether
466 {
467 hello
468 }
469 }
470 )CONFIG";
471
472 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
473 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
474}
475
476BOOST_AUTO_TEST_CASE(MulticastReinit)
477{
478 SKIP_IF_NOT_SUPERUSER();
479
480 const std::string CONFIG_WITH_MCAST = R"CONFIG(
481 face_system
482 {
483 ether
484 {
485 mcast yes
486 }
487 }
488 )CONFIG";
489
490 BOOST_CHECK_NO_THROW(parseConfig(CONFIG_WITH_MCAST, false));
491
492 auto factory = dynamic_cast<EthernetFactory*>(faceSystem.getProtocolFactory("ether"));
493 BOOST_REQUIRE(factory != nullptr);
494
495 if (factory->getMulticastFaces().empty()) {
496 BOOST_WARN_MESSAGE(false, "skipping assertions that require at least one Ethernet multicast face");
497 return;
498 }
499
500 const std::string CONFIG_WITHOUT_MCAST = R"CONFIG(
501 face_system
502 {
503 ether
504 {
505 mcast no
506 }
507 }
508 )CONFIG";
509
510 BOOST_CHECK_NO_THROW(parseConfig(CONFIG_WITHOUT_MCAST, false));
511 BOOST_REQUIRE_NO_THROW(g_io.poll());
512 BOOST_CHECK_EQUAL(factory->getMulticastFaces().size(), 0);
513}
514
515BOOST_AUTO_TEST_SUITE_END() // ConfigEther
516#endif // HAVE_LIBPCAP
517
518#ifdef HAVE_WEBSOCKET
519BOOST_AUTO_TEST_SUITE(ConfigWebSocket)
520
521BOOST_AUTO_TEST_CASE(Normal)
522{
523 const std::string CONFIG = R"CONFIG(
524 face_system
525 {
526 websocket
527 {
528 listen yes
529 port 9696
530 enable_v4 yes
531 enable_v6 yes
532 }
533 }
534 )CONFIG";
535
536 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
537 BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
538
539 auto factory = dynamic_cast<WebSocketFactory*>(faceSystem.getProtocolFactory("websocket"));
540 BOOST_REQUIRE(factory != nullptr);
541 BOOST_CHECK_EQUAL(factory->getChannels().size(), 1);
542}
543
544BOOST_AUTO_TEST_CASE(ChannelsDisabled)
545{
546 const std::string CONFIG = R"CONFIG(
547 face_system
548 {
549 websocket
550 {
551 listen yes
552 port 9696
553 enable_v4 no
554 enable_v6 no
555 }
556 }
557 )CONFIG";
558
559 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
560 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
561}
562
563BOOST_AUTO_TEST_CASE(Ipv4ChannelDisabled)
564{
565 const std::string CONFIG = R"CONFIG(
566 face_system
567 {
568 websocket
569 {
570 listen yes
571 port 9696
572 enable_v4 no
573 enable_v6 yes
574 }
575 }
576 )CONFIG";
577
578 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
579 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
580}
581
582BOOST_AUTO_TEST_SUITE_END() // ConfigWebSocket
583#endif // HAVE_WEBSOCKET
584
585BOOST_AUTO_TEST_SUITE_END() // TestFaceSystem
586BOOST_AUTO_TEST_SUITE_END() // Mgmt
587
588} // namespace tests
589} // namespace face
590} // namespace nfd