const auto& index = cb_globals.get<StampedValueNameIndexTag>();
for (auto cb_global = index.begin(); cb_global != index.end(); ++cb_global) {
- // If the global is an explicit member of SrvConfig handle it that way.
- if (handleExplicitGlobal(external_cfg, (*cb_global))) {
+
+ if ((*cb_global)->amNull()) {
continue;
}
- // Otherwise it must be added to the implicitly configured globals
- if (handleImplicitGlobal(external_cfg, (*cb_global))) {
+ // If the global is an explicit member of SrvConfig handle it that way.
+ if (handleExplicitGlobal(external_cfg, (*cb_global))) {
continue;
- }
- isc_throw (DhcpConfigError, "Config backend supplied unsupported global: " <<
- (*cb_global)->getName() << " = " << (*cb_global)->getValue());
+ } else {
+ // Otherwise it must be added to the implicitly configured globals
+ handleImplicitGlobal(external_cfg, (*cb_global));
+ }
}
}
return (was_handled);
}
-bool handleImplicitGlobal(SrvConfigPtr external_cfg, const data::StampedValuePtr& cb_global) {
-
- // @todo One day we convert it based on the type stored in StampedValue, but
- // that day is not today. For now, if we find it in the global defaults use
- // the element type there.
- for (auto global_default : SimpleParser4::GLOBAL4_DEFAULTS) {
- if (global_default.name_ == cb_global->getName()) {
- ElementPtr element = cb_global->toElement(global_default.type_);
- external_cfg->addConfiguredGlobal(cb_global->getName(), element);
- return (true);
- }
- }
-
- // We didn't find it in the default list, so is it an optional implicit?
- const std::string& name = cb_global->getName();
- if ((name == "renew-timer") ||
- (name == "rebind-timer")) {
- ElementPtr element = cb_global->toElement(Element::integer);
- external_cfg->addConfiguredGlobal(cb_global->getName(), element);
- return (true);
- }
-
- return (false);
+void handleImplicitGlobal(SrvConfigPtr external_cfg, const data::StampedValuePtr& cb_global) {
+ external_cfg->addConfiguredGlobal(cb_global->getName(), cb_global->getElementValue());
}
}; // end of isc::dhcp namespace
///
/// @param external_cfg SrvConfig instance to update
/// @param cb_global global parameter supplied by configuration backend
-///
-/// @return true if the global is recognized as a supported global, false
-/// otherwise
-///
-/// @throw BadValue if the global's value is not the expected data type
-bool handleImplicitGlobal(SrvConfigPtr external_cfg,
+void handleImplicitGlobal(SrvConfigPtr external_cfg,
const data::StampedValuePtr& cb_global);
}; // end of isc::dhcp namespace
TestConfigBackendDHCPv4Ptr db2_; ///< Second configuration backend instance
};
-// This test verifies that an implicit global whose data value
-// does not match the expected type is detected.
-TEST_F(Dhcp4CBTest, implicitGlobalWrongType) {
- string base_config =
- "{ \n"
- " \"config-control\": { \n"
- " \"config-databases\": [ { \n"
- " \"type\": \"memfile\", \n"
- " \"host\": \"db1\" \n"
- " },{ \n"
- " \"type\": \"memfile\", \n"
- " \"host\": \"db2\" \n"
- " } \n"
- " ] \n"
- " } \n"
- "} \n";
-
- extractConfig(base_config);
-
- // Make some globals:
- // @todo StampedValue is going to be extended to hold type.
- StampedValuePtr badGlobal(new StampedValue("valid-lifetime", "not an int"));
- db1_->createUpdateGlobalParameter4(ServerSelector::ALL(), badGlobal);
-
- // Should fail to merge with an error.
- configure(base_config, CONTROL_RESULT_ERROR,
- "StampedValue::toElement: integer value expected for:"
- " valid-lifetime, value is: not an int");
-}
-
-// This test verifies that unknown externally configured
-// globals is detected.
-TEST_F(Dhcp4CBTest, unknownGlobal) {
- string base_config =
- "{ \n"
- " \"config-control\": { \n"
- " \"config-databases\": [ { \n"
- " \"type\": \"memfile\", \n"
- " \"host\": \"db1\" \n"
- " },{ \n"
- " \"type\": \"memfile\", \n"
- " \"host\": \"db2\" \n"
- " } \n"
- " ] \n"
- " } \n"
- "} \n";
-
- extractConfig(base_config);
-
- // Make some globals:
- // @todo StampedValue is going to be extended to hold type.
- StampedValuePtr badGlobal(new StampedValue("bogus-global", "some value"));
- db1_->createUpdateGlobalParameter4(ServerSelector::ALL(), badGlobal);
-
- // Should fail to merge with an error.
- configure(base_config, CONTROL_RESULT_ERROR,
- "Config backend supplied unsupported global:"
- " bogus-global = some value");
-}
-
-
// This test verifies that externally configured globals are
// merged correctly into staging configuration.
// @todo enable test when SrvConfig can merge globals.
}
}
-ElementPtr
-StampedValue::toElement(Element::types elem_type) {
- ElementPtr element;
- switch(elem_type) {
- case Element::string: {
- element.reset(new StringElement(value_));
- break;
- }
- case Element::integer: {
- try {
- int64_t int_value = boost::lexical_cast<int64_t>(value_);
- element.reset(new IntElement(int_value));
- } catch (const std::exception& ex) {
- isc_throw(BadValue, "StampedValue::toElement: integer value expected for: "
- << name_ << ", value is: " << value_ );
- }
- break;
- }
- case Element::boolean: {
- bool bool_value;
- if (value_ == std::string("true")) {
- bool_value = true;
- } else if (value_ == std::string("false")) {
- bool_value = false;
- } else {
- isc_throw(BadValue, "StampedValue::toElement: boolean value specified as "
- << name_ << ", value is: " << value_
- << ", expected true or false");
- }
-
- element.reset(new BoolElement(bool_value));
- break;
- }
- case Element::real: {
- try {
- double dbl_value = boost::lexical_cast<double>(value_);
- element.reset(new DoubleElement(dbl_value));
- }
- catch (const std::exception& ex) {
- isc_throw(BadValue, "StampedValue::toElement: real number value expected for: "
- << name_ << ", value is: " << value_ );
- }
-
- break;
- }
- default:
- isc_throw (BadValue, "StampedValue::toElement: unsupported element type "
- << elem_type << " for: " << name_);
- break;
- }
-
- return (element);
-}
-
} // end of namespace isc::data
} // end of namespace isc
/// type.
int64_t getSignedIntegerValue() const;
- /// @brief Creates an Element with the appropriate value
- ///
- /// @param etype type of Element to create
- /// @todo If StampedValue is extended to contain the Element::type
- /// this parameter can be done away with.
- ///
- /// @return A pointer to the new Element
- /// @throw BadValue if the current value is invalid for the
- /// requested element type. InvalidOperation if the requested
- /// type is unsupported.
- ElementPtr toElement(const Element::types etype);
-
/// @brief Returns value as a boolean.
///
/// @return Stored value as a boolean.
/// type.
double getDoubleValue() const;
+ /// @brief Returns the value as @c Element.
+ ConstElementPtr getElementValue() const {
+ return (value_);
+ }
+
private:
/// @brief Checks if the values passed to the constructors
EXPECT_THROW(StampedValue::create("bar", "1", Element::null), TypeError);
}
-// Tests that Elements can be created from stamped values.
-TEST(StampedValueTest, toElement) {
- ElementPtr elem;
- boost::scoped_ptr<StampedValue> value;
-
- // Make sure we can create a StringElement.
- ASSERT_NO_THROW(value.reset(new StampedValue("foo", "boo")));
- ASSERT_NO_THROW(elem = value->toElement(Element::string));
- ASSERT_EQ(Element::string, elem->getType());
- ASSERT_EQ("boo", elem->stringValue());
-
- // Make non-string types fail.
- ASSERT_THROW(value->toElement(Element::integer), BadValue);
- ASSERT_THROW(value->toElement(Element::boolean), BadValue);
- ASSERT_THROW(value->toElement(Element::real), BadValue);
-
- // Make sure we can create a IntElement.
- ASSERT_NO_THROW(value.reset(new StampedValue("foo", "777")));
- ASSERT_NO_THROW(elem = value->toElement(Element::integer));
- ASSERT_EQ(Element::integer, elem->getType());
- ASSERT_EQ(777, elem->intValue());
-
- // String should work.
- ASSERT_NO_THROW(elem = value->toElement(Element::string));
- ASSERT_EQ("777", elem->stringValue());
-
- // Real should work.
- ASSERT_NO_THROW(elem = value->toElement(Element::real));
- ASSERT_EQ(777.0, elem->doubleValue());
-
- // Boolean will fail.
- ASSERT_THROW(value->toElement(Element::boolean), BadValue);
-
- // Make sure we can create a Boolean.
- ASSERT_NO_THROW(value.reset(new StampedValue("foo", "true")));
- ASSERT_NO_THROW(elem = value->toElement(Element::boolean));
- ASSERT_EQ(Element::boolean, elem->getType());
- ASSERT_TRUE(elem->boolValue());
-
- ASSERT_NO_THROW(value.reset(new StampedValue("foo", "false")));
- ASSERT_NO_THROW(elem = value->toElement(Element::boolean));
- ASSERT_EQ(Element::boolean, elem->getType());
- ASSERT_FALSE(elem->boolValue());
-
- // String should work.
- ASSERT_NO_THROW(elem = value->toElement(Element::string));
- ASSERT_EQ("false", elem->stringValue());
-
- // Make numerics should fail.
- ASSERT_THROW(value->toElement(Element::integer), BadValue);
- ASSERT_THROW(value->toElement(Element::real), BadValue);
-
- // Make sure only lower case "true" and "false" works for Booleans.
- ASSERT_NO_THROW(value.reset(new StampedValue("foo", "TRUE")));
- ASSERT_THROW(value->toElement(Element::boolean), BadValue);
- ASSERT_NO_THROW(value.reset(new StampedValue("foo", "FALSE")));
- ASSERT_THROW(value->toElement(Element::boolean), BadValue);
- ASSERT_NO_THROW(value.reset(new StampedValue("foo","nonsens")));
- ASSERT_THROW(value->toElement(Element::boolean), BadValue);
-
- // Make sure we can create a DoubleElement.
- ASSERT_NO_THROW(value.reset(new StampedValue("foo", "45.0")));
- ASSERT_NO_THROW(elem = value->toElement(Element::real));
- ASSERT_EQ(Element::real, elem->getType());
- ASSERT_EQ(45.0, elem->doubleValue());
-
- // String should work.
- ASSERT_NO_THROW(elem = value->toElement(Element::string));
- ASSERT_EQ("45.0", elem->stringValue());
-
- // Int and Boolean should fail.
- ASSERT_THROW(value->toElement(Element::integer), BadValue);
- ASSERT_THROW(value->toElement(Element::boolean), BadValue);
-}
-
}