From: Tomek Mrugalski Date: Mon, 14 Feb 2022 19:31:57 +0000 (+0100) Subject: [#1548] Initial tests added X-Git-Tag: Kea-2.1.5~48 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0be2cf114bd5b37cd63dae0c4a975b37038ad190;p=thirdparty%2Fkea.git [#1548] Initial tests added --- diff --git a/src/hooks/dhcp/ddns_tuning/libloadtests/Makefile.am b/src/hooks/dhcp/ddns_tuning/libloadtests/Makefile.am new file mode 100644 index 0000000000..ba2160f19e --- /dev/null +++ b/src/hooks/dhcp/ddns_tuning/libloadtests/Makefile.am @@ -0,0 +1,60 @@ +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) diff --git a/src/hooks/dhcp/ddns_tuning/libloadtests/callout_unittests.cc b/src/hooks/dhcp/ddns_tuning/libloadtests/callout_unittests.cc new file mode 100644 index 0000000000..289b4b44c6 --- /dev/null +++ b/src/hooks/dhcp/ddns_tuning/libloadtests/callout_unittests.cc @@ -0,0 +1,174 @@ +// 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 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +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 diff --git a/src/hooks/dhcp/ddns_tuning/libloadtests/load_unload_unittests.cc b/src/hooks/dhcp/ddns_tuning/libloadtests/load_unload_unittests.cc new file mode 100644 index 0000000000..657d72d5d9 --- /dev/null +++ b/src/hooks/dhcp/ddns_tuning/libloadtests/load_unload_unittests.cc @@ -0,0 +1,80 @@ +// 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 + +#include +#include + +#include +#include + +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 diff --git a/src/hooks/dhcp/ddns_tuning/libloadtests/run_unittests.cc b/src/hooks/dhcp/ddns_tuning/libloadtests/run_unittests.cc new file mode 100644 index 0000000000..96a0ba7bb7 --- /dev/null +++ b/src/hooks/dhcp/ddns_tuning/libloadtests/run_unittests.cc @@ -0,0 +1,19 @@ +// 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 + +#include +#include + +int +main(int argc, char* argv[]) { + ::testing::InitGoogleTest(&argc, argv); + isc::log::initLogger(); + int result = RUN_ALL_TESTS(); + + return (result); +} diff --git a/src/hooks/dhcp/ddns_tuning/tests/.gitignore b/src/hooks/dhcp/ddns_tuning/tests/.gitignore new file mode 100644 index 0000000000..0b2fe58c7a --- /dev/null +++ b/src/hooks/dhcp/ddns_tuning/tests/.gitignore @@ -0,0 +1 @@ +/ddns_tuning_unittests diff --git a/src/hooks/dhcp/ddns_tuning/tests/Makefile.am b/src/hooks/dhcp/ddns_tuning/tests/Makefile.am new file mode 100644 index 0000000000..c888f129c5 --- /dev/null +++ b/src/hooks/dhcp/ddns_tuning/tests/Makefile.am @@ -0,0 +1,60 @@ +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) diff --git a/src/hooks/dhcp/ddns_tuning/tests/ddns_tuning_unittests.cc b/src/hooks/dhcp/ddns_tuning/tests/ddns_tuning_unittests.cc new file mode 100644 index 0000000000..767c45cdd6 --- /dev/null +++ b/src/hooks/dhcp/ddns_tuning/tests/ddns_tuning_unittests.cc @@ -0,0 +1,247 @@ +// 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +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 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: :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(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(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(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(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(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 diff --git a/src/hooks/dhcp/ddns_tuning/tests/run_unittests.cc b/src/hooks/dhcp/ddns_tuning/tests/run_unittests.cc new file mode 100644 index 0000000000..96a0ba7bb7 --- /dev/null +++ b/src/hooks/dhcp/ddns_tuning/tests/run_unittests.cc @@ -0,0 +1,19 @@ +// 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 + +#include +#include + +int +main(int argc, char* argv[]) { + ::testing::InitGoogleTest(&argc, argv); + isc::log::initLogger(); + int result = RUN_ALL_TESTS(); + + return (result); +} diff --git a/src/hooks/dhcp/ddns_tuning/version.cc b/src/hooks/dhcp/ddns_tuning/version.cc new file mode 100644 index 0000000000..c50a24b0c3 --- /dev/null +++ b/src/hooks/dhcp/ddns_tuning/version.cc @@ -0,0 +1,17 @@ +// 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 +#include + +extern "C" { + +/// @brief returns Kea hooks version. +int version() { + return (KEA_HOOKS_VERSION); +} + +}