ClientClassDef::ClientClassDef(const std::string& name,
const ExpressionPtr& match_expr,
- const OptionCollectionPtr& options)
- : name_(name), match_expr_(match_expr), options_(options) {
+ const CfgOptionPtr& cfg_option)
+ : name_(name), match_expr_(match_expr), cfg_option_(cfg_option) {
// Name can't be blank
if (name_.empty()) {
// @todo Does it make sense for a class to NOT have match expression?
// For classes without options, make sure we have an empty collection
- if (!options_) {
- options_.reset(new OptionCollection());
+ if (!cfg_option_) {
+ cfg_option_.reset(new CfgOption());
}
}
match_expr_ = match_expr;
}
-const OptionCollectionPtr&
-ClientClassDef::getOptions() const {
- return (options_);
+const CfgOptionPtr&
+ClientClassDef::getCfgOption() const {
+ return (cfg_option_);
}
void
-ClientClassDef::setOptions(const OptionCollectionPtr& options) {
- options_ = options;
-}
-
-OptionPtr
-ClientClassDef::findOption(uint16_t option_code) const {
- if (options_) {
- isc::dhcp::OptionCollection::iterator it = options_->find(option_code);
- if (it != options_->end()) {
- return ((*it).second);
- }
- }
-
- return (OptionPtr());
+ClientClassDef::setCfgOption(const CfgOptionPtr& cfg_option) {
+ cfg_option_ = cfg_option;
}
std::ostream& operator<<(std::ostream& os, const ClientClassDef& x) {
void
ClientClassDictionary::addClass(const std::string& name,
const ExpressionPtr& match_expr,
- const OptionCollectionPtr& options) {
- ClientClassDefPtr cclass(new ClientClassDef(name, match_expr, options));
+ const CfgOptionPtr& cfg_option) {
+ ClientClassDefPtr cclass(new ClientClassDef(name, match_expr, cfg_option));
addClass(cclass);
}
#ifndef CLIENT_CLASS_DEF_H
#define CLIENT_CLASS_DEF_H
-#include <dhcp/option.h>
+#include <dhcpsrv/cfg_option.h>
#include <eval/token.h>
#include <exceptions/exceptions.h>
/// @param match_expr Expression the class will use to determine membership
/// @param options Collection of options members should be given
ClientClassDef(const std::string& name, const ExpressionPtr& match_expr,
- const OptionCollectionPtr& options = OptionCollectionPtr());
+ const CfgOptionPtr& options = CfgOptionPtr());
/// @brief Destructor
virtual ~ClientClassDef();
void setMatchExpr(const ExpressionPtr& match_expr);
/// @brief Fetches the class's option collection
- const OptionCollectionPtr& getOptions() const;
+ const CfgOptionPtr& getCfgOption() const;
/// @brief Sets the class's option collection
///
/// @param options the option collection to assign the class
- void setOptions(const OptionCollectionPtr& options);
-
- /// @brief Fetches an option from the class's collection by code
- ///
- /// @param option_code Option code value of the desired option
- /// @return A pointer to the option if found, otherwise an
- /// empty pointer
- OptionPtr findOption(uint16_t option_code) const;
+ void setCfgOption(const CfgOptionPtr& cfg_option);
/// @brief Provides a convenient text representation of the class
friend std::ostream& operator<<(std::ostream& os, const ClientClassDef& x);
/// this class.
ExpressionPtr match_expr_;
- /// @brief The collection of options members should be given
- /// Currently this is a multimap, not sure we need/want that complexity
- OptionCollectionPtr options_;
+ /// @brief The option data configuration for this class
+ CfgOptionPtr cfg_option_;
};
/// @brief a pointer to an ClientClassDef
/// dictionary. See @ref dhcp::ClientClassDef::ClientClassDef() for
/// others.
void addClass(const std::string& name, const ExpressionPtr& match_expr,
- const OptionCollectionPtr& options);
+ const CfgOptionPtr& options);
/// @brief Adds a new class to the list
///
namespace {
+// Tests basic construction of ClientClassDef
TEST(ClientClassDef, construction) {
boost::scoped_ptr<ClientClassDef> cclass;
std::string name = "class1";
ExpressionPtr expr;
- OptionCollectionPtr options;
+ CfgOptionPtr cfg_option;
// Classes cannot have blank names
- ASSERT_THROW(cclass.reset(new ClientClassDef("", expr, options)), BadValue);
+ ASSERT_THROW(cclass.reset(new ClientClassDef("", expr, cfg_option)), BadValue);
- // Verify we can create a class with a name, expression, and no options
+ // Verify we can create a class with a name, expression, and no cfg_option
ASSERT_NO_THROW(cclass.reset(new ClientClassDef(name, expr)));
EXPECT_EQ(name, cclass->getName());
ASSERT_FALSE(cclass->getMatchExpr());
- // Verify we get an empty collection of options
- options = cclass->getOptions();
- ASSERT_TRUE(options);
- EXPECT_EQ(0, options->size());
+ // Verify we get an empty collection of cfg_option
+ cfg_option = cclass->getCfgOption();
+ ASSERT_TRUE(cfg_option);
+ //EXPECT_EQ(0, cfg_option->size());
}
-TEST(ClientClassDef, optionsBasics) {
+// Tests options operations. Note we just do the basics
+// as CfgOption is heavily tested elsewhere.
+TEST(ClientClassDef, cfgOptionBasics) {
boost::scoped_ptr<ClientClassDef> cclass;
std::string name = "class1";
ExpressionPtr expr;
- OptionCollectionPtr options;
+ CfgOptionPtr test_options;
+ CfgOptionPtr class_options;
OptionPtr opt;
// First construct the class with empty option pointer
- ASSERT_NO_THROW(cclass.reset(new ClientClassDef(name, expr, options)));
+ ASSERT_NO_THROW(cclass.reset(new ClientClassDef(name, expr, test_options)));
// We should get back a collection with no entries,
// not an empty collection pointer
- options = cclass->getOptions();
- ASSERT_TRUE(options);
- EXPECT_EQ(0, options->size());
-
- // We should not be able find an option
- opt = cclass->findOption(17);
- ASSERT_FALSE(opt);
-
- // Create an option container with two options
- options.reset(new OptionCollection());
- EXPECT_NO_THROW(opt.reset(new Option(Option::V4, 17)));
- options->insert(make_pair(17, opt));
- EXPECT_NO_THROW(opt.reset(new Option(Option::V4, 18)));
- options->insert(make_pair(18, opt));
-
- // Now remake the client class with options
- ASSERT_NO_THROW(cclass.reset(new ClientClassDef(name, expr, options)));
-
- options = cclass->getOptions();
- ASSERT_TRUE(options);
- EXPECT_EQ(2, options->size());
-
- // We should be able to find option 17
- opt = cclass->findOption(17);
- ASSERT_TRUE(opt);
- EXPECT_EQ(17, opt->getType());
-
- // We should be able to find option 18
- opt = cclass->findOption(18);
- ASSERT_TRUE(opt);
- EXPECT_EQ(18, opt->getType());
-
- // We should not be able to find option 90
- opt = cclass->findOption(90);
- ASSERT_FALSE(opt);
+ class_options = cclass->getCfgOption();
+ ASSERT_TRUE(class_options);
+
+ // Create an option container and add some options
+ OptionPtr option;
+ test_options.reset(new CfgOption());
+ option.reset(new Option(Option::V4, 17, OptionBuffer(10, 0xFF)));
+ ASSERT_NO_THROW(test_options->add(option, false, "dhcp4"));
+
+ option.reset(new Option(Option::V6, 101, OptionBuffer(10, 0xFF)));
+ ASSERT_NO_THROW(test_options->add(option, false, "isc"));
+
+ option.reset(new Option(Option::V6, 100, OptionBuffer(10, 0xFF)));
+ ASSERT_NO_THROW(test_options->add(option, false, "dhcp6"));
+
+ // Now remake the client class with cfg_option
+ ASSERT_NO_THROW(cclass.reset(new ClientClassDef(name, expr, test_options)));
+ class_options = cclass->getCfgOption();
+ ASSERT_TRUE(class_options);
+
+ // Now make sure we can find all the options
+ OptionDescriptor opt_desc = class_options->get("dhcp4",17);
+ ASSERT_TRUE(opt_desc.option_);
+ EXPECT_EQ(100, opt_desc.option_->getType());
+
+ opt_desc = class_options->get("isc",101);
+ ASSERT_TRUE(opt_desc.option_);
+ EXPECT_EQ(101, opt_desc.option_->getType());
+
+ opt_desc = class_options->get("dhcp6",100);
+ ASSERT_TRUE(opt_desc.option_);
+ EXPECT_EQ(100, opt_desc.option_->getType());
}
+// Tests the basic operation of ClientClassDictionary
+// This includes adding, finding, and removing classes
TEST(ClientClassDictionary, basics) {
ClientClassDictionaryPtr dictionary;
ClientClassDefPtr cclass;
ExpressionPtr expr;
- OptionCollectionPtr options;
+ CfgOptionPtr cfg_option;
// Verify constructor doesn't throw
ASSERT_NO_THROW(dictionary.reset(new ClientClassDictionary()));
EXPECT_EQ(0, classes->size());
// Verify that we can add classes with both addClass variants
- // First addClass(name, expression, options)
- ASSERT_NO_THROW(dictionary->addClass("cc1", expr, options));
- ASSERT_NO_THROW(dictionary->addClass("cc2", expr, options));
+ // First addClass(name, expression, cfg_option)
+ ASSERT_NO_THROW(dictionary->addClass("cc1", expr, cfg_option));
+ ASSERT_NO_THROW(dictionary->addClass("cc2", expr, cfg_option));
// Verify duplicate add attempt throws
- ASSERT_THROW(dictionary->addClass("cc2", expr, options),
+ ASSERT_THROW(dictionary->addClass("cc2", expr, cfg_option),
DuplicateClientClassDef);
// Verify that you cannot add a class with no name.
- ASSERT_THROW(dictionary->addClass("", expr, options), BadValue);
+ ASSERT_THROW(dictionary->addClass("", expr, cfg_option), BadValue);
// Now with addClass(class pointer)
- ASSERT_NO_THROW(cclass.reset(new ClientClassDef("cc3", expr, options)));
+ ASSERT_NO_THROW(cclass.reset(new ClientClassDef("cc3", expr, cfg_option)));
ASSERT_NO_THROW(dictionary->addClass(cclass));
// Verify duplicate add attempt throws