123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258 |
- // Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
- //
- // Permission to use, copy, modify, and/or distribute this software for any
- // purpose with or without fee is hereby granted, provided that the above
- // copyright notice and this permission notice appear in all copies.
- //
- // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
- // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
- // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- // PERFORMANCE OF THIS SOFTWARE.
- #include <config.h>
- #include <dhcp/dhcp4.h>
- #include <dhcp/dhcp6.h>
- #include <dhcp/option_space.h>
- #include <dhcpsrv/cfg_option_def.h>
- #include <gtest/gtest.h>
- using namespace isc;
- using namespace isc::dhcp;
- namespace {
- // This test checks that two option definition configurations can be
- // compared for equality.
- TEST(CfgOptionDefTest, equal) {
- CfgOptionDef cfg1;
- CfgOptionDef cfg2;
- // Default objects must be equal.
- ASSERT_TRUE(cfg1 == cfg2);
- ASSERT_FALSE(cfg1 != cfg2);
- // Let's add the same option but to two different option spaces.
- cfg1.add(OptionDefinitionPtr(new OptionDefinition("option-foo",
- 5, "uint16")), "isc");
- cfg2.add(OptionDefinitionPtr(new OptionDefinition("option-foo",
- 5, "uint16")), "dns");
- // Configurations must be unequal.
- ASSERT_FALSE(cfg1 == cfg2);
- ASSERT_TRUE(cfg1 != cfg2);
- // Now, let's add them again but to original option spaces. Both objects
- // should now contain the same options under two option spaces. The
- // order should not matter so configurations should be equal.
- cfg1.add(OptionDefinitionPtr(new OptionDefinition("option-foo",
- 5, "uint16")), "dns");
- cfg2.add(OptionDefinitionPtr(new OptionDefinition("option-foo",
- 5, "uint16")), "isc");
- EXPECT_TRUE(cfg1 == cfg2);
- EXPECT_FALSE(cfg1 != cfg2);
- }
- // This test verifies that multiple option definitions can be added
- // under different option spaces.
- TEST(CfgOptionDefTest, getAll) {
- CfgOptionDef cfg;
- // Create a set of option definitions with codes between 100 and 109.
- for (uint16_t code = 100; code < 110; ++code) {
- std::ostringstream option_name;
- // Option name is unique, e.g. option-100, option-101 etc.
- option_name << "option-" << code;
- OptionDefinitionPtr def(new OptionDefinition(option_name.str(), code,
- "uint16"));
- // Add option definition to "isc" option space.
- // Option codes are not duplicated so expect no error
- // when adding them.
- ASSERT_NO_THROW(cfg.add(def, "isc"));
- }
- // Create a set of option definitions with codes between 105 and 114 and
- // add them to the different option space.
- for (uint16_t code = 105; code < 115; ++code) {
- std::ostringstream option_name;
- option_name << "option-" << code;
- OptionDefinitionPtr def(new OptionDefinition(option_name.str(), code,
- "uint16"));
- ASSERT_NO_THROW(cfg.add(def, "abcde"));
- }
- // Sanity check that all 10 option definitions are there.
- OptionDefContainerPtr option_defs1 = cfg.getAll("isc");
- ASSERT_TRUE(option_defs1);
- ASSERT_EQ(10, option_defs1->size());
- // Iterate over all option definitions and check that they have
- // valid codes. Also, their order should be the same as they
- // were added (codes 100-109).
- uint16_t code = 100;
- for (OptionDefContainer::const_iterator it = option_defs1->begin();
- it != option_defs1->end(); ++it, ++code) {
- OptionDefinitionPtr def(*it);
- ASSERT_TRUE(def);
- EXPECT_EQ(code, def->getCode());
- }
- // Sanity check that all 10 option definitions are there.
- OptionDefContainerPtr option_defs2 = cfg.getAll("abcde");
- ASSERT_TRUE(option_defs2);
- ASSERT_EQ(10, option_defs2->size());
- // Check that the option codes are valid.
- code = 105;
- for (OptionDefContainer::const_iterator it = option_defs2->begin();
- it != option_defs2->end(); ++it, ++code) {
- OptionDefinitionPtr def(*it);
- ASSERT_TRUE(def);
- EXPECT_EQ(code, def->getCode());
- }
- // Let's make one more check that the empty set is returned when
- // invalid option space is used.
- OptionDefContainerPtr option_defs3 = cfg.getAll("non-existing");
- ASSERT_TRUE(option_defs3);
- EXPECT_TRUE(option_defs3->empty());
- }
- // This test verifies that single option definition is correctly
- // returned with get function.
- TEST(CfgOptionDefTest, get) {
- CfgOptionDef cfg;
- // Create a set of option definitions with codes between 100 and 109.
- for (uint16_t code = 100; code < 110; ++code) {
- std::ostringstream option_name;
- // Option name is unique, e.g. option-100, option-101 etc.
- option_name << "option-" << code;
- OptionDefinitionPtr def(new OptionDefinition(option_name.str(), code,
- "uint16"));
- // Add option definition to "isc" option space.
- // Option codes are not duplicated so expect no error
- // when adding them.
- ASSERT_NO_THROW(cfg.add(def, "isc"));
- }
- // Create a set of option definitions with codes between 105 and 114 and
- // add them to the different option space.
- for (uint16_t code = 105; code < 115; ++code) {
- std::ostringstream option_name;
- option_name << "option-other-" << code;
- OptionDefinitionPtr def(new OptionDefinition(option_name.str(), code,
- "uint16"));
- ASSERT_NO_THROW(cfg.add(def, "abcde"));
- }
- // Try to get option definitions one by one using all codes
- // that we expect to be there.
- for (uint16_t code = 100; code < 110; ++code) {
- OptionDefinitionPtr def = cfg.get("isc", code);
- ASSERT_TRUE(def);
- // Check that the option name is in the format of 'option-[code]'.
- // That way we make sure that the options that have the same codes
- // within different option spaces are different.
- std::ostringstream option_name;
- option_name << "option-" << code;
- EXPECT_EQ(option_name.str(), def->getName());
- EXPECT_EQ(code, def->getCode());
- // Try to get the same option definition using an option name as
- // a key.
- def = cfg.get("isc", option_name.str());
- ASSERT_TRUE(def);
- EXPECT_EQ(code, def->getCode());
- }
- // Check that the option codes are valid.
- for (uint16_t code = 105; code < 115; ++code) {
- OptionDefinitionPtr def = cfg.get("abcde", code);
- ASSERT_TRUE(def);
- // Check that the option name is in the format of 'option-other-[code]'.
- // That way we make sure that the options that have the same codes
- // within different option spaces are different.
- std::ostringstream option_name;
- option_name << "option-other-" << code;
- EXPECT_EQ(option_name.str(), def->getName());
- EXPECT_EQ(code, def->getCode());
- // Try to get the same option definition using an option name as
- // a key.
- def = cfg.get("abcde", option_name.str());
- ASSERT_TRUE(def);
- EXPECT_EQ(code, def->getCode());
- }
- // Check that an option definition can be added to the standard
- // (dhcp4 and dhcp6) option spaces when the option code is not
- // reserved by the standard option.
- OptionDefinitionPtr def6(new OptionDefinition("option-foo", 79, "uint16"));
- EXPECT_NO_THROW(cfg.add(def6, DHCP6_OPTION_SPACE));
- OptionDefinitionPtr def4(new OptionDefinition("option-foo", 222, "uint16"));
- EXPECT_NO_THROW(cfg.add(def4, DHCP4_OPTION_SPACE));
- // Try to query the option definition from an non-existing
- // option space and expect NULL pointer.
- OptionDefinitionPtr def = cfg.get("non-existing", 56);
- EXPECT_FALSE(def);
- // Try to get the non-existing option definition from an
- // existing option space.
- EXPECT_FALSE(cfg.get("isc", 56));
- }
- // This test verifies that it is not allowed to override a definition of the
- // standard option which has its definition defined in libdhcp++, but it is
- // allowed to create a definition for the standard option which doesn't have
- // its definition in libdhcp++.
- TEST(CfgOptionDefTest, overrideStdOptionDef) {
- CfgOptionDef cfg;
- OptionDefinitionPtr def;
- // There is a definition for routers option in libdhcp++, so an attempt
- // to add (override) another definition for this option should fail.
- def.reset(new OptionDefinition("routers", DHO_ROUTERS, "uint32"));
- EXPECT_THROW(cfg.add(def, DHCP4_OPTION_SPACE), isc::BadValue);
- /// @todo There is no definition for the NIS Server Addr option in
- /// libdhcp++. Once it is implemented it should be not allowed to
- /// add a custom definition for it. At the moment, it should be ok
- /// to add a definition for this option (using configuration mechanism)
- /// because we haven't implemented the one in libdhcp++.
- def.reset(new OptionDefinition("nis-server-addr", 65, "uint16"));
- EXPECT_NO_THROW(cfg.add(def, DHCP4_OPTION_SPACE));
- // It is not allowed to override the definition of the option which
- // has its definition in the libdhcp++.
- def.reset(new OptionDefinition("sntp-servers", D6O_SNTP_SERVERS,
- "ipv4-address"));
- EXPECT_THROW(cfg.add(def, DHCP6_OPTION_SPACE), isc::BadValue);
- // There is no definition for option 63 in libdhcp++ yet, so it should
- // be possible provide a custom definition.
- def.reset(new OptionDefinition("geolocation", 63, "uint32"));
- EXPECT_NO_THROW(cfg.add(def, DHCP6_OPTION_SPACE));
- }
- // This test verifies that the function that adds new option definition
- // throws exceptions when arguments are invalid.
- TEST(CfgOptionDefTest, addNegative) {
- CfgOptionDef cfg;
- OptionDefinitionPtr def(new OptionDefinition("option-foo", 1000, "uint16"));
- // Try empty option space name.
- ASSERT_THROW(cfg.add(def, ""), isc::BadValue);
- // Try NULL option definition.
- ASSERT_THROW(cfg.add(OptionDefinitionPtr(), "isc"),
- isc::dhcp::MalformedOptionDefinition);
- // Try adding option definition twice and make sure that it
- // fails on the second attempt.
- ASSERT_NO_THROW(cfg.add(def, "isc"));
- EXPECT_THROW(cfg.add(def, "isc"), DuplicateOptionDefinition);
- }
- }
|