From b0cca7982a037a6c1e1999b8e257ccc4ae71eccb Mon Sep 17 00:00:00 2001 From: Marcin Siodelski Date: Mon, 4 Sep 2017 19:24:43 +0200 Subject: [PATCH] [5305] Parsers for shared networks added. --- src/lib/dhcpsrv/cfg_shared_networks.h | 13 + src/lib/dhcpsrv/parsers/dhcp_parsers.cc | 41 +++ src/lib/dhcpsrv/parsers/dhcp_parsers.h | 17 ++ src/lib/dhcpsrv/parsers/option_data_parser.h | 1 + .../dhcpsrv/parsers/shared_network_parser.cc | 109 +++++++- .../dhcpsrv/parsers/shared_network_parser.h | 30 ++- .../parsers/shared_networks_list_parser.h | 57 ++++- src/lib/dhcpsrv/tests/Makefile.am | 2 + .../tests/shared_network_parser_unittest.cc | 242 ++++++++++++++++++ .../shared_networks_list_parser_unittest.cc | 75 ++++++ 10 files changed, 573 insertions(+), 14 deletions(-) create mode 100644 src/lib/dhcpsrv/tests/shared_network_parser_unittest.cc create mode 100644 src/lib/dhcpsrv/tests/shared_networks_list_parser_unittest.cc diff --git a/src/lib/dhcpsrv/cfg_shared_networks.h b/src/lib/dhcpsrv/cfg_shared_networks.h index a15af93e6a..b3965f6d59 100644 --- a/src/lib/dhcpsrv/cfg_shared_networks.h +++ b/src/lib/dhcpsrv/cfg_shared_networks.h @@ -105,6 +105,13 @@ protected: /// @brief Represents configuration of IPv4 shared networks. class CfgSharedNetworks4 : public CfgSharedNetworks { +public: + + /// @brief Returns pointer to all configured shared networks. + const SharedNetwork4Collection* getAll() const { + return (&networks_); + } + }; /// @brief Pointer to the configuration of IPv4 shared networks. @@ -112,6 +119,12 @@ typedef boost::shared_ptr CfgSharedNetworks4Ptr; /// @brief Represents configuration of IPv6 shared networks. class CfgSharedNetworks6 : public CfgSharedNetworks { +public: + + /// @brief Returns pointer to all configured shared networks. + const SharedNetwork6Collection* getAll() const { + return (&networks_); + } }; /// @brief Pointer to the configuration of IPv6 shared networks. diff --git a/src/lib/dhcpsrv/parsers/dhcp_parsers.cc b/src/lib/dhcpsrv/parsers/dhcp_parsers.cc index 30995de0d0..07084558c1 100644 --- a/src/lib/dhcpsrv/parsers/dhcp_parsers.cc +++ b/src/lib/dhcpsrv/parsers/dhcp_parsers.cc @@ -809,6 +809,28 @@ Subnets4ListConfigParser::parse(SrvConfigPtr cfg, ConstElementPtr subnets_list) return (cnt); } +size_t +Subnets4ListConfigParser::parse(Subnet4Collection& subnets, + data::ConstElementPtr subnets_list) { + size_t cnt = 0; + BOOST_FOREACH(ConstElementPtr subnet_json, subnets_list->listValue()) { + + Subnet4ConfigParser parser; + Subnet4Ptr subnet = parser.parse(subnet_json); + if (subnet) { + try { + subnets.push_back(subnet); + ++cnt; + } catch (const std::exception& ex) { + isc_throw(DhcpConfigError, ex.what() << " (" + << subnet_json->getPosition() << ")"); + } + } + } + return (cnt); +} + + //**************************** Pool6Parser ********************************* PoolPtr @@ -1062,6 +1084,25 @@ Subnets6ListConfigParser::parse(SrvConfigPtr cfg, ConstElementPtr subnets_list) return (cnt); } +size_t +Subnets6ListConfigParser::parse(Subnet6Collection& subnets, + ConstElementPtr subnets_list) { + size_t cnt = 0; + BOOST_FOREACH(ConstElementPtr subnet_json, subnets_list->listValue()) { + + Subnet6ConfigParser parser; + Subnet6Ptr subnet = parser.parse(subnet_json); + try { + subnets.push_back(subnet); + ++cnt; + } catch (const std::exception& ex) { + isc_throw(DhcpConfigError, ex.what() << " (" + << subnet_json->getPosition() << ")"); + } + } + return (cnt); +} + //**************************** D2ClientConfigParser ********************** diff --git a/src/lib/dhcpsrv/parsers/dhcp_parsers.h b/src/lib/dhcpsrv/parsers/dhcp_parsers.h index 5e03b00d51..66ac7e2c3d 100644 --- a/src/lib/dhcpsrv/parsers/dhcp_parsers.h +++ b/src/lib/dhcpsrv/parsers/dhcp_parsers.h @@ -672,6 +672,14 @@ public: /// @param subnets_list pointer to a list of IPv4 subnets /// @return number of subnets created size_t parse(SrvConfigPtr cfg, data::ConstElementPtr subnets_list); + + /// @brief Parses contents of the subnet4 list. + /// + /// @param [out] subnets Container where parsed subnets will be stored. + /// @param subnets_list pointer to a list of IPv4 subnets + /// @return Number of subnets created. + size_t parse(Subnet4Collection& subnets, + data::ConstElementPtr subnets_list); }; /// @brief Parser for IPv6 pool definitions. @@ -849,6 +857,15 @@ public: /// @param subnets_list pointer to a list of IPv6 subnets /// @throw DhcpConfigError if CfgMgr rejects the subnet (e.g. subnet-id is a duplicate) size_t parse(SrvConfigPtr cfg, data::ConstElementPtr subnets_list); + + /// @brief Parses contents of the subnet6 list. + /// + /// @param [out] subnets Container where parsed subnets will be stored. + /// @param subnets_list pointer to a list of IPv6 subnets + /// @return Number of subnets created. + size_t parse(Subnet6Collection& subnets, + data::ConstElementPtr subnets_list); + }; /// @brief Parser for D2ClientConfig diff --git a/src/lib/dhcpsrv/parsers/option_data_parser.h b/src/lib/dhcpsrv/parsers/option_data_parser.h index b4fefeb65e..cf31a606e1 100644 --- a/src/lib/dhcpsrv/parsers/option_data_parser.h +++ b/src/lib/dhcpsrv/parsers/option_data_parser.h @@ -9,6 +9,7 @@ #include #include +#include #include #include #include diff --git a/src/lib/dhcpsrv/parsers/shared_network_parser.cc b/src/lib/dhcpsrv/parsers/shared_network_parser.cc index d73dd64b33..990ca1b8aa 100644 --- a/src/lib/dhcpsrv/parsers/shared_network_parser.cc +++ b/src/lib/dhcpsrv/parsers/shared_network_parser.cc @@ -8,20 +8,121 @@ #define SHARED_NETWORK_PARSER_H #include +#include +#include +#include #include #include +#include +#include using namespace isc::data; namespace isc { namespace dhcp { -SharedNetworkParser::~SharedNetworkParser() { +SharedNetwork4Ptr +SharedNetwork4Parser::parse(const data::ConstElementPtr& shared_network_data) { + SharedNetwork4Ptr shared_network; + std::string name; + try { + // Shared network is a map. + const auto& element = shared_network_data->mapValue(); + + // Make sure that the network name has been specified. The name is required + // to create a SharedNetwork4 object. + const auto& name_it = element.find("name"); + if (name_it == element.cend()) { + isc_throw(DhcpConfigError, "parameter \"name\" must be specified for" + " a shared network"); + + } + shared_network.reset(new SharedNetwork4(name_it->second->stringValue())); + + // Iterate over all parameters within the map and assign them to the + // shared network. + for (auto param = element.cbegin(); param != element.cend(); ++param) { + if (param->first == "interface") { + shared_network->setIface(param->second->stringValue()); + + } else if (param->first == "option-data") { + // Create parser instance for option-data. + CfgOptionPtr cfg_option = shared_network->getCfgOption(); + OptionDataListParser parser(AF_INET); + parser.parse(cfg_option, param->second); + + } else if (param->first == "subnet4") { + // Create parser instance of subnet4. + Subnets4ListConfigParser parser; + Subnet4Collection subnets; + parser.parse(subnets, param->second); + + // Add all returned subnets into shared network. + for (auto subnet = subnets.cbegin(); subnet != subnets.cend(); + ++subnet) { + shared_network->add(*subnet); + } + } + } + + } catch (const std::exception& ex) { + isc_throw(DhcpConfigError, ex.what() << " (" + << shared_network_data->getPosition() << ")"); + } + + return (shared_network); } -SharedNetworkPtr -SharedNetworkParser::parse(const ConstElementPtr& shared_network_data) { - return (SharedNetworkPtr()); +SharedNetwork6Ptr +SharedNetwork6Parser::parse(const data::ConstElementPtr& shared_network_data) { + SharedNetwork6Ptr shared_network; + std::string name; + try { + // Shared network is a map. + const auto& element = shared_network_data->mapValue(); + + // Make sure that the network name has been specified. The name is required + // to create a SharedNetwork6 object. + const auto& name_it = element.find("name"); + if (name_it == element.cend()) { + isc_throw(DhcpConfigError, "parameter \"name\" must be specified for" + " a shared network"); + + } + shared_network.reset(new SharedNetwork6(name_it->second->stringValue())); + + // Iterate over all parameters within the map and assign them to the + // shared network. + for (auto param = element.cbegin(); param != element.cend(); ++param) { + if (param->first == "interface") { + shared_network->setIface(param->second->stringValue()); + + } else if (param->first == "option-data") { + // Create parser instance for option-data. + CfgOptionPtr cfg_option = shared_network->getCfgOption(); + OptionDataListParser parser(AF_INET6); + parser.parse(cfg_option, param->second); + + } else if (param->first == "subnet6") { + // Create parser instance of subnet6. + Subnets6ListConfigParser parser; + Subnet6Collection subnets; + parser.parse(subnets, param->second); + + // Add all returned subnets into shared network. + for (auto subnet = subnets.cbegin(); subnet != subnets.cend(); + ++subnet) { + shared_network->add(*subnet); + } + } + } + + } catch (const std::exception& ex) { + isc_throw(DhcpConfigError, ex.what() << " (" + << shared_network_data->getPosition() << ")"); + } + + return (shared_network); } } // end of namespace isc::dhcp diff --git a/src/lib/dhcpsrv/parsers/shared_network_parser.h b/src/lib/dhcpsrv/parsers/shared_network_parser.h index aab0bcaadf..1c4d33131a 100644 --- a/src/lib/dhcpsrv/parsers/shared_network_parser.h +++ b/src/lib/dhcpsrv/parsers/shared_network_parser.h @@ -9,19 +9,41 @@ #include #include +#include +#include #include namespace isc { namespace dhcp { -class SharedNetworkParser : public isc::data::SimpleParser { +/// @brief Implements parser for IPv4 shared networks. +class SharedNetwork4Parser { public: - virtual ~SharedNetworkParser(); - - virtual SharedNetworkPtr + /// @brief Parses shared configuration information for IPv4 shared network. + /// + /// @param shared_network_data Data element holding shared network + /// configuration to be parsed. + /// + /// @return Pointer to an object representing shared network. + /// @throw DhcpConfigError when shared network configuration is invalid. + SharedNetwork4Ptr parse(const data::ConstElementPtr& shared_network_data); +}; +/// @brief Implements parser for IPv6 shared networks. +class SharedNetwork6Parser { +public: + + /// @brief Parses shared configuration information for IPv6 shared network. + /// + /// @param shared_network_data Data element holding shared network + /// configuration to be parsed. + /// + /// @return Pointer to an object representing shared network. + /// @throw DhcpConfigError when shared network configuration is invalid. + SharedNetwork6Ptr + parse(const data::ConstElementPtr& shared_network_data); }; } // enf of namespace isc::dhcp diff --git a/src/lib/dhcpsrv/parsers/shared_networks_list_parser.h b/src/lib/dhcpsrv/parsers/shared_networks_list_parser.h index ea9eb89813..1ae04a004a 100644 --- a/src/lib/dhcpsrv/parsers/shared_networks_list_parser.h +++ b/src/lib/dhcpsrv/parsers/shared_networks_list_parser.h @@ -13,24 +13,69 @@ #include #include #include +#include namespace isc { namespace dhcp { +/// @brief Parser for a list of shared networks. +/// +/// This is a generic parser for a list of IPv4 or IPv6 shared networks. +/// +/// @tparam SharedNetworkParserType Type of the parser to be used for +/// parsing shared network, i.e. @ref SharedNetwork4Parser or +/// @ref SharedNetwork6Parser. template class SharedNetworksListParser : public data::SimpleParser { -protected: +public: + /// @brief Parses a list of shared networks. + /// + /// @param [out] cfg Shared networks configuration structure into which + /// the data should be parsed. + /// @param shared_networks_list_data List element holding a list of + /// shared networks. + /// @tparam Type of the configuration structure into which the result + /// will be stored, i.e. @ref CfgSharedNetworks4 or @ref CfgSharedNetworks6. + /// + /// @throw DhcpConfigError when error has occurred, e.g. when networks + /// with duplicated names have been specified. template - void parse(const data::ConstElementPtr& shared_networks_list_data, - CfgSharedNetworksTypePtr& cfg) { - if (shared_networks_list_data->getType() != Element::list) { - isc_throw(data::DhcpConfigError, "shared-networks value must be a list"); + void parse(CfgSharedNetworksTypePtr& cfg, + const data::ConstElementPtr& shared_networks_list_data) { + try { + // Get the C++ vector holding networks. + const std::vector& networks_list = + shared_networks_list_data->listValue(); + // Iterate over all networks and do the parsing. + for (auto network_element = networks_list.cbegin(); + network_element != networks_list.cend(); ++network_element) { + SharedNetworkParserType parser; + auto network = parser.parse(*network_element); + cfg->add(network); + } + } catch (const DhcpConfigError&) { + // Such exceptions are emitted by the lower level parsers and + // errors should already include element's positions. So, we + // simply rethrow. + throw; + + } catch (const std::exception& ex) { + // Other exceptions don't include positions of the elements, so + // we should append one. + isc_throw(DhcpConfigError, ex.what() << " (" + << shared_networks_list_data->getPosition() << ")"); } } - }; +/// @brief Type of the shared networks list parser for IPv4. +typedef SharedNetworksListParser SharedNetworks4ListParser; + +/// @brief Type of the shared networks list parser for IPv6. +typedef SharedNetworksListParser SharedNetworks6ListParser; + + } // end of namespace isc::dhcp } // end of namespace isc diff --git a/src/lib/dhcpsrv/tests/Makefile.am b/src/lib/dhcpsrv/tests/Makefile.am index 6702cafc8a..88e2f6511f 100644 --- a/src/lib/dhcpsrv/tests/Makefile.am +++ b/src/lib/dhcpsrv/tests/Makefile.am @@ -123,7 +123,9 @@ if HAVE_CQL libdhcpsrv_unittests_SOURCES += cql_lease_mgr_unittest.cc endif libdhcpsrv_unittests_SOURCES += pool_unittest.cc +libdhcpsrv_unittests_SOURCES += shared_network_parser_unittest.cc libdhcpsrv_unittests_SOURCES += shared_network_unittest.cc +libdhcpsrv_unittests_SOURCES += shared_networks_list_parser_unittest.cc libdhcpsrv_unittests_SOURCES += srv_config_unittest.cc libdhcpsrv_unittests_SOURCES += subnet_unittest.cc libdhcpsrv_unittests_SOURCES += test_get_callout_handle.cc test_get_callout_handle.h diff --git a/src/lib/dhcpsrv/tests/shared_network_parser_unittest.cc b/src/lib/dhcpsrv/tests/shared_network_parser_unittest.cc new file mode 100644 index 0000000000..218029f1e6 --- /dev/null +++ b/src/lib/dhcpsrv/tests/shared_network_parser_unittest.cc @@ -0,0 +1,242 @@ +// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace isc; +using namespace isc::data; +using namespace isc::dhcp; + +namespace { + +/// @brief Test fixture class for SharedNetwork4Parser class. +class SharedNetwork4ParserTest : public ::testing::Test { +public: + + /// @brief Creates valid shared network configuration. + /// + /// @return Valid shared network configuration. + std::string getWorkingConfig() const { + std::string config = "{" + " \"name\": \"bird\"," + " \"interface\": \"eth1\"," + " \"option-data\": [" + " {" + " \"name\": \"domain-name-servers\"," + " \"data\": \"192.0.2.3\"" + " }" + " ]," + " \"subnet4\": [" + " {" + " \"id\": 1," + " \"subnet\": \"10.1.2.0/24\"," + " \"interface\": \"\"," + " \"renew-timer\": 100," + " \"rebind-timer\": 200," + " \"valid-lifetime\": 300," + " \"match-client-id\": false," + " \"next-server\": \"\"," + " \"client-class\": \"\"," + " \"reservation-mode\": \"all\"," + " \"4o6-interface\": \"\"," + " \"4o6-interface-id\": \"\"," + " \"4o6-subnet\": \"\"," + " \"dhcp4o6-port\": 0," + " \"decline-probation-period\": 86400," + " \"reservation-mode\": \"all\"" + " }," + " {" + " \"id\": 2," + " \"subnet\": \"192.0.2.0/24\"," + " \"interface\": \"\"," + " \"renew-timer\": 10," + " \"rebind-timer\": 20," + " \"valid-lifetime\": 30," + " \"match-client-id\": false," + " \"next-server\": \"\"," + " \"client-class\": \"\"," + " \"reservation-mode\": \"all\"," + " \"4o6-interface\": \"\"," + " \"4o6-interface-id\": \"\"," + " \"4o6-subnet\": \"\"," + " \"dhcp4o6-port\": 0," + " \"decline-probation-period\": 86400," + " \"reservation-mode\": \"all\"" + " }" + " ]" + "}"; + + return (config); + } +}; + +// This test verifies that shared network parser for IPv4 works properly +// in a positive test scenario. +TEST_F(SharedNetwork4ParserTest, parse) { + // Basic configuration for shared network. A bunch of parameters + // have to be specified for subnets because subnet parsers expect + // that default and global values are set. + std::string config = getWorkingConfig(); + ElementPtr config_element = Element::fromJSON(config); + + // Parse configuration specified above. + SharedNetwork4Parser parser; + SharedNetwork4Ptr network; + ASSERT_NO_THROW(network = parser.parse(config_element)); + ASSERT_TRUE(network); + + // Check basic parameters. + EXPECT_EQ("bird", network->getName()); + EXPECT_EQ("eth1", network->getIface()); + + // Subnet with id 1 + Subnet4Ptr subnet1 = network->getSubnet(SubnetID(1)); + ASSERT_TRUE(subnet1); + EXPECT_EQ("10.1.2.0", subnet1->get().first.toText()); + + // Subnet with id 2 + Subnet4Ptr subnet2 = network->getSubnet(SubnetID(2)); + ASSERT_TRUE(subnet2); + EXPECT_EQ("192.0.2.0", subnet2->get().first.toText()); + + // DHCP options + ConstCfgOptionPtr cfg_option = network->getCfgOption(); + ASSERT_TRUE(cfg_option); + OptionDescriptor opt_dns_servers = cfg_option->get("dhcp4", + DHO_DOMAIN_NAME_SERVERS); + ASSERT_TRUE(opt_dns_servers.option_); + Option4AddrLstPtr dns_servers = boost::dynamic_pointer_cast< + Option4AddrLst>(opt_dns_servers.option_); + ASSERT_TRUE(dns_servers); + Option4AddrLst::AddressContainer addresses = dns_servers->getAddresses(); + ASSERT_EQ(1, addresses.size()); + EXPECT_EQ("192.0.2.3", addresses[0].toText()); +} + +// This test verifies that parser throws an exception when mandatory parameter +// "name" is not specified. +TEST_F(SharedNetwork4ParserTest, missingName) { + // Remove a name parameter from the valid configuration. + std::string config = getWorkingConfig(); + ElementPtr config_element = Element::fromJSON(config); + ASSERT_NO_THROW(config_element->remove("name")); + + // Parse configuration specified above. + SharedNetwork4Parser parser; + SharedNetwork4Ptr network; + ASSERT_THROW(network = parser.parse(config_element), DhcpConfigError); +} + +/// @brief Test fixture class for SharedNetwork6Parser class. +class SharedNetwork6ParserTest : public ::testing::Test { +public: + + /// @brief Creates valid shared network configuration. + /// + /// @return Valid shared network configuration. + std::string getWorkingConfig() const { + std::string config = "{" + " \"name\": \"bird\"," + " \"interface\": \"eth1\"," + " \"option-data\": [" + " {" + " \"name\": \"dns-servers\"," + " \"data\": \"2001:db8:1::cafe\"" + " }" + " ]," + " \"subnet6\": [" + " {" + " \"id\": 1," + " \"subnet\": \"3000::/16\"," + " \"interface\": \"\"," + " \"interface-id\": \"\"," + " \"renew-timer\": 100," + " \"rebind-timer\": 200," + " \"preferred-lifetime\": 300," + " \"valid-lifetime\": 400," + " \"client-class\": \"\"," + " \"reservation-mode\": \"all\"," + " \"decline-probation-period\": 86400," + " \"dhcp4o6-port\": 0," + " \"rapid-commit\": false" + " }," + " {" + " \"id\": 2," + " \"subnet\": \"2001:db8:1::/64\"," + " \"interface\": \"\"," + " \"interface-id\": \"\"," + " \"renew-timer\": 10," + " \"rebind-timer\": 20," + " \"preferred-lifetime\": 30," + " \"valid-lifetime\": 40," + " \"client-class\": \"\"," + " \"reservation-mode\": \"all\"," + " \"decline-probation-period\": 86400," + " \"dhcp4o6-port\": 0," + " \"rapid-commit\": false" + " }" + " ]" + "}"; + + return (config); + } +}; + +// This test verifies that shared network parser for IPv4 works properly +// in a positive test scenario. +TEST_F(SharedNetwork6ParserTest, parse) { + // Basic configuration for shared network. A bunch of parameters + // have to be specified for subnets because subnet parsers expect + // that default and global values are set. + std::string config = getWorkingConfig(); + ElementPtr config_element = Element::fromJSON(config); + + // Parse configuration specified above. + SharedNetwork6Parser parser; + SharedNetwork6Ptr network; + ASSERT_NO_THROW(network = parser.parse(config_element)); + ASSERT_TRUE(network); + + // Check basic parameters. + EXPECT_EQ("bird", network->getName()); + EXPECT_EQ("eth1", network->getIface()); + + // Subnet with id 1 + Subnet6Ptr subnet1 = network->getSubnet(SubnetID(1)); + ASSERT_TRUE(subnet1); + EXPECT_EQ("3000::", subnet1->get().first.toText()); + + // Subnet with id 2 + Subnet6Ptr subnet2 = network->getSubnet(SubnetID(2)); + ASSERT_TRUE(subnet2); + EXPECT_EQ("2001:db8:1::", subnet2->get().first.toText()); + + // DHCP options + ConstCfgOptionPtr cfg_option = network->getCfgOption(); + ASSERT_TRUE(cfg_option); + OptionDescriptor opt_dns_servers = cfg_option->get("dhcp6", + D6O_NAME_SERVERS); + ASSERT_TRUE(opt_dns_servers.option_); + Option6AddrLstPtr dns_servers = boost::dynamic_pointer_cast< + Option6AddrLst>(opt_dns_servers.option_); + ASSERT_TRUE(dns_servers); + Option6AddrLst::AddressContainer addresses = dns_servers->getAddresses(); + ASSERT_EQ(1, addresses.size()); + EXPECT_EQ("2001:db8:1::cafe", addresses[0].toText()); +} + + +} // end of anonymous namespace diff --git a/src/lib/dhcpsrv/tests/shared_networks_list_parser_unittest.cc b/src/lib/dhcpsrv/tests/shared_networks_list_parser_unittest.cc new file mode 100644 index 0000000000..2ac57f84c5 --- /dev/null +++ b/src/lib/dhcpsrv/tests/shared_networks_list_parser_unittest.cc @@ -0,0 +1,75 @@ +// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include +#include +#include +#include +#include +#include +#include + +using namespace isc; +using namespace isc::data; +using namespace isc::dhcp; + +namespace { + +// This is a basic test verifying that all shared networks are correctly +// parsed. +TEST(SharedNetworkListParserTest, parse) { + // Basic configuration with array of shared networks. + std::string config = "[" + " {" + " \"name\": \"bird\"," + " \"interface\": \"eth0\"" + " }," + " {" + " \"name\": \"monkey\"," + " \"interface\": \"eth1\"" + " }" + "]"; + + ElementPtr config_element = Element::fromJSON(config); + + SharedNetworks4ListParser parser; + CfgSharedNetworks4Ptr cfg(new CfgSharedNetworks4());; + ASSERT_NO_THROW(parser.parse(cfg, config_element)); + + SharedNetwork4Ptr network1 = cfg->getByName("bird"); + ASSERT_TRUE(network1); + EXPECT_EQ("bird", network1->getName()); + EXPECT_EQ("eth0", network1->getIface()); + + SharedNetwork4Ptr network2 = cfg->getByName("monkey"); + ASSERT_TRUE(network2); + EXPECT_EQ("monkey", network2->getName()); + EXPECT_EQ("eth1", network2->getIface()); +} + +// This test verifies that specifying two networks with the same name +// yields an error. +TEST(SharedNetworkListParserTest, duplicatedName) { + // Basic configuration with two networks having the same name. + std::string config = "[" + " {" + " \"name\": \"bird\"," + " \"interface\": \"eth0\"" + " }," + " {" + " \"name\": \"bird\"," + " \"interface\": \"eth1\"" + " }" + "]"; + + ElementPtr config_element = Element::fromJSON(config); + + SharedNetworks4ListParser parser; + CfgSharedNetworks4Ptr cfg(new CfgSharedNetworks4());; + EXPECT_THROW(parser.parse(cfg, config_element), DhcpConfigError); +} + +} // end of anonymous namespace -- 2.47.2