mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-31 22:15:23 +00:00
[219-allow-an-option-value-to-be-set-from-an-expression] Checkpoint: almost finished
This commit is contained in:
@@ -1695,6 +1695,7 @@ AC_CONFIG_FILES([Makefile
|
|||||||
src/hooks/Makefile
|
src/hooks/Makefile
|
||||||
src/hooks/dhcp/Makefile
|
src/hooks/dhcp/Makefile
|
||||||
src/hooks/dhcp/flex_option/Makefile
|
src/hooks/dhcp/flex_option/Makefile
|
||||||
|
src/hooks/dhcp/flex_option/libloadtests/Makefile
|
||||||
src/hooks/dhcp/flex_option/tests/Makefile
|
src/hooks/dhcp/flex_option/tests/Makefile
|
||||||
src/hooks/dhcp/high_availability/Makefile
|
src/hooks/dhcp/high_availability/Makefile
|
||||||
src/hooks/dhcp/high_availability/tests/Makefile
|
src/hooks/dhcp/high_availability/tests/Makefile
|
||||||
@@ -1702,11 +1703,11 @@ AC_CONFIG_FILES([Makefile
|
|||||||
src/hooks/dhcp/lease_cmds/tests/Makefile
|
src/hooks/dhcp/lease_cmds/tests/Makefile
|
||||||
src/hooks/dhcp/mysql_cb/Makefile
|
src/hooks/dhcp/mysql_cb/Makefile
|
||||||
src/hooks/dhcp/mysql_cb/tests/Makefile
|
src/hooks/dhcp/mysql_cb/tests/Makefile
|
||||||
|
src/hooks/dhcp/stat_cmds/Makefile
|
||||||
|
src/hooks/dhcp/stat_cmds/tests/Makefile
|
||||||
src/hooks/dhcp/user_chk/Makefile
|
src/hooks/dhcp/user_chk/Makefile
|
||||||
src/hooks/dhcp/user_chk/tests/Makefile
|
src/hooks/dhcp/user_chk/tests/Makefile
|
||||||
src/hooks/dhcp/user_chk/tests/test_data_files_config.h
|
src/hooks/dhcp/user_chk/tests/test_data_files_config.h
|
||||||
src/hooks/dhcp/stat_cmds/Makefile
|
|
||||||
src/hooks/dhcp/stat_cmds/tests/Makefile
|
|
||||||
src/lib/Makefile
|
src/lib/Makefile
|
||||||
src/lib/asiodns/Makefile
|
src/lib/asiodns/Makefile
|
||||||
src/lib/asiodns/tests/Makefile
|
src/lib/asiodns/tests/Makefile
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
SUBDIRS = . tests
|
SUBDIRS = . libloadtests tests
|
||||||
|
|
||||||
AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
|
AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
|
||||||
AM_CPPFLAGS += $(BOOST_INCLUDES)
|
AM_CPPFLAGS += $(BOOST_INCLUDES)
|
||||||
|
@@ -24,7 +24,8 @@ using namespace std;
|
|||||||
namespace isc {
|
namespace isc {
|
||||||
namespace flex_option {
|
namespace flex_option {
|
||||||
|
|
||||||
FlexOptionImpl::OptionConfig::OptionConfig(uint16_t code) : code_(code) {
|
FlexOptionImpl::OptionConfig::OptionConfig(uint16_t code)
|
||||||
|
: code_(code), action_(NONE) {
|
||||||
}
|
}
|
||||||
|
|
||||||
FlexOptionImpl::OptionConfig::~OptionConfig() {
|
FlexOptionImpl::OptionConfig::~OptionConfig() {
|
||||||
@@ -217,6 +218,11 @@ FlexOptionImpl::parseOptionConfig(ConstElementPtr option) {
|
|||||||
<< remove << "] error: " << ex.what());
|
<< remove << "] error: " << ex.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opt_cfg->getAction() == NONE) {
|
||||||
|
isc_throw(BadValue, "no action: " << option->str());
|
||||||
|
}
|
||||||
|
option_config_map_[code] = opt_cfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end of namespace flex_option
|
} // end of namespace flex_option
|
||||||
|
@@ -194,6 +194,14 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// @brief Get a mutable reference to the option config map
|
||||||
|
///
|
||||||
|
/// @return The option config map.
|
||||||
|
OptionConfigMap& getMutableOptionConfigMap() {
|
||||||
|
return (option_config_map_);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// @brief The option config map (code and pointer to option config).
|
/// @brief The option config map (code and pointer to option config).
|
||||||
OptionConfigMap option_config_map_;
|
OptionConfigMap option_config_map_;
|
||||||
|
1
src/hooks/dhcp/flex_option/libloadtests/.gitignore
vendored
Normal file
1
src/hooks/dhcp/flex_option/libloadtests/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/html
|
54
src/hooks/dhcp/flex_option/libloadtests/Makefile.am
Normal file
54
src/hooks/dhcp/flex_option/libloadtests/Makefile.am
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
SUBDIRS = .
|
||||||
|
|
||||||
|
AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
|
||||||
|
AM_CPPFLAGS += -I$(top_builddir)/src/hooks/dhcp/flex_option -I$(top_srcdir)/src/hooks/dhcp/flex_option
|
||||||
|
AM_CPPFLAGS += $(BOOST_INCLUDES)
|
||||||
|
AM_CPPFLAGS += -DFLEX_OPTION_LIB_SO=\"$(abs_top_builddir)/src/hooks/dhcp/flex_option/.libs/libdhcp_flex_option.so\"
|
||||||
|
AM_CPPFLAGS += -DINSTALL_PROG=\"$(abs_top_srcdir)/install-sh\"
|
||||||
|
|
||||||
|
AM_CXXFLAGS = $(KEA_CXXFLAGS)
|
||||||
|
|
||||||
|
if USE_STATIC_LINK
|
||||||
|
AM_LDFLAGS = -static
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Unit test data files need to get installed.
|
||||||
|
EXTRA_DIST =
|
||||||
|
|
||||||
|
CLEANFILES = *.gcno *.gcda
|
||||||
|
|
||||||
|
# TESTS_ENVIRONMENT = $(LIBTOOL) --mode=execute $(VALGRIND_COMMAND)
|
||||||
|
LOG_COMPILER = $(LIBTOOL)
|
||||||
|
AM_LOG_FLAGS = --mode=execute
|
||||||
|
|
||||||
|
TESTS =
|
||||||
|
if HAVE_GTEST
|
||||||
|
TESTS += flex_option_unittests
|
||||||
|
|
||||||
|
flex_option_unittests_SOURCES = run_unittests.cc
|
||||||
|
flex_option_unittests_SOURCES += load_unload_unittests.cc
|
||||||
|
|
||||||
|
flex_option_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) $(LOG4CPLUS_INCLUDES)
|
||||||
|
|
||||||
|
flex_option_unittests_LDFLAGS = $(AM_LDFLAGS) $(CRYPTO_LDFLAGS) $(GTEST_LDFLAGS)
|
||||||
|
|
||||||
|
flex_option_unittests_CXXFLAGS = $(AM_CXXFLAGS)
|
||||||
|
|
||||||
|
flex_option_unittests_LDADD = $(top_builddir)/src/lib/dhcpsrv/libkea-dhcpsrv.la
|
||||||
|
flex_option_unittests_LDADD += $(top_builddir)/src/lib/eval/libkea-eval.la
|
||||||
|
flex_option_unittests_LDADD += $(top_builddir)/src/lib/dhcp/libkea-dhcp++.la
|
||||||
|
flex_option_unittests_LDADD += $(top_builddir)/src/lib/hooks/libkea-hooks.la
|
||||||
|
flex_option_unittests_LDADD += $(top_builddir)/src/lib/database/libkea-database.la
|
||||||
|
flex_option_unittests_LDADD += $(top_builddir)/src/lib/cc/libkea-cc.la
|
||||||
|
flex_option_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la
|
||||||
|
flex_option_unittests_LDADD += $(top_builddir)/src/lib/dns/libkea-dns++.la
|
||||||
|
flex_option_unittests_LDADD += $(top_builddir)/src/lib/cryptolink/libkea-cryptolink.la
|
||||||
|
flex_option_unittests_LDADD += $(top_builddir)/src/lib/log/libkea-log.la
|
||||||
|
flex_option_unittests_LDADD += $(top_builddir)/src/lib/util/libkea-util.la
|
||||||
|
flex_option_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
|
||||||
|
flex_option_unittests_LDADD += $(LOG4CPLUS_LIBS)
|
||||||
|
flex_option_unittests_LDADD += $(CRYPTO_LIBS)
|
||||||
|
flex_option_unittests_LDADD += $(BOOST_LIBS)
|
||||||
|
flex_option_unittests_LDADD += $(GTEST_LDADD)
|
||||||
|
endif
|
||||||
|
noinst_PROGRAMS = $(TESTS)
|
@@ -12,20 +12,21 @@
|
|||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
#include <exceptions/exceptions.h>
|
#include <flex_option.h>
|
||||||
#include <hooks/hooks_manager.h>
|
#include <hooks/hooks_manager.h>
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <cc/data.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace isc;
|
using namespace isc;
|
||||||
using namespace hooks;
|
using namespace isc::hooks;
|
||||||
using namespace isc::data;
|
using namespace isc::data;
|
||||||
|
using namespace isc::dhcp;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/// @brief Test fixture for testing loading and unloading the flex-id library
|
/// @brief Test fixture for testing loading and unloading the flex-option library
|
||||||
class LibLoadTest : public ::testing::Test {
|
class LibLoadTest : public ::testing::Test {
|
||||||
public:
|
public:
|
||||||
/// @brief Constructor
|
/// @brief Constructor
|
19
src/hooks/dhcp/flex_option/libloadtests/run_unittests.cc
Normal file
19
src/hooks/dhcp/flex_option/libloadtests/run_unittests.cc
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
// Copyright (C) 2019 Internet Systems Consortium, Inc. ("ISC")
|
||||||
|
//
|
||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <log/logger_support.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char* argv[]) {
|
||||||
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
|
isc::log::initLogger();
|
||||||
|
int result = RUN_ALL_TESTS();
|
||||||
|
|
||||||
|
return (result);
|
||||||
|
}
|
@@ -26,8 +26,7 @@ if HAVE_GTEST
|
|||||||
TESTS += flex_option_unittests
|
TESTS += flex_option_unittests
|
||||||
|
|
||||||
flex_option_unittests_SOURCES = run_unittests.cc
|
flex_option_unittests_SOURCES = run_unittests.cc
|
||||||
flex_option_unittests_SOURCES += callout_unittests.cc
|
flex_option_unittests_SOURCES += flex_option_unittests.cc
|
||||||
flex_option_unittests_SOURCES += load_unload_unittests.cc
|
|
||||||
|
|
||||||
flex_option_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) $(LOG4CPLUS_INCLUDES)
|
flex_option_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) $(LOG4CPLUS_INCLUDES)
|
||||||
|
|
||||||
@@ -35,7 +34,8 @@ flex_option_unittests_LDFLAGS = $(AM_LDFLAGS) $(CRYPTO_LDFLAGS) $(GTEST_LDFLAGS
|
|||||||
|
|
||||||
flex_option_unittests_CXXFLAGS = $(AM_CXXFLAGS)
|
flex_option_unittests_CXXFLAGS = $(AM_CXXFLAGS)
|
||||||
|
|
||||||
flex_option_unittests_LDADD = $(top_builddir)/src/lib/dhcpsrv/libkea-dhcpsrv.la
|
flex_option_unittests_LDADD = $(top_builddir)/src/hooks/dhcp/flex_option/libflex_option.la
|
||||||
|
flex_option_unittests_LDADD += $(top_builddir)/src/lib/dhcpsrv/libkea-dhcpsrv.la
|
||||||
flex_option_unittests_LDADD += $(top_builddir)/src/lib/eval/libkea-eval.la
|
flex_option_unittests_LDADD += $(top_builddir)/src/lib/eval/libkea-eval.la
|
||||||
flex_option_unittests_LDADD += $(top_builddir)/src/lib/dhcp/libkea-dhcp++.la
|
flex_option_unittests_LDADD += $(top_builddir)/src/lib/dhcp/libkea-dhcp++.la
|
||||||
flex_option_unittests_LDADD += $(top_builddir)/src/lib/hooks/libkea-hooks.la
|
flex_option_unittests_LDADD += $(top_builddir)/src/lib/hooks/libkea-hooks.la
|
||||||
|
@@ -1,40 +0,0 @@
|
|||||||
// Copyright (C) 2019 Internet Systems Consortium, Inc. ("ISC")
|
|
||||||
//
|
|
||||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
/// @file This file contains tests which verify flexible option callouts.
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <asiolink/asio_wrapper.h>
|
|
||||||
#include <exceptions/exceptions.h>
|
|
||||||
#include <dhcp/dhcp4.h>
|
|
||||||
#include <dhcp/dhcp6.h>
|
|
||||||
#include <dhcp/option.h>
|
|
||||||
#include <dhcp/pkt4.h>
|
|
||||||
#include <dhcp/pkt6.h>
|
|
||||||
#include <dhcpsrv/host.h>
|
|
||||||
#include <dhcp/option.h>
|
|
||||||
#include <dhcp/option_string.h>
|
|
||||||
#include <hooks/callout_manager.h>
|
|
||||||
#include <hooks/hooks.h>
|
|
||||||
#include <flex_option.h>
|
|
||||||
#include <flex_option_log.h>
|
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace isc;
|
|
||||||
using namespace isc::dhcp;
|
|
||||||
using namespace isc::hooks;
|
|
||||||
using namespace isc::flex_option;
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
extern int pkt4_send(CalloutHandle& handle);
|
|
||||||
extern int pkt6_send(CalloutHandle& handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
} // end of anonymous namespace
|
|
885
src/hooks/dhcp/flex_option/tests/flex_option_unittests.cc
Normal file
885
src/hooks/dhcp/flex_option/tests/flex_option_unittests.cc
Normal file
@@ -0,0 +1,885 @@
|
|||||||
|
// Copyright (C) 2019 Internet Systems Consortium, Inc. ("ISC")
|
||||||
|
//
|
||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
/// @file This file contains tests which verify flexible option.
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
#include <flex_option.h>
|
||||||
|
#include <flex_option_log.h>
|
||||||
|
#include <dhcp/option_string.h>
|
||||||
|
#include <dhcp/libdhcp++.h>
|
||||||
|
#include <dhcpsrv/cfgmgr.h>
|
||||||
|
#include <eval/eval_context.h>
|
||||||
|
#include <hooks/callout_manager.h>
|
||||||
|
#include <hooks/hooks.h>
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace isc;
|
||||||
|
using namespace isc::data;
|
||||||
|
using namespace isc::dhcp;
|
||||||
|
using namespace isc::eval;
|
||||||
|
using namespace isc::hooks;
|
||||||
|
using namespace isc::flex_option;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
extern int pkt4_send(CalloutHandle& handle);
|
||||||
|
extern int pkt6_send(CalloutHandle& handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
/// @brief Test class derived from FlexOptionImpl
|
||||||
|
class TestFlexOptionImpl : public FlexOptionImpl {
|
||||||
|
public:
|
||||||
|
using FlexOptionImpl::getMutableOptionConfigMap;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @brief The type of shared pointers to TestFlexOptionImpl
|
||||||
|
typedef boost::shared_ptr<TestFlexOptionImpl> TestFlexOptionImplPtr;
|
||||||
|
|
||||||
|
/// @brief Test fixture for testing the Flex Option library.
|
||||||
|
class FlexOptionTest : public ::testing::Test {
|
||||||
|
public:
|
||||||
|
/// @brief Constructor.
|
||||||
|
FlexOptionTest() {
|
||||||
|
impl_.reset(new TestFlexOptionImpl());
|
||||||
|
CfgMgr::instance().setFamily(AF_INET);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Destructor.
|
||||||
|
virtual ~FlexOptionTest() {
|
||||||
|
CfgMgr::instance().setFamily(AF_INET);
|
||||||
|
impl_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Flex Option implementation.
|
||||||
|
TestFlexOptionImplPtr impl_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Verify that the configuration must exist.
|
||||||
|
TEST_F(FlexOptionTest, noConfig) {
|
||||||
|
ElementPtr options;
|
||||||
|
EXPECT_THROW(impl_->configure(options), BadValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the configuration must be a list.
|
||||||
|
TEST_F(FlexOptionTest, configNotList) {
|
||||||
|
ElementPtr options = Element::createMap();
|
||||||
|
EXPECT_THROW(impl_->configure(options), BadValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the configuration can be the empty list.
|
||||||
|
TEST_F(FlexOptionTest, configEmpty) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
EXPECT_NO_THROW(impl_->configure(options));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that an option configuration must exist.
|
||||||
|
TEST_F(FlexOptionTest, noOptionConfig) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option;
|
||||||
|
options->add(option);
|
||||||
|
EXPECT_THROW(impl_->configure(options), BadValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that an option configuration must be a map.
|
||||||
|
TEST_F(FlexOptionTest, optionConfigNotMap) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createList();
|
||||||
|
options->add(option);
|
||||||
|
EXPECT_THROW(impl_->configure(options), BadValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that an option configuration must have code or name.
|
||||||
|
TEST_F(FlexOptionTest, optionConfigNoCodeName) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
EXPECT_THROW(impl_->configure(options), BadValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the v4 option code must be in [1..254].
|
||||||
|
TEST_F(FlexOptionTest, optionConfigBadCode4) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr add = Element::create(string("'ab'"));
|
||||||
|
option->set("add", add);
|
||||||
|
ElementPtr code = Element::create(-1);
|
||||||
|
option->set("code", code);
|
||||||
|
EXPECT_THROW(impl_->configure(options), OutOfRange);
|
||||||
|
|
||||||
|
code = Element::create(DHO_PAD);
|
||||||
|
option->set("code", code);
|
||||||
|
EXPECT_THROW(impl_->configure(options), BadValue);
|
||||||
|
|
||||||
|
code = Element::create(DHO_END);
|
||||||
|
option->set("code", code);
|
||||||
|
EXPECT_THROW(impl_->configure(options), BadValue);
|
||||||
|
|
||||||
|
code = Element::create(256);
|
||||||
|
option->set("code", code);
|
||||||
|
EXPECT_THROW(impl_->configure(options), OutOfRange);
|
||||||
|
|
||||||
|
code = Element::create(1);
|
||||||
|
option->set("code", code);
|
||||||
|
EXPECT_NO_THROW(impl_->configure(options));
|
||||||
|
|
||||||
|
code = Element::create(254);
|
||||||
|
option->set("code", code);
|
||||||
|
EXPECT_NO_THROW(impl_->configure(options));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the v6 option code must be in [1..65535].
|
||||||
|
TEST_F(FlexOptionTest, optionConfigBadCode6) {
|
||||||
|
CfgMgr::instance().setFamily(AF_INET6);
|
||||||
|
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr add = Element::create(string("'ab'"));
|
||||||
|
option->set("add", add);
|
||||||
|
ElementPtr code = Element::create(-1);
|
||||||
|
option->set("code", code);
|
||||||
|
EXPECT_THROW(impl_->configure(options), OutOfRange);
|
||||||
|
|
||||||
|
code = Element::create(0);
|
||||||
|
option->set("code", code);
|
||||||
|
EXPECT_THROW(impl_->configure(options), BadValue);
|
||||||
|
|
||||||
|
code = Element::create(65536);
|
||||||
|
option->set("code", code);
|
||||||
|
EXPECT_THROW(impl_->configure(options), OutOfRange);
|
||||||
|
|
||||||
|
code = Element::create(1);
|
||||||
|
option->set("code", code);
|
||||||
|
EXPECT_NO_THROW(impl_->configure(options));
|
||||||
|
|
||||||
|
code = Element::create(65535);
|
||||||
|
option->set("code", code);
|
||||||
|
EXPECT_NO_THROW(impl_->configure(options));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the name must be a string.
|
||||||
|
TEST_F(FlexOptionTest, optionConfigBadName) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr add = Element::create(string("'ab'"));
|
||||||
|
option->set("add", add);
|
||||||
|
ElementPtr name = Element::create(true);
|
||||||
|
option->set("name", name);
|
||||||
|
EXPECT_THROW(impl_->configure(options), BadValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the name must not be empty.
|
||||||
|
TEST_F(FlexOptionTest, optionConfigEmptyName) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr add = Element::create(string("'ab'"));
|
||||||
|
option->set("add", add);
|
||||||
|
ElementPtr name = Element::create(string());
|
||||||
|
option->set("name",name);
|
||||||
|
EXPECT_THROW(impl_->configure(options), BadValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the name must be a known option.
|
||||||
|
TEST_F(FlexOptionTest, optionConfigUnknownName) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr add = Element::create(string("'ab'"));
|
||||||
|
option->set("add", add);
|
||||||
|
ElementPtr name = Element::create(string("foobar"));
|
||||||
|
option->set("name",name);
|
||||||
|
EXPECT_THROW(impl_->configure(options), BadValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the name can be a standard option.
|
||||||
|
TEST_F(FlexOptionTest, optionConfigStandardName) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr add = Element::create(string("'ab'"));
|
||||||
|
option->set("add", add);
|
||||||
|
ElementPtr name = Element::create(string("host-name"));
|
||||||
|
option->set("name", name);
|
||||||
|
EXPECT_NO_THROW(impl_->configure(options));
|
||||||
|
|
||||||
|
auto map = impl_->getOptionConfigMap();
|
||||||
|
EXPECT_EQ(1, map.count(DHO_HOST_NAME));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the name can be an user defined option.
|
||||||
|
TEST_F(FlexOptionTest, optionConfigDefinedName) {
|
||||||
|
OptionDefSpaceContainer defs;
|
||||||
|
OptionDefinitionPtr def(new OptionDefinition("my-option", 222, "string"));
|
||||||
|
defs.addItem(def, DHCP4_OPTION_SPACE);
|
||||||
|
EXPECT_NO_THROW(LibDHCP::setRuntimeOptionDefs(defs));
|
||||||
|
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr add = Element::create(string("'ab'"));
|
||||||
|
option->set("add", add);
|
||||||
|
ElementPtr name = Element::create(string("my-option"));
|
||||||
|
option->set("name", name);
|
||||||
|
EXPECT_NO_THROW(impl_->configure(options));
|
||||||
|
|
||||||
|
auto map = impl_->getOptionConfigMap();
|
||||||
|
EXPECT_EQ(1, map.count(222));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last resort is only option 43...
|
||||||
|
|
||||||
|
// Verify that the name must match the code.
|
||||||
|
TEST_F(FlexOptionTest, optionConfigCodeNameMismatch) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr add = Element::create(string("'ab'"));
|
||||||
|
option->set("add", add);
|
||||||
|
ElementPtr code = Element::create(DHO_HOST_NAME + 1);
|
||||||
|
option->set("code", code);
|
||||||
|
ElementPtr name = Element::create(string("host-name"));
|
||||||
|
option->set("name", name);
|
||||||
|
EXPECT_THROW(impl_->configure(options), BadValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that an option can be configured only once.
|
||||||
|
TEST_F(FlexOptionTest, optionConfigTwice) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr add = Element::create(string("'ab'"));
|
||||||
|
option->set("add", add);
|
||||||
|
ElementPtr code = Element::create(DHO_HOST_NAME);
|
||||||
|
option->set("code", code);
|
||||||
|
|
||||||
|
options->add(option);
|
||||||
|
EXPECT_THROW(impl_->configure(options), BadValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the add value must be a string.
|
||||||
|
TEST_F(FlexOptionTest, optionConfigAddNotString) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr code = Element::create(DHO_HOST_NAME);
|
||||||
|
option->set("code", code);
|
||||||
|
ElementPtr add = Element::create(true);
|
||||||
|
option->set("add", add);
|
||||||
|
EXPECT_THROW(impl_->configure(options), BadValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the add value must not be empty.
|
||||||
|
TEST_F(FlexOptionTest, optionConfigEmptyAdd) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr code = Element::create(DHO_HOST_NAME);
|
||||||
|
option->set("code", code);
|
||||||
|
ElementPtr add = Element::create(string());
|
||||||
|
option->set("add", add);
|
||||||
|
EXPECT_THROW(impl_->configure(options), BadValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the add value must parse.
|
||||||
|
TEST_F(FlexOptionTest, optionConfigBadAdd) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr code = Element::create(DHO_HOST_NAME);
|
||||||
|
option->set("code", code);
|
||||||
|
ElementPtr add = Element::create(string("if"));
|
||||||
|
option->set("add", add);
|
||||||
|
EXPECT_THROW(impl_->configure(options), BadValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that a valid v4 add value is accepted.
|
||||||
|
TEST_F(FlexOptionTest, optionConfigAdd4) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr code = Element::create(DHO_HOST_NAME);
|
||||||
|
option->set("code", code);
|
||||||
|
ElementPtr add = Element::create(string("'abc'"));
|
||||||
|
option->set("add", add);
|
||||||
|
EXPECT_NO_THROW(impl_->configure(options));
|
||||||
|
|
||||||
|
auto map = impl_->getOptionConfigMap();
|
||||||
|
FlexOptionImpl::OptionConfigPtr opt_cfg;
|
||||||
|
ASSERT_NO_THROW(opt_cfg = map.at(DHO_HOST_NAME));
|
||||||
|
ASSERT_TRUE(opt_cfg);
|
||||||
|
EXPECT_EQ(DHO_HOST_NAME, opt_cfg->getCode());
|
||||||
|
EXPECT_EQ(FlexOptionImpl::ADD, opt_cfg->getAction());
|
||||||
|
EXPECT_EQ("'abc'", opt_cfg->getText());
|
||||||
|
|
||||||
|
ExpressionPtr expr = opt_cfg->getExpr();
|
||||||
|
ASSERT_TRUE(expr);
|
||||||
|
ASSERT_EQ(1, expr->size());
|
||||||
|
Pkt4Ptr pkt4(new Pkt4(DHCPDISCOVER, 12345));
|
||||||
|
ValueStack values;
|
||||||
|
EXPECT_NO_THROW(expr->at(0)->evaluate(*pkt4, values));
|
||||||
|
ASSERT_EQ(1, values.size());
|
||||||
|
EXPECT_EQ("abc", values.top());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that a valid v6 add value is accepted.
|
||||||
|
TEST_F(FlexOptionTest, optionConfigAdd6) {
|
||||||
|
CfgMgr::instance().setFamily(AF_INET6);
|
||||||
|
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr code = Element::create(D6O_BOOTFILE_URL);
|
||||||
|
option->set("code", code);
|
||||||
|
ElementPtr add = Element::create(string("'abc'"));
|
||||||
|
option->set("add", add);
|
||||||
|
EXPECT_NO_THROW(impl_->configure(options));
|
||||||
|
|
||||||
|
auto map = impl_->getOptionConfigMap();
|
||||||
|
FlexOptionImpl::OptionConfigPtr opt_cfg;
|
||||||
|
ASSERT_NO_THROW(opt_cfg = map.at(D6O_BOOTFILE_URL));
|
||||||
|
ASSERT_TRUE(opt_cfg);
|
||||||
|
EXPECT_EQ(D6O_BOOTFILE_URL, opt_cfg->getCode());
|
||||||
|
EXPECT_EQ(FlexOptionImpl::ADD, opt_cfg->getAction());
|
||||||
|
EXPECT_EQ("'abc'", opt_cfg->getText());
|
||||||
|
|
||||||
|
ExpressionPtr expr = opt_cfg->getExpr();
|
||||||
|
ASSERT_TRUE(expr);
|
||||||
|
ASSERT_EQ(1, expr->size());
|
||||||
|
Pkt6Ptr pkt6(new Pkt6(DHCPV6_SOLICIT, 12345));
|
||||||
|
ValueStack values;
|
||||||
|
EXPECT_NO_THROW(expr->at(0)->evaluate(*pkt6, values));
|
||||||
|
ASSERT_EQ(1, values.size());
|
||||||
|
EXPECT_EQ("abc", values.top());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the supersede value must be a string.
|
||||||
|
TEST_F(FlexOptionTest, optionConfigSupersedeNotString) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr code = Element::create(DHO_HOST_NAME);
|
||||||
|
option->set("code", code);
|
||||||
|
ElementPtr supersede = Element::create(true);
|
||||||
|
option->set("supersede", supersede);
|
||||||
|
EXPECT_THROW(impl_->configure(options), BadValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the supersede value must not be empty.
|
||||||
|
TEST_F(FlexOptionTest, optionConfigEmptySupersede) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr code = Element::create(DHO_HOST_NAME);
|
||||||
|
option->set("code", code);
|
||||||
|
ElementPtr supersede = Element::create(string());
|
||||||
|
option->set("supersede", supersede);
|
||||||
|
EXPECT_THROW(impl_->configure(options), BadValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the supersede value must parse.
|
||||||
|
TEST_F(FlexOptionTest, optionConfigBadSupersede) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr code = Element::create(DHO_HOST_NAME);
|
||||||
|
option->set("code", code);
|
||||||
|
ElementPtr supersede = Element::create(string("if"));
|
||||||
|
option->set("supersede", supersede);
|
||||||
|
EXPECT_THROW(impl_->configure(options), BadValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that a valid v4 supersede value is accepted.
|
||||||
|
TEST_F(FlexOptionTest, optionConfigSupersede4) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr code = Element::create(DHO_HOST_NAME);
|
||||||
|
option->set("code", code);
|
||||||
|
ElementPtr supersede = Element::create(string("'abc'"));
|
||||||
|
option->set("supersede", supersede);
|
||||||
|
EXPECT_NO_THROW(impl_->configure(options));
|
||||||
|
|
||||||
|
auto map = impl_->getOptionConfigMap();
|
||||||
|
FlexOptionImpl::OptionConfigPtr opt_cfg;
|
||||||
|
ASSERT_NO_THROW(opt_cfg = map.at(DHO_HOST_NAME));
|
||||||
|
ASSERT_TRUE(opt_cfg);
|
||||||
|
EXPECT_EQ(DHO_HOST_NAME, opt_cfg->getCode());
|
||||||
|
EXPECT_EQ(FlexOptionImpl::SUPERSEDE, opt_cfg->getAction());
|
||||||
|
EXPECT_EQ("'abc'", opt_cfg->getText());
|
||||||
|
|
||||||
|
ExpressionPtr expr = opt_cfg->getExpr();
|
||||||
|
ASSERT_TRUE(expr);
|
||||||
|
ASSERT_EQ(1, expr->size());
|
||||||
|
Pkt4Ptr pkt4(new Pkt4(DHCPDISCOVER, 12345));
|
||||||
|
ValueStack values;
|
||||||
|
EXPECT_NO_THROW(expr->at(0)->evaluate(*pkt4, values));
|
||||||
|
ASSERT_EQ(1, values.size());
|
||||||
|
EXPECT_EQ("abc", values.top());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that a valid v6 supersede value is accepted.
|
||||||
|
TEST_F(FlexOptionTest, optionConfigSupersede6) {
|
||||||
|
CfgMgr::instance().setFamily(AF_INET6);
|
||||||
|
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr code = Element::create(D6O_BOOTFILE_URL);
|
||||||
|
option->set("code", code);
|
||||||
|
ElementPtr supersede = Element::create(string("'abc'"));
|
||||||
|
option->set("supersede", supersede);
|
||||||
|
EXPECT_NO_THROW(impl_->configure(options));
|
||||||
|
|
||||||
|
auto map = impl_->getOptionConfigMap();
|
||||||
|
FlexOptionImpl::OptionConfigPtr opt_cfg;
|
||||||
|
ASSERT_NO_THROW(opt_cfg = map.at(D6O_BOOTFILE_URL));
|
||||||
|
ASSERT_TRUE(opt_cfg);
|
||||||
|
EXPECT_EQ(D6O_BOOTFILE_URL, opt_cfg->getCode());
|
||||||
|
EXPECT_EQ(FlexOptionImpl::SUPERSEDE, opt_cfg->getAction());
|
||||||
|
EXPECT_EQ("'abc'", opt_cfg->getText());
|
||||||
|
|
||||||
|
ExpressionPtr expr = opt_cfg->getExpr();
|
||||||
|
ASSERT_TRUE(expr);
|
||||||
|
ASSERT_EQ(1, expr->size());
|
||||||
|
Pkt6Ptr pkt6(new Pkt6(DHCPV6_SOLICIT, 12345));
|
||||||
|
ValueStack values;
|
||||||
|
EXPECT_NO_THROW(expr->at(0)->evaluate(*pkt6, values));
|
||||||
|
ASSERT_EQ(1, values.size());
|
||||||
|
EXPECT_EQ("abc", values.top());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the remove value must be a string.
|
||||||
|
TEST_F(FlexOptionTest, optionConfigRemoveNotString) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr code = Element::create(DHO_HOST_NAME);
|
||||||
|
option->set("code", code);
|
||||||
|
ElementPtr remove = Element::create(true);
|
||||||
|
option->set("remove", remove);
|
||||||
|
EXPECT_THROW(impl_->configure(options), BadValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the remove value must not be empty.
|
||||||
|
TEST_F(FlexOptionTest, optionConfigEmptyRemove) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr code = Element::create(DHO_HOST_NAME);
|
||||||
|
option->set("code", code);
|
||||||
|
ElementPtr remove = Element::create(string());
|
||||||
|
option->set("remove", remove);
|
||||||
|
EXPECT_THROW(impl_->configure(options), BadValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the remove value must parse.
|
||||||
|
TEST_F(FlexOptionTest, optionConfigBadRemove) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr code = Element::create(DHO_HOST_NAME);
|
||||||
|
option->set("code", code);
|
||||||
|
ElementPtr remove = Element::create(string("'abc'"));
|
||||||
|
option->set("remove", remove);
|
||||||
|
EXPECT_THROW(impl_->configure(options), BadValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that a valid v4 remove value is accepted.
|
||||||
|
TEST_F(FlexOptionTest, optionConfigRemove4) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr code = Element::create(DHO_HOST_NAME);
|
||||||
|
option->set("code", code);
|
||||||
|
ElementPtr remove = Element::create(string("'abc' == 'abc'"));
|
||||||
|
option->set("remove", remove);
|
||||||
|
EXPECT_NO_THROW(impl_->configure(options));
|
||||||
|
|
||||||
|
auto map = impl_->getOptionConfigMap();
|
||||||
|
FlexOptionImpl::OptionConfigPtr opt_cfg;
|
||||||
|
ASSERT_NO_THROW(opt_cfg = map.at(DHO_HOST_NAME));
|
||||||
|
ASSERT_TRUE(opt_cfg);
|
||||||
|
EXPECT_EQ(DHO_HOST_NAME, opt_cfg->getCode());
|
||||||
|
EXPECT_EQ(FlexOptionImpl::REMOVE, opt_cfg->getAction());
|
||||||
|
EXPECT_EQ("'abc' == 'abc'", opt_cfg->getText());
|
||||||
|
|
||||||
|
ExpressionPtr expr = opt_cfg->getExpr();
|
||||||
|
ASSERT_TRUE(expr);
|
||||||
|
ASSERT_EQ(3, expr->size());
|
||||||
|
Pkt4Ptr pkt4(new Pkt4(DHCPDISCOVER, 12345));
|
||||||
|
ValueStack values;
|
||||||
|
EXPECT_NO_THROW(expr->at(0)->evaluate(*pkt4, values));
|
||||||
|
ASSERT_EQ(1, values.size());
|
||||||
|
EXPECT_EQ("abc", values.top());
|
||||||
|
EXPECT_NO_THROW(expr->at(1)->evaluate(*pkt4, values));
|
||||||
|
ASSERT_EQ(2, values.size());
|
||||||
|
EXPECT_NO_THROW(expr->at(2)->evaluate(*pkt4, values));
|
||||||
|
ASSERT_EQ(1, values.size());
|
||||||
|
EXPECT_EQ("true", values.top());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that a valid v6 remove value is accepted.
|
||||||
|
TEST_F(FlexOptionTest, optionConfigRemove6) {
|
||||||
|
CfgMgr::instance().setFamily(AF_INET6);
|
||||||
|
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr code = Element::create(D6O_BOOTFILE_URL);
|
||||||
|
option->set("code", code);
|
||||||
|
ElementPtr remove = Element::create(string("'abc' == 'abc'"));
|
||||||
|
option->set("remove", remove);
|
||||||
|
EXPECT_NO_THROW(impl_->configure(options));
|
||||||
|
|
||||||
|
auto map = impl_->getOptionConfigMap();
|
||||||
|
FlexOptionImpl::OptionConfigPtr opt_cfg;
|
||||||
|
ASSERT_NO_THROW(opt_cfg = map.at(D6O_BOOTFILE_URL));
|
||||||
|
ASSERT_TRUE(opt_cfg);
|
||||||
|
EXPECT_EQ(D6O_BOOTFILE_URL, opt_cfg->getCode());
|
||||||
|
EXPECT_EQ(FlexOptionImpl::REMOVE, opt_cfg->getAction());
|
||||||
|
EXPECT_EQ("'abc' == 'abc'", opt_cfg->getText());
|
||||||
|
|
||||||
|
ExpressionPtr expr = opt_cfg->getExpr();
|
||||||
|
ASSERT_TRUE(expr);
|
||||||
|
ASSERT_EQ(3, expr->size());
|
||||||
|
Pkt6Ptr pkt6(new Pkt6(DHCPV6_SOLICIT, 12345));
|
||||||
|
ValueStack values;
|
||||||
|
EXPECT_NO_THROW(expr->at(0)->evaluate(*pkt6, values));
|
||||||
|
ASSERT_EQ(1, values.size());
|
||||||
|
EXPECT_EQ("abc", values.top());
|
||||||
|
EXPECT_NO_THROW(expr->at(1)->evaluate(*pkt6, values));
|
||||||
|
ASSERT_EQ(2, values.size());
|
||||||
|
EXPECT_NO_THROW(expr->at(2)->evaluate(*pkt6, values));
|
||||||
|
ASSERT_EQ(1, values.size());
|
||||||
|
EXPECT_EQ("true", values.top());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that multiple actions are not accepted.
|
||||||
|
TEST_F(FlexOptionTest, optionConfigMultipleAction) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr code = Element::create(DHO_HOST_NAME);
|
||||||
|
option->set("code", code);
|
||||||
|
|
||||||
|
// add and supersede.
|
||||||
|
ElementPtr add = Element::create(string("'abc'"));
|
||||||
|
option->set("add", add);
|
||||||
|
ElementPtr supersede = Element::create(string("'abc'"));
|
||||||
|
option->set("supersede", supersede);
|
||||||
|
EXPECT_THROW(impl_->configure(options), BadValue);
|
||||||
|
|
||||||
|
// supersede and remove.
|
||||||
|
option->remove("add");
|
||||||
|
ElementPtr remove = Element::create(string("'abc' == 'abc'"));
|
||||||
|
option->set("remove", remove);
|
||||||
|
EXPECT_THROW(impl_->configure(options), BadValue);
|
||||||
|
|
||||||
|
// add and remove.
|
||||||
|
option->remove("supersede");
|
||||||
|
option->set("add", add);
|
||||||
|
EXPECT_THROW(impl_->configure(options), BadValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that multiple options are accepted.
|
||||||
|
TEST_F(FlexOptionTest, optionConfigList) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
|
||||||
|
ElementPtr option1 = Element::createMap();
|
||||||
|
options->add(option1);
|
||||||
|
ElementPtr code1 = Element::create(DHO_HOST_NAME);
|
||||||
|
option1->set("code", code1);
|
||||||
|
ElementPtr add1 = Element::create(string("'abc'"));
|
||||||
|
option1->set("add", add1);
|
||||||
|
|
||||||
|
ElementPtr option2 = Element::createMap();
|
||||||
|
options->add(option2);
|
||||||
|
ElementPtr code2 = Element::create(DHO_ROOT_PATH);
|
||||||
|
option2->set("code", code2);
|
||||||
|
ElementPtr supersede2 = Element::create(string("'/'"));
|
||||||
|
option2->set("supersede", supersede2);
|
||||||
|
|
||||||
|
EXPECT_NO_THROW(impl_->configure(options));
|
||||||
|
|
||||||
|
auto map = impl_->getOptionConfigMap();
|
||||||
|
EXPECT_EQ(2, map.size());
|
||||||
|
|
||||||
|
FlexOptionImpl::OptionConfigPtr opt1_cfg;
|
||||||
|
ASSERT_NO_THROW(opt1_cfg = map.at(DHO_HOST_NAME));
|
||||||
|
ASSERT_TRUE(opt1_cfg);
|
||||||
|
EXPECT_EQ(DHO_HOST_NAME, opt1_cfg->getCode());
|
||||||
|
EXPECT_EQ(FlexOptionImpl::ADD, opt1_cfg->getAction());
|
||||||
|
EXPECT_EQ("'abc'", opt1_cfg->getText());
|
||||||
|
|
||||||
|
FlexOptionImpl::OptionConfigPtr opt2_cfg;
|
||||||
|
ASSERT_NO_THROW(opt2_cfg = map.at(DHO_ROOT_PATH));
|
||||||
|
ASSERT_TRUE(opt2_cfg);
|
||||||
|
EXPECT_EQ(DHO_ROOT_PATH, opt2_cfg->getCode());
|
||||||
|
EXPECT_EQ(FlexOptionImpl::SUPERSEDE, opt2_cfg->getAction());
|
||||||
|
EXPECT_EQ("'/'", opt2_cfg->getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that empty option config list does nothing.
|
||||||
|
TEST_F(FlexOptionTest, processEmpty) {
|
||||||
|
Pkt4Ptr query(new Pkt4(DHCPDISCOVER, 12345));
|
||||||
|
Pkt4Ptr response(new Pkt4(DHCPOFFER, 12345));
|
||||||
|
string response_txt = response->toText();
|
||||||
|
|
||||||
|
EXPECT_NO_THROW(impl_->process<Pkt4Ptr>(Option::V4, query, response));
|
||||||
|
|
||||||
|
EXPECT_EQ(response_txt, response->toText());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that NONE action really does nothing.
|
||||||
|
TEST_F(FlexOptionTest, processNone) {
|
||||||
|
CfgMgr::instance().setFamily(AF_INET6);
|
||||||
|
|
||||||
|
FlexOptionImpl::OptionConfigPtr
|
||||||
|
opt_cfg(new FlexOptionImpl::OptionConfig(D6O_BOOTFILE_URL));
|
||||||
|
EXPECT_EQ(FlexOptionImpl::NONE, opt_cfg->getAction());
|
||||||
|
auto map = impl_->getMutableOptionConfigMap();
|
||||||
|
map[DHO_HOST_NAME] = opt_cfg;
|
||||||
|
|
||||||
|
Pkt6Ptr query(new Pkt6(DHCPV6_SOLICIT, 12345));
|
||||||
|
Pkt6Ptr response(new Pkt6(DHCPV6_ADVERTISE, 12345));
|
||||||
|
string response_txt = response->toText();
|
||||||
|
|
||||||
|
EXPECT_NO_THROW(impl_->process<Pkt6Ptr>(Option::V6, query, response));
|
||||||
|
|
||||||
|
EXPECT_EQ(response_txt, response->toText());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that ADD action adds the specified option.
|
||||||
|
TEST_F(FlexOptionTest, processAdd) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr code = Element::create(DHO_HOST_NAME);
|
||||||
|
option->set("code", code);
|
||||||
|
ElementPtr add = Element::create(string("'abc'"));
|
||||||
|
option->set("add", add);
|
||||||
|
EXPECT_NO_THROW(impl_->configure(options));
|
||||||
|
|
||||||
|
Pkt4Ptr query(new Pkt4(DHCPDISCOVER, 12345));
|
||||||
|
Pkt4Ptr response(new Pkt4(DHCPOFFER, 12345));
|
||||||
|
EXPECT_FALSE(response->getOption(DHO_HOST_NAME));
|
||||||
|
|
||||||
|
EXPECT_NO_THROW(impl_->process<Pkt4Ptr>(Option::V4, query, response));
|
||||||
|
|
||||||
|
OptionPtr opt = response->getOption(DHO_HOST_NAME);
|
||||||
|
ASSERT_TRUE(opt);
|
||||||
|
EXPECT_EQ(DHO_HOST_NAME, opt->getType());
|
||||||
|
const OptionBuffer& buffer = opt->getData();
|
||||||
|
ASSERT_EQ(3, buffer.size());
|
||||||
|
EXPECT_EQ(0, memcmp(&buffer[0], "abc", 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that ADD action does not add an already existing option.
|
||||||
|
TEST_F(FlexOptionTest, processAddExisting) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr code = Element::create(D6O_BOOTFILE_URL);
|
||||||
|
option->set("code", code);
|
||||||
|
ElementPtr add = Element::create(string("'abc'"));
|
||||||
|
option->set("add", add);
|
||||||
|
EXPECT_NO_THROW(impl_->configure(options));
|
||||||
|
|
||||||
|
Pkt6Ptr query(new Pkt6(DHCPV6_SOLICIT, 12345));
|
||||||
|
Pkt6Ptr response(new Pkt6(DHCPV6_ADVERTISE, 12345));
|
||||||
|
OptionStringPtr str(new OptionString(Option::V6, D6O_BOOTFILE_URL, "http"));
|
||||||
|
response->addOption(str);
|
||||||
|
|
||||||
|
EXPECT_NO_THROW(impl_->process<Pkt6Ptr>(Option::V6, query, response));
|
||||||
|
|
||||||
|
OptionPtr opt = response->getOption(D6O_BOOTFILE_URL);
|
||||||
|
ASSERT_TRUE(opt);
|
||||||
|
EXPECT_EQ(D6O_BOOTFILE_URL, opt->getType());
|
||||||
|
EXPECT_EQ("http", opt->toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that ADD action does not add an empty value.
|
||||||
|
TEST_F(FlexOptionTest, processAddEmpty) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr code = Element::create(DHO_HOST_NAME);
|
||||||
|
option->set("code", code);
|
||||||
|
ElementPtr add = Element::create(string("''"));
|
||||||
|
option->set("add", add);
|
||||||
|
EXPECT_NO_THROW(impl_->configure(options));
|
||||||
|
|
||||||
|
Pkt4Ptr query(new Pkt4(DHCPDISCOVER, 12345));
|
||||||
|
Pkt4Ptr response(new Pkt4(DHCPOFFER, 12345));
|
||||||
|
string response_txt = response->toText();
|
||||||
|
EXPECT_FALSE(response->getOption(DHO_HOST_NAME));
|
||||||
|
|
||||||
|
EXPECT_NO_THROW(impl_->process<Pkt4Ptr>(Option::V4, query, response));
|
||||||
|
|
||||||
|
EXPECT_EQ(response_txt, response->toText());
|
||||||
|
EXPECT_FALSE(response->getOption(DHO_HOST_NAME));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that SUPERSEDE action supersedes the specified option.
|
||||||
|
TEST_F(FlexOptionTest, processSupersede) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr code = Element::create(DHO_HOST_NAME);
|
||||||
|
option->set("code", code);
|
||||||
|
ElementPtr supersede = Element::create(string("'abc'"));
|
||||||
|
option->set("supersede", supersede);
|
||||||
|
EXPECT_NO_THROW(impl_->configure(options));
|
||||||
|
|
||||||
|
Pkt4Ptr query(new Pkt4(DHCPDISCOVER, 12345));
|
||||||
|
Pkt4Ptr response(new Pkt4(DHCPOFFER, 12345));
|
||||||
|
EXPECT_FALSE(response->getOption(DHO_HOST_NAME));
|
||||||
|
|
||||||
|
EXPECT_NO_THROW(impl_->process<Pkt4Ptr>(Option::V4, query, response));
|
||||||
|
|
||||||
|
OptionPtr opt = response->getOption(DHO_HOST_NAME);
|
||||||
|
ASSERT_TRUE(opt);
|
||||||
|
EXPECT_EQ(DHO_HOST_NAME, opt->getType());
|
||||||
|
const OptionBuffer& buffer = opt->getData();
|
||||||
|
ASSERT_EQ(3, buffer.size());
|
||||||
|
EXPECT_EQ(0, memcmp(&buffer[0], "abc", 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that SUPERSEDE action supersedes an already existing option.
|
||||||
|
TEST_F(FlexOptionTest, processSupersedeExisting) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr code = Element::create(D6O_BOOTFILE_URL);
|
||||||
|
option->set("code", code);
|
||||||
|
ElementPtr supersede = Element::create(string("'abc'"));
|
||||||
|
option->set("supersede", supersede);
|
||||||
|
EXPECT_NO_THROW(impl_->configure(options));
|
||||||
|
|
||||||
|
Pkt6Ptr query(new Pkt6(DHCPV6_SOLICIT, 12345));
|
||||||
|
Pkt6Ptr response(new Pkt6(DHCPV6_ADVERTISE, 12345));
|
||||||
|
OptionStringPtr str(new OptionString(Option::V6, D6O_BOOTFILE_URL, "http"));
|
||||||
|
response->addOption(str);
|
||||||
|
|
||||||
|
EXPECT_NO_THROW(impl_->process<Pkt6Ptr>(Option::V6, query, response));
|
||||||
|
|
||||||
|
OptionPtr opt = response->getOption(D6O_BOOTFILE_URL);
|
||||||
|
ASSERT_TRUE(opt);
|
||||||
|
EXPECT_EQ(D6O_BOOTFILE_URL, opt->getType());
|
||||||
|
const OptionBuffer& buffer = opt->getData();
|
||||||
|
ASSERT_EQ(3, buffer.size());
|
||||||
|
EXPECT_EQ(0, memcmp(&buffer[0], "abc", 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that SUPERSEDE action does not supersede an empty value.
|
||||||
|
TEST_F(FlexOptionTest, processSupersedeEmpty) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr code = Element::create(DHO_HOST_NAME);
|
||||||
|
option->set("code", code);
|
||||||
|
ElementPtr supersede = Element::create(string("''"));
|
||||||
|
option->set("supersede", supersede);
|
||||||
|
EXPECT_NO_THROW(impl_->configure(options));
|
||||||
|
|
||||||
|
Pkt4Ptr query(new Pkt4(DHCPDISCOVER, 12345));
|
||||||
|
Pkt4Ptr response(new Pkt4(DHCPOFFER, 12345));
|
||||||
|
string response_txt = response->toText();
|
||||||
|
EXPECT_FALSE(response->getOption(DHO_HOST_NAME));
|
||||||
|
|
||||||
|
EXPECT_NO_THROW(impl_->process<Pkt4Ptr>(Option::V4, query, response));
|
||||||
|
|
||||||
|
EXPECT_EQ(response_txt, response->toText());
|
||||||
|
EXPECT_FALSE(response->getOption(DHO_HOST_NAME));
|
||||||
|
|
||||||
|
// Empty value does not remove existing values.
|
||||||
|
OptionStringPtr str(new OptionString(Option::V4, DHO_HOST_NAME, "abc"));
|
||||||
|
response->addOption(str);
|
||||||
|
|
||||||
|
EXPECT_NO_THROW(impl_->process<Pkt4Ptr>(Option::V4, query, response));
|
||||||
|
|
||||||
|
OptionPtr opt = response->getOption(DHO_HOST_NAME);
|
||||||
|
ASSERT_TRUE(opt);
|
||||||
|
EXPECT_EQ(DHO_HOST_NAME, opt->getType());
|
||||||
|
const OptionBuffer& buffer = opt->getData();
|
||||||
|
ASSERT_EQ(3, buffer.size());
|
||||||
|
EXPECT_EQ(0, memcmp(&buffer[0], "abc", 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that REMOVE action removes an already existing option.
|
||||||
|
TEST_F(FlexOptionTest, processRemove) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr code = Element::create(D6O_BOOTFILE_URL);
|
||||||
|
option->set("code", code);
|
||||||
|
ElementPtr remove = Element::create(string("'abc' == 'abc'"));
|
||||||
|
option->set("remove", remove);
|
||||||
|
EXPECT_NO_THROW(impl_->configure(options));
|
||||||
|
|
||||||
|
Pkt6Ptr query(new Pkt6(DHCPV6_SOLICIT, 12345));
|
||||||
|
Pkt6Ptr response(new Pkt6(DHCPV6_ADVERTISE, 12345));
|
||||||
|
OptionStringPtr str(new OptionString(Option::V6, D6O_BOOTFILE_URL, "http"));
|
||||||
|
response->addOption(str);
|
||||||
|
|
||||||
|
EXPECT_NO_THROW(impl_->process<Pkt6Ptr>(Option::V6, query, response));
|
||||||
|
|
||||||
|
EXPECT_FALSE(response->getOption(D6O_BOOTFILE_URL));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that REMOVE action does nothing if the option is not present.
|
||||||
|
TEST_F(FlexOptionTest, processRemoveNoOption) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr code = Element::create(DHO_HOST_NAME);
|
||||||
|
option->set("code", code);
|
||||||
|
ElementPtr remove = Element::create(string("'abc' == 'abc'"));
|
||||||
|
option->set("remove", remove);
|
||||||
|
EXPECT_NO_THROW(impl_->configure(options));
|
||||||
|
|
||||||
|
Pkt4Ptr query(new Pkt4(DHCPDISCOVER, 12345));
|
||||||
|
Pkt4Ptr response(new Pkt4(DHCPOFFER, 12345));
|
||||||
|
string response_txt = response->toText();
|
||||||
|
EXPECT_FALSE(response->getOption(DHO_HOST_NAME));
|
||||||
|
|
||||||
|
EXPECT_NO_THROW(impl_->process<Pkt4Ptr>(Option::V4, query, response));
|
||||||
|
|
||||||
|
EXPECT_EQ(response_txt, response->toText());
|
||||||
|
EXPECT_FALSE(response->getOption(DHO_HOST_NAME));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that REMOVE action does nothing when the expression evaluates to false.
|
||||||
|
TEST_F(FlexOptionTest, processRemoveFalse) {
|
||||||
|
ElementPtr options = Element::createList();
|
||||||
|
ElementPtr option = Element::createMap();
|
||||||
|
options->add(option);
|
||||||
|
ElementPtr code = Element::create(D6O_BOOTFILE_URL);
|
||||||
|
option->set("code", code);
|
||||||
|
ElementPtr remove = Element::create(string("'abc' == 'xyz'"));
|
||||||
|
option->set("remove", remove);
|
||||||
|
EXPECT_NO_THROW(impl_->configure(options));
|
||||||
|
|
||||||
|
Pkt4Ptr query(new Pkt4(DHCPDISCOVER, 12345));
|
||||||
|
Pkt4Ptr response(new Pkt4(DHCPOFFER, 12345));
|
||||||
|
OptionStringPtr str(new OptionString(Option::V6, D6O_BOOTFILE_URL, "http"));
|
||||||
|
response->addOption(str);
|
||||||
|
string response_txt = response->toText();
|
||||||
|
|
||||||
|
EXPECT_NO_THROW(impl_->process<Pkt4Ptr>(Option::V6, query, response));
|
||||||
|
|
||||||
|
EXPECT_EQ(response_txt, response->toText());
|
||||||
|
EXPECT_TRUE(response->getOption(D6O_BOOTFILE_URL));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end of anonymous namespace
|
Reference in New Issue
Block a user