blob: 6616d3ce053a2a764b69a4bd6c4ffbc9fae81386 [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/*
Davide Pesaventoe422f9e2022-06-03 01:30:23 -04003 * Copyright (c) 2014-2022, 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
Davide Pesaventoe422f9e2022-06-03 01:30:23 -040034namespace nfd::tests {
Steve DiBenedettobb75b552014-02-08 12:12:11 -070035
Davide Pesaventocf7db2f2019-03-24 23:17:28 -040036BOOST_AUTO_TEST_SUITE(TestConfigFile)
Steve DiBenedettobb75b552014-02-08 12:12:11 -070037
Davide Pesavento20d94f62022-09-26 03:30:53 -040038const std::string CONFIG = R"CONFIG(
Davide Pesavento85244372018-02-03 19:10:55 -050039 a
40 {
41 akey avalue
42 }
43 b
44 {
45 bkey bvalue
46 }
47)CONFIG";
Steve DiBenedettobb75b552014-02-08 12:12:11 -070048
49// counts of the respective section counts in config_example.info
Davide Pesavento20d94f62022-09-26 03:30:53 -040050constexpr int CONFIG_N_A_SECTIONS = 1;
51constexpr int CONFIG_N_B_SECTIONS = 1;
Steve DiBenedettobb75b552014-02-08 12:12:11 -070052
53class DummySubscriber
54{
55public:
Davide Pesavento97210d52016-10-14 15:45:48 +020056 DummySubscriber(ConfigFile& config, int nASections, int nBSections, bool expectDryRun)
57 : m_nASections(nASections)
58 , m_nBSections(nBSections)
59 , m_nRemainingACallbacks(nASections)
60 , m_nRemainingBCallbacks(nBSections)
61 , m_expectDryRun(expectDryRun)
Steve DiBenedettobb75b552014-02-08 12:12:11 -070062 {
Steve DiBenedettobb75b552014-02-08 12:12:11 -070063 }
64
65 void
66 onA(const ConfigSection& section, bool isDryRun)
67 {
Steve DiBenedettobb75b552014-02-08 12:12:11 -070068 BOOST_CHECK_EQUAL(isDryRun, m_expectDryRun);
69 --m_nRemainingACallbacks;
70 }
71
Steve DiBenedettobb75b552014-02-08 12:12:11 -070072 void
73 onB(const ConfigSection& section, bool isDryRun)
74 {
Steve DiBenedettobb75b552014-02-08 12:12:11 -070075 BOOST_CHECK_EQUAL(isDryRun, m_expectDryRun);
76 --m_nRemainingBCallbacks;
77 }
78
79 bool
80 allCallbacksFired() const
81 {
82 return m_nRemainingACallbacks == 0 &&
83 m_nRemainingBCallbacks == 0;
84 }
85
86 bool
87 noCallbacksFired() const
88 {
89 return m_nRemainingACallbacks == m_nASections &&
90 m_nRemainingBCallbacks == m_nBSections;
91 }
92
Steve DiBenedettobb75b552014-02-08 12:12:11 -070093private:
94 int m_nASections;
95 int m_nBSections;
96 int m_nRemainingACallbacks;
97 int m_nRemainingBCallbacks;
98 bool m_expectDryRun;
99};
100
101class DummyAllSubscriber : public DummySubscriber
102{
103public:
Davide Pesavento85244372018-02-03 19:10:55 -0500104 explicit
Davide Pesavento97210d52016-10-14 15:45:48 +0200105 DummyAllSubscriber(ConfigFile& config, bool expectDryRun = false)
Davide Pesavento85244372018-02-03 19:10:55 -0500106 : DummySubscriber(config, CONFIG_N_A_SECTIONS, CONFIG_N_B_SECTIONS, expectDryRun)
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700107 {
Davide Pesavento412c9822021-07-02 00:21:05 -0400108 config.addSectionHandler("a", std::bind(&DummySubscriber::onA, this, _1, _2));
109 config.addSectionHandler("b", std::bind(&DummySubscriber::onB, this, _1, _2));
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700110 }
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700111};
112
113class DummyOneSubscriber : public DummySubscriber
114{
115public:
Davide Pesavento85244372018-02-03 19:10:55 -0500116 DummyOneSubscriber(ConfigFile& config, const std::string& sectionName, bool expectDryRun = false)
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700117 : DummySubscriber(config,
118 (sectionName == "a"),
119 (sectionName == "b"),
120 expectDryRun)
121 {
Davide Pesavento85244372018-02-03 19:10:55 -0500122 if (sectionName == "a") {
Davide Pesavento412c9822021-07-02 00:21:05 -0400123 config.addSectionHandler(sectionName, std::bind(&DummySubscriber::onA, this, _1, _2));
Davide Pesavento85244372018-02-03 19:10:55 -0500124 }
125 else if (sectionName == "b") {
Davide Pesavento412c9822021-07-02 00:21:05 -0400126 config.addSectionHandler(sectionName, std::bind(&DummySubscriber::onB, this, _1, _2));
Davide Pesavento85244372018-02-03 19:10:55 -0500127 }
128 else {
129 BOOST_FAIL("Test setup error: Unexpected section name '" << sectionName << "'");
130 }
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700131 }
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700132};
133
134class DummyNoSubscriber : public DummySubscriber
135{
136public:
137 DummyNoSubscriber(ConfigFile& config, bool expectDryRun)
138 : DummySubscriber(config, 0, 0, expectDryRun)
139 {
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700140 }
141};
142
Davide Pesavento85244372018-02-03 19:10:55 -0500143BOOST_AUTO_TEST_CASE(ParseFromStream)
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700144{
145 ConfigFile file;
146 DummyAllSubscriber sub(file);
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700147
Davide Pesavento2cae8ca2019-04-18 20:48:05 -0400148 std::ifstream input("tests/daemon/common/config_example.info");
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700149 BOOST_REQUIRE(input.is_open());
150
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600151 file.parse(input, false, "config_example.info");
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700152 BOOST_CHECK(sub.allCallbacksFired());
153}
154
Davide Pesavento85244372018-02-03 19:10:55 -0500155BOOST_AUTO_TEST_CASE(ParseFromEmptyStream)
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700156{
157 ConfigFile file;
158 DummyAllSubscriber sub(file);
159
Davide Pesavento85244372018-02-03 19:10:55 -0500160 std::istringstream input;
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700161
Davide Pesavento85244372018-02-03 19:10:55 -0500162 file.parse(input, false, "empty");
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700163 BOOST_CHECK(sub.noCallbacksFired());
164}
165
Davide Pesavento85244372018-02-03 19:10:55 -0500166BOOST_AUTO_TEST_CASE(ParseFromStreamDryRun)
167{
168 ConfigFile file;
169 DummyAllSubscriber sub(file, true);
170
Davide Pesavento2cae8ca2019-04-18 20:48:05 -0400171 std::ifstream input("tests/daemon/common/config_example.info");
Davide Pesavento85244372018-02-03 19:10:55 -0500172 BOOST_REQUIRE(input.is_open());
173
Davide Pesavento2cae8ca2019-04-18 20:48:05 -0400174 file.parse(input, true, "tests/daemon/common/config_example.info");
Davide Pesavento85244372018-02-03 19:10:55 -0500175 BOOST_CHECK(sub.allCallbacksFired());
176}
177
178BOOST_AUTO_TEST_CASE(ParseFromConfigSection)
Alexander Afanasyevc0273e32015-01-06 13:05:50 -0800179{
180 ConfigFile file;
181 DummyAllSubscriber sub(file);
182
183 std::istringstream input(CONFIG);
184 ConfigSection section;
185 boost::property_tree::read_info(input, section);
186
187 file.parse(section, false, "dummy-config");
188 BOOST_CHECK(sub.allCallbacksFired());
189}
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700190
Davide Pesavento85244372018-02-03 19:10:55 -0500191BOOST_AUTO_TEST_CASE(ParseFromString)
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700192{
193 ConfigFile file;
194 DummyAllSubscriber sub(file);
195
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600196 file.parse(CONFIG, false, "dummy-config");
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700197 BOOST_CHECK(sub.allCallbacksFired());
198}
199
Davide Pesavento85244372018-02-03 19:10:55 -0500200BOOST_AUTO_TEST_CASE(ParseFromEmptyString)
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700201{
202 ConfigFile file;
203 DummyAllSubscriber sub(file);
204
Davide Pesavento85244372018-02-03 19:10:55 -0500205 file.parse("", false, "empty");
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700206 BOOST_CHECK(sub.noCallbacksFired());
207}
208
Davide Pesavento85244372018-02-03 19:10:55 -0500209BOOST_AUTO_TEST_CASE(ParseFromMalformedString)
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700210{
211 ConfigFile file;
212 DummyAllSubscriber sub(file);
213
Davide Pesavento85244372018-02-03 19:10:55 -0500214 const std::string malformed = R"CONFIG(
215 a
216 {
217 akey avalue
218 }
219 b
220 bkey bvalue
221 }
222 )CONFIG";
223
224 BOOST_CHECK_THROW(file.parse(malformed, false, "dummy-config"), ConfigFile::Error);
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700225 BOOST_CHECK(sub.noCallbacksFired());
226}
227
Davide Pesavento85244372018-02-03 19:10:55 -0500228BOOST_AUTO_TEST_CASE(ParseFromStringDryRun)
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700229{
230 ConfigFile file;
231 DummyAllSubscriber sub(file, true);
232
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600233 file.parse(CONFIG, true, "dummy-config");
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700234 BOOST_CHECK(sub.allCallbacksFired());
235}
236
Davide Pesavento85244372018-02-03 19:10:55 -0500237BOOST_AUTO_TEST_CASE(ParseFromFilename)
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700238{
239 ConfigFile file;
240 DummyAllSubscriber sub(file);
241
Davide Pesavento2cae8ca2019-04-18 20:48:05 -0400242 file.parse("tests/daemon/common/config_example.info", false);
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700243 BOOST_CHECK(sub.allCallbacksFired());
244}
245
Davide Pesavento85244372018-02-03 19:10:55 -0500246BOOST_AUTO_TEST_CASE(ParseFromFilenameNonExistent)
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700247{
248 ConfigFile file;
249 DummyAllSubscriber sub(file);
250
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600251 BOOST_CHECK_THROW(file.parse("i_made_this_up.info", false), ConfigFile::Error);
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700252 BOOST_CHECK(sub.noCallbacksFired());
253}
254
Davide Pesavento85244372018-02-03 19:10:55 -0500255BOOST_AUTO_TEST_CASE(ParseFromFilenameMalformed)
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700256{
257 ConfigFile file;
258 DummyAllSubscriber sub(file);
259
Davide Pesavento2cae8ca2019-04-18 20:48:05 -0400260 BOOST_CHECK_THROW(file.parse("tests/daemon/common/config_malformed.info", false), ConfigFile::Error);
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700261 BOOST_CHECK(sub.noCallbacksFired());
262}
263
Davide Pesavento85244372018-02-03 19:10:55 -0500264BOOST_AUTO_TEST_CASE(ParseFromFilenameDryRun)
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700265{
266 ConfigFile file;
267 DummyAllSubscriber sub(file, true);
268
Davide Pesavento2cae8ca2019-04-18 20:48:05 -0400269 file.parse("tests/daemon/common/config_example.info", true);
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700270 BOOST_CHECK(sub.allCallbacksFired());
271}
272
Davide Pesavento85244372018-02-03 19:10:55 -0500273BOOST_AUTO_TEST_CASE(ReplaceSubscriber)
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700274{
275 ConfigFile file;
276 DummyAllSubscriber sub1(file);
277 DummyAllSubscriber sub2(file);
278
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600279 file.parse(CONFIG, false, "dummy-config");
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700280
281 BOOST_CHECK(sub1.noCallbacksFired());
282 BOOST_CHECK(sub2.allCallbacksFired());
283}
284
Davide Pesaventocf7db2f2019-03-24 23:17:28 -0400285class MissingCallbackFixture
Steve DiBenedetto34c95f72014-04-17 20:56:00 -0600286{
287public:
Steve DiBenedetto34c95f72014-04-17 20:56:00 -0600288 void
289 checkMissingHandler(const std::string& filename,
290 const std::string& sectionName,
291 const ConfigSection& section,
292 bool isDryRun)
293 {
294 m_missingFired = true;
295 }
296
297protected:
Davide Pesavento85244372018-02-03 19:10:55 -0500298 bool m_missingFired = false;
Steve DiBenedetto34c95f72014-04-17 20:56:00 -0600299};
300
Davide Pesavento85244372018-02-03 19:10:55 -0500301BOOST_FIXTURE_TEST_CASE(UncoveredSections, MissingCallbackFixture)
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700302{
303 ConfigFile file;
Steve DiBenedetto34c95f72014-04-17 20:56:00 -0600304 BOOST_REQUIRE_THROW(file.parse(CONFIG, false, "dummy-config"), ConfigFile::Error);
305
Davide Pesavento412c9822021-07-02 00:21:05 -0400306 ConfigFile permissiveFile(std::bind(&MissingCallbackFixture::checkMissingHandler,
307 this, _1, _2, _3, _4));
Steve DiBenedetto34c95f72014-04-17 20:56:00 -0600308 DummyOneSubscriber subA(permissiveFile, "a");
309
310 BOOST_REQUIRE_NO_THROW(permissiveFile.parse(CONFIG, false, "dummy-config"));
311 BOOST_CHECK(subA.allCallbacksFired());
312 BOOST_CHECK(m_missingFired);
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700313}
314
Davide Pesavento85244372018-02-03 19:10:55 -0500315BOOST_AUTO_TEST_CASE(CoveredByPartialSubscribers)
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700316{
317 ConfigFile file;
318 DummyOneSubscriber subA(file, "a");
319 DummyOneSubscriber subB(file, "b");
320
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600321 file.parse(CONFIG, false, "dummy-config");
Steve DiBenedettobb75b552014-02-08 12:12:11 -0700322
323 BOOST_CHECK(subA.allCallbacksFired());
324 BOOST_CHECK(subB.allCallbacksFired());
325}
326
Eric Newberrycb27d912020-04-08 19:38:18 -0700327BOOST_AUTO_TEST_CASE(ParseNumber)
328{
329 std::istringstream input(R"CONFIG(
330 a -125
331 b 156
332 c 100000
333 d efg
334 e 123.456e-10
335 f 123abc
336 g ""
337 h " -1"
338 )CONFIG");
339 ConfigSection section;
340 boost::property_tree::read_info(input, section);
341
342 // Read various types and ensure they return the correct value
343 BOOST_CHECK_EQUAL(ConfigFile::parseNumber<short>(section.get_child("a"), "a", "section"), -125);
344 BOOST_CHECK_EQUAL(ConfigFile::parseNumber<int>(section.get_child("a"), "a", "section"), -125);
345 BOOST_CHECK_EQUAL(ConfigFile::parseNumber<long>(section.get_child("a"), "a", "section"), -125);
346 BOOST_CHECK_EQUAL(ConfigFile::parseNumber<double>(section.get_child("a"), "a", "section"), -125.0);
347 BOOST_CHECK_EQUAL(ConfigFile::parseNumber<float>(section.get_child("a"), "a", "section"), -125.0);
348 BOOST_CHECK_EQUAL(ConfigFile::parseNumber<short>(section.get_child("b"), "b", "section"), 156);
349 BOOST_CHECK_EQUAL(ConfigFile::parseNumber<int>(section.get_child("b"), "b", "section"), 156);
350 BOOST_CHECK_EQUAL(ConfigFile::parseNumber<long>(section.get_child("b"), "b", "section"), 156);
351 BOOST_CHECK_CLOSE(ConfigFile::parseNumber<double>(section.get_child("e"), "e", "section"), 123.456e-10, 0.0001);
352 BOOST_CHECK_CLOSE(ConfigFile::parseNumber<float>(section.get_child("e"), "e", "section"), 123.456e-10, 0.0001);
353 BOOST_CHECK_EQUAL(ConfigFile::parseNumber<int>(section.get_child("h"), "h", "section"), -1);
354
355 // Check throw on out of range
356 BOOST_CHECK_THROW(ConfigFile::parseNumber<int16_t>(section.get_child("c"), "c", "section"),
357 ConfigFile::Error);
358
359 // Check throw on non-integer for integer types
360 BOOST_CHECK_THROW(ConfigFile::parseNumber<int>(section.get_child("d"), "d", "section"),
361 ConfigFile::Error);
362 BOOST_CHECK_THROW(ConfigFile::parseNumber<int>(section.get_child("e"), "e", "section"),
363 ConfigFile::Error);
364 BOOST_CHECK_THROW(ConfigFile::parseNumber<int>(section.get_child("f"), "f", "section"),
365 ConfigFile::Error);
366 BOOST_CHECK_THROW(ConfigFile::parseNumber<int>(section.get_child("g"), "g", "section"),
367 ConfigFile::Error);
368
369 // Should throw exception if try to read unsigned from negative value
370 BOOST_CHECK_THROW(ConfigFile::parseNumber<uint16_t>(section.get_child("a"), "a", "section"),
371 ConfigFile::Error);
372 BOOST_CHECK_EQUAL(ConfigFile::parseNumber<uint16_t>(section.get_child("b"), "b", "section"), 156);
373 BOOST_CHECK_THROW(ConfigFile::parseNumber<uint32_t>(section.get_child("h"), "h", "section"),
374 ConfigFile::Error);
375}
376
Junxiao Shia6286a92021-02-23 06:43:52 -0700377BOOST_AUTO_TEST_CASE(CheckRange)
378{
379 {
380 uint32_t value = 8000;
381 uint32_t min = 8000;
382 uint32_t max = 8999;
383 ConfigFile::checkRange(value, min, max, "key", "section");
384 }
385
386 {
387 size_t value = 8999;
388 size_t min = 8000;
389 size_t max = 8999;
390 ConfigFile::checkRange(value, min, max, "key", "section");
391 }
392
393 {
394 int64_t value = -7000;
395 int64_t min = -7999;
396 int64_t max = 1000;
397 ConfigFile::checkRange(value, min, max, "key", "section");
398 }
399
400 {
401 uint32_t value = 7999;
402 uint32_t min = 8000;
403 uint32_t max = 8999;
404 BOOST_CHECK_THROW(ConfigFile::checkRange(value, min, max, "key", "section"), ConfigFile::Error);
405 }
406
407 {
408 int16_t value = 9000;
409 int16_t min = 8000;
410 int16_t max = 8999;
411 BOOST_CHECK_THROW(ConfigFile::checkRange(value, min, max, "key", "section"), ConfigFile::Error);
412 }
413
414 {
415 int32_t value = -8000;
416 int32_t min = -7999;
417 int32_t max = 1000;
418 BOOST_CHECK_THROW(ConfigFile::checkRange(value, min, max, "key", "section"), ConfigFile::Error);
419 }
420
421 {
422 int64_t value = 0x1001;
423 int64_t min = -0x7fff;
424 int64_t max = 0x1000;
425 BOOST_CHECK_THROW(ConfigFile::checkRange(value, min, max, "key", "section"), ConfigFile::Error);
426 }
427}
428
Davide Pesavento14e71f02019-03-28 17:35:25 -0400429BOOST_AUTO_TEST_SUITE_END() // TestConfigFile
Junxiao Shid9ee45c2014-02-27 15:38:11 -0700430
Davide Pesaventoe422f9e2022-06-03 01:30:23 -0400431} // namespace nfd::tests