blob: e1c73331d9d85542b4848137a898bd323635388d [file] [log] [blame]
Steve DiBenedettobb75b552014-02-08 12:12:11 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesaventoa997d292017-08-24 20:16:59 -04002/*
Junxiao Shia6286a92021-02-23 06:43:52 -07003 * Copyright (c) 2014-2021, Regents of the University of California,
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -08004 * 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.
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -070010 *
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/>.
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -080024 */
Steve DiBenedettobb75b552014-02-08 12:12:11 -070025
Davide Pesavento2cae8ca2019-04-18 20:48:05 -040026#include "common/config-file.hpp"
Steve DiBenedettobb75b552014-02-08 12:12:11 -070027
Junxiao Shid9ee45c2014-02-27 15:38:11 -070028#include "tests/test-common.hpp"
Steve DiBenedettobb75b552014-02-08 12:12:11 -070029
Alexander Afanasyevc0273e32015-01-06 13:05:50 -080030#include <boost/property_tree/info_parser.hpp>
Davide Pesaventoa997d292017-08-24 20:16:59 -040031#include <fstream>
32#include <sstream>
Davide Pesavento52a18f92014-04-10 00:55:01 +020033
Steve DiBenedettobb75b552014-02-08 12:12:11 -070034namespace nfd {
Junxiao Shid9ee45c2014-02-27 15:38:11 -070035namespace tests {
Steve DiBenedettobb75b552014-02-08 12:12:11 -070036
Davide Pesaventocf7db2f2019-03-24 23:17:28 -040037BOOST_AUTO_TEST_SUITE(TestConfigFile)
Steve DiBenedettobb75b552014-02-08 12:12:11 -070038
Davide Pesavento85244372018-02-03 19:10:55 -050039static const std::string CONFIG = R"CONFIG(
40 a
41 {
42 akey avalue
43 }
44 b
45 {
46 bkey bvalue
47 }
48)CONFIG";
Steve DiBenedettobb75b552014-02-08 12:12:11 -070049
50// counts of the respective section counts in config_example.info
Steve DiBenedettobb75b552014-02-08 12:12:11 -070051const int CONFIG_N_A_SECTIONS = 1;
52const int CONFIG_N_B_SECTIONS = 1;
53
54class DummySubscriber
55{
56public:
Davide Pesavento97210d52016-10-14 15:45:48 +020057 DummySubscriber(ConfigFile& config, int nASections, int nBSections, bool expectDryRun)
58 : m_nASections(nASections)
59 , m_nBSections(nBSections)
60 , m_nRemainingACallbacks(nASections)
61 , m_nRemainingBCallbacks(nBSections)
62 , m_expectDryRun(expectDryRun)
Steve DiBenedettobb75b552014-02-08 12:12:11 -070063 {
Steve DiBenedettobb75b552014-02-08 12:12:11 -070064 }
65
66 void
67 onA(const ConfigSection& section, bool isDryRun)
68 {
Steve DiBenedettobb75b552014-02-08 12:12:11 -070069 BOOST_CHECK_EQUAL(isDryRun, m_expectDryRun);
70 --m_nRemainingACallbacks;
71 }
72
Steve DiBenedettobb75b552014-02-08 12:12:11 -070073 void
74 onB(const ConfigSection& section, bool isDryRun)
75 {
Steve DiBenedettobb75b552014-02-08 12:12:11 -070076 BOOST_CHECK_EQUAL(isDryRun, m_expectDryRun);
77 --m_nRemainingBCallbacks;
78 }
79
80 bool
81 allCallbacksFired() const
82 {
83 return m_nRemainingACallbacks == 0 &&
84 m_nRemainingBCallbacks == 0;
85 }
86
87 bool
88 noCallbacksFired() const
89 {
90 return m_nRemainingACallbacks == m_nASections &&
91 m_nRemainingBCallbacks == m_nBSections;
92 }
93
Steve DiBenedettobb75b552014-02-08 12:12:11 -070094private:
95 int m_nASections;
96 int m_nBSections;
97 int m_nRemainingACallbacks;
98 int m_nRemainingBCallbacks;
99 bool m_expectDryRun;
100};
101
102class DummyAllSubscriber : public DummySubscriber
103{
104public:
Davide Pesavento85244372018-02-03 19:10:55 -0500105 explicit
Davide Pesavento97210d52016-10-14 15:45:48 +0200106 DummyAllSubscriber(ConfigFile& config, bool expectDryRun = false)
Davide Pesavento85244372018-02-03 19:10:55 -0500107 : DummySubscriber(config, CONFIG_N_A_SECTIONS, CONFIG_N_B_SECTIONS, expectDryRun)
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700108 {
Davide Pesavento412c9822021-07-02 00:21:05 -0400109 config.addSectionHandler("a", std::bind(&DummySubscriber::onA, this, _1, _2));
110 config.addSectionHandler("b", std::bind(&DummySubscriber::onB, this, _1, _2));
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700111 }
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700112};
113
114class DummyOneSubscriber : public DummySubscriber
115{
116public:
Davide Pesavento85244372018-02-03 19:10:55 -0500117 DummyOneSubscriber(ConfigFile& config, const std::string& sectionName, bool expectDryRun = false)
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700118 : DummySubscriber(config,
119 (sectionName == "a"),
120 (sectionName == "b"),
121 expectDryRun)
122 {
Davide Pesavento85244372018-02-03 19:10:55 -0500123 if (sectionName == "a") {
Davide Pesavento412c9822021-07-02 00:21:05 -0400124 config.addSectionHandler(sectionName, std::bind(&DummySubscriber::onA, this, _1, _2));
Davide Pesavento85244372018-02-03 19:10:55 -0500125 }
126 else if (sectionName == "b") {
Davide Pesavento412c9822021-07-02 00:21:05 -0400127 config.addSectionHandler(sectionName, std::bind(&DummySubscriber::onB, this, _1, _2));
Davide Pesavento85244372018-02-03 19:10:55 -0500128 }
129 else {
130 BOOST_FAIL("Test setup error: Unexpected section name '" << sectionName << "'");
131 }
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700132 }
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700133};
134
135class DummyNoSubscriber : public DummySubscriber
136{
137public:
138 DummyNoSubscriber(ConfigFile& config, bool expectDryRun)
139 : DummySubscriber(config, 0, 0, expectDryRun)
140 {
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700141 }
142};
143
Davide Pesavento85244372018-02-03 19:10:55 -0500144BOOST_AUTO_TEST_CASE(ParseFromStream)
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700145{
146 ConfigFile file;
147 DummyAllSubscriber sub(file);
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700148
Davide Pesavento2cae8ca2019-04-18 20:48:05 -0400149 std::ifstream input("tests/daemon/common/config_example.info");
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700150 BOOST_REQUIRE(input.is_open());
151
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600152 file.parse(input, false, "config_example.info");
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700153 BOOST_CHECK(sub.allCallbacksFired());
154}
155
Davide Pesavento85244372018-02-03 19:10:55 -0500156BOOST_AUTO_TEST_CASE(ParseFromEmptyStream)
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700157{
158 ConfigFile file;
159 DummyAllSubscriber sub(file);
160
Davide Pesavento85244372018-02-03 19:10:55 -0500161 std::istringstream input;
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700162
Davide Pesavento85244372018-02-03 19:10:55 -0500163 file.parse(input, false, "empty");
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700164 BOOST_CHECK(sub.noCallbacksFired());
165}
166
Davide Pesavento85244372018-02-03 19:10:55 -0500167BOOST_AUTO_TEST_CASE(ParseFromStreamDryRun)
168{
169 ConfigFile file;
170 DummyAllSubscriber sub(file, true);
171
Davide Pesavento2cae8ca2019-04-18 20:48:05 -0400172 std::ifstream input("tests/daemon/common/config_example.info");
Davide Pesavento85244372018-02-03 19:10:55 -0500173 BOOST_REQUIRE(input.is_open());
174
Davide Pesavento2cae8ca2019-04-18 20:48:05 -0400175 file.parse(input, true, "tests/daemon/common/config_example.info");
Davide Pesavento85244372018-02-03 19:10:55 -0500176 BOOST_CHECK(sub.allCallbacksFired());
177}
178
179BOOST_AUTO_TEST_CASE(ParseFromConfigSection)
Alexander Afanasyevc0273e32015-01-06 13:05:50 -0800180{
181 ConfigFile file;
182 DummyAllSubscriber sub(file);
183
184 std::istringstream input(CONFIG);
185 ConfigSection section;
186 boost::property_tree::read_info(input, section);
187
188 file.parse(section, false, "dummy-config");
189 BOOST_CHECK(sub.allCallbacksFired());
190}
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700191
Davide Pesavento85244372018-02-03 19:10:55 -0500192BOOST_AUTO_TEST_CASE(ParseFromString)
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700193{
194 ConfigFile file;
195 DummyAllSubscriber sub(file);
196
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600197 file.parse(CONFIG, false, "dummy-config");
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700198 BOOST_CHECK(sub.allCallbacksFired());
199}
200
Davide Pesavento85244372018-02-03 19:10:55 -0500201BOOST_AUTO_TEST_CASE(ParseFromEmptyString)
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700202{
203 ConfigFile file;
204 DummyAllSubscriber sub(file);
205
Davide Pesavento85244372018-02-03 19:10:55 -0500206 file.parse("", false, "empty");
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700207 BOOST_CHECK(sub.noCallbacksFired());
208}
209
Davide Pesavento85244372018-02-03 19:10:55 -0500210BOOST_AUTO_TEST_CASE(ParseFromMalformedString)
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700211{
212 ConfigFile file;
213 DummyAllSubscriber sub(file);
214
Davide Pesavento85244372018-02-03 19:10:55 -0500215 const std::string malformed = R"CONFIG(
216 a
217 {
218 akey avalue
219 }
220 b
221 bkey bvalue
222 }
223 )CONFIG";
224
225 BOOST_CHECK_THROW(file.parse(malformed, false, "dummy-config"), ConfigFile::Error);
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700226 BOOST_CHECK(sub.noCallbacksFired());
227}
228
Davide Pesavento85244372018-02-03 19:10:55 -0500229BOOST_AUTO_TEST_CASE(ParseFromStringDryRun)
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700230{
231 ConfigFile file;
232 DummyAllSubscriber sub(file, true);
233
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600234 file.parse(CONFIG, true, "dummy-config");
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700235 BOOST_CHECK(sub.allCallbacksFired());
236}
237
Davide Pesavento85244372018-02-03 19:10:55 -0500238BOOST_AUTO_TEST_CASE(ParseFromFilename)
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700239{
240 ConfigFile file;
241 DummyAllSubscriber sub(file);
242
Davide Pesavento2cae8ca2019-04-18 20:48:05 -0400243 file.parse("tests/daemon/common/config_example.info", false);
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700244 BOOST_CHECK(sub.allCallbacksFired());
245}
246
Davide Pesavento85244372018-02-03 19:10:55 -0500247BOOST_AUTO_TEST_CASE(ParseFromFilenameNonExistent)
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700248{
249 ConfigFile file;
250 DummyAllSubscriber sub(file);
251
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600252 BOOST_CHECK_THROW(file.parse("i_made_this_up.info", false), ConfigFile::Error);
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700253 BOOST_CHECK(sub.noCallbacksFired());
254}
255
Davide Pesavento85244372018-02-03 19:10:55 -0500256BOOST_AUTO_TEST_CASE(ParseFromFilenameMalformed)
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700257{
258 ConfigFile file;
259 DummyAllSubscriber sub(file);
260
Davide Pesavento2cae8ca2019-04-18 20:48:05 -0400261 BOOST_CHECK_THROW(file.parse("tests/daemon/common/config_malformed.info", false), ConfigFile::Error);
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700262 BOOST_CHECK(sub.noCallbacksFired());
263}
264
Davide Pesavento85244372018-02-03 19:10:55 -0500265BOOST_AUTO_TEST_CASE(ParseFromFilenameDryRun)
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700266{
267 ConfigFile file;
268 DummyAllSubscriber sub(file, true);
269
Davide Pesavento2cae8ca2019-04-18 20:48:05 -0400270 file.parse("tests/daemon/common/config_example.info", true);
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700271 BOOST_CHECK(sub.allCallbacksFired());
272}
273
Davide Pesavento85244372018-02-03 19:10:55 -0500274BOOST_AUTO_TEST_CASE(ReplaceSubscriber)
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700275{
276 ConfigFile file;
277 DummyAllSubscriber sub1(file);
278 DummyAllSubscriber sub2(file);
279
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600280 file.parse(CONFIG, false, "dummy-config");
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700281
282 BOOST_CHECK(sub1.noCallbacksFired());
283 BOOST_CHECK(sub2.allCallbacksFired());
284}
285
Davide Pesaventocf7db2f2019-03-24 23:17:28 -0400286class MissingCallbackFixture
Steve DiBenedetto34c95f72014-04-17 20:56:00 -0600287{
288public:
Steve DiBenedetto34c95f72014-04-17 20:56:00 -0600289 void
290 checkMissingHandler(const std::string& filename,
291 const std::string& sectionName,
292 const ConfigSection& section,
293 bool isDryRun)
294 {
295 m_missingFired = true;
296 }
297
298protected:
Davide Pesavento85244372018-02-03 19:10:55 -0500299 bool m_missingFired = false;
Steve DiBenedetto34c95f72014-04-17 20:56:00 -0600300};
301
Davide Pesavento85244372018-02-03 19:10:55 -0500302BOOST_FIXTURE_TEST_CASE(UncoveredSections, MissingCallbackFixture)
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700303{
304 ConfigFile file;
Steve DiBenedetto34c95f72014-04-17 20:56:00 -0600305 BOOST_REQUIRE_THROW(file.parse(CONFIG, false, "dummy-config"), ConfigFile::Error);
306
Davide Pesavento412c9822021-07-02 00:21:05 -0400307 ConfigFile permissiveFile(std::bind(&MissingCallbackFixture::checkMissingHandler,
308 this, _1, _2, _3, _4));
Steve DiBenedetto34c95f72014-04-17 20:56:00 -0600309 DummyOneSubscriber subA(permissiveFile, "a");
310
311 BOOST_REQUIRE_NO_THROW(permissiveFile.parse(CONFIG, false, "dummy-config"));
312 BOOST_CHECK(subA.allCallbacksFired());
313 BOOST_CHECK(m_missingFired);
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700314}
315
Davide Pesavento85244372018-02-03 19:10:55 -0500316BOOST_AUTO_TEST_CASE(CoveredByPartialSubscribers)
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700317{
318 ConfigFile file;
319 DummyOneSubscriber subA(file, "a");
320 DummyOneSubscriber subB(file, "b");
321
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600322 file.parse(CONFIG, false, "dummy-config");
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700323
324 BOOST_CHECK(subA.allCallbacksFired());
325 BOOST_CHECK(subB.allCallbacksFired());
326}
327
Eric Newberrycb27d912020-04-08 19:38:18 -0700328BOOST_AUTO_TEST_CASE(ParseNumber)
329{
330 std::istringstream input(R"CONFIG(
331 a -125
332 b 156
333 c 100000
334 d efg
335 e 123.456e-10
336 f 123abc
337 g ""
338 h " -1"
339 )CONFIG");
340 ConfigSection section;
341 boost::property_tree::read_info(input, section);
342
343 // Read various types and ensure they return the correct value
344 BOOST_CHECK_EQUAL(ConfigFile::parseNumber<short>(section.get_child("a"), "a", "section"), -125);
345 BOOST_CHECK_EQUAL(ConfigFile::parseNumber<int>(section.get_child("a"), "a", "section"), -125);
346 BOOST_CHECK_EQUAL(ConfigFile::parseNumber<long>(section.get_child("a"), "a", "section"), -125);
347 BOOST_CHECK_EQUAL(ConfigFile::parseNumber<double>(section.get_child("a"), "a", "section"), -125.0);
348 BOOST_CHECK_EQUAL(ConfigFile::parseNumber<float>(section.get_child("a"), "a", "section"), -125.0);
349 BOOST_CHECK_EQUAL(ConfigFile::parseNumber<short>(section.get_child("b"), "b", "section"), 156);
350 BOOST_CHECK_EQUAL(ConfigFile::parseNumber<int>(section.get_child("b"), "b", "section"), 156);
351 BOOST_CHECK_EQUAL(ConfigFile::parseNumber<long>(section.get_child("b"), "b", "section"), 156);
352 BOOST_CHECK_CLOSE(ConfigFile::parseNumber<double>(section.get_child("e"), "e", "section"), 123.456e-10, 0.0001);
353 BOOST_CHECK_CLOSE(ConfigFile::parseNumber<float>(section.get_child("e"), "e", "section"), 123.456e-10, 0.0001);
354 BOOST_CHECK_EQUAL(ConfigFile::parseNumber<int>(section.get_child("h"), "h", "section"), -1);
355
356 // Check throw on out of range
357 BOOST_CHECK_THROW(ConfigFile::parseNumber<int16_t>(section.get_child("c"), "c", "section"),
358 ConfigFile::Error);
359
360 // Check throw on non-integer for integer types
361 BOOST_CHECK_THROW(ConfigFile::parseNumber<int>(section.get_child("d"), "d", "section"),
362 ConfigFile::Error);
363 BOOST_CHECK_THROW(ConfigFile::parseNumber<int>(section.get_child("e"), "e", "section"),
364 ConfigFile::Error);
365 BOOST_CHECK_THROW(ConfigFile::parseNumber<int>(section.get_child("f"), "f", "section"),
366 ConfigFile::Error);
367 BOOST_CHECK_THROW(ConfigFile::parseNumber<int>(section.get_child("g"), "g", "section"),
368 ConfigFile::Error);
369
370 // Should throw exception if try to read unsigned from negative value
371 BOOST_CHECK_THROW(ConfigFile::parseNumber<uint16_t>(section.get_child("a"), "a", "section"),
372 ConfigFile::Error);
373 BOOST_CHECK_EQUAL(ConfigFile::parseNumber<uint16_t>(section.get_child("b"), "b", "section"), 156);
374 BOOST_CHECK_THROW(ConfigFile::parseNumber<uint32_t>(section.get_child("h"), "h", "section"),
375 ConfigFile::Error);
376}
377
Junxiao Shia6286a92021-02-23 06:43:52 -0700378BOOST_AUTO_TEST_CASE(CheckRange)
379{
380 {
381 uint32_t value = 8000;
382 uint32_t min = 8000;
383 uint32_t max = 8999;
384 ConfigFile::checkRange(value, min, max, "key", "section");
385 }
386
387 {
388 size_t value = 8999;
389 size_t min = 8000;
390 size_t max = 8999;
391 ConfigFile::checkRange(value, min, max, "key", "section");
392 }
393
394 {
395 int64_t value = -7000;
396 int64_t min = -7999;
397 int64_t max = 1000;
398 ConfigFile::checkRange(value, min, max, "key", "section");
399 }
400
401 {
402 uint32_t value = 7999;
403 uint32_t min = 8000;
404 uint32_t max = 8999;
405 BOOST_CHECK_THROW(ConfigFile::checkRange(value, min, max, "key", "section"), ConfigFile::Error);
406 }
407
408 {
409 int16_t value = 9000;
410 int16_t min = 8000;
411 int16_t max = 8999;
412 BOOST_CHECK_THROW(ConfigFile::checkRange(value, min, max, "key", "section"), ConfigFile::Error);
413 }
414
415 {
416 int32_t value = -8000;
417 int32_t min = -7999;
418 int32_t max = 1000;
419 BOOST_CHECK_THROW(ConfigFile::checkRange(value, min, max, "key", "section"), ConfigFile::Error);
420 }
421
422 {
423 int64_t value = 0x1001;
424 int64_t min = -0x7fff;
425 int64_t max = 0x1000;
426 BOOST_CHECK_THROW(ConfigFile::checkRange(value, min, max, "key", "section"), ConfigFile::Error);
427 }
428}
429
Davide Pesavento14e71f02019-03-28 17:35:25 -0400430BOOST_AUTO_TEST_SUITE_END() // TestConfigFile
Junxiao Shid9ee45c2014-02-27 15:38:11 -0700431
432} // namespace tests
433} // namespace nfd