From: Marcin Siodelski Date: Wed, 19 Dec 2018 20:00:33 +0000 (+0100) Subject: [#99,!176] Added unit test for deleting an option from option space. X-Git-Tag: 380-unexpected-boost-include-capture_base~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ec01471346384cc1b0805809601cf497ad59c267;p=thirdparty%2Fkea.git [#99,!176] Added unit test for deleting an option from option space. --- diff --git a/src/lib/dhcpsrv/cfg_option.cc b/src/lib/dhcpsrv/cfg_option.cc index 1ef4d9061a..0125709a68 100644 --- a/src/lib/dhcpsrv/cfg_option.cc +++ b/src/lib/dhcpsrv/cfg_option.cc @@ -189,6 +189,43 @@ CfgOption::getAll(const uint32_t vendor_id) const { return (vendor_options_.getItems(vendor_id)); } +size_t +CfgOption::del(const std::string& option_space, const uint16_t option_code) { + // Check for presence of options. + OptionContainerPtr options = getAll(option_space); + if (!options || options->empty()) { + // There are no options, so there is nothing to do. + return (0); + } + + // If this is not top level option we may also need to delete the + // option instance from options encapsulating the particular option + // space. + if ((option_space != DHCP4_OPTION_SPACE) && + (option_space != DHCP6_OPTION_SPACE)) { + // For each option space name iterate over the existing options. + auto option_space_names = getOptionSpaceNames(); + for (auto option_space_from_list : option_space_names) { + // Get all options within the particular option space. + auto options_in_space = getAll(option_space_from_list); + for (auto option_it = options_in_space->begin(); + option_it != options_in_space->end(); + ++option_it) { + + // Check if the option encapsulates our option space and + // it does, try to delete our option. + if (option_it->option_ && + (option_it->option_->getEncapsulatedSpace() == option_space)) { + option_it->option_->delOption(option_code); + } + } + } + } + + auto& idx = options->get<1>(); + return (idx.erase(option_code)); +} + ElementPtr CfgOption::toElement() const { // option-data value is a list of maps diff --git a/src/lib/dhcpsrv/cfg_option.h b/src/lib/dhcpsrv/cfg_option.h index 533439a5a4..a618076c6d 100644 --- a/src/lib/dhcpsrv/cfg_option.h +++ b/src/lib/dhcpsrv/cfg_option.h @@ -414,30 +414,17 @@ public: return (*od_itr); } - /// @brief Deletes option for the specified key and option code. + /// @brief Deletes option for the specified option space and option code. /// - /// The key should be a string, in which case it specifies an option space - /// name, or an uint32_t value, in which case it specifies a vendor - /// identifier. + /// If the option is encapsulated within some non top level option space, + /// it is also deleted from all option instances encapsulating this + /// option space. /// /// @param key Option space name or vendor identifier. /// @param option_code Code of the option to be returned. - /// @tparam Selector one of: @c std::string or @c uint32_t /// /// @return Number of deleted options. - template - size_t del(const Selector& key, const uint16_t option_code) { - // Check for presence of options. - OptionContainerPtr options = getAll(key); - if (!options || options->empty()) { - // There are no options, so there is nothing to do. - return (0); - } - - // Some options present, locate the one we are interested in. - auto& idx = options->get<1>(); - return (idx.erase(option_code)); - } + size_t del(const std::string& key, const uint16_t option_code); /// @brief Returns a list of configured option space names. /// diff --git a/src/lib/dhcpsrv/tests/cfg_option_unittest.cc b/src/lib/dhcpsrv/tests/cfg_option_unittest.cc index 7d41f2779f..0a619d2931 100644 --- a/src/lib/dhcpsrv/tests/cfg_option_unittest.cc +++ b/src/lib/dhcpsrv/tests/cfg_option_unittest.cc @@ -399,6 +399,48 @@ TEST_F(CfgOptionTest, encapsulate) { } } +// This test verifies that an option can be deleted from the configuration. +TEST_F(CfgOptionTest, del) { + CfgOption cfg; + + generateEncapsulatedOptions(cfg); + + // Append options from "foo" and "bar" space as sub-options and options + // from "foo-subs" and "bar-subs" as sub-options of "foo" and "bar" + // options. + ASSERT_NO_THROW(cfg.encapsulate()); + + // The option with the code 5 should exist in the option space "foo". + ASSERT_TRUE(cfg.get("foo", 5).option_); + + // Because we called "encapsulate", this option should have been + // propagated to the options encapsulating option space "foo". + for (uint16_t code = 1000; code < 1020; ++code) { + OptionDescriptor top_level_option(false); + ASSERT_NO_THROW(top_level_option = cfg.get(DHCP6_OPTION_SPACE, code)); + // Make sure that the option with code 5 is there. + ASSERT_TRUE(top_level_option.option_); + ASSERT_TRUE(top_level_option.option_->getOption(5)); + } + + // Delete option with the code 5 and belonging to option space "foo". + uint64_t deleted_num; + ASSERT_NO_THROW(deleted_num = cfg.del("foo", 5)); + EXPECT_EQ(1, deleted_num); + + // The option should now be gone from options config. + EXPECT_FALSE(cfg.get("foo", 5).option_); + + // Iterate over the options encapsulating "foo" option space. Make sure + // that the option with code 5 is no longer encapsulated by these options. + for (uint16_t code = 1000; code < 1020; ++code) { + OptionDescriptor top_level_option(false); + ASSERT_NO_THROW(top_level_option = cfg.get(DHCP6_OPTION_SPACE, code)); + ASSERT_TRUE(top_level_option.option_); + EXPECT_FALSE(top_level_option.option_->getOption(5)); + } +} + // This test verifies that single option can be retrieved from the configuration // using option code and option space. TEST_F(CfgOptionTest, get) {