#include <hooks/hooks.h>
#include <gtest/gtest.h>
+#include <sstream>
using namespace std;
using namespace isc;
/// @brief Test class derived from FlexOptionImpl
class TestFlexOptionImpl : public FlexOptionImpl {
public:
+ /// Export getMutableOptionConfigMap.
using FlexOptionImpl::getMutableOptionConfigMap;
+
+ /// @brief Configure clone which records the error.
+ ///
+ /// @param options The element with option config list.
+ void testConfigure(ConstElementPtr options) {
+ err_msg_.clear();
+ try {
+ configure(options);
+ } catch (const std::exception& ex) {
+ err_msg_ = string(ex.what());
+ throw;
+ }
+ }
+
+ /// @brief Get the last error message.
+ ///
+ /// @return The last error message.
+ const string& getErrMsg() const {
+ return (err_msg_);
+ }
+
+private:
+ /// @brief Last error message.
+ string err_msg_;
};
/// @brief The type of shared pointers to TestFlexOptionImpl
// Verify that the configuration must exist.
TEST_F(FlexOptionTest, noConfig) {
ElementPtr options;
- EXPECT_THROW(impl_->configure(options), BadValue);
+ EXPECT_THROW(impl_->testConfigure(options), BadValue);
+ EXPECT_EQ("'options' parameter is mandatory", impl_->getErrMsg());
}
// Verify that the configuration must be a list.
TEST_F(FlexOptionTest, configNotList) {
ElementPtr options = Element::createMap();
- EXPECT_THROW(impl_->configure(options), BadValue);
+ EXPECT_THROW(impl_->testConfigure(options), BadValue);
+ EXPECT_EQ("'options' parameter must be a list", impl_->getErrMsg());
}
// Verify that the configuration can be the empty list.
TEST_F(FlexOptionTest, configEmpty) {
ElementPtr options = Element::createList();
- EXPECT_NO_THROW(impl_->configure(options));
+ EXPECT_NO_THROW(impl_->testConfigure(options));
+ EXPECT_TRUE(impl_->getErrMsg().empty());
}
// Verify that an option configuration must exist.
ElementPtr options = Element::createList();
ElementPtr option;
options->add(option);
- EXPECT_THROW(impl_->configure(options), BadValue);
+ EXPECT_THROW(impl_->testConfigure(options), BadValue);
+ EXPECT_EQ("null option element", impl_->getErrMsg());
}
// Verify that an option configuration must be a map.
ElementPtr options = Element::createList();
ElementPtr option = Element::createList();
options->add(option);
- EXPECT_THROW(impl_->configure(options), BadValue);
+ EXPECT_THROW(impl_->testConfigure(options), BadValue);
+ EXPECT_EQ("option element is not a map", impl_->getErrMsg());
}
// Verify that an option configuration must have code or name.
ElementPtr options = Element::createList();
ElementPtr option = Element::createMap();
options->add(option);
- EXPECT_THROW(impl_->configure(options), BadValue);
+ EXPECT_THROW(impl_->testConfigure(options), BadValue);
+ ostringstream errmsg;
+ errmsg << "'code' or 'name' must be specified: " << option->str();
+ EXPECT_EQ(errmsg.str(), impl_->getErrMsg());
}
// Verify that the v4 option code must be in [1..254].
options->add(option);
ElementPtr add = Element::create(string("'ab'"));
option->set("add", add);
- ElementPtr code = Element::create(-1);
+ ElementPtr code = Element::create(false);
option->set("code", code);
- EXPECT_THROW(impl_->configure(options), OutOfRange);
+ EXPECT_THROW(impl_->testConfigure(options), BadValue);
+ EXPECT_EQ("'code' must be an integer: false", impl_->getErrMsg());
+
+ code = Element::create(-1);
+ option->set("code", code);
+ EXPECT_THROW(impl_->testConfigure(options), OutOfRange);
+ EXPECT_EQ("invalid 'code' value -1 not in [0..255]", impl_->getErrMsg());
code = Element::create(DHO_PAD);
option->set("code", code);
- EXPECT_THROW(impl_->configure(options), BadValue);
+ EXPECT_THROW(impl_->testConfigure(options), BadValue);
+ EXPECT_EQ("invalid 'code' value 0: reserved for PAD", impl_->getErrMsg());
code = Element::create(DHO_END);
option->set("code", code);
- EXPECT_THROW(impl_->configure(options), BadValue);
+ EXPECT_THROW(impl_->testConfigure(options), BadValue);
+ EXPECT_EQ("invalid 'code' value 255: reserved for END", impl_->getErrMsg());
code = Element::create(256);
option->set("code", code);
- EXPECT_THROW(impl_->configure(options), OutOfRange);
+ EXPECT_THROW(impl_->testConfigure(options), OutOfRange);
+ EXPECT_EQ("invalid 'code' value 256 not in [0..255]", impl_->getErrMsg());
code = Element::create(1);
option->set("code", code);
- EXPECT_NO_THROW(impl_->configure(options));
+ EXPECT_NO_THROW(impl_->testConfigure(options));
+ EXPECT_TRUE(impl_->getErrMsg().empty());
code = Element::create(254);
option->set("code", code);
- EXPECT_NO_THROW(impl_->configure(options));
+ EXPECT_NO_THROW(impl_->testConfigure(options));
+ EXPECT_TRUE(impl_->getErrMsg().empty());
}
// Verify that the v6 option code must be in [1..65535].
options->add(option);
ElementPtr add = Element::create(string("'ab'"));
option->set("add", add);
- ElementPtr code = Element::create(-1);
+ ElementPtr code = Element::create(false);
option->set("code", code);
- EXPECT_THROW(impl_->configure(options), OutOfRange);
+ EXPECT_THROW(impl_->testConfigure(options), BadValue);
+ EXPECT_EQ("'code' must be an integer: false", impl_->getErrMsg());
+
+ code = Element::create(-1);
+ option->set("code", code);
+ EXPECT_THROW(impl_->testConfigure(options), OutOfRange);
+ EXPECT_EQ("invalid 'code' value -1 not in [0..65535]", impl_->getErrMsg());
code = Element::create(0);
option->set("code", code);
- EXPECT_THROW(impl_->configure(options), BadValue);
+ EXPECT_THROW(impl_->testConfigure(options), BadValue);
+ EXPECT_EQ("invalid 'code' value 0: reserved", impl_->getErrMsg());
code = Element::create(65536);
option->set("code", code);
- EXPECT_THROW(impl_->configure(options), OutOfRange);
+ EXPECT_THROW(impl_->testConfigure(options), OutOfRange);
+ EXPECT_EQ("invalid 'code' value 65536 not in [0..65535]", impl_->getErrMsg());
code = Element::create(1);
option->set("code", code);
- EXPECT_NO_THROW(impl_->configure(options));
+ EXPECT_NO_THROW(impl_->testConfigure(options));
+ EXPECT_TRUE(impl_->getErrMsg().empty());
code = Element::create(65535);
option->set("code", code);
- EXPECT_NO_THROW(impl_->configure(options));
+ EXPECT_NO_THROW(impl_->testConfigure(options));
+ EXPECT_TRUE(impl_->getErrMsg().empty());
}
// Verify that the name must be a string.
option->set("add", add);
ElementPtr name = Element::create(true);
option->set("name", name);
- EXPECT_THROW(impl_->configure(options), BadValue);
+ EXPECT_THROW(impl_->testConfigure(options), BadValue);
+ EXPECT_EQ("'name' must be a string: true", impl_->getErrMsg());
}
// Verify that the name must not be empty.
option->set("add", add);
ElementPtr name = Element::create(string());
option->set("name",name);
- EXPECT_THROW(impl_->configure(options), BadValue);
+ EXPECT_THROW(impl_->testConfigure(options), BadValue);
+ EXPECT_EQ("'name' must not be empty", impl_->getErrMsg());
}
// Verify that the name must be a known option.
option->set("add", add);
ElementPtr name = Element::create(string("foobar"));
option->set("name",name);
- EXPECT_THROW(impl_->configure(options), BadValue);
+ EXPECT_THROW(impl_->testConfigure(options), BadValue);
+ EXPECT_EQ("no known 'foobar' option in 'dhcp4' space", impl_->getErrMsg());
}
// Verify that the name can be a standard option.
option->set("add", add);
ElementPtr name = Element::create(string("host-name"));
option->set("name", name);
- EXPECT_NO_THROW(impl_->configure(options));
+ EXPECT_NO_THROW(impl_->testConfigure(options));
+ EXPECT_TRUE(impl_->getErrMsg().empty());
auto map = impl_->getOptionConfigMap();
EXPECT_EQ(1, map.count(DHO_HOST_NAME));
option->set("add", add);
ElementPtr name = Element::create(string("my-option"));
option->set("name", name);
- EXPECT_NO_THROW(impl_->configure(options));
+ EXPECT_NO_THROW(impl_->testConfigure(options));
+ EXPECT_TRUE(impl_->getErrMsg().empty());
auto map = impl_->getOptionConfigMap();
EXPECT_EQ(1, map.count(222));
option->set("code", code);
ElementPtr name = Element::create(string("host-name"));
option->set("name", name);
- EXPECT_THROW(impl_->configure(options), BadValue);
+ EXPECT_THROW(impl_->testConfigure(options), BadValue);
+ EXPECT_EQ("option 'host-name' has code 12 but 'code' is 13", impl_->getErrMsg());
}
// Verify that an option can be configured only once.
option->set("code", code);
options->add(option);
- EXPECT_THROW(impl_->configure(options), BadValue);
+ EXPECT_THROW(impl_->testConfigure(options), BadValue);
+ EXPECT_EQ("option 12 was already specified", impl_->getErrMsg());
}
// Verify that the add value must be a string.
option->set("code", code);
ElementPtr add = Element::create(true);
option->set("add", add);
- EXPECT_THROW(impl_->configure(options), BadValue);
+ EXPECT_THROW(impl_->testConfigure(options), BadValue);
+ EXPECT_EQ("'add' must be a string: true", impl_->getErrMsg());
}
// Verify that the add value must not be empty.
option->set("code", code);
ElementPtr add = Element::create(string());
option->set("add", add);
- EXPECT_THROW(impl_->configure(options), BadValue);
+ EXPECT_THROW(impl_->testConfigure(options), BadValue);
+ EXPECT_EQ("'add' must not be empty", impl_->getErrMsg());
}
// Verify that the add value must parse.
option->set("code", code);
ElementPtr add = Element::create(string("if"));
option->set("add", add);
- EXPECT_THROW(impl_->configure(options), BadValue);
+ EXPECT_THROW(impl_->testConfigure(options), BadValue);
+ EXPECT_EQ("can't parse add expression [if] error: "
+ "<string>:1.1: Invalid character: i",
+ impl_->getErrMsg());
}
// Verify that a valid v4 add value is accepted.
option->set("code", code);
ElementPtr add = Element::create(string("'abc'"));
option->set("add", add);
- EXPECT_NO_THROW(impl_->configure(options));
+ EXPECT_NO_THROW(impl_->testConfigure(options));
+ EXPECT_TRUE(impl_->getErrMsg().empty());
auto map = impl_->getOptionConfigMap();
FlexOptionImpl::OptionConfigPtr opt_cfg;
option->set("code", code);
ElementPtr add = Element::create(string("'abc'"));
option->set("add", add);
- EXPECT_NO_THROW(impl_->configure(options));
+ EXPECT_NO_THROW(impl_->testConfigure(options));
+ EXPECT_TRUE(impl_->getErrMsg().empty());
auto map = impl_->getOptionConfigMap();
FlexOptionImpl::OptionConfigPtr opt_cfg;
options->add(option);
ElementPtr code = Element::create(DHO_HOST_NAME);
option->set("code", code);
- ElementPtr supersede = Element::create(true);
+ ElementPtr supersede = Element::create(123);
option->set("supersede", supersede);
- EXPECT_THROW(impl_->configure(options), BadValue);
+ EXPECT_THROW(impl_->testConfigure(options), BadValue);
+ EXPECT_EQ("'supersede' must be a string: 123", impl_->getErrMsg());
}
// Verify that the supersede value must not be empty.
option->set("code", code);
ElementPtr supersede = Element::create(string());
option->set("supersede", supersede);
- EXPECT_THROW(impl_->configure(options), BadValue);
+ EXPECT_THROW(impl_->testConfigure(options), BadValue);
+ EXPECT_EQ("'supersede' must not be empty", impl_->getErrMsg());
}
// Verify that the supersede value must parse.
option->set("code", code);
ElementPtr supersede = Element::create(string("if"));
option->set("supersede", supersede);
- EXPECT_THROW(impl_->configure(options), BadValue);
+ EXPECT_THROW(impl_->testConfigure(options), BadValue);
+ string expected = "can't parse supersede expression [if] error: ";
+ expected += "<string>:1.1: Invalid character: i";
+ EXPECT_EQ(expected, impl_->getErrMsg());
}
// Verify that a valid v4 supersede value is accepted.
option->set("code", code);
ElementPtr supersede = Element::create(string("'abc'"));
option->set("supersede", supersede);
- EXPECT_NO_THROW(impl_->configure(options));
+ EXPECT_NO_THROW(impl_->testConfigure(options));
+ EXPECT_TRUE(impl_->getErrMsg().empty());
auto map = impl_->getOptionConfigMap();
FlexOptionImpl::OptionConfigPtr opt_cfg;
option->set("code", code);
ElementPtr supersede = Element::create(string("'abc'"));
option->set("supersede", supersede);
- EXPECT_NO_THROW(impl_->configure(options));
+ EXPECT_NO_THROW(impl_->testConfigure(options));
+ EXPECT_TRUE(impl_->getErrMsg().empty());
auto map = impl_->getOptionConfigMap();
FlexOptionImpl::OptionConfigPtr opt_cfg;
options->add(option);
ElementPtr code = Element::create(DHO_HOST_NAME);
option->set("code", code);
- ElementPtr remove = Element::create(true);
+ ElementPtr remove = Element::createMap();
option->set("remove", remove);
- EXPECT_THROW(impl_->configure(options), BadValue);
+ EXPECT_THROW(impl_->testConfigure(options), BadValue);
+ EXPECT_EQ("'remove' must be a string: { }", impl_->getErrMsg());
}
// Verify that the remove value must not be empty.
option->set("code", code);
ElementPtr remove = Element::create(string());
option->set("remove", remove);
- EXPECT_THROW(impl_->configure(options), BadValue);
+ EXPECT_THROW(impl_->testConfigure(options), BadValue);
+ EXPECT_EQ("'remove' must not be empty", impl_->getErrMsg());
}
// Verify that the remove value must parse.
option->set("code", code);
ElementPtr remove = Element::create(string("'abc'"));
option->set("remove", remove);
- EXPECT_THROW(impl_->configure(options), BadValue);
+ EXPECT_THROW(impl_->testConfigure(options), BadValue);
+ string expected = "can't parse remove expression ['abc'] error: ";
+ expected += "<string>:1.6: syntax error, unexpected end of file, ";
+ expected += "expecting ==";
+ EXPECT_EQ(expected,impl_->getErrMsg());
}
// Verify that a valid v4 remove value is accepted.
option->set("code", code);
ElementPtr remove = Element::create(string("'abc' == 'abc'"));
option->set("remove", remove);
- EXPECT_NO_THROW(impl_->configure(options));
+ EXPECT_NO_THROW(impl_->testConfigure(options));
+ EXPECT_TRUE(impl_->getErrMsg().empty());
auto map = impl_->getOptionConfigMap();
FlexOptionImpl::OptionConfigPtr opt_cfg;
option->set("code", code);
ElementPtr remove = Element::create(string("'abc' == 'abc'"));
option->set("remove", remove);
- EXPECT_NO_THROW(impl_->configure(options));
+ EXPECT_NO_THROW(impl_->testConfigure(options));
+ EXPECT_TRUE(impl_->getErrMsg().empty());
auto map = impl_->getOptionConfigMap();
FlexOptionImpl::OptionConfigPtr opt_cfg;
option->set("add", add);
ElementPtr supersede = Element::create(string("'abc'"));
option->set("supersede", supersede);
- EXPECT_THROW(impl_->configure(options), BadValue);
+ EXPECT_THROW(impl_->testConfigure(options), BadValue);
+ ostringstream errmsg;
+ errmsg << "multiple actions: " << option->str();
+ EXPECT_EQ(errmsg.str(), impl_->getErrMsg());
// supersede and remove.
option->remove("add");
ElementPtr remove = Element::create(string("'abc' == 'abc'"));
option->set("remove", remove);
- EXPECT_THROW(impl_->configure(options), BadValue);
-
+ EXPECT_THROW(impl_->testConfigure(options), BadValue);
+ errmsg.str("");
+ errmsg << "multiple actions: " << option->str();
+ EXPECT_EQ(errmsg.str(), impl_->getErrMsg());
+
// add and remove.
option->remove("supersede");
option->set("add", add);
- EXPECT_THROW(impl_->configure(options), BadValue);
+ EXPECT_THROW(impl_->testConfigure(options), BadValue);
+ errmsg.str("");
+ errmsg << "multiple actions: " << option->str();
+ EXPECT_EQ(errmsg.str(), impl_->getErrMsg());
}
// Verify that multiple options are accepted.
ElementPtr supersede2 = Element::create(string("'/'"));
option2->set("supersede", supersede2);
- EXPECT_NO_THROW(impl_->configure(options));
+ EXPECT_NO_THROW(impl_->testConfigure(options));
+ EXPECT_TRUE(impl_->getErrMsg().empty());
auto map = impl_->getOptionConfigMap();
EXPECT_EQ(2, map.size());
option->set("code", code);
ElementPtr add = Element::create(string("'abc'"));
option->set("add", add);
- EXPECT_NO_THROW(impl_->configure(options));
+ EXPECT_NO_THROW(impl_->testConfigure(options));
+ EXPECT_TRUE(impl_->getErrMsg().empty());
Pkt4Ptr query(new Pkt4(DHCPDISCOVER, 12345));
Pkt4Ptr response(new Pkt4(DHCPOFFER, 12345));
option->set("code", code);
ElementPtr add = Element::create(string("'abc'"));
option->set("add", add);
- EXPECT_NO_THROW(impl_->configure(options));
+ EXPECT_NO_THROW(impl_->testConfigure(options));
+ EXPECT_TRUE(impl_->getErrMsg().empty());
Pkt6Ptr query(new Pkt6(DHCPV6_SOLICIT, 12345));
Pkt6Ptr response(new Pkt6(DHCPV6_ADVERTISE, 12345));
option->set("code", code);
ElementPtr add = Element::create(string("''"));
option->set("add", add);
- EXPECT_NO_THROW(impl_->configure(options));
+ EXPECT_NO_THROW(impl_->testConfigure(options));
+ EXPECT_TRUE(impl_->getErrMsg().empty());
Pkt4Ptr query(new Pkt4(DHCPDISCOVER, 12345));
Pkt4Ptr response(new Pkt4(DHCPOFFER, 12345));
option->set("code", code);
ElementPtr supersede = Element::create(string("'abc'"));
option->set("supersede", supersede);
- EXPECT_NO_THROW(impl_->configure(options));
+ EXPECT_NO_THROW(impl_->testConfigure(options));
+ EXPECT_TRUE(impl_->getErrMsg().empty());
Pkt4Ptr query(new Pkt4(DHCPDISCOVER, 12345));
Pkt4Ptr response(new Pkt4(DHCPOFFER, 12345));
option->set("code", code);
ElementPtr supersede = Element::create(string("'abc'"));
option->set("supersede", supersede);
- EXPECT_NO_THROW(impl_->configure(options));
+ EXPECT_NO_THROW(impl_->testConfigure(options));
+ EXPECT_TRUE(impl_->getErrMsg().empty());
Pkt6Ptr query(new Pkt6(DHCPV6_SOLICIT, 12345));
Pkt6Ptr response(new Pkt6(DHCPV6_ADVERTISE, 12345));
option->set("code", code);
ElementPtr supersede = Element::create(string("''"));
option->set("supersede", supersede);
- EXPECT_NO_THROW(impl_->configure(options));
+ EXPECT_NO_THROW(impl_->testConfigure(options));
+ EXPECT_TRUE(impl_->getErrMsg().empty());
Pkt4Ptr query(new Pkt4(DHCPDISCOVER, 12345));
Pkt4Ptr response(new Pkt4(DHCPOFFER, 12345));
option->set("code", code);
ElementPtr remove = Element::create(string("'abc' == 'abc'"));
option->set("remove", remove);
- EXPECT_NO_THROW(impl_->configure(options));
+ EXPECT_NO_THROW(impl_->testConfigure(options));
+ EXPECT_TRUE(impl_->getErrMsg().empty());
Pkt6Ptr query(new Pkt6(DHCPV6_SOLICIT, 12345));
Pkt6Ptr response(new Pkt6(DHCPV6_ADVERTISE, 12345));
option->set("code", code);
ElementPtr remove = Element::create(string("'abc' == 'abc'"));
option->set("remove", remove);
- EXPECT_NO_THROW(impl_->configure(options));
+ EXPECT_NO_THROW(impl_->testConfigure(options));
+ EXPECT_TRUE(impl_->getErrMsg().empty());
Pkt4Ptr query(new Pkt4(DHCPDISCOVER, 12345));
Pkt4Ptr response(new Pkt4(DHCPOFFER, 12345));
option->set("code", code);
ElementPtr remove = Element::create(string("'abc' == 'xyz'"));
option->set("remove", remove);
- EXPECT_NO_THROW(impl_->configure(options));
+ EXPECT_NO_THROW(impl_->testConfigure(options));
+ EXPECT_TRUE(impl_->getErrMsg().empty());
Pkt4Ptr query(new Pkt4(DHCPDISCOVER, 12345));
Pkt4Ptr response(new Pkt4(DHCPOFFER, 12345));