ClientClassDefParser::parse(ClientClassDictionaryPtr& class_dictionary,
ConstElementPtr class_def_cfg,
uint16_t family,
- bool append_error_position) {
+ bool append_error_position,
+ bool check_dependencies) {
// name is now mandatory, so let's deal with it first.
std::string name = getString(class_def_cfg, "name");
if (name.empty()) {
if (test_cfg) {
ExpressionParser parser;
auto check_defined =
- [&class_dictionary, &depend_on_known]
+ [&class_dictionary, &depend_on_known, check_dependencies]
(const ClientClass& cclass) {
- return (isClientClassDefined(class_dictionary,
- depend_on_known,
- cclass));
+ return (!check_dependencies || isClientClassDefined(class_dictionary,
+ depend_on_known,
+ cclass));
};
parser.parse(match_expr, test_cfg, family, check_defined);
test = test_cfg->stringValue();
ClientClassDictionaryPtr
ClientClassDefListParser::parse(ConstElementPtr client_class_def_list,
- uint16_t family) {
+ uint16_t family, bool check_dependencies) {
ClientClassDictionaryPtr dictionary(new ClientClassDictionary());
BOOST_FOREACH(ConstElementPtr client_class_def,
client_class_def_list->listValue()) {
ClientClassDefParser parser;
- parser.parse(dictionary, client_class_def, family);
+ parser.parse(dictionary, client_class_def, family, true, check_dependencies);
}
return (dictionary);
}
/// of the parsed string within parsed JSON should be appended. The
/// default setting is to append it, but it is typically set to false
/// when this parser is used by hooks libraries.
+ /// @param check_dependencies indicates if the parser should evaluate an
+ /// expression to see if the referenced client classes exist.
///
/// @throw DhcpConfigError if parsing was unsuccessful.
void parse(ClientClassDictionaryPtr& class_dictionary,
isc::data::ConstElementPtr client_class_def,
uint16_t family,
- bool append_error_position = true);
+ bool append_error_position = true,
+ bool check_dependencies = true);
/// @brief Iterates over class parameters and checks if they are supported.
///
/// @param class_def_list pointer to an element that holds entries
/// for client class definitions.
/// @param family the address family of the client class definitions.
+ /// @param check_dependencies indicates if the parser should evaluate an
+ /// expression to see if the referenced client classes exist.
/// @return a pointer to the filled dictionary
/// @throw DhcpConfigError if configuration parsing fails.
ClientClassDictionaryPtr
- parse(isc::data::ConstElementPtr class_def_list, uint16_t family);
+ parse(isc::data::ConstElementPtr class_def_list, uint16_t family,
+ bool check_dependencies = true);
};
} // end of namespace isc::dhcp
/// @param config - JSON string containing the list of definitions to parse.
/// @param family - the address family in which the parsing should
/// occur.
+ /// @param check_dependencies - indicates if the parser should check whether
+ /// referenced classes exist.
/// @return Returns a pointer to class dictionary created
/// @throw indirectly, exceptions converting the JSON text to elements,
/// or by the parsing itself are not caught
ClientClassDictionaryPtr parseClientClassDefList(const std::string& config,
- uint16_t family)
+ uint16_t family,
+ bool check_dependencies = true)
{
// Turn config into elements. This may emit exceptions.
ElementPtr config_element = Element::fromJSON(config);
// Parse the configuration. This may emit exceptions.
ClientClassDefListParser parser;
- return (parser.parse(config_element, family));
+ return (parser.parse(config_element, family, check_dependencies));
}
};
EXPECT_THROW(parseClientClassDefList(cfg_text, AF_INET6), DhcpConfigError);
}
+// Verifies that error is not reported when a class references another
+// not defined class, but dependency checking is disabled.
+TEST_F(ClientClassDefListParserTest, dependencyCheckingDisabled) {
+ std::string cfg_text =
+ "[ \n"
+ " { \n"
+ " \"name\": \"one\", \n"
+ " \"test\": \"member('foo')\" \n"
+ " } \n"
+ "] \n";
+ try {
+ parseClientClassDefList(cfg_text, AF_INET6, false);
+ } catch ( const std::exception& ex) {
+ std::cout << ex.what() << std::endl;
+ }
+ EXPECT_NO_THROW(parseClientClassDefList(cfg_text, AF_INET6, false));
+}
+
// Verifies that forward dependencies will not parse.
TEST_F(ClientClassDefListParserTest, dependentForwardError) {
std::string cfg_text =