/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /** * Copyright (c) 2014 Regents of the University of California, * Arizona Board of Regents, * Colorado State University, * University Pierre & Marie Curie, Sorbonne University, * Washington University in St. Louis, * Beijing Institute of Technology * * This file is part of NFD (Named Data Networking Forwarding Daemon). * See AUTHORS.md for complete list of NFD authors and contributors. * * NFD is free software: you can redistribute it and/or modify it under the terms * of the GNU General Public License as published by the Free Software Foundation, * either version 3 of the License, or (at your option) any later version. * * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with * NFD, e.g., in COPYING.md file. If not, see . **/ #include "core/config-file.hpp" #include "tests/test-common.hpp" #include namespace nfd { namespace tests { NFD_LOG_INIT("ConfigFileTest"); BOOST_FIXTURE_TEST_SUITE(MgmtConfigFile, BaseFixture) // a // { // akey "avalue" // } // b // { // bkey "bvalue" // } const std::string CONFIG = "a\n" "{\n" " akey \"avalue\"\n" "}\n" "b\n" "{\n" " bkey \"bvalue\"\n" "}\n"; // a // { // akey "avalue" // } // b // // bkey "bvalue" // } const std::string MALFORMED_CONFIG = "a\n" "{\n" " akey \"avalue\"\n" "}\n" "b\n" "\n" " bkey \"bvalue\"\n" "}\n"; // counts of the respective section counts in config_example.info const int CONFIG_N_A_SECTIONS = 1; const int CONFIG_N_B_SECTIONS = 1; class DummySubscriber { public: DummySubscriber(ConfigFile& config, int nASections, int nBSections, bool expectDryRun) : m_nASections(nASections), m_nBSections(nBSections), m_nRemainingACallbacks(nASections), m_nRemainingBCallbacks(nBSections), m_expectDryRun(expectDryRun) { } void onA(const ConfigSection& section, bool isDryRun) { // NFD_LOG_DEBUG("a"); BOOST_CHECK_EQUAL(isDryRun, m_expectDryRun); --m_nRemainingACallbacks; } void onB(const ConfigSection& section, bool isDryRun) { // NFD_LOG_DEBUG("b"); BOOST_CHECK_EQUAL(isDryRun, m_expectDryRun); --m_nRemainingBCallbacks; } bool allCallbacksFired() const { return m_nRemainingACallbacks == 0 && m_nRemainingBCallbacks == 0; } bool noCallbacksFired() const { return m_nRemainingACallbacks == m_nASections && m_nRemainingBCallbacks == m_nBSections; } virtual ~DummySubscriber() { } private: int m_nASections; int m_nBSections; int m_nRemainingACallbacks; int m_nRemainingBCallbacks; bool m_expectDryRun; }; class DummyAllSubscriber : public DummySubscriber { public: DummyAllSubscriber(ConfigFile& config, bool expectDryRun=false) : DummySubscriber(config, CONFIG_N_A_SECTIONS, CONFIG_N_B_SECTIONS, expectDryRun) { config.addSectionHandler("a", bind(&DummySubscriber::onA, this, _1, _2)); config.addSectionHandler("b", bind(&DummySubscriber::onB, this, _1, _2)); } virtual ~DummyAllSubscriber() { } }; class DummyOneSubscriber : public DummySubscriber { public: DummyOneSubscriber(ConfigFile& config, const std::string& sectionName, bool expectDryRun=false) : DummySubscriber(config, (sectionName == "a"), (sectionName == "b"), expectDryRun) { if (sectionName == "a") { config.addSectionHandler(sectionName, bind(&DummySubscriber::onA, this, _1, _2)); } else if (sectionName == "b") { config.addSectionHandler(sectionName, bind(&DummySubscriber::onB, this, _1, _2)); } else { BOOST_FAIL("Test setup error: " << "Unexpected section name " <<"\"" << sectionName << "\""); } } virtual ~DummyOneSubscriber() { } }; class DummyNoSubscriber : public DummySubscriber { public: DummyNoSubscriber(ConfigFile& config, bool expectDryRun) : DummySubscriber(config, 0, 0, expectDryRun) { } virtual ~DummyNoSubscriber() { } }; BOOST_AUTO_TEST_CASE(OnConfigStream) { ConfigFile file; DummyAllSubscriber sub(file); std::ifstream input; input.open("tests/core/config_example.info"); BOOST_REQUIRE(input.is_open()); file.parse(input, false, "config_example.info"); BOOST_CHECK(sub.allCallbacksFired()); } BOOST_AUTO_TEST_CASE(OnConfigStreamEmptyStream) { ConfigFile file; DummyAllSubscriber sub(file); std::ifstream input; BOOST_CHECK_THROW(file.parse(input, false, "unknown"), ConfigFile::Error); BOOST_CHECK(sub.noCallbacksFired()); } BOOST_AUTO_TEST_CASE(OnConfigString) { ConfigFile file; DummyAllSubscriber sub(file); file.parse(CONFIG, false, "dummy-config"); BOOST_CHECK(sub.allCallbacksFired()); } BOOST_AUTO_TEST_CASE(OnConfigStringEmpty) { ConfigFile file; DummyAllSubscriber sub(file); BOOST_CHECK_THROW(file.parse(std::string(), false, "dummy-config"), ConfigFile::Error); BOOST_CHECK(sub.noCallbacksFired()); } BOOST_AUTO_TEST_CASE(OnConfigStringMalformed) { ConfigFile file; DummyAllSubscriber sub(file); BOOST_CHECK_THROW(file.parse(MALFORMED_CONFIG, false, "dummy-config"), ConfigFile::Error); BOOST_CHECK(sub.noCallbacksFired()); } BOOST_AUTO_TEST_CASE(OnConfigStringDryRun) { ConfigFile file; DummyAllSubscriber sub(file, true); file.parse(CONFIG, true, "dummy-config"); BOOST_CHECK(sub.allCallbacksFired()); } BOOST_AUTO_TEST_CASE(OnConfigFilename) { ConfigFile file; DummyAllSubscriber sub(file); file.parse("tests/core/config_example.info", false); BOOST_CHECK(sub.allCallbacksFired()); } BOOST_AUTO_TEST_CASE(OnConfigFilenameNoFile) { ConfigFile file; DummyAllSubscriber sub(file); BOOST_CHECK_THROW(file.parse("i_made_this_up.info", false), ConfigFile::Error); BOOST_CHECK(sub.noCallbacksFired()); } BOOST_AUTO_TEST_CASE(OnConfigFilenameMalformed) { ConfigFile file; DummyAllSubscriber sub(file); BOOST_CHECK_THROW(file.parse("tests/core/config_malformed.info", false), ConfigFile::Error); BOOST_CHECK(sub.noCallbacksFired()); } BOOST_AUTO_TEST_CASE(OnConfigStreamDryRun) { ConfigFile file; DummyAllSubscriber sub(file, true); std::ifstream input; input.open("tests/core/config_example.info"); BOOST_REQUIRE(input.is_open()); file.parse(input, true, "tests/core/config_example.info"); BOOST_CHECK(sub.allCallbacksFired()); input.close(); } BOOST_AUTO_TEST_CASE(OnConfigFilenameDryRun) { ConfigFile file; DummyAllSubscriber sub(file, true); file.parse("tests/core/config_example.info", true); BOOST_CHECK(sub.allCallbacksFired()); } BOOST_AUTO_TEST_CASE(OnConfigReplaceSubscriber) { ConfigFile file; DummyAllSubscriber sub1(file); DummyAllSubscriber sub2(file); file.parse(CONFIG, false, "dummy-config"); BOOST_CHECK(sub1.noCallbacksFired()); BOOST_CHECK(sub2.allCallbacksFired()); } class MissingCallbackFixture : public BaseFixture { public: MissingCallbackFixture() : m_missingFired(false) { } void checkMissingHandler(const std::string& filename, const std::string& sectionName, const ConfigSection& section, bool isDryRun) { m_missingFired = true; } protected: bool m_missingFired; }; BOOST_FIXTURE_TEST_CASE(OnConfigUncoveredSections, MissingCallbackFixture) { ConfigFile file; BOOST_REQUIRE_THROW(file.parse(CONFIG, false, "dummy-config"), ConfigFile::Error); ConfigFile permissiveFile(bind(&MissingCallbackFixture::checkMissingHandler, this, _1, _2, _3, _4)); DummyOneSubscriber subA(permissiveFile, "a"); BOOST_REQUIRE_NO_THROW(permissiveFile.parse(CONFIG, false, "dummy-config")); BOOST_CHECK(subA.allCallbacksFired()); BOOST_CHECK(m_missingFired); } BOOST_AUTO_TEST_CASE(OnConfigCoveredByPartialSubscribers) { ConfigFile file; DummyOneSubscriber subA(file, "a"); DummyOneSubscriber subB(file, "b"); file.parse(CONFIG, false, "dummy-config"); BOOST_CHECK(subA.allCallbacksFired()); BOOST_CHECK(subB.allCallbacksFired()); } BOOST_AUTO_TEST_SUITE_END() } // namespace tests } // namespace nfd