--- /dev/null
+SUBDIRS = .
+
+AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
+AM_CPPFLAGS += -I$(top_builddir)/src/hooks/dhcp/ddns_tuning -I$(top_srcdir)/src/hooks/dhcp/ddns_tuning
+AM_CPPFLAGS += $(BOOST_INCLUDES)
+AM_CPPFLAGS += -DDDNS_TUNING_LIB_SO=\"$(abs_top_builddir)/src/hooks/dhcp/ddns_tuning/.libs/libdhcp_ddns_tuning.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 += hook_unittests
+
+hook_unittests_SOURCES = run_unittests.cc
+hook_unittests_SOURCES += callout_unittests.cc
+hook_unittests_SOURCES += load_unload_unittests.cc
+
+ddns_tuning_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) $(LOG4CPLUS_INCLUDES)
+
+ddns_tuning_unittests_LDFLAGS = $(AM_LDFLAGS) $(CRYPTO_LDFLAGS) $(GTEST_LDFLAGS)
+
+ddns_tuning_unittests_CXXFLAGS = $(AM_CXXFLAGS)
+
+ddns_tuning_unittests_LDADD = $(top_builddir)/src/lib/dhcpsrv/libkea-dhcpsrv.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/process/libkea-process.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/eval/libkea-eval.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/dhcp_ddns/libkea-dhcp_ddns.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/stats/libkea-stats.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/config/libkea-cfgclient.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/http/libkea-http.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/dhcp/libkea-dhcp++.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/hooks/libkea-hooks.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/database/libkea-database.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/cc/libkea-cc.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/dns/libkea-dns++.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/cryptolink/libkea-cryptolink.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/log/libkea-log.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/util/libkea-util.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
+ddns_tuning_unittests_LDADD += $(LOG4CPLUS_LIBS)
+ddns_tuning_unittests_LDADD += $(CRYPTO_LIBS)
+ddns_tuning_unittests_LDADD += $(BOOST_LIBS)
+ddns_tuning_unittests_LDADD += $(GTEST_LDADD)
+endif
+noinst_PROGRAMS = $(TESTS)
--- /dev/null
+// Copyright (C) 2022 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 exercise the pkt[46]_send callouis
+/// called by the flexible option hook library. In order to test the callouts
+/// one must be able to pass to the load function it hook library parameters
+/// because the only way to populate these parameters is by actually loading
+/// the library via HooksManager::loadLibraries().
+
+#include <config.h>
+
+#include <ddns_tuning.h>
+#include <hooks/hooks.h>
+#include <hooks/hooks_manager.h>
+#include <hooks/callout_manager.h>
+#include <dhcp/pkt4.h>
+#include <dhcp/pkt6.h>
+#include <dhcpsrv/cfgmgr.h>
+
+#include <gtest/gtest.h>
+#include <errno.h>
+
+using namespace std;
+using namespace isc;
+using namespace isc::hooks;
+using namespace isc::data;
+using namespace isc::dhcp;
+
+namespace {
+
+/// @brief Structure that holds registered hook indexes.
+struct TestHooks {
+ /// @brief Index of pkt4_send callout.
+ int hook_index_pkt4_send_;
+
+ /// @brief Index of pkt6_send callout.
+ int hook_index_pkt6_send_;
+
+ /// @brief Constructor
+ ///
+ /// The constructor registers hook points for callout tests.
+ TestHooks() {
+ hook_index_pkt4_send_ = HooksManager::registerHook("pkt4_send");
+ hook_index_pkt6_send_ = HooksManager::registerHook("pkt6_send");
+ }
+};
+
+TestHooks testHooks;
+
+/// @brief Test fixture for testing callouts called by the flex-option library
+class CalloutTest : public ::testing::Test {
+public:
+ /// @brief Constructor
+ CalloutTest() {
+ reset();
+ }
+
+ /// @brief Destructor
+ /// Removes files that may be left over from previous tests
+ virtual ~CalloutTest() {
+ reset();
+ }
+
+ /// @brief Removes files that may be left over from previous tests
+ virtual void reset() {
+ HooksManager::unloadLibraries();
+ }
+
+ void addLib(const std::string& lib, ConstElementPtr params) {
+ libraries_.push_back(make_pair(lib, params));
+ }
+
+ void loadLibs() {
+ EXPECT_TRUE(HooksManager::loadLibraries(libraries_));
+ }
+
+ void unloadLibs() {
+ EXPECT_NO_THROW(HooksManager::unloadLibraries());
+ }
+
+ HookLibsCollection libraries_;
+};
+
+// Simple test which exercises the pkt4_send callout.
+TEST_F(CalloutTest, pkt4Send) {
+ // Prepare load() parameters.
+ ElementPtr params = Element::createMap();
+ ElementPtr options = Element::createList();
+ params->set("options", options);
+ 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);
+
+ // Load the library.
+ addLib(DDNS_TUNING_LIB_SO, params);
+ loadLibs();
+
+ // Prepare packets.
+ Pkt4Ptr query(new Pkt4(DHCPDISCOVER, 12345));
+ Pkt4Ptr response(new Pkt4(DHCPOFFER, 12345));
+ EXPECT_FALSE(response->getOption(DHO_HOST_NAME));
+
+ // Get and setup the callout handle.
+ EXPECT_TRUE(HooksManager::calloutsPresent(testHooks.hook_index_pkt4_send_));
+ CalloutHandlePtr handle = HooksManager::createCalloutHandle();
+ handle->setArgument("query4", query);
+ handle->setArgument("response4", response);
+
+ // Execute the callout.
+ EXPECT_NO_THROW(HooksManager::callCallouts(testHooks.hook_index_pkt4_send_,
+ *handle));
+ EXPECT_EQ(0, handle->getStatus());
+
+ // Check the result.
+ 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));
+}
+
+// Simple test which exercises the pkt6_send callout.
+TEST_F(CalloutTest, pkt6Send) {
+ // Move to DHCPv6.
+ CfgMgr::instance().setFamily(AF_INET6);
+
+ // Prepare load() parameters.
+ ElementPtr params = Element::createMap();
+ ElementPtr options = Element::createList();
+ params->set("options", options);
+ 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);
+
+ // Load the library.
+ addLib(DDNS_TUNING_LIB_SO, params);
+ loadLibs();
+
+ // Prepare packets.
+ Pkt6Ptr query(new Pkt6(DHCPV6_SOLICIT, 12345));
+ Pkt6Ptr response(new Pkt6(DHCPV6_ADVERTISE, 12345));
+ EXPECT_FALSE(response->getOption(D6O_BOOTFILE_URL));
+
+ // Get and setup the callout handle.
+ EXPECT_TRUE(HooksManager::calloutsPresent(testHooks.hook_index_pkt6_send_));
+ CalloutHandlePtr handle = HooksManager::createCalloutHandle();
+ handle->setArgument("query6", query);
+ handle->setArgument("response6", response);
+
+ // Execute the callout.
+ EXPECT_NO_THROW(HooksManager::callCallouts(testHooks.hook_index_pkt6_send_,
+ *handle));
+ EXPECT_EQ(0, handle->getStatus());
+
+ // Check the result.
+ 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));
+}
+
+} // end of anonymous namespace
--- /dev/null
+// Copyright (C) 2022 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 exercise the load and unload
+/// functions in the ddns tuning hook library. In order to test the load
+/// function, one must be able to pass it hook library parameters. The
+/// the only way to populate these parameters is by actually loading the
+/// library via HooksManager::loadLibraries().
+
+#include <config.h>
+
+#include <ddns_tuning.h>
+#include <hooks/hooks_manager.h>
+
+#include <gtest/gtest.h>
+#include <errno.h>
+
+using namespace std;
+using namespace isc;
+using namespace isc::hooks;
+using namespace isc::data;
+using namespace isc::dhcp;
+
+namespace {
+
+/// @brief Test fixture for testing loading and unloading the flex-option library
+class LibLoadTest : public ::testing::Test {
+public:
+ /// @brief Constructor
+ LibLoadTest() {
+ reset();
+ }
+
+ /// @brief Destructor
+ /// Removes files that may be left over from previous tests
+ virtual ~LibLoadTest() {
+ reset();
+ }
+
+ /// @brief Removes files that may be left over from previous tests
+ virtual void reset() {
+ HooksManager::unloadLibraries();
+ }
+
+ void addLib(const std::string& lib, ConstElementPtr params) {
+ libraries_.push_back(make_pair(lib, params));
+ }
+
+ void loadLibs() {
+ EXPECT_TRUE(HooksManager::loadLibraries(libraries_));
+ }
+
+ void unloadLibs() {
+ EXPECT_NO_THROW(HooksManager::unloadLibraries());
+ }
+
+ HookLibsCollection libraries_;
+};
+
+// Simple test that checks the library can be loaded and unloaded several times.
+TEST_F(LibLoadTest, validLoad) {
+
+ // Prepare parameters for the callout parameters library.
+ // ElementPtr params = Element::createMap();
+ // ElementPtr options = Element::createList();
+ // params->set("hostname-expr", options);
+
+ addLib(DDNS_TUNING_LIB_SO, params);
+
+ loadLibs();
+ unloadLibs();
+
+ loadLibs();
+ unloadLibs();
+}
+
+} // end of anonymous namespace
--- /dev/null
+// Copyright (C) 2022 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);
+}
--- /dev/null
+/ddns_tuning_unittests
--- /dev/null
+SUBDIRS = .
+
+AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
+AM_CPPFLAGS += -I$(top_builddir)/src/hooks/dhcp/ddns_tuning -I$(top_srcdir)/src/hooks/dhcp/ddns_tuning
+AM_CPPFLAGS += $(BOOST_INCLUDES)
+AM_CPPFLAGS += -DDDNS_TUNING_LIB_SO=\"$(abs_top_builddir)/src/hooks/dhcp/ddns_tuning/.libs/libdhcp_ddns_tuning.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 += ddns_tuning_unittests
+
+ddns_tuning_unittests_SOURCES = run_unittests.cc
+ddns_tuning_unittests_SOURCES += ddns_tuning_unittests.cc
+
+ddns_tuning_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) $(LOG4CPLUS_INCLUDES)
+
+ddns_tuning_unittests_LDFLAGS = $(AM_LDFLAGS) $(CRYPTO_LDFLAGS) $(GTEST_LDFLAGS)
+
+ddns_tuning_unittests_CXXFLAGS = $(AM_CXXFLAGS)
+
+ddns_tuning_unittests_LDADD = $(top_builddir)/src/hooks/dhcp/ddns_tuning/libddns_tuning.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/dhcpsrv/libkea-dhcpsrv.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/process/libkea-process.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/eval/libkea-eval.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/dhcp_ddns/libkea-dhcp_ddns.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/stats/libkea-stats.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/config/libkea-cfgclient.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/http/libkea-http.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/dhcp/libkea-dhcp++.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/hooks/libkea-hooks.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/database/libkea-database.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/cc/libkea-cc.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/dns/libkea-dns++.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/cryptolink/libkea-cryptolink.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/log/libkea-log.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/util/libkea-util.la
+ddns_tuning_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
+ddns_tuning_unittests_LDADD += $(LOG4CPLUS_LIBS)
+ddns_tuning_unittests_LDADD += $(CRYPTO_LIBS)
+ddns_tuning_unittests_LDADD += $(BOOST_LIBS)
+ddns_tuning_unittests_LDADD += $(GTEST_LDADD)
+endif
+noinst_PROGRAMS = $(TESTS)
--- /dev/null
+// Copyright (C) 2022 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 <ddns_tuning.h>
+#include <ddns_tuning_log.h>
+#include <dhcp/libdhcp++.h>
+#include <dhcp/option_string.h>
+#include <dhcpsrv/cfgmgr.h>
+#include <eval/eval_context.h>
+#include <hooks/callout_manager.h>
+#include <hooks/hooks.h>
+
+#include <gtest/gtest.h>
+#include <sstream>
+
+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::ddns_tuning;
+
+namespace {
+
+/// @brief Test class derived from DdnsTuningImpl
+class TestDdnsTuningImpl : public DdnsTuningImpl {
+public:
+ /// @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 TestDdnsTuningImpl
+typedef boost::shared_ptr<TestDdnsTuningImpl> TestDdnsTuningImplPtr;
+
+/// @brief Test fixture for testing the DDNS Tuning library.
+class DdnsTuningTest : public ::testing::Test {
+public:
+ /// @brief Constructor.
+ DdnsTuningTest() {
+ impl_.reset(new TestDdnsTuningImpl());
+ CfgMgr::instance().setFamily(AF_INET);
+ }
+
+ /// @brief Destructor.
+ virtual ~DdnsTuningTest() {
+ CfgMgr::instance().setFamily(AF_INET);
+ impl_.reset();
+ }
+
+ /// @brief Flex Option implementation.
+ TestDdnsTuningImplPtr impl_;
+};
+
+// Verify that the configuration must exist.
+TEST_F(DdnsTuningTest, noConfig) {
+ ElementPtr options;
+ EXPECT_THROW(impl_->testConfigure(options), BadValue);
+ EXPECT_EQ("'hostname' parameter is mandatory", impl_->getErrMsg());
+}
+
+// Verify that the configuration must be a list.
+TEST_F(DdnsTuningTest, configNotList) {
+ ElementPtr options = Element::createMap();
+ EXPECT_THROW(impl_->testConfigure(options), BadValue);
+ EXPECT_EQ("'hostname' parameter must be a string", impl_->getErrMsg());
+}
+
+// Verify that the configuration can be the empty list.
+TEST_F(DdnsTuningTest, configEmpty) {
+ ElementPtr options = Element::createList();
+ EXPECT_NO_THROW(impl_->testConfigure(options));
+ EXPECT_TRUE(impl_->getErrMsg().empty());
+}
+
+
+
+// Verify that the add value must parse.
+TEST_F(DdnsTuningTest, optionConfigBadAdd) {
+ ElementPtr params = Element::createList();
+ params->set("hostname", Element::create(string("ifelse('a','b','c')")));
+ EXPECT_THROW(impl_->testConfigure(params), BadValue);
+ string expected = "can't parse add expression [ifelse('a','b','c')] ";
+ expected += "error: <string>:1.11: syntax error, ";
+ expected += "unexpected \",\", expecting == or +";
+ EXPECT_EQ(expected, impl_->getErrMsg());
+}
+
+// Verify that a valid v4 add value is accepted.
+TEST_F(DdnsTuningTest, optionConfigAdd4) {
+ ElementPtr params = Element::createList();
+ params->set("hostname", Element::create(string("ifelse('a','b','c')")));
+ EXPECT_NO_THROW(impl_->testConfigure(params));
+ EXPECT_TRUE(impl_->getErrMsg().empty());
+
+ /* TODO: verify it was really configured
+ auto map = impl_->getOptionConfigMap();
+ DdnsTuningImpl::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(DdnsTuningImpl::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 empty option config list does nothing.
+TEST_F(DdnsTuningTest, 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(DdnsTuningTest, processNone) {
+ CfgMgr::instance().setFamily(AF_INET6);
+
+ 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 REMOVE action does nothing if the option is not present.
+TEST_F(DdnsTuningTest, 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_->testConfigure(options));
+ EXPECT_TRUE(impl_->getErrMsg().empty());
+
+ 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(DdnsTuningTest, processRemoveFalse) {
+ 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' == 'xyz'"));
+ option->set("remove", remove);
+ 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));
+ OptionStringPtr str(new OptionString(Option::V6, D6O_BOOTFILE_URL, "http"));
+ response->addOption(str);
+ string response_txt = response->toText();
+
+ EXPECT_NO_THROW(impl_->process<Pkt6Ptr>(Option::V6, query, response));
+
+ EXPECT_EQ(response_txt, response->toText());
+ EXPECT_TRUE(response->getOption(D6O_BOOTFILE_URL));
+}
+
+// A more complex check...
+TEST_F(DdnsTuningTest, processFullTest) {
+ ElementPtr options = Element::createList();
+ ElementPtr option = Element::createMap();
+ options->add(option);
+ ElementPtr code = Element::create(DHO_BOOT_FILE_NAME);
+ option->set("code", code);
+ string expr = "ifelse(option[host-name].exists,";
+ expr += "concat(option[host-name].text,'.boot'),'')";
+ ElementPtr add = Element::create(expr);
+ option->set("add", add);
+ EXPECT_NO_THROW(impl_->testConfigure(options));
+ EXPECT_TRUE(impl_->getErrMsg().empty());
+
+ Pkt4Ptr query(new Pkt4(DHCPDISCOVER, 12345));
+ Pkt4Ptr response(new Pkt4(DHCPOFFER, 12345));
+ OptionStringPtr str(new OptionString(Option::V4, DHO_HOST_NAME, "foo"));
+ query->addOption(str);
+ EXPECT_FALSE(response->getOption(DHO_BOOT_FILE_NAME));
+
+ EXPECT_NO_THROW(impl_->process<Pkt4Ptr>(Option::V4, query, response));
+
+ OptionPtr opt = response->getOption(DHO_BOOT_FILE_NAME);
+ ASSERT_TRUE(opt);
+ EXPECT_EQ(DHO_BOOT_FILE_NAME, opt->getType());
+ const OptionBuffer& buffer = opt->getData();
+ ASSERT_EQ(8, buffer.size());
+ EXPECT_EQ(0, memcmp(&buffer[0], "foo.boot", 8));
+}
+
+
+
+} // end of anonymous namespace
--- /dev/null
+// Copyright (C) 2022 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);
+}
--- /dev/null
+// Copyright (C) 2022 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 <hooks/hooks.h>
+
+extern "C" {
+
+/// @brief returns Kea hooks version.
+int version() {
+ return (KEA_HOOKS_VERSION);
+}
+
+}