mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-30 21:45:37 +00:00
[5124a] Rebased
This commit is contained in:
@@ -119,6 +119,10 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
|
||||
return isc::dhcp::Dhcp4Parser::make_SUB_POOL4(driver.loc_);
|
||||
case Parser4Context::PARSER_HOST_RESERVATION:
|
||||
return isc::dhcp::Dhcp4Parser::make_SUB_RESERVATION(driver.loc_);
|
||||
case Parser4Context::PARSER_OPTION_DEFS:
|
||||
return isc::dhcp::Dhcp4Parser::make_SUB_OPTION_DEFS(driver.loc_);
|
||||
case Parser4Context::PARSER_OPTION_DEF:
|
||||
return isc::dhcp::Dhcp4Parser::make_SUB_OPTION_DEF(driver.loc_);
|
||||
case Parser4Context::PARSER_OPTION_DATA:
|
||||
return isc::dhcp::Dhcp4Parser::make_SUB_OPTION_DATA(driver.loc_);
|
||||
case Parser4Context::PARSER_HOOKS_LIBRARY:
|
||||
|
@@ -195,6 +195,7 @@ using namespace std;
|
||||
SUB_SUBNET4
|
||||
SUB_POOL4
|
||||
SUB_RESERVATION
|
||||
SUB_OPTION_DEFS
|
||||
SUB_OPTION_DEF
|
||||
SUB_OPTION_DATA
|
||||
SUB_HOOKS_LIBRARY
|
||||
@@ -230,6 +231,7 @@ start: TOPLEVEL_JSON { ctx.ctx_ = ctx.NO_KEYWORD; } sub_json
|
||||
| SUB_SUBNET4 { ctx.ctx_ = ctx.SUBNET4; } sub_subnet4
|
||||
| SUB_POOL4 { ctx.ctx_ = ctx.POOLS; } sub_pool4
|
||||
| SUB_RESERVATION { ctx.ctx_ = ctx.RESERVATIONS; } sub_reservation
|
||||
| SUB_OPTION_DEFS { ctx.ctx_ = ctx.DHCP4; } sub_option_def_list
|
||||
| SUB_OPTION_DEF { ctx.ctx_ = ctx.OPTION_DEF; } sub_option_def
|
||||
| SUB_OPTION_DATA { ctx.ctx_ = ctx.OPTION_DATA; } sub_option_data
|
||||
| SUB_HOOKS_LIBRARY { ctx.ctx_ = ctx.HOOKS_LIBRARIES; } sub_hooks_library
|
||||
@@ -351,6 +353,9 @@ syntax_map: LCURLY_BRACKET {
|
||||
// map parsing completed. If we ever want to do any wrap up
|
||||
// (maybe some sanity checking), this would be the best place
|
||||
// for it.
|
||||
|
||||
// Dhcp4 is required
|
||||
ctx.require("Dhcp4", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
};
|
||||
|
||||
// This represents top-level entries: Control-agent, Dhcp6, Dhcp4,
|
||||
@@ -376,9 +381,7 @@ dhcp4_object: DHCP4 {
|
||||
ctx.stack_.push_back(m);
|
||||
ctx.enter(ctx.DHCP4);
|
||||
} COLON LCURLY_BRACKET global_params RCURLY_BRACKET {
|
||||
// map parsing completed. If we ever want to do any wrap up
|
||||
// (maybe some sanity checking), this would be the best place
|
||||
// for it.
|
||||
// No global parameter is required
|
||||
ctx.stack_.pop_back();
|
||||
ctx.leave();
|
||||
};
|
||||
@@ -390,6 +393,7 @@ sub_dhcp4: LCURLY_BRACKET {
|
||||
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
|
||||
ctx.stack_.push_back(m);
|
||||
} global_params RCURLY_BRACKET {
|
||||
// No global parameter is required
|
||||
// parsing completed
|
||||
};
|
||||
|
||||
@@ -459,6 +463,7 @@ interfaces_config: INTERFACES_CONFIG {
|
||||
ctx.stack_.push_back(i);
|
||||
ctx.enter(ctx.INTERFACES_CONFIG);
|
||||
} COLON LCURLY_BRACKET interfaces_config_params RCURLY_BRACKET {
|
||||
// No interfaces config param is required
|
||||
ctx.stack_.pop_back();
|
||||
ctx.leave();
|
||||
};
|
||||
@@ -477,6 +482,7 @@ sub_interfaces4: LCURLY_BRACKET {
|
||||
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
|
||||
ctx.stack_.push_back(m);
|
||||
} interfaces_config_params RCURLY_BRACKET {
|
||||
// No interfaces config param is required
|
||||
// parsing completed
|
||||
};
|
||||
|
||||
@@ -513,6 +519,8 @@ lease_database: LEASE_DATABASE {
|
||||
ctx.stack_.push_back(i);
|
||||
ctx.enter(ctx.LEASE_DATABASE);
|
||||
} COLON LCURLY_BRACKET database_map_params RCURLY_BRACKET {
|
||||
// The type parameter is required
|
||||
ctx.require("type", ctx.loc2pos(@4), ctx.loc2pos(@6));
|
||||
ctx.stack_.pop_back();
|
||||
ctx.leave();
|
||||
};
|
||||
@@ -523,6 +531,8 @@ hosts_database: HOSTS_DATABASE {
|
||||
ctx.stack_.push_back(i);
|
||||
ctx.enter(ctx.HOSTS_DATABASE);
|
||||
} COLON LCURLY_BRACKET database_map_params RCURLY_BRACKET {
|
||||
// The type parameter is required
|
||||
ctx.require("type", ctx.loc2pos(@4), ctx.loc2pos(@6));
|
||||
ctx.stack_.pop_back();
|
||||
ctx.leave();
|
||||
};
|
||||
@@ -702,6 +712,8 @@ hooks_library: LCURLY_BRACKET {
|
||||
ctx.stack_.back()->add(m);
|
||||
ctx.stack_.push_back(m);
|
||||
} hooks_params RCURLY_BRACKET {
|
||||
// The library hooks parameter is required
|
||||
ctx.require("library", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
ctx.stack_.pop_back();
|
||||
};
|
||||
|
||||
@@ -710,6 +722,8 @@ sub_hooks_library: LCURLY_BRACKET {
|
||||
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
|
||||
ctx.stack_.push_back(m);
|
||||
} hooks_params RCURLY_BRACKET {
|
||||
// The library hooks parameter is required
|
||||
ctx.require("library", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
// parsing completed
|
||||
};
|
||||
|
||||
@@ -744,6 +758,7 @@ expired_leases_processing: EXPIRED_LEASES_PROCESSING {
|
||||
ctx.stack_.push_back(m);
|
||||
ctx.enter(ctx.EXPIRED_LEASES_PROCESSING);
|
||||
} COLON LCURLY_BRACKET expired_leases_params RCURLY_BRACKET {
|
||||
// No expired lease parameter is required
|
||||
ctx.stack_.pop_back();
|
||||
ctx.leave();
|
||||
};
|
||||
@@ -838,6 +853,9 @@ subnet4: LCURLY_BRACKET {
|
||||
// ctx.stack_.back()->set("renew-timer", renew);
|
||||
// }
|
||||
// }
|
||||
|
||||
// The subnet subnet4 parameter is required
|
||||
ctx.require("subnet", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
ctx.stack_.pop_back();
|
||||
};
|
||||
|
||||
@@ -846,6 +864,8 @@ sub_subnet4: LCURLY_BRACKET {
|
||||
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
|
||||
ctx.stack_.push_back(m);
|
||||
} subnet4_params RCURLY_BRACKET {
|
||||
// The subnet subnet4 parameter is required
|
||||
ctx.require("subnet", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
// parsing completed
|
||||
};
|
||||
|
||||
@@ -969,6 +989,16 @@ option_def_list: OPTION_DEF {
|
||||
ctx.leave();
|
||||
};
|
||||
|
||||
// This defines the top level scope when the parser is told to parse
|
||||
// option definitions. It works as a subset limited to option
|
||||
// definitions
|
||||
sub_option_def_list: LCURLY_BRACKET {
|
||||
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
|
||||
ctx.stack_.push_back(m);
|
||||
} option_def_list RCURLY_BRACKET {
|
||||
// parsing completed
|
||||
};
|
||||
|
||||
// This defines the content of option-def. It may be empty,
|
||||
// have one entry or multiple entries separated by comma.
|
||||
option_def_list_content: %empty
|
||||
@@ -986,6 +1016,10 @@ option_def_entry: LCURLY_BRACKET {
|
||||
ctx.stack_.back()->add(m);
|
||||
ctx.stack_.push_back(m);
|
||||
} option_def_params RCURLY_BRACKET {
|
||||
// The name, code and type option def parameters are required.
|
||||
ctx.require("name", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
ctx.require("code", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
ctx.require("type", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
ctx.stack_.pop_back();
|
||||
};
|
||||
|
||||
@@ -997,6 +1031,10 @@ sub_option_def: LCURLY_BRACKET {
|
||||
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
|
||||
ctx.stack_.push_back(m);
|
||||
} option_def_params RCURLY_BRACKET {
|
||||
// The name, code and type option def parameters are required.
|
||||
ctx.require("name", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
ctx.require("code", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
ctx.require("type", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
// parsing completed
|
||||
};
|
||||
|
||||
@@ -1101,6 +1139,7 @@ option_data_entry: LCURLY_BRACKET {
|
||||
ctx.stack_.back()->add(m);
|
||||
ctx.stack_.push_back(m);
|
||||
} option_data_params RCURLY_BRACKET {
|
||||
/// @todo: the code or name parameters are required.
|
||||
ctx.stack_.pop_back();
|
||||
};
|
||||
|
||||
@@ -1112,6 +1151,7 @@ sub_option_data: LCURLY_BRACKET {
|
||||
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
|
||||
ctx.stack_.push_back(m);
|
||||
} option_data_params RCURLY_BRACKET {
|
||||
/// @todo: the code or name parameters are required.
|
||||
// parsing completed
|
||||
};
|
||||
|
||||
@@ -1191,6 +1231,8 @@ pool_list_entry: LCURLY_BRACKET {
|
||||
ctx.stack_.back()->add(m);
|
||||
ctx.stack_.push_back(m);
|
||||
} pool_params RCURLY_BRACKET {
|
||||
// The pool parameter is required.
|
||||
ctx.require("pool", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
ctx.stack_.pop_back();
|
||||
};
|
||||
|
||||
@@ -1199,6 +1241,8 @@ sub_pool4: LCURLY_BRACKET {
|
||||
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
|
||||
ctx.stack_.push_back(m);
|
||||
} pool_params RCURLY_BRACKET {
|
||||
// The pool parameter is required.
|
||||
ctx.require("pool", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
// parsing completed
|
||||
};
|
||||
|
||||
@@ -1253,6 +1297,7 @@ reservation: LCURLY_BRACKET {
|
||||
ctx.stack_.back()->add(m);
|
||||
ctx.stack_.push_back(m);
|
||||
} reservation_params RCURLY_BRACKET {
|
||||
/// @todo: an identifier parameter is required.
|
||||
ctx.stack_.pop_back();
|
||||
};
|
||||
|
||||
@@ -1261,6 +1306,7 @@ sub_reservation: LCURLY_BRACKET {
|
||||
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
|
||||
ctx.stack_.push_back(m);
|
||||
} reservation_params RCURLY_BRACKET {
|
||||
/// @todo: an identifier parameter is required.
|
||||
// parsing completed
|
||||
};
|
||||
|
||||
@@ -1272,7 +1318,7 @@ not_empty_reservation_params: reservation_param
|
||||
| not_empty_reservation_params COMMA reservation_param
|
||||
;
|
||||
|
||||
// @todo probably need to add mac-address as well here
|
||||
/// @todo probably need to add mac-address as well here
|
||||
reservation_param: duid
|
||||
| reservation_client_classes
|
||||
| client_id_value
|
||||
@@ -1421,6 +1467,8 @@ client_class: LCURLY_BRACKET {
|
||||
ctx.stack_.back()->add(m);
|
||||
ctx.stack_.push_back(m);
|
||||
} client_class_params RCURLY_BRACKET {
|
||||
// The name client class parameter is required.
|
||||
ctx.require("name", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
ctx.stack_.pop_back();
|
||||
};
|
||||
|
||||
@@ -1504,6 +1552,8 @@ dhcp_ddns: DHCP_DDNS {
|
||||
ctx.stack_.push_back(m);
|
||||
ctx.enter(ctx.DHCP_DDNS);
|
||||
} COLON LCURLY_BRACKET dhcp_ddns_params RCURLY_BRACKET {
|
||||
// The enable updates DHCP DDNS parameter is required.
|
||||
ctx.require("enable-updates", ctx.loc2pos(@4), ctx.loc2pos(@6));
|
||||
ctx.stack_.pop_back();
|
||||
ctx.leave();
|
||||
};
|
||||
@@ -1513,6 +1563,8 @@ sub_dhcp_ddns: LCURLY_BRACKET {
|
||||
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
|
||||
ctx.stack_.push_back(m);
|
||||
} dhcp_ddns_params RCURLY_BRACKET {
|
||||
// The enable updates DHCP DDNS parameter is required.
|
||||
ctx.require("enable-updates", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
// parsing completed
|
||||
};
|
||||
|
||||
|
@@ -74,13 +74,13 @@ Parser4Context::error(const isc::dhcp::location& loc, const std::string& what)
|
||||
}
|
||||
|
||||
void
|
||||
Parser4Context::error (const std::string& what)
|
||||
Parser4Context::error(const std::string& what)
|
||||
{
|
||||
isc_throw(Dhcp4ParseError, what);
|
||||
}
|
||||
|
||||
void
|
||||
Parser4Context::fatal (const std::string& what)
|
||||
Parser4Context::fatal(const std::string& what)
|
||||
{
|
||||
isc_throw(Dhcp4ParseError, what);
|
||||
}
|
||||
@@ -94,6 +94,21 @@ Parser4Context::loc2pos(isc::dhcp::location& loc)
|
||||
return (isc::data::Element::Position(file, line, pos));
|
||||
}
|
||||
|
||||
void
|
||||
Parser4Context::require(const std::string& name,
|
||||
isc::data::Element::Position open_loc,
|
||||
isc::data::Element::Position close_loc)
|
||||
{
|
||||
ConstElementPtr value = stack_.back()->get(name);
|
||||
if (!value) {
|
||||
isc_throw(Dhcp4ParseError,
|
||||
"missing parameter '" << name << "' ("
|
||||
<< stack_.back()->getPosition() << ") ["
|
||||
<< contextName() << " map between "
|
||||
<< open_loc << " and " << close_loc << "]");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Parser4Context::enter(const ParserContext& ctx)
|
||||
{
|
||||
|
@@ -73,6 +73,9 @@ public:
|
||||
/// This will parse the input as host-reservation.
|
||||
PARSER_HOST_RESERVATION,
|
||||
|
||||
/// This will parse the input option definitions (for tests).
|
||||
PARSER_OPTION_DEFS,
|
||||
|
||||
/// This will parse the input as option definition.
|
||||
PARSER_OPTION_DEF,
|
||||
|
||||
@@ -176,6 +179,19 @@ public:
|
||||
/// @return Position in format accepted by Element
|
||||
isc::data::Element::Position loc2pos(isc::dhcp::location& loc);
|
||||
|
||||
/// @brief Check if a required parameter is present
|
||||
///
|
||||
/// Check if a required parameter is present in the map at the top
|
||||
/// of the stack and raise an error when it is not.
|
||||
///
|
||||
/// @param name name of the parameter to check
|
||||
/// @param open_loc location of the opening curly bracket
|
||||
/// @param close_loc ocation of the closing curly bracket
|
||||
/// @throw Dhcp4ParseError
|
||||
void require(const std::string& name,
|
||||
isc::data::Element::Position open_loc,
|
||||
isc::data::Element::Position close_loc);
|
||||
|
||||
/// @brief Defines syntactic contexts for lexical tie-ins
|
||||
typedef enum {
|
||||
///< This one is used in pure JSON mode.
|
||||
|
@@ -1618,7 +1618,7 @@ TEST_F(Dhcp4ParserTest, optionDefIpv4Address) {
|
||||
" } ]"
|
||||
"}";
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config, true));
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEFS(config, true));
|
||||
extractConfig(config);
|
||||
|
||||
// Make sure that the particular option definition does not exist.
|
||||
@@ -1659,10 +1659,8 @@ TEST_F(Dhcp4ParserTest, optionDefIpv4Address) {
|
||||
|
||||
// Let's apply empty configuration. This removes the option definitions
|
||||
// configuration and should result in removal of the option 100 from the
|
||||
// libdhcp++.
|
||||
config = "{ }";
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config, true));
|
||||
|
||||
// libdhcp++. Note DHCP4 or OPTION_DEFS parsers do not accept empty maps.
|
||||
json.reset(new MapElement());
|
||||
ASSERT_NO_THROW(status = configureDhcp4Server(*srv_, json));
|
||||
checkResult(status, 0);
|
||||
|
||||
@@ -1685,7 +1683,7 @@ TEST_F(Dhcp4ParserTest, optionDefRecord) {
|
||||
" } ]"
|
||||
"}";
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config));
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
|
||||
extractConfig(config);
|
||||
|
||||
// Make sure that the particular option definition does not exist.
|
||||
@@ -1740,7 +1738,7 @@ TEST_F(Dhcp4ParserTest, optionDefMultiple) {
|
||||
" } ]"
|
||||
"}";
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config));
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
|
||||
extractConfig(config);
|
||||
|
||||
// Make sure that the option definitions do not exist yet.
|
||||
@@ -1810,7 +1808,7 @@ TEST_F(Dhcp4ParserTest, optionDefDuplicate) {
|
||||
" } ]"
|
||||
"}";
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config));
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
|
||||
|
||||
// Make sure that the option definition does not exist yet.
|
||||
ASSERT_FALSE(CfgMgr::instance().getStagingCfg()->
|
||||
@@ -1849,7 +1847,7 @@ TEST_F(Dhcp4ParserTest, optionDefArray) {
|
||||
" } ]"
|
||||
"}";
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config));
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
|
||||
extractConfig(config);
|
||||
|
||||
// Make sure that the particular option definition does not exist.
|
||||
@@ -1892,7 +1890,7 @@ TEST_F(Dhcp4ParserTest, optionDefEncapsulate) {
|
||||
" } ]"
|
||||
"}";
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config));
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
|
||||
extractConfig(config);
|
||||
|
||||
// Make sure that the particular option definition does not exist.
|
||||
@@ -1933,7 +1931,7 @@ TEST_F(Dhcp4ParserTest, optionDefInvalidName) {
|
||||
" } ]"
|
||||
"}";
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config));
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
|
||||
|
||||
// Use the configuration string to create new option definition.
|
||||
ConstElementPtr status;
|
||||
@@ -1958,7 +1956,7 @@ TEST_F(Dhcp4ParserTest, optionDefInvalidType) {
|
||||
" } ]"
|
||||
"}";
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config));
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
|
||||
|
||||
// Use the configuration string to create new option definition.
|
||||
ConstElementPtr status;
|
||||
@@ -1984,7 +1982,7 @@ TEST_F(Dhcp4ParserTest, optionDefInvalidRecordType) {
|
||||
" } ]"
|
||||
"}";
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config));
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
|
||||
|
||||
// Use the configuration string to create new option definition.
|
||||
ConstElementPtr status;
|
||||
@@ -2010,7 +2008,7 @@ TEST_F(Dhcp4ParserTest, optionIntegerTypes) {
|
||||
" } ]"
|
||||
"}";
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config));
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
|
||||
|
||||
// Use the configuration string to create new option definition.
|
||||
ConstElementPtr status;
|
||||
@@ -2035,7 +2033,7 @@ TEST_F(Dhcp4ParserTest, optionDefInvalidEncapsulatedSpace) {
|
||||
" } ]"
|
||||
"}";
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config));
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
|
||||
|
||||
// Use the configuration string to create new option definition.
|
||||
ConstElementPtr status;
|
||||
@@ -2064,7 +2062,7 @@ TEST_F(Dhcp4ParserTest, optionDefEncapsulatedSpaceAndArray) {
|
||||
" } ]"
|
||||
"}";
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config));
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
|
||||
|
||||
// Use the configuration string to create new option definition.
|
||||
ConstElementPtr status;
|
||||
@@ -2090,7 +2088,7 @@ TEST_F(Dhcp4ParserTest, optionDefEncapsulateOwnSpace) {
|
||||
" } ]"
|
||||
"}";
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config));
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
|
||||
|
||||
// Use the configuration string to create new option definition.
|
||||
ConstElementPtr status;
|
||||
@@ -2119,7 +2117,7 @@ TEST_F(Dhcp4ParserTest, optionStandardDefOverride) {
|
||||
" } ]"
|
||||
"}";
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config));
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
|
||||
extractConfig(config);
|
||||
|
||||
OptionDefinitionPtr def = CfgMgr::instance().getStagingCfg()->
|
||||
@@ -2154,7 +2152,7 @@ TEST_F(Dhcp4ParserTest, optionStandardDefOverride) {
|
||||
" \"space\": \"dhcp4\""
|
||||
" } ]"
|
||||
"}";
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config));
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
|
||||
|
||||
// Use the configuration string to create new option definition.
|
||||
EXPECT_NO_THROW(status = configureDhcp4Server(*srv_, json));
|
||||
@@ -2176,7 +2174,7 @@ TEST_F(Dhcp4ParserTest, optionStandardDefOverride) {
|
||||
" \"space\": \"dhcp4\""
|
||||
" } ]"
|
||||
"}";
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config));
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
|
||||
extractConfig(config);
|
||||
|
||||
// Use the configuration string to create new option definition.
|
||||
|
@@ -536,11 +536,11 @@ parseDHCP4(const std::string& in, bool verbose = false)
|
||||
/// @param verbose display the exception message when it fails
|
||||
/// @return ElementPtr structure representing parsed JSON
|
||||
inline isc::data::ElementPtr
|
||||
parseOPTION_DEF(const std::string& in, bool verbose = false)
|
||||
parseOPTION_DEFS(const std::string& in, bool verbose = false)
|
||||
{
|
||||
try {
|
||||
isc::dhcp::Parser4Context ctx;
|
||||
return (ctx.parseString(in, isc::dhcp::Parser4Context::PARSER_OPTION_DEF));
|
||||
return (ctx.parseString(in, isc::dhcp::Parser4Context::PARSER_OPTION_DEFS));
|
||||
}
|
||||
catch (const std::exception& ex) {
|
||||
if (verbose) {
|
||||
|
@@ -501,6 +501,13 @@ TEST(ParserTest, errors) {
|
||||
Parser4Context::PARSER_DHCP4,
|
||||
"<string>:2.2-17: got unexpected keyword "
|
||||
"\"valid_lifetime\" in Dhcp4 map.");
|
||||
|
||||
// missing parameter
|
||||
testError("{ \"name\": \"foo\",\n"
|
||||
" \"code\": 123 }\n",
|
||||
Parser4Context::PARSER_OPTION_DEF,
|
||||
"missing parameter 'type' (<string>:1:1) "
|
||||
"[option-def map between <string>:1:1 and <string>:2:15]");
|
||||
}
|
||||
|
||||
// Check unicode escapes
|
||||
|
@@ -121,6 +121,10 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
|
||||
return isc::dhcp::Dhcp6Parser::make_SUB_PD_POOL(driver.loc_);
|
||||
case Parser6Context::PARSER_HOST_RESERVATION:
|
||||
return isc::dhcp::Dhcp6Parser::make_SUB_RESERVATION(driver.loc_);
|
||||
case Parser6Context::PARSER_OPTION_DEFS:
|
||||
return isc::dhcp::Dhcp6Parser::make_SUB_OPTION_DEFS(driver.loc_);
|
||||
case Parser6Context::PARSER_OPTION_DEF:
|
||||
return isc::dhcp::Dhcp6Parser::make_SUB_OPTION_DEF(driver.loc_);
|
||||
case Parser6Context::PARSER_OPTION_DATA:
|
||||
return isc::dhcp::Dhcp6Parser::make_SUB_OPTION_DATA(driver.loc_);
|
||||
case Parser6Context::PARSER_HOOKS_LIBRARY:
|
||||
|
@@ -203,6 +203,7 @@ using namespace std;
|
||||
SUB_POOL6
|
||||
SUB_PD_POOL
|
||||
SUB_RESERVATION
|
||||
SUB_OPTION_DEFS
|
||||
SUB_OPTION_DEF
|
||||
SUB_OPTION_DATA
|
||||
SUB_HOOKS_LIBRARY
|
||||
@@ -239,6 +240,7 @@ start: TOPLEVEL_JSON { ctx.ctx_ = ctx.NO_KEYWORD; } sub_json
|
||||
| SUB_POOL6 { ctx.ctx_ = ctx.POOLS; } sub_pool6
|
||||
| SUB_PD_POOL { ctx.ctx_ = ctx.PD_POOLS; } sub_pd_pool
|
||||
| SUB_RESERVATION { ctx.ctx_ = ctx.RESERVATIONS; } sub_reservation
|
||||
| SUB_OPTION_DEFS { ctx.ctx_ = ctx.DHCP6; } sub_option_def_list
|
||||
| SUB_OPTION_DEF { ctx.ctx_ = ctx.OPTION_DEF; } sub_option_def
|
||||
| SUB_OPTION_DATA { ctx.ctx_ = ctx.OPTION_DATA; } sub_option_data
|
||||
| SUB_HOOKS_LIBRARY { ctx.ctx_ = ctx.HOOKS_LIBRARIES; } sub_hooks_library
|
||||
@@ -360,6 +362,9 @@ syntax_map: LCURLY_BRACKET {
|
||||
// map parsing completed. If we ever want to do any wrap up
|
||||
// (maybe some sanity checking), this would be the best place
|
||||
// for it.
|
||||
|
||||
// Dhcp6 is required
|
||||
ctx.require("Dhcp6", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
};
|
||||
|
||||
// This represents top-level entries: Dhcp6, Dhcp4, DhcpDdns, Logging
|
||||
@@ -384,9 +389,7 @@ dhcp6_object: DHCP6 {
|
||||
ctx.stack_.push_back(m);
|
||||
ctx.enter(ctx.DHCP6);
|
||||
} COLON LCURLY_BRACKET global_params RCURLY_BRACKET {
|
||||
// map parsing completed. If we ever want to do any wrap up
|
||||
// (maybe some sanity checking), this would be the best place
|
||||
// for it.
|
||||
// No global parameter is required
|
||||
ctx.stack_.pop_back();
|
||||
ctx.leave();
|
||||
};
|
||||
@@ -398,6 +401,7 @@ sub_dhcp6: LCURLY_BRACKET {
|
||||
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
|
||||
ctx.stack_.push_back(m);
|
||||
} global_params RCURLY_BRACKET {
|
||||
// No global parameter is required
|
||||
// parsing completed
|
||||
};
|
||||
|
||||
@@ -462,6 +466,7 @@ interfaces_config: INTERFACES_CONFIG {
|
||||
ctx.stack_.push_back(i);
|
||||
ctx.enter(ctx.INTERFACES_CONFIG);
|
||||
} COLON LCURLY_BRACKET interfaces_config_params RCURLY_BRACKET {
|
||||
// No interfaces config param is required
|
||||
ctx.stack_.pop_back();
|
||||
ctx.leave();
|
||||
};
|
||||
@@ -471,6 +476,7 @@ sub_interfaces6: LCURLY_BRACKET {
|
||||
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
|
||||
ctx.stack_.push_back(m);
|
||||
} interfaces_config_params RCURLY_BRACKET {
|
||||
// No interfaces config param is required
|
||||
// parsing completed
|
||||
};
|
||||
|
||||
@@ -504,6 +510,8 @@ lease_database: LEASE_DATABASE {
|
||||
ctx.stack_.push_back(i);
|
||||
ctx.enter(ctx.LEASE_DATABASE);
|
||||
} COLON LCURLY_BRACKET database_map_params RCURLY_BRACKET {
|
||||
// The type parameter is required
|
||||
ctx.require("type", ctx.loc2pos(@4), ctx.loc2pos(@6));
|
||||
ctx.stack_.pop_back();
|
||||
ctx.leave();
|
||||
};
|
||||
@@ -514,6 +522,8 @@ hosts_database: HOSTS_DATABASE {
|
||||
ctx.stack_.push_back(i);
|
||||
ctx.enter(ctx.HOSTS_DATABASE);
|
||||
} COLON LCURLY_BRACKET database_map_params RCURLY_BRACKET {
|
||||
// The type parameter is required
|
||||
ctx.require("type", ctx.loc2pos(@4), ctx.loc2pos(@6));
|
||||
ctx.stack_.pop_back();
|
||||
ctx.leave();
|
||||
};
|
||||
@@ -716,6 +726,8 @@ hooks_library: LCURLY_BRACKET {
|
||||
ctx.stack_.back()->add(m);
|
||||
ctx.stack_.push_back(m);
|
||||
} hooks_params RCURLY_BRACKET {
|
||||
// The library hooks parameter is required
|
||||
ctx.require("library", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
ctx.stack_.pop_back();
|
||||
};
|
||||
|
||||
@@ -724,6 +736,8 @@ sub_hooks_library: LCURLY_BRACKET {
|
||||
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
|
||||
ctx.stack_.push_back(m);
|
||||
} hooks_params RCURLY_BRACKET {
|
||||
// The library hooks parameter is required
|
||||
ctx.require("library", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
// parsing completed
|
||||
};
|
||||
|
||||
@@ -758,6 +772,7 @@ expired_leases_processing: EXPIRED_LEASES_PROCESSING {
|
||||
ctx.stack_.push_back(m);
|
||||
ctx.enter(ctx.EXPIRED_LEASES_PROCESSING);
|
||||
} COLON LCURLY_BRACKET expired_leases_params RCURLY_BRACKET {
|
||||
// No expired lease parameter is required
|
||||
ctx.stack_.pop_back();
|
||||
ctx.leave();
|
||||
};
|
||||
@@ -852,6 +867,9 @@ subnet6: LCURLY_BRACKET {
|
||||
// ctx.stack_.back()->set("renew-timer", renew);
|
||||
// }
|
||||
// }
|
||||
|
||||
// The subnet subnet6 parameter is required
|
||||
ctx.require("subnet", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
ctx.stack_.pop_back();
|
||||
};
|
||||
|
||||
@@ -860,6 +878,8 @@ sub_subnet6: LCURLY_BRACKET {
|
||||
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
|
||||
ctx.stack_.push_back(m);
|
||||
} subnet6_params RCURLY_BRACKET {
|
||||
// The subnet subnet6 parameter is required
|
||||
ctx.require("subnet", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
// parsing completed
|
||||
};
|
||||
|
||||
@@ -956,6 +976,16 @@ option_def_list: OPTION_DEF {
|
||||
ctx.leave();
|
||||
};
|
||||
|
||||
// This defines the top level scope when the parser is told to parse
|
||||
// option definitions. It works as a subset limited to option
|
||||
// definitions
|
||||
sub_option_def_list: LCURLY_BRACKET {
|
||||
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
|
||||
ctx.stack_.push_back(m);
|
||||
} option_def_list RCURLY_BRACKET {
|
||||
// parsing completed
|
||||
};
|
||||
|
||||
// This defines the content of option-def. It may be empty,
|
||||
// have one entry or multiple entries separated by comma.
|
||||
option_def_list_content: %empty
|
||||
@@ -973,6 +1003,10 @@ option_def_entry: LCURLY_BRACKET {
|
||||
ctx.stack_.back()->add(m);
|
||||
ctx.stack_.push_back(m);
|
||||
} option_def_params RCURLY_BRACKET {
|
||||
// The name, code and type option def parameters are required.
|
||||
ctx.require("name", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
ctx.require("code", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
ctx.require("type", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
ctx.stack_.pop_back();
|
||||
};
|
||||
|
||||
@@ -984,6 +1018,10 @@ sub_option_def: LCURLY_BRACKET {
|
||||
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
|
||||
ctx.stack_.push_back(m);
|
||||
} option_def_params RCURLY_BRACKET {
|
||||
// The name, code and type option def parameters are required.
|
||||
ctx.require("name", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
ctx.require("code", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
ctx.require("type", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
// parsing completed
|
||||
};
|
||||
|
||||
@@ -1088,6 +1126,7 @@ option_data_entry: LCURLY_BRACKET {
|
||||
ctx.stack_.back()->add(m);
|
||||
ctx.stack_.push_back(m);
|
||||
} option_data_params RCURLY_BRACKET {
|
||||
/// @todo: the code or name parameters are required.
|
||||
ctx.stack_.pop_back();
|
||||
};
|
||||
|
||||
@@ -1099,6 +1138,7 @@ sub_option_data: LCURLY_BRACKET {
|
||||
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
|
||||
ctx.stack_.push_back(m);
|
||||
} option_data_params RCURLY_BRACKET {
|
||||
/// @todo: the code or name parameters are required.
|
||||
// parsing completed
|
||||
};
|
||||
|
||||
@@ -1178,6 +1218,8 @@ pool_list_entry: LCURLY_BRACKET {
|
||||
ctx.stack_.back()->add(m);
|
||||
ctx.stack_.push_back(m);
|
||||
} pool_params RCURLY_BRACKET {
|
||||
// The pool parameter is required.
|
||||
ctx.require("pool", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
ctx.stack_.pop_back();
|
||||
};
|
||||
|
||||
@@ -1186,7 +1228,8 @@ sub_pool6: LCURLY_BRACKET {
|
||||
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
|
||||
ctx.stack_.push_back(m);
|
||||
} pool_params RCURLY_BRACKET {
|
||||
// parsing completed
|
||||
// The pool parameter is required.
|
||||
ctx.require("pool", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
};
|
||||
|
||||
pool_params: pool_param
|
||||
@@ -1242,6 +1285,10 @@ pd_pool_entry: LCURLY_BRACKET {
|
||||
ctx.stack_.back()->add(m);
|
||||
ctx.stack_.push_back(m);
|
||||
} pd_pool_params RCURLY_BRACKET {
|
||||
// The prefix, prefix len and delegated len parameters are required.
|
||||
ctx.require("prefix", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
ctx.require("prefix-len", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
ctx.require("delegated-len", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
ctx.stack_.pop_back();
|
||||
};
|
||||
|
||||
@@ -1250,6 +1297,10 @@ sub_pd_pool: LCURLY_BRACKET {
|
||||
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
|
||||
ctx.stack_.push_back(m);
|
||||
} pd_pool_params RCURLY_BRACKET {
|
||||
// The prefix, prefix len and delegated len parameters are required.
|
||||
ctx.require("prefix", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
ctx.require("prefix-len", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
ctx.require("delegated-len", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
// parsing completed
|
||||
};
|
||||
|
||||
@@ -1324,6 +1375,7 @@ reservation: LCURLY_BRACKET {
|
||||
ctx.stack_.back()->add(m);
|
||||
ctx.stack_.push_back(m);
|
||||
} reservation_params RCURLY_BRACKET {
|
||||
/// @todo: an identifier parameter is required.
|
||||
ctx.stack_.pop_back();
|
||||
};
|
||||
|
||||
@@ -1332,6 +1384,7 @@ sub_reservation: LCURLY_BRACKET {
|
||||
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
|
||||
ctx.stack_.push_back(m);
|
||||
} reservation_params RCURLY_BRACKET {
|
||||
/// @todo: an identifier parameter is required.
|
||||
// parsing completed
|
||||
};
|
||||
|
||||
@@ -1343,7 +1396,7 @@ not_empty_reservation_params: reservation_param
|
||||
| not_empty_reservation_params COMMA reservation_param
|
||||
;
|
||||
|
||||
// @todo probably need to add mac-address as well here
|
||||
/// @todo probably need to add mac-address as well here
|
||||
reservation_param: duid
|
||||
| reservation_client_classes
|
||||
| ip_addresses
|
||||
@@ -1460,6 +1513,8 @@ client_class: LCURLY_BRACKET {
|
||||
ctx.stack_.back()->add(m);
|
||||
ctx.stack_.push_back(m);
|
||||
} client_class_params RCURLY_BRACKET {
|
||||
// The name client class parameter is required.
|
||||
ctx.require("name", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
ctx.stack_.pop_back();
|
||||
};
|
||||
|
||||
@@ -1496,6 +1551,8 @@ server_id: SERVER_ID {
|
||||
ctx.stack_.push_back(m);
|
||||
ctx.enter(ctx.SERVER_ID);
|
||||
} COLON LCURLY_BRACKET server_id_params RCURLY_BRACKET {
|
||||
// The type parameter is required.
|
||||
ctx.require("type", ctx.loc2pos(@4), ctx.loc2pos(@6));
|
||||
ctx.stack_.pop_back();
|
||||
ctx.leave();
|
||||
};
|
||||
@@ -1599,6 +1656,8 @@ dhcp_ddns: DHCP_DDNS {
|
||||
ctx.stack_.push_back(m);
|
||||
ctx.enter(ctx.DHCP_DDNS);
|
||||
} COLON LCURLY_BRACKET dhcp_ddns_params RCURLY_BRACKET {
|
||||
// The enable updates DHCP DDNS parameter is required.
|
||||
ctx.require("enable-updates", ctx.loc2pos(@4), ctx.loc2pos(@6));
|
||||
ctx.stack_.pop_back();
|
||||
ctx.leave();
|
||||
};
|
||||
@@ -1608,6 +1667,8 @@ sub_dhcp_ddns: LCURLY_BRACKET {
|
||||
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
|
||||
ctx.stack_.push_back(m);
|
||||
} dhcp_ddns_params RCURLY_BRACKET {
|
||||
// The enable updates DHCP DDNS parameter is required.
|
||||
ctx.require("enable-updates", ctx.loc2pos(@1), ctx.loc2pos(@4));
|
||||
// parsing completed
|
||||
};
|
||||
|
||||
|
@@ -94,6 +94,21 @@ Parser6Context::loc2pos(isc::dhcp::location& loc)
|
||||
return (isc::data::Element::Position(file, line, pos));
|
||||
}
|
||||
|
||||
void
|
||||
Parser6Context::require(const std::string& name,
|
||||
isc::data::Element::Position open_loc,
|
||||
isc::data::Element::Position close_loc)
|
||||
{
|
||||
ConstElementPtr value = stack_.back()->get(name);
|
||||
if (!value) {
|
||||
isc_throw(Dhcp6ParseError,
|
||||
"missing parameter '" << name << "' ("
|
||||
<< stack_.back()->getPosition() << ") ["
|
||||
<< contextName() << " map between "
|
||||
<< open_loc << " and " << close_loc << "]");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Parser6Context::enter(const ParserContext& ctx)
|
||||
{
|
||||
|
@@ -76,6 +76,9 @@ public:
|
||||
/// This will parse the input as host-reservation.
|
||||
PARSER_HOST_RESERVATION,
|
||||
|
||||
/// This will parse the input option definitions (for tests).
|
||||
PARSER_OPTION_DEFS,
|
||||
|
||||
/// This will parse the input as option definition.
|
||||
PARSER_OPTION_DEF,
|
||||
|
||||
@@ -179,6 +182,19 @@ public:
|
||||
/// @return Position in format accepted by Element
|
||||
isc::data::Element::Position loc2pos(isc::dhcp::location& loc);
|
||||
|
||||
/// @brief Check if a required parameter is present
|
||||
///
|
||||
/// Check if a required parameter is present in the map at the top
|
||||
/// of the stack and raise an error when it is not.
|
||||
///
|
||||
/// @param name name of the parameter expected to be present
|
||||
/// @param open_loc location of the opening curly bracket
|
||||
/// @param close_loc ocation of the closing curly bracket
|
||||
/// @throw Dhcp6ParseError
|
||||
void require(const std::string& name,
|
||||
isc::data::Element::Position open_loc,
|
||||
isc::data::Element::Position close_loc);
|
||||
|
||||
/// @brief Defines syntactic contexts for lexical tie-ins
|
||||
typedef enum {
|
||||
///< This one is used in pure JSON mode.
|
||||
|
@@ -1998,7 +1998,13 @@ TEST_F(Dhcp6ParserTest, invalidPdPools) {
|
||||
int num_msgs = sizeof(config)/sizeof(char*);
|
||||
for (unsigned int i = 0; i < num_msgs; i++) {
|
||||
// Convert JSON string to Elements.
|
||||
ASSERT_NO_THROW(json = parseDHCP6(config[i]));
|
||||
// The 3 first configs should fail to parse.
|
||||
if (i < 3) {
|
||||
EXPECT_THROW(parseDHCP6(config[i]), Dhcp6ParseError);
|
||||
json = parseJSON(config[i]);
|
||||
} else {
|
||||
ASSERT_NO_THROW(json = parseDHCP6(config[i]));
|
||||
}
|
||||
|
||||
// Configuration processing should fail without a throw.
|
||||
ASSERT_NO_THROW(x = configureDhcp6Server(srv_, json));
|
||||
@@ -2024,7 +2030,7 @@ TEST_F(Dhcp6ParserTest, optionDefIpv6Address) {
|
||||
" } ]"
|
||||
"}";
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config));
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
|
||||
extractConfig(config);
|
||||
|
||||
// Make sure that the particular option definition does not exist.
|
||||
@@ -2064,9 +2070,8 @@ TEST_F(Dhcp6ParserTest, optionDefIpv6Address) {
|
||||
|
||||
// Let's apply empty configuration. This removes the option definitions
|
||||
// configuration and should result in removal of the option 100 from the
|
||||
// libdhcp++.
|
||||
config = "{ }";
|
||||
json = parseOPTION_DEF(config);
|
||||
// libdhcp++. Note DHCP6 or OPTION_DEFS parsers do not accept empty maps.
|
||||
json.reset(new MapElement());
|
||||
ASSERT_NO_THROW(status = configureDhcp6Server(srv_, json));
|
||||
checkResult(status, 0);
|
||||
|
||||
@@ -2089,7 +2094,7 @@ TEST_F(Dhcp6ParserTest, optionDefRecord) {
|
||||
" } ]"
|
||||
"}";
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config));
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
|
||||
extractConfig(config);
|
||||
|
||||
// Make sure that the particular option definition does not exist.
|
||||
@@ -2143,7 +2148,7 @@ TEST_F(Dhcp6ParserTest, optionDefMultiple) {
|
||||
" } ]"
|
||||
"}";
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config));
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
|
||||
extractConfig(config);
|
||||
|
||||
// Make sure that the option definitions do not exist yet.
|
||||
@@ -2211,7 +2216,7 @@ TEST_F(Dhcp6ParserTest, optionDefDuplicate) {
|
||||
" } ]"
|
||||
"}";
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config));
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
|
||||
|
||||
// Make sure that the option definition does not exist yet.
|
||||
ASSERT_FALSE(CfgMgr::instance().getStagingCfg()->
|
||||
@@ -2250,7 +2255,7 @@ TEST_F(Dhcp6ParserTest, optionDefArray) {
|
||||
" } ]"
|
||||
"}";
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config));
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
|
||||
extractConfig(config);
|
||||
|
||||
// Make sure that the particular option definition does not exist.
|
||||
@@ -2291,7 +2296,7 @@ TEST_F(Dhcp6ParserTest, optionDefEncapsulate) {
|
||||
" } ]"
|
||||
"}";
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config));
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
|
||||
extractConfig(config);
|
||||
|
||||
// Make sure that the particular option definition does not exist.
|
||||
@@ -2331,7 +2336,7 @@ TEST_F(Dhcp6ParserTest, optionDefInvalidName) {
|
||||
" } ]"
|
||||
"}";
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config));
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
|
||||
|
||||
// Use the configuration string to create new option definition.
|
||||
ConstElementPtr status;
|
||||
@@ -2356,7 +2361,7 @@ TEST_F(Dhcp6ParserTest, optionDefInvalidType) {
|
||||
" } ]"
|
||||
"}";
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config));
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
|
||||
|
||||
// Use the configuration string to create new option definition.
|
||||
ConstElementPtr status;
|
||||
@@ -2382,7 +2387,7 @@ TEST_F(Dhcp6ParserTest, optionDefInvalidRecordType) {
|
||||
" } ]"
|
||||
"}";
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config));
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
|
||||
|
||||
// Use the configuration string to create new option definition.
|
||||
ConstElementPtr status;
|
||||
@@ -2408,7 +2413,7 @@ TEST_F(Dhcp6ParserTest, optionIntegerTypes) {
|
||||
" } ]"
|
||||
"}";
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config));
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
|
||||
|
||||
// Use the configuration string to create new option definition.
|
||||
ConstElementPtr status;
|
||||
@@ -2434,7 +2439,7 @@ TEST_F(Dhcp6ParserTest, optionDefInvalidEncapsulatedSpace) {
|
||||
" } ]"
|
||||
"}";
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config));
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
|
||||
|
||||
// Use the configuration string to create new option definition.
|
||||
ConstElementPtr status;
|
||||
@@ -2463,7 +2468,7 @@ TEST_F(Dhcp6ParserTest, optionDefEncapsulatedSpaceAndArray) {
|
||||
" } ]"
|
||||
"}";
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config));
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
|
||||
|
||||
// Use the configuration string to create new option definition.
|
||||
ConstElementPtr status;
|
||||
@@ -2489,7 +2494,7 @@ TEST_F(Dhcp6ParserTest, optionDefEncapsulateOwnSpace) {
|
||||
" } ]"
|
||||
"}";
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config));
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
|
||||
|
||||
// Use the configuration string to create new option definition.
|
||||
ConstElementPtr status;
|
||||
@@ -2519,7 +2524,7 @@ TEST_F(Dhcp6ParserTest, optionStandardDefOverride) {
|
||||
" } ]"
|
||||
"}";
|
||||
ConstElementPtr json;
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEF(config));
|
||||
ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
|
||||
|
||||
OptionDefinitionPtr def = CfgMgr::instance().getStagingCfg()->
|
||||
getCfgOptionDef()->get(DHCP6_OPTION_SPACE, 100);
|
||||
@@ -2553,7 +2558,7 @@ TEST_F(Dhcp6ParserTest, optionStandardDefOverride) {
|
||||
" \"space\": \"dhcp6\""
|
||||
" } ]"
|
||||
"}";
|
||||
json = parseOPTION_DEF(config);
|
||||
json = parseOPTION_DEFS(config);
|
||||
|
||||
// Use the configuration string to create new option definition.
|
||||
EXPECT_NO_THROW(status = configureDhcp6Server(srv_, json));
|
||||
@@ -2575,7 +2580,7 @@ TEST_F(Dhcp6ParserTest, optionStandardDefOverride) {
|
||||
" \"space\": \"dhcp6\""
|
||||
" } ]"
|
||||
"}";
|
||||
json = parseOPTION_DEF(config);
|
||||
json = parseOPTION_DEFS(config);
|
||||
|
||||
// Use the configuration string to create new option definition.
|
||||
EXPECT_NO_THROW(status = configureDhcp6Server(srv_, json));
|
||||
|
@@ -696,11 +696,11 @@ parseDHCP6(const std::string& in, bool verbose = false)
|
||||
/// @param verbose display the exception message when it fails
|
||||
/// @return ElementPtr structure representing parsed JSON
|
||||
inline isc::data::ElementPtr
|
||||
parseOPTION_DEF(const std::string& in, bool verbose = false)
|
||||
parseOPTION_DEFS(const std::string& in, bool verbose = false)
|
||||
{
|
||||
try {
|
||||
isc::dhcp::Parser6Context ctx;
|
||||
return (ctx.parseString(in, isc::dhcp::Parser6Context::PARSER_OPTION_DEF));
|
||||
return (ctx.parseString(in, isc::dhcp::Parser6Context::PARSER_OPTION_DEFS));
|
||||
}
|
||||
catch (const std::exception& ex) {
|
||||
if (verbose) {
|
||||
|
@@ -506,6 +506,13 @@ TEST(ParserTest, errors) {
|
||||
Parser6Context::PARSER_DHCP6,
|
||||
"<string>:2.2-21: got unexpected keyword "
|
||||
"\"preferred_lifetime\" in Dhcp6 map.");
|
||||
|
||||
// missing parameter
|
||||
testError("{ \"name\": \"foo\",\n"
|
||||
" \"code\": 123 }\n",
|
||||
Parser6Context::PARSER_OPTION_DEF,
|
||||
"missing parameter 'type' (<string>:1:1) "
|
||||
"[option-def map between <string>:1:1 and <string>:2:15]");
|
||||
}
|
||||
|
||||
// Check unicode escapes
|
||||
|
Reference in New Issue
Block a user