summaryrefslogtreecommitdiffstats
path: root/src/hooks/dhcp/lease_cmds/tests
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:15:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:15:43 +0000
commitf5f56e1a1c4d9e9496fcb9d81131066a964ccd23 (patch)
tree49e44c6f87febed37efb953ab5485aa49f6481a7 /src/hooks/dhcp/lease_cmds/tests
parentInitial commit. (diff)
downloadisc-kea-upstream.tar.xz
isc-kea-upstream.zip
Adding upstream version 2.4.1.upstream/2.4.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/hooks/dhcp/lease_cmds/tests')
-rw-r--r--src/hooks/dhcp/lease_cmds/tests/Makefile.am63
-rw-r--r--src/hooks/dhcp/lease_cmds/tests/Makefile.in1095
-rw-r--r--src/hooks/dhcp/lease_cmds/tests/lease_cmds4_unittest.cc4150
-rw-r--r--src/hooks/dhcp/lease_cmds/tests/lease_cmds6_unittest.cc4962
-rw-r--r--src/hooks/dhcp/lease_cmds/tests/lease_cmds_unittest.cc105
-rw-r--r--src/hooks/dhcp/lease_cmds/tests/lease_cmds_unittest.h572
-rw-r--r--src/hooks/dhcp/lease_cmds/tests/run_unittests.cc19
7 files changed, 10966 insertions, 0 deletions
diff --git a/src/hooks/dhcp/lease_cmds/tests/Makefile.am b/src/hooks/dhcp/lease_cmds/tests/Makefile.am
new file mode 100644
index 0000000..868e773
--- /dev/null
+++ b/src/hooks/dhcp/lease_cmds/tests/Makefile.am
@@ -0,0 +1,63 @@
+SUBDIRS = .
+
+AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
+AM_CPPFLAGS += -I$(top_builddir)/src/hooks/dhcp/lease_cmds -I$(top_srcdir)/src/hooks/dhcp/lease_cmds
+AM_CPPFLAGS += $(BOOST_INCLUDES)
+AM_CPPFLAGS += -DLEASE_CMDS_LIB_SO=\"$(abs_top_builddir)/src/hooks/dhcp/lease_cmds/.libs/libdhcp_lease_cmds.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 += lease_cmds_unittests
+
+lease_cmds_unittests_SOURCES = run_unittests.cc
+lease_cmds_unittests_SOURCES += lease_cmds_unittest.h lease_cmds_unittest.cc
+lease_cmds_unittests_SOURCES += lease_cmds4_unittest.cc
+lease_cmds_unittests_SOURCES += lease_cmds6_unittest.cc
+
+lease_cmds_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) $(LOG4CPLUS_INCLUDES)
+
+lease_cmds_unittests_LDFLAGS = $(AM_LDFLAGS) $(CRYPTO_LDFLAGS) $(GTEST_LDFLAGS)
+
+lease_cmds_unittests_CXXFLAGS = $(AM_CXXFLAGS)
+
+lease_cmds_unittests_LDADD = $(top_builddir)/src/lib/dhcpsrv/libkea-dhcpsrv.la
+lease_cmds_unittests_LDADD += $(top_builddir)/src/lib/process/libkea-process.la
+lease_cmds_unittests_LDADD += $(top_builddir)/src/lib/eval/libkea-eval.la
+lease_cmds_unittests_LDADD += $(top_builddir)/src/lib/dhcp_ddns/libkea-dhcp_ddns.la
+lease_cmds_unittests_LDADD += $(top_builddir)/src/lib/stats/libkea-stats.la
+lease_cmds_unittests_LDADD += $(top_builddir)/src/lib/config/libkea-cfgclient.la
+lease_cmds_unittests_LDADD += $(top_builddir)/src/lib/http/libkea-http.la
+lease_cmds_unittests_LDADD += $(top_builddir)/src/lib/dhcp/libkea-dhcp++.la
+lease_cmds_unittests_LDADD += $(top_builddir)/src/lib/hooks/libkea-hooks.la
+lease_cmds_unittests_LDADD += $(top_builddir)/src/lib/database/libkea-database.la
+lease_cmds_unittests_LDADD += $(top_builddir)/src/lib/cc/libkea-cc.la
+lease_cmds_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la
+lease_cmds_unittests_LDADD += $(top_builddir)/src/lib/dns/libkea-dns++.la
+lease_cmds_unittests_LDADD += $(top_builddir)/src/lib/cryptolink/libkea-cryptolink.la
+lease_cmds_unittests_LDADD += $(top_builddir)/src/lib/log/libkea-log.la
+lease_cmds_unittests_LDADD += $(top_builddir)/src/lib/util/libkea-util.la
+lease_cmds_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
+lease_cmds_unittests_LDADD += $(LOG4CPLUS_LIBS)
+lease_cmds_unittests_LDADD += $(CRYPTO_LIBS)
+lease_cmds_unittests_LDADD += $(BOOST_LIBS)
+lease_cmds_unittests_LDADD += $(GTEST_LDADD)
+
+endif
+noinst_PROGRAMS = $(TESTS)
diff --git a/src/hooks/dhcp/lease_cmds/tests/Makefile.in b/src/hooks/dhcp/lease_cmds/tests/Makefile.in
new file mode 100644
index 0000000..ced409e
--- /dev/null
+++ b/src/hooks/dhcp/lease_cmds/tests/Makefile.in
@@ -0,0 +1,1095 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+TESTS = $(am__EXEEXT_1)
+@HAVE_GTEST_TRUE@am__append_1 = lease_cmds_unittests
+noinst_PROGRAMS = $(am__EXEEXT_2)
+subdir = src/hooks/dhcp/lease_cmds/tests
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4macros/ax_boost_for_kea.m4 \
+ $(top_srcdir)/m4macros/ax_cpp11.m4 \
+ $(top_srcdir)/m4macros/ax_cpp20.m4 \
+ $(top_srcdir)/m4macros/ax_crypto.m4 \
+ $(top_srcdir)/m4macros/ax_find_library.m4 \
+ $(top_srcdir)/m4macros/ax_gssapi.m4 \
+ $(top_srcdir)/m4macros/ax_gtest.m4 \
+ $(top_srcdir)/m4macros/ax_isc_rpath.m4 \
+ $(top_srcdir)/m4macros/ax_netconf.m4 \
+ $(top_srcdir)/m4macros/libtool.m4 \
+ $(top_srcdir)/m4macros/ltoptions.m4 \
+ $(top_srcdir)/m4macros/ltsugar.m4 \
+ $(top_srcdir)/m4macros/ltversion.m4 \
+ $(top_srcdir)/m4macros/lt~obsolete.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+@HAVE_GTEST_TRUE@am__EXEEXT_1 = lease_cmds_unittests$(EXEEXT)
+am__EXEEXT_2 = $(am__EXEEXT_1)
+PROGRAMS = $(noinst_PROGRAMS)
+am__lease_cmds_unittests_SOURCES_DIST = run_unittests.cc \
+ lease_cmds_unittest.h lease_cmds_unittest.cc \
+ lease_cmds4_unittest.cc lease_cmds6_unittest.cc
+@HAVE_GTEST_TRUE@am_lease_cmds_unittests_OBJECTS = \
+@HAVE_GTEST_TRUE@ lease_cmds_unittests-run_unittests.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ lease_cmds_unittests-lease_cmds_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ lease_cmds_unittests-lease_cmds4_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ lease_cmds_unittests-lease_cmds6_unittest.$(OBJEXT)
+lease_cmds_unittests_OBJECTS = $(am_lease_cmds_unittests_OBJECTS)
+am__DEPENDENCIES_1 =
+@HAVE_GTEST_TRUE@lease_cmds_unittests_DEPENDENCIES = $(top_builddir)/src/lib/dhcpsrv/libkea-dhcpsrv.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/process/libkea-process.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/eval/libkea-eval.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/dhcp_ddns/libkea-dhcp_ddns.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/stats/libkea-stats.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/config/libkea-cfgclient.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/http/libkea-http.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/dhcp/libkea-dhcp++.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/hooks/libkea-hooks.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/database/libkea-database.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/cc/libkea-cc.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/asiolink/libkea-asiolink.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/dns/libkea-dns++.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/cryptolink/libkea-cryptolink.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/log/libkea-log.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/util/libkea-util.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/exceptions/libkea-exceptions.la \
+@HAVE_GTEST_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+@HAVE_GTEST_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+lease_cmds_unittests_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+ $(lease_cmds_unittests_CXXFLAGS) $(CXXFLAGS) \
+ $(lease_cmds_unittests_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = \
+ ./$(DEPDIR)/lease_cmds_unittests-lease_cmds4_unittest.Po \
+ ./$(DEPDIR)/lease_cmds_unittests-lease_cmds6_unittest.Po \
+ ./$(DEPDIR)/lease_cmds_unittests-lease_cmds_unittest.Po \
+ ./$(DEPDIR)/lease_cmds_unittests-run_unittests.Po
+am__mv = mv -f
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CXXFLAGS) $(CXXFLAGS)
+AM_V_CXX = $(am__v_CXX_@AM_V@)
+am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@)
+am__v_CXX_0 = @echo " CXX " $@;
+am__v_CXX_1 =
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CXXLD = $(am__v_CXXLD_@AM_V@)
+am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
+am__v_CXXLD_0 = @echo " CXXLD " $@;
+am__v_CXXLD_1 =
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(lease_cmds_unittests_SOURCES)
+DIST_SOURCES = $(am__lease_cmds_unittests_SOURCES_DIST)
+RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
+ ctags-recursive dvi-recursive html-recursive info-recursive \
+ install-data-recursive install-dvi-recursive \
+ install-exec-recursive install-html-recursive \
+ install-info-recursive install-pdf-recursive \
+ install-ps-recursive install-recursive installcheck-recursive \
+ installdirs-recursive pdf-recursive ps-recursive \
+ tags-recursive uninstall-recursive
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+am__recursive_targets = \
+ $(RECURSIVE_TARGETS) \
+ $(RECURSIVE_CLEAN_TARGETS) \
+ $(am__extra_recursive_targets)
+AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
+ distdir distdir-am
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors_dummy = \
+ mgn= red= grn= lgn= blu= brg= std=; \
+ am__color_tests=no
+am__tty_colors = { \
+ $(am__tty_colors_dummy); \
+ if test "X$(AM_COLOR_TESTS)" = Xno; then \
+ am__color_tests=no; \
+ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+ am__color_tests=yes; \
+ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+ am__color_tests=yes; \
+ fi; \
+ if test $$am__color_tests = yes; then \
+ red=''; \
+ grn=''; \
+ lgn=''; \
+ blu=''; \
+ mgn=''; \
+ brg=''; \
+ std=''; \
+ fi; \
+}
+DIST_SUBDIRS = $(SUBDIRS)
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+ASCIIDOC = @ASCIIDOC@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BOOST_INCLUDES = @BOOST_INCLUDES@
+BOOST_LIBS = @BOOST_LIBS@
+BOTAN_TOOL = @BOTAN_TOOL@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONTRIB_DIR = @CONTRIB_DIR@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CRYPTO_CFLAGS = @CRYPTO_CFLAGS@
+CRYPTO_INCLUDES = @CRYPTO_INCLUDES@
+CRYPTO_LDFLAGS = @CRYPTO_LDFLAGS@
+CRYPTO_LIBS = @CRYPTO_LIBS@
+CRYPTO_PACKAGE = @CRYPTO_PACKAGE@
+CRYPTO_RPATH = @CRYPTO_RPATH@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DISTCHECK_BOOST_CONFIGURE_FLAG = @DISTCHECK_BOOST_CONFIGURE_FLAG@
+DISTCHECK_CONTRIB_CONFIGURE_FLAG = @DISTCHECK_CONTRIB_CONFIGURE_FLAG@
+DISTCHECK_CRYPTO_CONFIGURE_FLAG = @DISTCHECK_CRYPTO_CONFIGURE_FLAG@
+DISTCHECK_GSSAPI_CONFIGURE_FLAG = @DISTCHECK_GSSAPI_CONFIGURE_FLAG@
+DISTCHECK_GTEST_CONFIGURE_FLAG = @DISTCHECK_GTEST_CONFIGURE_FLAG@
+DISTCHECK_KEA_SHELL_CONFIGURE_FLAG = @DISTCHECK_KEA_SHELL_CONFIGURE_FLAG@
+DISTCHECK_LIBYANGCPP_CONFIGURE_FLAG = @DISTCHECK_LIBYANGCPP_CONFIGURE_FLAG@
+DISTCHECK_LIBYANG_CONFIGURE_FLAG = @DISTCHECK_LIBYANG_CONFIGURE_FLAG@
+DISTCHECK_LOG4CPLUS_CONFIGURE_FLAG = @DISTCHECK_LOG4CPLUS_CONFIGURE_FLAG@
+DISTCHECK_MYSQL_CONFIGURE_FLAG = @DISTCHECK_MYSQL_CONFIGURE_FLAG@
+DISTCHECK_PERFDHCP_CONFIGURE_FLAG = @DISTCHECK_PERFDHCP_CONFIGURE_FLAG@
+DISTCHECK_PGSQL_CONFIGURE_FLAG = @DISTCHECK_PGSQL_CONFIGURE_FLAG@
+DISTCHECK_PREMIUM_CONFIGURE_FLAG = @DISTCHECK_PREMIUM_CONFIGURE_FLAG@
+DISTCHECK_SYSREPOCPP_CONFIGURE_FLAG = @DISTCHECK_SYSREPOCPP_CONFIGURE_FLAG@
+DISTCHECK_SYSREPO_CONFIGURE_FLAG = @DISTCHECK_SYSREPO_CONFIGURE_FLAG@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GENHTML = @GENHTML@
+GREP = @GREP@
+GSSAPI_CFLAGS = @GSSAPI_CFLAGS@
+GSSAPI_LIBS = @GSSAPI_LIBS@
+GTEST_CONFIG = @GTEST_CONFIG@
+GTEST_INCLUDES = @GTEST_INCLUDES@
+GTEST_LDADD = @GTEST_LDADD@
+GTEST_LDFLAGS = @GTEST_LDFLAGS@
+GTEST_SOURCE = @GTEST_SOURCE@
+HAVE_NETCONF = @HAVE_NETCONF@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+KEA_CXXFLAGS = @KEA_CXXFLAGS@
+KEA_SRCID = @KEA_SRCID@
+KRB5_CONFIG = @KRB5_CONFIG@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBYANGCPP_CPPFLAGS = @LIBYANGCPP_CPPFLAGS@
+LIBYANGCPP_INCLUDEDIR = @LIBYANGCPP_INCLUDEDIR@
+LIBYANGCPP_LIBS = @LIBYANGCPP_LIBS@
+LIBYANGCPP_PREFIX = @LIBYANGCPP_PREFIX@
+LIBYANGCPP_VERSION = @LIBYANGCPP_VERSION@
+LIBYANG_CPPFLAGS = @LIBYANG_CPPFLAGS@
+LIBYANG_INCLUDEDIR = @LIBYANG_INCLUDEDIR@
+LIBYANG_LIBS = @LIBYANG_LIBS@
+LIBYANG_PREFIX = @LIBYANG_PREFIX@
+LIBYANG_VERSION = @LIBYANG_VERSION@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LOG4CPLUS_INCLUDES = @LOG4CPLUS_INCLUDES@
+LOG4CPLUS_LIBS = @LOG4CPLUS_LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_TYPE = @PACKAGE_VERSION_TYPE@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PDFLATEX = @PDFLATEX@
+PERL = @PERL@
+PGSQL_CPPFLAGS = @PGSQL_CPPFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PKGPYTHONDIR = @PKGPYTHONDIR@
+PKG_CONFIG = @PKG_CONFIG@
+PLANTUML = @PLANTUML@
+PREMIUM_DIR = @PREMIUM_DIR@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+SED = @SED@
+SEP = @SEP@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPHINXBUILD = @SPHINXBUILD@
+SRPD_PLUGINS_PATH = @SRPD_PLUGINS_PATH@
+SR_PLUGINS_PATH = @SR_PLUGINS_PATH@
+SR_REPO_PATH = @SR_REPO_PATH@
+STRIP = @STRIP@
+SYSREPOCPP_CPPFLAGS = @SYSREPOCPP_CPPFLAGS@
+SYSREPOCPP_INCLUDEDIR = @SYSREPOCPP_INCLUDEDIR@
+SYSREPOCPP_LIBS = @SYSREPOCPP_LIBS@
+SYSREPOCPP_PREFIX = @SYSREPOCPP_PREFIX@
+SYSREPOCPP_VERSION = @SYSREPOCPP_VERSION@
+SYSREPO_CPPFLAGS = @SYSREPO_CPPFLAGS@
+SYSREPO_INCLUDEDIR = @SYSREPO_INCLUDEDIR@
+SYSREPO_LIBS = @SYSREPO_LIBS@
+SYSREPO_PREFIX = @SYSREPO_PREFIX@
+SYSREPO_VERSION = @SYSREPO_VERSION@
+USE_LCOV = @USE_LCOV@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARNING_GCC_44_STRICT_ALIASING_CFLAG = @WARNING_GCC_44_STRICT_ALIASING_CFLAG@
+YACC = @YACC@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = .
+AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib \
+ -I$(top_builddir)/src/hooks/dhcp/lease_cmds \
+ -I$(top_srcdir)/src/hooks/dhcp/lease_cmds $(BOOST_INCLUDES) \
+ -DLEASE_CMDS_LIB_SO=\"$(abs_top_builddir)/src/hooks/dhcp/lease_cmds/.libs/libdhcp_lease_cmds.so\" \
+ -DINSTALL_PROG=\"$(abs_top_srcdir)/install-sh\"
+AM_CXXFLAGS = $(KEA_CXXFLAGS)
+@USE_STATIC_LINK_TRUE@AM_LDFLAGS = -static
+
+# 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
+@HAVE_GTEST_TRUE@lease_cmds_unittests_SOURCES = run_unittests.cc \
+@HAVE_GTEST_TRUE@ lease_cmds_unittest.h lease_cmds_unittest.cc \
+@HAVE_GTEST_TRUE@ lease_cmds4_unittest.cc \
+@HAVE_GTEST_TRUE@ lease_cmds6_unittest.cc
+@HAVE_GTEST_TRUE@lease_cmds_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) $(LOG4CPLUS_INCLUDES)
+@HAVE_GTEST_TRUE@lease_cmds_unittests_LDFLAGS = $(AM_LDFLAGS) $(CRYPTO_LDFLAGS) $(GTEST_LDFLAGS)
+@HAVE_GTEST_TRUE@lease_cmds_unittests_CXXFLAGS = $(AM_CXXFLAGS)
+@HAVE_GTEST_TRUE@lease_cmds_unittests_LDADD = $(top_builddir)/src/lib/dhcpsrv/libkea-dhcpsrv.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/process/libkea-process.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/eval/libkea-eval.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/dhcp_ddns/libkea-dhcp_ddns.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/stats/libkea-stats.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/config/libkea-cfgclient.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/http/libkea-http.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/dhcp/libkea-dhcp++.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/hooks/libkea-hooks.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/database/libkea-database.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/cc/libkea-cc.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/asiolink/libkea-asiolink.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/dns/libkea-dns++.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/cryptolink/libkea-cryptolink.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/log/libkea-log.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/util/libkea-util.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/exceptions/libkea-exceptions.la \
+@HAVE_GTEST_TRUE@ $(LOG4CPLUS_LIBS) $(CRYPTO_LIBS) \
+@HAVE_GTEST_TRUE@ $(BOOST_LIBS) $(GTEST_LDADD)
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .cc .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/hooks/dhcp/lease_cmds/tests/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/hooks/dhcp/lease_cmds/tests/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+lease_cmds_unittests$(EXEEXT): $(lease_cmds_unittests_OBJECTS) $(lease_cmds_unittests_DEPENDENCIES) $(EXTRA_lease_cmds_unittests_DEPENDENCIES)
+ @rm -f lease_cmds_unittests$(EXEEXT)
+ $(AM_V_CXXLD)$(lease_cmds_unittests_LINK) $(lease_cmds_unittests_OBJECTS) $(lease_cmds_unittests_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lease_cmds_unittests-lease_cmds4_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lease_cmds_unittests-lease_cmds6_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lease_cmds_unittests-lease_cmds_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lease_cmds_unittests-run_unittests.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.cc.o:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
+
+lease_cmds_unittests-run_unittests.o: run_unittests.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lease_cmds_unittests_CPPFLAGS) $(CPPFLAGS) $(lease_cmds_unittests_CXXFLAGS) $(CXXFLAGS) -MT lease_cmds_unittests-run_unittests.o -MD -MP -MF $(DEPDIR)/lease_cmds_unittests-run_unittests.Tpo -c -o lease_cmds_unittests-run_unittests.o `test -f 'run_unittests.cc' || echo '$(srcdir)/'`run_unittests.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lease_cmds_unittests-run_unittests.Tpo $(DEPDIR)/lease_cmds_unittests-run_unittests.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='run_unittests.cc' object='lease_cmds_unittests-run_unittests.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lease_cmds_unittests_CPPFLAGS) $(CPPFLAGS) $(lease_cmds_unittests_CXXFLAGS) $(CXXFLAGS) -c -o lease_cmds_unittests-run_unittests.o `test -f 'run_unittests.cc' || echo '$(srcdir)/'`run_unittests.cc
+
+lease_cmds_unittests-run_unittests.obj: run_unittests.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lease_cmds_unittests_CPPFLAGS) $(CPPFLAGS) $(lease_cmds_unittests_CXXFLAGS) $(CXXFLAGS) -MT lease_cmds_unittests-run_unittests.obj -MD -MP -MF $(DEPDIR)/lease_cmds_unittests-run_unittests.Tpo -c -o lease_cmds_unittests-run_unittests.obj `if test -f 'run_unittests.cc'; then $(CYGPATH_W) 'run_unittests.cc'; else $(CYGPATH_W) '$(srcdir)/run_unittests.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lease_cmds_unittests-run_unittests.Tpo $(DEPDIR)/lease_cmds_unittests-run_unittests.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='run_unittests.cc' object='lease_cmds_unittests-run_unittests.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lease_cmds_unittests_CPPFLAGS) $(CPPFLAGS) $(lease_cmds_unittests_CXXFLAGS) $(CXXFLAGS) -c -o lease_cmds_unittests-run_unittests.obj `if test -f 'run_unittests.cc'; then $(CYGPATH_W) 'run_unittests.cc'; else $(CYGPATH_W) '$(srcdir)/run_unittests.cc'; fi`
+
+lease_cmds_unittests-lease_cmds_unittest.o: lease_cmds_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lease_cmds_unittests_CPPFLAGS) $(CPPFLAGS) $(lease_cmds_unittests_CXXFLAGS) $(CXXFLAGS) -MT lease_cmds_unittests-lease_cmds_unittest.o -MD -MP -MF $(DEPDIR)/lease_cmds_unittests-lease_cmds_unittest.Tpo -c -o lease_cmds_unittests-lease_cmds_unittest.o `test -f 'lease_cmds_unittest.cc' || echo '$(srcdir)/'`lease_cmds_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lease_cmds_unittests-lease_cmds_unittest.Tpo $(DEPDIR)/lease_cmds_unittests-lease_cmds_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='lease_cmds_unittest.cc' object='lease_cmds_unittests-lease_cmds_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lease_cmds_unittests_CPPFLAGS) $(CPPFLAGS) $(lease_cmds_unittests_CXXFLAGS) $(CXXFLAGS) -c -o lease_cmds_unittests-lease_cmds_unittest.o `test -f 'lease_cmds_unittest.cc' || echo '$(srcdir)/'`lease_cmds_unittest.cc
+
+lease_cmds_unittests-lease_cmds_unittest.obj: lease_cmds_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lease_cmds_unittests_CPPFLAGS) $(CPPFLAGS) $(lease_cmds_unittests_CXXFLAGS) $(CXXFLAGS) -MT lease_cmds_unittests-lease_cmds_unittest.obj -MD -MP -MF $(DEPDIR)/lease_cmds_unittests-lease_cmds_unittest.Tpo -c -o lease_cmds_unittests-lease_cmds_unittest.obj `if test -f 'lease_cmds_unittest.cc'; then $(CYGPATH_W) 'lease_cmds_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/lease_cmds_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lease_cmds_unittests-lease_cmds_unittest.Tpo $(DEPDIR)/lease_cmds_unittests-lease_cmds_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='lease_cmds_unittest.cc' object='lease_cmds_unittests-lease_cmds_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lease_cmds_unittests_CPPFLAGS) $(CPPFLAGS) $(lease_cmds_unittests_CXXFLAGS) $(CXXFLAGS) -c -o lease_cmds_unittests-lease_cmds_unittest.obj `if test -f 'lease_cmds_unittest.cc'; then $(CYGPATH_W) 'lease_cmds_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/lease_cmds_unittest.cc'; fi`
+
+lease_cmds_unittests-lease_cmds4_unittest.o: lease_cmds4_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lease_cmds_unittests_CPPFLAGS) $(CPPFLAGS) $(lease_cmds_unittests_CXXFLAGS) $(CXXFLAGS) -MT lease_cmds_unittests-lease_cmds4_unittest.o -MD -MP -MF $(DEPDIR)/lease_cmds_unittests-lease_cmds4_unittest.Tpo -c -o lease_cmds_unittests-lease_cmds4_unittest.o `test -f 'lease_cmds4_unittest.cc' || echo '$(srcdir)/'`lease_cmds4_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lease_cmds_unittests-lease_cmds4_unittest.Tpo $(DEPDIR)/lease_cmds_unittests-lease_cmds4_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='lease_cmds4_unittest.cc' object='lease_cmds_unittests-lease_cmds4_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lease_cmds_unittests_CPPFLAGS) $(CPPFLAGS) $(lease_cmds_unittests_CXXFLAGS) $(CXXFLAGS) -c -o lease_cmds_unittests-lease_cmds4_unittest.o `test -f 'lease_cmds4_unittest.cc' || echo '$(srcdir)/'`lease_cmds4_unittest.cc
+
+lease_cmds_unittests-lease_cmds4_unittest.obj: lease_cmds4_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lease_cmds_unittests_CPPFLAGS) $(CPPFLAGS) $(lease_cmds_unittests_CXXFLAGS) $(CXXFLAGS) -MT lease_cmds_unittests-lease_cmds4_unittest.obj -MD -MP -MF $(DEPDIR)/lease_cmds_unittests-lease_cmds4_unittest.Tpo -c -o lease_cmds_unittests-lease_cmds4_unittest.obj `if test -f 'lease_cmds4_unittest.cc'; then $(CYGPATH_W) 'lease_cmds4_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/lease_cmds4_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lease_cmds_unittests-lease_cmds4_unittest.Tpo $(DEPDIR)/lease_cmds_unittests-lease_cmds4_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='lease_cmds4_unittest.cc' object='lease_cmds_unittests-lease_cmds4_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lease_cmds_unittests_CPPFLAGS) $(CPPFLAGS) $(lease_cmds_unittests_CXXFLAGS) $(CXXFLAGS) -c -o lease_cmds_unittests-lease_cmds4_unittest.obj `if test -f 'lease_cmds4_unittest.cc'; then $(CYGPATH_W) 'lease_cmds4_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/lease_cmds4_unittest.cc'; fi`
+
+lease_cmds_unittests-lease_cmds6_unittest.o: lease_cmds6_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lease_cmds_unittests_CPPFLAGS) $(CPPFLAGS) $(lease_cmds_unittests_CXXFLAGS) $(CXXFLAGS) -MT lease_cmds_unittests-lease_cmds6_unittest.o -MD -MP -MF $(DEPDIR)/lease_cmds_unittests-lease_cmds6_unittest.Tpo -c -o lease_cmds_unittests-lease_cmds6_unittest.o `test -f 'lease_cmds6_unittest.cc' || echo '$(srcdir)/'`lease_cmds6_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lease_cmds_unittests-lease_cmds6_unittest.Tpo $(DEPDIR)/lease_cmds_unittests-lease_cmds6_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='lease_cmds6_unittest.cc' object='lease_cmds_unittests-lease_cmds6_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lease_cmds_unittests_CPPFLAGS) $(CPPFLAGS) $(lease_cmds_unittests_CXXFLAGS) $(CXXFLAGS) -c -o lease_cmds_unittests-lease_cmds6_unittest.o `test -f 'lease_cmds6_unittest.cc' || echo '$(srcdir)/'`lease_cmds6_unittest.cc
+
+lease_cmds_unittests-lease_cmds6_unittest.obj: lease_cmds6_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lease_cmds_unittests_CPPFLAGS) $(CPPFLAGS) $(lease_cmds_unittests_CXXFLAGS) $(CXXFLAGS) -MT lease_cmds_unittests-lease_cmds6_unittest.obj -MD -MP -MF $(DEPDIR)/lease_cmds_unittests-lease_cmds6_unittest.Tpo -c -o lease_cmds_unittests-lease_cmds6_unittest.obj `if test -f 'lease_cmds6_unittest.cc'; then $(CYGPATH_W) 'lease_cmds6_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/lease_cmds6_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lease_cmds_unittests-lease_cmds6_unittest.Tpo $(DEPDIR)/lease_cmds_unittests-lease_cmds6_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='lease_cmds6_unittest.cc' object='lease_cmds_unittests-lease_cmds6_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lease_cmds_unittests_CPPFLAGS) $(CPPFLAGS) $(lease_cmds_unittests_CXXFLAGS) $(CXXFLAGS) -c -o lease_cmds_unittests-lease_cmds6_unittest.obj `if test -f 'lease_cmds6_unittest.cc'; then $(CYGPATH_W) 'lease_cmds6_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/lease_cmds6_unittest.cc'; fi`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run 'make' without going through this Makefile.
+# To change the values of 'make' variables: instead of editing Makefiles,
+# (1) if the variable is set in 'config.status', edit 'config.status'
+# (which will cause the Makefiles to be regenerated when you run 'make');
+# (2) otherwise, pass the desired values on the 'make' command line.
+$(am__recursive_targets):
+ @fail=; \
+ if $(am__make_keepgoing); then \
+ failcom='fail=yes'; \
+ else \
+ failcom='exit 1'; \
+ fi; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-recursive
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-recursive
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-recursive
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+ @failed=0; all=0; xfail=0; xpass=0; skip=0; \
+ srcdir=$(srcdir); export srcdir; \
+ list=' $(TESTS) '; \
+ $(am__tty_colors); \
+ if test -n "$$list"; then \
+ for tst in $$list; do \
+ if test -f ./$$tst; then dir=./; \
+ elif test -f $$tst; then dir=; \
+ else dir="$(srcdir)/"; fi; \
+ if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xpass=`expr $$xpass + 1`; \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=XPASS; \
+ ;; \
+ *) \
+ col=$$grn; res=PASS; \
+ ;; \
+ esac; \
+ elif test $$? -ne 77; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xfail=`expr $$xfail + 1`; \
+ col=$$lgn; res=XFAIL; \
+ ;; \
+ *) \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=FAIL; \
+ ;; \
+ esac; \
+ else \
+ skip=`expr $$skip + 1`; \
+ col=$$blu; res=SKIP; \
+ fi; \
+ echo "$${col}$$res$${std}: $$tst"; \
+ done; \
+ if test "$$all" -eq 1; then \
+ tests="test"; \
+ All=""; \
+ else \
+ tests="tests"; \
+ All="All "; \
+ fi; \
+ if test "$$failed" -eq 0; then \
+ if test "$$xfail" -eq 0; then \
+ banner="$$All$$all $$tests passed"; \
+ else \
+ if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
+ banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
+ fi; \
+ else \
+ if test "$$xpass" -eq 0; then \
+ banner="$$failed of $$all $$tests failed"; \
+ else \
+ if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
+ banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
+ fi; \
+ fi; \
+ dashes="$$banner"; \
+ skipped=""; \
+ if test "$$skip" -ne 0; then \
+ if test "$$skip" -eq 1; then \
+ skipped="($$skip test was not run)"; \
+ else \
+ skipped="($$skip tests were not run)"; \
+ fi; \
+ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$skipped"; \
+ fi; \
+ report=""; \
+ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+ report="Please report to $(PACKAGE_BUGREPORT)"; \
+ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$report"; \
+ fi; \
+ dashes=`echo "$$dashes" | sed s/./=/g`; \
+ if test "$$failed" -eq 0; then \
+ col="$$grn"; \
+ else \
+ col="$$red"; \
+ fi; \
+ echo "$${col}$$dashes$${std}"; \
+ echo "$${col}$$banner$${std}"; \
+ test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \
+ test -z "$$report" || echo "$${col}$$report$${std}"; \
+ echo "$${col}$$dashes$${std}"; \
+ test "$$failed" -eq 0; \
+ else :; fi
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ $(am__make_dryrun) \
+ || test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-recursive
+all-am: Makefile $(PROGRAMS)
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f ./$(DEPDIR)/lease_cmds_unittests-lease_cmds4_unittest.Po
+ -rm -f ./$(DEPDIR)/lease_cmds_unittests-lease_cmds6_unittest.Po
+ -rm -f ./$(DEPDIR)/lease_cmds_unittests-lease_cmds_unittest.Po
+ -rm -f ./$(DEPDIR)/lease_cmds_unittests-run_unittests.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f ./$(DEPDIR)/lease_cmds_unittests-lease_cmds4_unittest.Po
+ -rm -f ./$(DEPDIR)/lease_cmds_unittests-lease_cmds6_unittest.Po
+ -rm -f ./$(DEPDIR)/lease_cmds_unittests-lease_cmds_unittest.Po
+ -rm -f ./$(DEPDIR)/lease_cmds_unittests-run_unittests.Po
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(am__recursive_targets) check-am install-am install-strip
+
+.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \
+ am--depfiles check check-TESTS check-am clean clean-generic \
+ clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \
+ ctags-am distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs installdirs-am maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-am uninstall uninstall-am
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/hooks/dhcp/lease_cmds/tests/lease_cmds4_unittest.cc b/src/hooks/dhcp/lease_cmds/tests/lease_cmds4_unittest.cc
new file mode 100644
index 0000000..444b4be
--- /dev/null
+++ b/src/hooks/dhcp/lease_cmds/tests/lease_cmds4_unittest.cc
@@ -0,0 +1,4150 @@
+// Copyright (C) 2017-2023 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 <exceptions/exceptions.h>
+#include <hooks/hooks_manager.h>
+#include <config/command_mgr.h>
+#include <dhcpsrv/lease_mgr.h>
+#include <dhcpsrv/lease_mgr_factory.h>
+#include <dhcpsrv/ncr_generator.h>
+#include <dhcpsrv/cfgmgr.h>
+#include <dhcpsrv/resource_handler.h>
+#include <cc/command_interpreter.h>
+#include <cc/data.h>
+#include <lease_cmds_unittest.h>
+#include <stats/stats_mgr.h>
+#include <testutils/user_context_utils.h>
+#include <testutils/multi_threading_utils.h>
+
+#include <gtest/gtest.h>
+
+#include <errno.h>
+#include <set>
+
+using namespace std;
+using namespace isc;
+using namespace isc::hooks;
+using namespace isc::config;
+using namespace isc::data;
+using namespace isc::dhcp;
+using namespace isc::dhcp_ddns;
+using namespace isc::asiolink;
+using namespace isc::stats;
+using namespace isc::test;
+
+namespace {
+
+/// @brief Class dedicated to testing v4 part of lease_cmds library.
+///
+/// Provides convenience methods for loading, testing all commands and
+/// unloading the lease_cmds library.
+class Lease4CmdsTest : public LeaseCmdsTest {
+public:
+ /// @brief Constructor.
+ Lease4CmdsTest() {
+ setFamily(AF_INET);
+ }
+
+ /// @brief Checks if specified response contains IPv4 lease
+ ///
+ /// @param lease Element tree that represents a lease
+ /// @param ip expected IP address
+ /// @param subnet_id expected subnet-id
+ /// @param hwaddr expected value of hardware address
+ /// @param client_id_required true if client-id is expected
+ /// @param pool_id expected pool-id (if value is 0 the parameter pool-id should not be present)
+ void checkLease4(isc::data::ConstElementPtr l, std::string ip,
+ uint32_t subnet_id, std::string hwaddr,
+ bool client_id_required, uint32_t pool_id = 0) {
+ ASSERT_TRUE(l);
+
+ // If the element is a list we need to retrieve the lease that
+ // we're interested in.
+ if (l->getType() == isc::data::Element::list) {
+ std::vector<isc::data::ElementPtr> e = l->listValue();
+ for (auto it = e.begin(); it != e.end(); ++it) {
+ isc::data::ConstElementPtr ip_address = (*it)->get("ip-address");
+ if (ip_address && ip_address->stringValue() == ip) {
+ l = (*it);
+ break;
+ }
+ }
+
+ ASSERT_TRUE(l);
+ }
+
+ ASSERT_TRUE(l->get("ip-address"));
+ EXPECT_EQ(ip, l->get("ip-address")->stringValue());
+
+ ASSERT_TRUE(l->get("subnet-id"));
+ EXPECT_EQ(subnet_id, l->get("subnet-id")->intValue());
+
+ ASSERT_TRUE(l->get("hw-address"));
+ EXPECT_EQ(hwaddr, l->get("hw-address")->stringValue());
+
+ // client-id may or may not appear
+ if (client_id_required) {
+ EXPECT_TRUE(l->get("client-id"));
+ }
+
+ if (pool_id) {
+ ASSERT_TRUE(l->get("pool-id"));
+ EXPECT_EQ(pool_id, l->get("pool-id")->intValue());
+ } else {
+ EXPECT_FALSE(l->get("pool-id"));
+ }
+
+ // Check that all expected fields are there.
+ ASSERT_TRUE(l->contains("valid-lft"));
+ ASSERT_TRUE(l->contains("cltt"));
+ ASSERT_TRUE(l->contains("subnet-id"));
+ ASSERT_TRUE(l->contains("state"));
+ ASSERT_TRUE(l->contains("fqdn-fwd"));
+ ASSERT_TRUE(l->contains("fqdn-rev"));
+ ASSERT_TRUE(l->contains("hostname"));
+ ASSERT_TRUE(l->contains("state"));
+
+ // Check that there are no v6 specific fields.
+ ASSERT_FALSE(l->contains("prefix"));
+ ASSERT_FALSE(l->contains("duid"));
+ ASSERT_FALSE(l->contains("preferred-lft"));
+
+ // Assuming that these values were used to create the lease.
+ // If we ever want to test different values they will need to
+ // be added as parameters to this function.
+ EXPECT_EQ(HIGH_VALID_LIFETIME,
+ static_cast<uint32_t>(l->get("valid-lft")->intValue()));
+ EXPECT_EQ(DEC_2030_TIME, l->get("cltt")->intValue());
+ }
+
+ /// @brief Check lease4 statistics.
+ ///
+ /// @param id Subnet id of the stats to check.
+ /// @assigned The expected value of assigned addresses in subnet.
+ /// @declined The expected value of declined addresses in subnet.
+ void checkLease4Stats(isc::dhcp::SubnetID id, int32_t assigned, int32_t declined) {
+ ASSERT_EQ(isc::stats::StatsMgr::instance().getObservation(
+ isc::stats::StatsMgr::generateName("subnet", id,
+ "assigned-addresses"))->getInteger().first, assigned);
+
+ ASSERT_EQ(isc::stats::StatsMgr::instance().getObservation(
+ isc::stats::StatsMgr::generateName("subnet", id,
+ "declined-addresses"))->getInteger().first, declined);
+ }
+
+ /// @brief Check that lease4-add with missing parameters will fail.
+ void testLease4AddMissingParams();
+
+ /// @brief Verify that lease4-add can be rejected if parameters are
+ /// specified, but have incorrect values.
+ void testLease4AddBadParams();
+
+ /// @brief Check that a simple, well formed lease4 can be added.
+ void testLease4Add();
+
+ /// @brief Check that a simple, well formed lease4 can be added.
+ void testLease4AddDeclinedLeases();
+
+ /// @brief Check that a lease4 is not added when it already exists.
+ void testLease4AddExisting();
+
+ /// @brief Check that subnet-id is optional. If not specified, Kea should
+ /// select it on its own.
+ void testLease4AddSubnetIdMissing();
+
+ /// @brief Check that subnet-id is optional. If not specified, Kea should
+ /// select it on its own.
+ void testLease4AddSubnetIdMissingDeclinedLeases();
+
+ /// @brief Check that subnet-id is optional. If not specified, Kea should
+ /// select it on its own, but if there's no subnet for address being added,
+ /// it should fail.
+ void testLease4AddSubnetIdMissingBadAddr();
+
+ /// @brief Check that the lease with negative expiration time is rejected.
+ void testLease4AddNegativeExpireTime();
+
+ /// @brief Check that the lease with negative cltt is rejected.
+ void testLease4AddNegativeCltt();
+
+ /// @brief Check that a well formed lease4 with tons of parameters can be
+ /// added.
+ void testLease4AddFullAddr();
+
+ /// @brief Check that a well formed lease4 with a comment can be added.
+ void testLease4AddComment();
+
+ /// @brief Check that a well formed lease4 with relay and remote ids
+ /// can be added.
+ void testLease4AddExtendedInfo();
+
+ /// @brief Check that lease4-get can handle a situation when the query is
+ /// broken (some required parameters are missing).
+ void testLease4GetMissingParams();
+
+ /// @brief Check that lease4-get sanitizes its input.
+ void testLease4GetByAddrBadParam();
+
+ /// @brief Check that lease4-get can handle a situation when the query is
+ /// correctly formed, but the lease is not there.
+ void testLease4GetByAddrNotFound();
+
+ /// @brief Check that lease4-get can return a lease by address.
+ void testLease4GetByAddr();
+
+ /// @brief Check that lease4-get can handle a situation when the query is
+ /// correctly formed, but the lease is not there.
+ void testLease4GetByHWAddrNotFound();
+
+ /// @brief Check that lease4-get can find a lease by hardware address.
+ void testLease4GetByHWAddr();
+
+ /// @brief Check that lease4-get can handle a situation when the query is
+ /// correctly formed, but the lease is not there.
+ void testLease4GetByClientIdNotFound();
+
+ /// @brief Check that lease4-get can find a lease by client identifier.
+ void testLease4GetByClientId();
+
+ /// @brief Check that lease4-get-all returns all leases.
+ void testLease4GetAll();
+
+ /// @brief Check that lease4-get-all returns empty set if no leases are
+ /// found.
+ void testLease4GetAllNoLeases();
+
+ /// @brief Check that lease4-get-all returns all leases for a subnet.
+ void testLease4GetAllBySubnetId();
+
+ /// @brief Check that lease4-get-all returns empty set when no leases are
+ /// found.
+ void testLease4GetAllBySubnetIdNoLeases();
+
+ /// @brief Check that lease4-get-all returns leases from multiple subnets.
+ void testLease4GetAllByMultipleSubnetIds();
+
+ /// @brief Check that lease4-get-all checks its input arguments.
+ void testLease4GetBySubnetIdInvalidArguments();
+
+ /// @brief Check that multiple calls to lease4-get-page return all leases.
+ void testLease4GetPaged();
+
+ /// @brief Verifies that first page of IPv4 leases can be retrieved by
+ /// specifying zero IPv4 address.
+ void testLease4GetPagedZeroAddress();
+
+ /// @brief Verifies that IPv6 address as a start address is rejected.
+ void testLease4GetPagedIPv6Address();
+
+ /// @brief Verifies that value of 'from' parameter other than 'start' or an
+ /// IPv4 address is rejected.
+ void testLease4GetPagedInvalidFrom();
+
+ /// @brief Verifies that limit is mandatory.
+ void testLease4GetPagedNoLimit();
+
+ /// @brief Verifies that the limit must be a number.
+ void testLease4GetPagedLimitNotNumber();
+
+ /// @brief Verifies that the limit of 0 is rejected.
+ void testLease4GetPagedLimitIsZero();
+
+ /// @brief Check that lease4-get-by-hw-address can handle a situation when
+ /// the query is broken (required parameter is missing).
+ void testLease4GetByHwAddressParams();
+
+ /// @brief Check that lease4-get-by-hw-address works as expected (find no
+ /// lease).
+ void testLease4GetByHwAddressFind0();
+
+ /// @brief Check that lease4-get-by-hw-address works as expected (find two
+ /// leases).
+ void testLease4GetByHwAddressFind2();
+
+ /// @brief Check that lease4-get-by-client-id can handle a situation when
+ /// the query is broken (required parameter is missing).
+ void testLease4GetByClientIdParams();
+
+ /// @brief Check that lease4-get-by-client-id works as expected (find no
+ /// lease).
+ void testLease4GetByClientIdFind0();
+
+ /// @brief Check that lease4-get-by-client-id works as expected (find two
+ /// leases).
+ void testLease4GetByClientIdFind2();
+
+ /// @brief Check that lease4-get-by-hostname can handle a situation when
+ /// the query is broken (required parameter is missing).
+ void testLease4GetByHostnameParams();
+
+ /// @brief Check that lease4-get-by-hostname works as expected (find no
+ /// lease).
+ void testLease4GetByHostnameFind0();
+
+ /// @brief Check that lease4-get-by-hostname works as expected (find two
+ /// leases).
+ void testLease4GetByHostnameFind2();
+
+ /// @brief Test checks if lease4-update handler refuses calls with missing
+ /// parameters.
+ void testLease4UpdateMissingParams();
+
+ /// @brief Verify that lease4-update can be rejected if parameters are
+ /// specified, but have incorrect values.
+ void testLease4UpdateBadParams();
+
+ /// @brief Check that lease4-update correctly handles case when there is no
+ /// lease to be updated.
+ void testLease4UpdateNoLease();
+
+ /// @brief Check that a lease4 can be updated. We're changing hw-address and
+ /// a hostname.
+ void testLease4Update();
+
+ /// @brief Check that a lease4 can be updated. We're changing hw-address and
+ /// a hostname.
+ void testLease4UpdateDeclinedLeases();
+
+ /// @brief Check that a lease4 can be updated. We're changing hw-address and
+ /// a hostname. The subnet-id is not specified.
+ void testLease4UpdateNoSubnetId();
+
+ /// @brief Check that a lease4 can be updated. We're changing hw-address and
+ /// a hostname. The subnet-id is not specified.
+ void testLease4UpdateNoSubnetIdDeclinedLeases();
+
+ /// @brief Check that a lease4 is created if it doesn't exist during the
+ /// update. To trigger this behavior 'force-create' boolean parameter must
+ /// be included in the command.
+ void testLease4UpdateForceCreate();
+
+ /// @brief Check that a lease4 is created if it doesn't exist during the
+ /// update. To trigger this behavior 'force-create' boolean parameter must
+ /// be included in the command. The subnet-id is not specified, Kea will
+ /// figure it out.
+ void testLease4UpdateForceCreateNoSubnetId();
+
+ /// @brief Check that lease4-update correctly handles case when the
+ /// 'force-create' parameter is explicitly set to false.
+ void testLease4UpdateDoNotForceCreate();
+
+ /// @brief Check that a lease4 can be updated. We're adding a comment and an
+ /// user context.
+ void testLease4UpdateComment();
+
+ /// @brief Check that a lease4 can be updated. We're adding relay and
+ /// remote ids.
+ void testLease4UpdateExtendedInfo();
+
+ /// @brief Check that lease4-del can handle a situation when the query is
+ /// broken (some required parameters are missing).
+ void testLease4DelMissingParams();
+
+ /// @brief Check that lease4-del can handle a situation when the query is
+ /// valid, but the lease is not there.
+ void testLease4DelByAddrNotFound();
+
+ /// @brief Check that lease4-del sanitizes its input.
+ void testLease4DelByAddrBadParam();
+
+ /// @brief Check that lease4-del can handle a situation when the query is
+ /// correctly formed and the lease is deleted.
+ void testLease4DelByAddr();
+
+ /// @brief Check that lease4-del can handle a situation when the query is
+ /// correctly formed and the lease is deleted.
+ void testLease4DelByAddrDeclinedLeases();
+
+ /// @brief Check that lease4-del can handle a situation when the query is
+ /// correctly formed, but the lease is not there.
+ void testLease4DelByHWAddrNotFound();
+
+ /// @brief Check that lease4-del can find and delete a lease by hardware
+ /// address.
+ void testLease4DelByHWAddr();
+
+ /// @brief Check that lease4-del can handle a situation when the query is
+ /// correctly formed, but the lease is not there.
+ void testLease4DelByClientIdNotFound();
+
+ /// @brief Check that lease4-del can find and delete a lease by client
+ /// identifier.
+ void testLease4DelByClientId();
+
+ /// @brief Check that lease4-wipe can remove leases.
+ void testLease4Wipe();
+
+ /// @brief Check that lease4-wipe can remove leases from all subnets at
+ /// once.
+ void testLease4WipeAll();
+
+ /// @brief Check that lease4-wipe can remove leases from all subnets at
+ /// once (when no parameters are specified).
+ void testLease4WipeAllNoArgs();
+
+ /// @brief Check that lease4-wipe properly reports when no leases were
+ /// deleted.
+ void testLease4WipeNoLeases();
+
+ /// @brief Check that lease4-wipe properly reports when no leases were
+ /// deleted.
+ void testLease4WipeNoLeasesAll();
+
+ /// @brief Check that an attempt to update a lease (set incorrect
+ /// subnet-id) will fail.
+ void testLease4BrokenUpdate();
+
+ /// @brief Check that lease4-resend-ddns sanitizes its input.
+ void testLease4ResendDdnsBadParam();
+
+ /// @brief Check that lease4-resend-ddns does not generate an NCR for given
+ /// lease when DDNS updating is disabled.
+ void testLease4ResendDdnsDisabled();
+
+ /// @brief Check that lease4-resend-ddns does not generate an NCR for when
+ /// there is no matching lease.
+ void testLease4ResendDdnsNoLease();
+
+ /// @brief Check that lease4-resend-ddns does not generate an NCR for given
+ /// lease when updates are enabled but Lease::hostname_ is blank.
+ void testLease4ResendNoHostname();
+
+ /// @brief Check that lease4-resend-ddns does not generate an NCR for given
+ /// lease when updates are enabled, Lease::hostname_ is not blank, but both
+ /// Lease::fqdn_fwd_ and fdqn_rev_ are false.
+ void testLease4ResendNoDirectionsEnabled();
+
+ /// @brief Check that lease4-resend-ddns can generate an NCR for given
+ /// lease when updates are enabled, Lease::hostname_ is not blank, and at
+ /// least one of Lease::fqdn_fwd_ or fdqn_rev_ are true.
+ void testLease4ResendDdnsEnabled();
+
+ /// @brief Check that lease4-del does (or does not) generate an NCR to
+ /// remove DNS for a given lease based on lease content when DDNS updates
+ /// are enabled.
+ void testLease4DnsRemoveD2Enabled();
+
+ /// @brief Check that lease4-del does not generate an NCR to remove DNS for
+ /// a given lease based on lease content when DDNS updates are disabled.
+ void testLease4DnsRemoveD2Disabled();
+
+ /// @brief Verify that v4 lease add handles conflict as expected.
+ void testLease4ConflictingAdd();
+
+ /// @brief Verify that v4 lease update handles conflict as expected.
+ void testLease4ConflictingUpdate();
+
+ /// @brief Check that lease4-write works as expected.
+ void testLease4Write();
+};
+
+void Lease4CmdsTest::testLease4AddMissingParams() {
+ // Initialize lease manager (false = v4, false = don't add leases)
+ initLeaseMgr(false, false);
+
+ // Everything missing. What sort of nonsense is that?
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-add\",\n"
+ " \"arguments\": {"
+ " }\n"
+ "}";
+ string exp_rsp = "missing parameter 'ip-address' (<string>:3:19)";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Just ip is not enough (subnet-id and hwaddr missing, although
+ // subnet-id can now be figured out by Kea code)
+ txt =
+ "{\n"
+ " \"command\": \"lease4-add\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"192.0.2.123\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "missing parameter 'hw-address' (<string>:3:19)";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Just subnet-id and ip is not enough. (hwaddr missing).
+ txt =
+ "{\n"
+ " \"command\": \"lease4-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44,\n"
+ " \"ip-address\": \"192.0.2.202\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "missing parameter 'hw-address' (<string>:3:19)";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Close, but no cigars. (ip-address missing).
+ txt =
+ "{\n"
+ " \"command\": \"lease4-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44,\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "missing parameter 'ip-address' (<string>:3:19)";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease4CmdsTest::testLease4AddBadParams() {
+ // Initialize lease manager (false = v4, false = don't add leases)
+ initLeaseMgr(false, false);
+
+ // All params are there, but there's no subnet-id 123 configured.
+ // (initLeaseMgr initialized subnet-id 44 for v4 and subnet-id 66 for v6).
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 123,\n"
+ " \"ip-address\": \"192.0.2.202\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\"\n"
+ " }\n"
+ "}";
+ string exp_rsp = "Invalid subnet-id: No IPv4 subnet with subnet-id=123 currently configured.";
+ testCommand(txt, CONTROL_RESULT_CONFLICT, exp_rsp);
+
+ // This time the IP address does not belong to the subnet.
+ txt =
+ "{\n"
+ " \"command\": \"lease4-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44,\n"
+ " \"ip-address\": \"10.0.0.1\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "The address 10.0.0.1 does not belong to subnet 192.0.2.0/24, subnet-id=44";
+ testCommand(txt, CONTROL_RESULT_CONFLICT, exp_rsp);
+
+ // We don't use any of that bleeding edge nonsense in this museum. v4 only.
+ txt =
+ "{\n"
+ " \"command\": \"lease4-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44,\n"
+ " \"ip-address\": \"2001:db8:1::1\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "Non-IPv4 address specified: 2001:db8:1::1";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Invalid state: the only supported values are 0,1,2.
+ txt =
+ "{\n"
+ " \"command\": \"lease4-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44,\n"
+ " \"ip-address\": \"192.0.2.1\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"state\": 123\n"
+ " }\n"
+ "}";
+ exp_rsp = "Invalid state value: 123, supported values are: 0 (default), 1 "
+ "(declined) and 2 (expired-reclaimed)";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Bad user context: not a map.
+ txt =
+ "{\n"
+ " \"command\": \"lease4-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44,\n"
+ " \"ip-address\": \"192.0.2.1\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"user-context\": \"bad value\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "Invalid user context '\"bad value\"' is not a JSON map.";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Duplicated comment.
+ txt =
+ "{\n"
+ " \"command\": \"lease4-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44,\n"
+ " \"ip-address\": \"192.0.2.1\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"user-context\": { \"comment\": \"in user context\" },\n"
+ " \"comment\": \"direct\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "Duplicated comment entry '\"direct\"' in user context "
+ "'{ \"comment\": \"in user context\" }'";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Negative expiration time.
+ txt =
+ "{\n"
+ " \"command\": \"lease4-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44,\n"
+ " \"ip-address\": \"192.0.2.1\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"user-context\": { \"comment\": \"in user context\" },\n"
+ " \"expire\": -6218189367\n"
+ " }\n"
+ "}";
+ exp_rsp = "expiration time must be positive for address 192.0.2.1";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Negative cltt
+ txt =
+ "{\n"
+ " \"command\": \"lease4-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44,\n"
+ " \"ip-address\": \"192.0.2.1\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"user-context\": { \"comment\": \"in user context\" },\n"
+ " \"expire\": 123456,\n"
+ " \"valid-lft\": 123457"
+ " }\n"
+ "}";
+ exp_rsp = "expiration time must be greater than valid lifetime for address "
+ "192.0.2.1";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease4CmdsTest::testLease4Add() {
+ // Initialize lease manager (false = v4, false = don't add leases)
+ initLeaseMgr(false, false);
+
+ checkLease4Stats(44, 0, 0);
+
+ checkLease4Stats(88, 0, 0);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44,\n"
+ " \"ip-address\": \"192.0.2.202\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\"\n"
+ " }\n"
+ "}";
+ string exp_rsp = "Lease for address 192.0.2.202, subnet-id 44 added.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease4Stats(44, 1, 0);
+
+ checkLease4Stats(88, 0, 0);
+
+ // Now check that the lease is really there.
+ Lease4Ptr l = lmptr_->getLease4(IOAddress("192.0.2.202"));
+ ASSERT_TRUE(l);
+
+ // Make sure the lease has proper value set.
+ ASSERT_TRUE(l->hwaddr_);
+ EXPECT_EQ("1a:1b:1c:1d:1e:1f", l->hwaddr_->toText(false));
+ EXPECT_EQ(3, l->valid_lft_); // taken from subnet configuration
+ EXPECT_FALSE(l->fqdn_fwd_);
+ EXPECT_FALSE(l->fqdn_rev_);
+ EXPECT_EQ("", l->hostname_);
+ EXPECT_FALSE(l->getContext());
+
+ // Test execution is fast. The cltt should be set to now. In some rare
+ // cases we could have the seconds counter to tick, so having a value off
+ // by one is ok.
+ EXPECT_LE(abs(l->cltt_ - time(NULL)), 1);
+ EXPECT_EQ(0, l->state_);
+}
+
+void Lease4CmdsTest::testLease4AddDeclinedLeases() {
+ // Initialize lease manager (false = v4, false = don't add leases)
+ initLeaseMgr(false, false);
+
+ checkLease4Stats(44, 0, 0);
+
+ checkLease4Stats(88, 0, 0);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44,\n"
+ " \"ip-address\": \"192.0.2.202\",\n"
+ " \"state\": 1,\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\"\n"
+ " }\n"
+ "}";
+ string exp_rsp = "Lease for address 192.0.2.202, subnet-id 44 added.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease4Stats(44, 1, 1);
+
+ checkLease4Stats(88, 0, 0);
+
+ // Now check that the lease is really there.
+ Lease4Ptr l = lmptr_->getLease4(IOAddress("192.0.2.202"));
+ ASSERT_TRUE(l);
+
+ // Make sure the lease has proper value set.
+ ASSERT_TRUE(l->hwaddr_);
+ EXPECT_EQ("1a:1b:1c:1d:1e:1f", l->hwaddr_->toText(false));
+ EXPECT_EQ(3, l->valid_lft_); // taken from subnet configuration
+ EXPECT_FALSE(l->fqdn_fwd_);
+ EXPECT_FALSE(l->fqdn_rev_);
+ EXPECT_EQ("", l->hostname_);
+ EXPECT_FALSE(l->getContext());
+
+ // Test execution is fast. The cltt should be set to now. In some rare
+ // cases we could have the seconds counter to tick, so having a value off
+ // by one is ok.
+ EXPECT_LE(abs(l->cltt_ - time(NULL)), 1);
+ EXPECT_EQ(1, l->state_);
+}
+
+void Lease4CmdsTest::testLease4AddExisting() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ checkLease4Stats(44, 2, 0);
+
+ checkLease4Stats(88, 2, 0);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44,\n"
+ " \"ip-address\": \"192.0.2.1\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\"\n"
+ " }\n"
+ "}";
+ string exp_rsp = "IPv4 lease already exists.";
+ testCommand(txt, CONTROL_RESULT_CONFLICT, exp_rsp);
+
+ checkLease4Stats(44, 2, 0);
+
+ checkLease4Stats(88, 2, 0);
+}
+
+void Lease4CmdsTest::testLease4AddSubnetIdMissing() {
+ // Initialize lease manager (false = v4, false = don't add leases)
+ initLeaseMgr(false, false);
+
+ checkLease4Stats(44, 0, 0);
+
+ checkLease4Stats(88, 0, 0);
+
+ // Now send the command without subnet-id. Kea should select
+ // the subnet id on its own.
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-add\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"192.0.2.202\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\"\n"
+ " }\n"
+ "}";
+ string exp_rsp = "Lease for address 192.0.2.202, subnet-id 44 added.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease4Stats(44, 1, 0);
+
+ checkLease4Stats(88, 0, 0);
+
+ // Now check that the lease is really there and has correct subnet-id.
+ Lease4Ptr l = lmptr_->getLease4(IOAddress("192.0.2.202"));
+ ASSERT_TRUE(l);
+ EXPECT_EQ(44, l->subnet_id_);
+}
+
+void Lease4CmdsTest::testLease4AddSubnetIdMissingDeclinedLeases() {
+ // Initialize lease manager (false = v4, false = don't add leases)
+ initLeaseMgr(false, false);
+
+ checkLease4Stats(44, 0, 0);
+
+ checkLease4Stats(88, 0, 0);
+
+ // Now send the command without subnet-id. Kea should select
+ // the subnet id on its own.
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-add\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"192.0.2.202\",\n"
+ " \"state\": 1,\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\"\n"
+ " }\n"
+ "}";
+ string exp_rsp = "Lease for address 192.0.2.202, subnet-id 44 added.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease4Stats(44, 1, 1);
+
+ checkLease4Stats(88, 0, 0);
+
+ // Now check that the lease is really there and has correct subnet-id.
+ Lease4Ptr l = lmptr_->getLease4(IOAddress("192.0.2.202"));
+ ASSERT_TRUE(l);
+ EXPECT_EQ(44, l->subnet_id_);
+}
+
+void Lease4CmdsTest::testLease4AddSubnetIdMissingBadAddr() {
+ // Initialize lease manager (false = v4, false = don't add leases)
+ initLeaseMgr(false, false);
+
+ checkLease4Stats(44, 0, 0);
+
+ checkLease4Stats(88, 0, 0);
+
+ // Now send the command without subnet-id. Kea should select
+ // the subnet id on its own.
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-add\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"192.0.55.1\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\"\n"
+ " }\n"
+ "}";
+ string exp_rsp = "subnet-id not specified and failed to find a subnet for "
+ "address 192.0.55.1";
+ testCommand(txt, CONTROL_RESULT_CONFLICT, exp_rsp);
+
+ checkLease4Stats(44, 0, 0);
+
+ checkLease4Stats(88, 0, 0);
+
+ // Now check that the lease was not added.
+ Lease4Ptr l = lmptr_->getLease4(IOAddress("192.0.55.1"));
+ ASSERT_FALSE(l);
+}
+
+void Lease4CmdsTest::testLease4AddNegativeExpireTime() {
+ // Initialize lease manager (false = v4, false = don't add leases)
+ initLeaseMgr(false, false);
+
+ checkLease4Stats(44, 0, 0);
+
+ checkLease4Stats(88, 0, 0);
+
+ // Add a lease with negative expiration time.
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-add\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"192.0.2.202\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"expire\": -6218189367\n"
+ " }\n"
+ "}";
+ string exp_rsp = "expiration time must be positive for address 192.0.2.202";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ checkLease4Stats(44, 0, 0);
+
+ checkLease4Stats(88, 0, 0);
+
+ // Now check that the lease was not added.
+ Lease4Ptr l = lmptr_->getLease4(IOAddress("192.0.2.202"));
+ ASSERT_FALSE(l);
+}
+
+void Lease4CmdsTest::testLease4AddNegativeCltt() {
+ // Initialize lease manager (false = v4, false = don't add leases)
+ initLeaseMgr(false, false);
+
+ checkLease4Stats(44, 0, 0);
+
+ checkLease4Stats(88, 0, 0);
+
+ // Add a lease with negative cltt (expiration time - valid lifetime)
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-add\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"192.0.2.202\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"expire\": 123456,\n"
+ " \"valid-lft\": 123457"
+ " }\n"
+ "}";
+ string exp_rsp = "expiration time must be greater than valid lifetime for "
+ "address 192.0.2.202";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ checkLease4Stats(44, 0, 0);
+
+ checkLease4Stats(88, 0, 0);
+
+ // Now check that the lease was not added.
+ Lease4Ptr l = lmptr_->getLease4(IOAddress("192.0.2.202"));
+ ASSERT_FALSE(l);
+}
+
+void Lease4CmdsTest::testLease4AddFullAddr() {
+ // Initialize lease manager (false = v4, false = don't add leases)
+ initLeaseMgr(false, false);
+
+ checkLease4Stats(44, 0, 0);
+
+ checkLease4Stats(88, 0, 0);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44,\n"
+ " \"ip-address\": \"192.0.2.202\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"client-id\": \"01:02:03:04:05:06:07:08\",\n"
+ " \"valid-lft\": 1000,\n"
+ " \"expire\": 6218189367,\n"
+ " \"fqdn-fwd\": true,\n"
+ " \"fqdn-rev\": true,\n"
+ " \"hostname\": \"urania.example.org\",\n"
+ " \"pool-id\": 5,\n"
+ " \"user-context\": { \"foobar\": true }\n"
+ " }\n"
+ "}";
+ string exp_rsp = "Lease for address 192.0.2.202, subnet-id 44 added.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease4Stats(44, 1, 0);
+
+ checkLease4Stats(88, 0, 0);
+
+ // Now check that the lease is really there.
+ Lease4Ptr l = lmptr_->getLease4(IOAddress("192.0.2.202"));
+ ASSERT_TRUE(l);
+ EXPECT_EQ("192.0.2.202", l->addr_.toText());
+ ASSERT_TRUE(l->hwaddr_);
+ EXPECT_EQ("1a:1b:1c:1d:1e:1f", l->hwaddr_->toText(false));
+ ASSERT_TRUE(l->client_id_);
+ EXPECT_EQ("01:02:03:04:05:06:07:08", l->client_id_->toText());
+ // expire (6218189367) - valid_lft(1000)
+ EXPECT_EQ(static_cast<time_t>(6218189367 - 1000), l->cltt_);
+ EXPECT_EQ(true, l->fqdn_fwd_);
+ EXPECT_EQ(true, l->fqdn_rev_);
+ EXPECT_EQ("urania.example.org", l->hostname_);
+ EXPECT_EQ(5, l->pool_id_);
+ ASSERT_TRUE(l->getContext());
+ EXPECT_EQ("{ \"foobar\": true }", l->getContext()->str());
+}
+
+void Lease4CmdsTest::testLease4AddComment() {
+ // Initialize lease manager (false = v4, false = don't add leases)
+ initLeaseMgr(false, false);
+
+ checkLease4Stats(44, 0, 0);
+
+ checkLease4Stats(88, 0, 0);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44,\n"
+ " \"ip-address\": \"192.0.2.202\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"comment\": \"a comment\"\n"
+ " }\n"
+ "}";
+ string exp_rsp = "Lease for address 192.0.2.202, subnet-id 44 added.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease4Stats(44, 1, 0);
+
+ checkLease4Stats(88, 0, 0);
+
+ // Now check that the lease is really there.
+ Lease4Ptr l = lmptr_->getLease4(IOAddress("192.0.2.202"));
+ ASSERT_TRUE(l);
+
+ // Make sure the lease has proper value set.
+ ASSERT_TRUE(l->hwaddr_);
+ EXPECT_EQ("1a:1b:1c:1d:1e:1f", l->hwaddr_->toText(false));
+ ASSERT_TRUE(l->getContext());
+ EXPECT_EQ("{ \"comment\": \"a comment\" }", l->getContext()->str());
+}
+
+void Lease4CmdsTest::testLease4AddExtendedInfo() {
+ // Initialize lease manager (false = v4, false = don't add leases)
+ initLeaseMgr(false, false);
+
+ checkLease4Stats(44, 0, 0);
+
+ checkLease4Stats(88, 0, 0);
+
+ Lease4Collection leases;
+ const vector<uint8_t> relay_id = { 0xaa, 0xbb, 0xcc };
+ leases = lmptr_->getLeases4ByRelayId(relay_id,
+ IOAddress::IPV4_ZERO_ADDRESS(),
+ LeasePageSize(10));
+ EXPECT_TRUE(leases.empty());
+ const vector<uint8_t> remote_id = { 1, 2, 3 };
+ leases = lmptr_->getLeases4ByRemoteId(remote_id,
+ IOAddress::IPV4_ZERO_ADDRESS(),
+ LeasePageSize(10));
+ EXPECT_TRUE(leases.empty());
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44,\n"
+ " \"ip-address\": \"192.0.2.202\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"user-context\": { \"ISC\": { \"relay-agent-info\": {\n"
+ " \"sub-options\": \"0x02030102030C03AABBCC\",\n"
+ " \"remote-id\": \"010203\",\n"
+ " \"relay-id\": \"AABBCC\"\n"
+ " } } }\n"
+ " }\n"
+ "}";
+ string exp_rsp = "Lease for address 192.0.2.202, subnet-id 44 added.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease4Stats(44, 1, 0);
+
+ checkLease4Stats(88, 0, 0);
+
+ // Now check that the lease is really there.
+ Lease4Ptr l = lmptr_->getLease4(IOAddress("192.0.2.202"));
+ ASSERT_TRUE(l);
+
+ // Make sure the lease has proper value set.
+ ASSERT_TRUE(l->hwaddr_);
+ EXPECT_EQ("1a:1b:1c:1d:1e:1f", l->hwaddr_->toText(false));
+
+ // Check the user context / extended info too.
+ ConstElementPtr ctx = l->getContext();
+ ASSERT_TRUE(ctx);
+ string expected = "{ \"ISC\": { \"relay-agent-info\": ";
+ expected += "{ \"relay-id\": \"AABBCC\", ";
+ expected += "\"remote-id\": \"010203\", ";
+ expected += "\"sub-options\": \"0x02030102030C03AABBCC\" } } }";
+ EXPECT_EQ(expected, ctx->str());
+ EXPECT_EQ(relay_id, l->relay_id_);
+ EXPECT_EQ(remote_id, l->remote_id_);
+
+ // Check the lease can be retrieved by its relay or remote id too.
+ leases = lmptr_->getLeases4ByRelayId(relay_id,
+ IOAddress::IPV4_ZERO_ADDRESS(),
+ LeasePageSize(10));
+ ASSERT_EQ(1, leases.size());
+ EXPECT_EQ(*l, *leases[0]);
+ leases = lmptr_->getLeases4ByRemoteId(remote_id,
+ IOAddress::IPV4_ZERO_ADDRESS(),
+ LeasePageSize(10));
+ ASSERT_EQ(1, leases.size());
+ EXPECT_EQ(*l, *leases[0]);
+}
+
+void Lease4CmdsTest::testLease4GetMissingParams() {
+ // No parameters whatsoever. You want just a lease, any lease?
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-get\",\n"
+ " \"arguments\": {"
+ " }\n"
+ "}";
+ string exp_rsp = "Mandatory 'subnet-id' parameter missing.";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Just the subnet-id won't cut it, either.
+ cmd =
+ "{\n"
+ " \"command\": \"lease4-get\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 123"
+ " }\n"
+ "}";
+ exp_rsp = "No 'ip-address' provided and 'identifier-type' is either missing or not a string.";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // We can't identify your laptop by color. Sorry, buddy.
+ cmd =
+ "{\n"
+ " \"command\": \"lease4-get\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 123,\n"
+ " \"identifier-type\": \"color\",\n"
+ " \"identifier\": \"blue\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "Incorrect identifier type: color, the only supported values are: "
+ "address, hw-address, duid";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Query by DUID is not supported in v4. Sorry.
+ cmd =
+ "{\n"
+ " \"command\": \"lease4-get\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 123,\n"
+ " \"identifier-type\": \"duid\",\n"
+ " \"identifier\": \"01:01:01:01:01:01\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "Query by duid is not allowed in v4.";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Identifier value is missing.
+ cmd =
+ "{\n"
+ " \"command\": \"lease4-get\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 123,\n"
+ " \"identifier-type\": \"hw-address\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "No 'ip-address' provided and 'identifier' is either missing or not a string.";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Identifier-type is missing.
+ cmd =
+ "{\n"
+ " \"command\": \"lease4-get\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 123,\n"
+ " \"identifier\": \"01:02:03:04:05\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "No 'ip-address' provided and 'identifier-type' is either missing or not a string.";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease4CmdsTest::testLease4GetByAddrBadParam() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ // Invalid family
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-get\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"2001:db8:1::1\""
+ " }\n"
+ "}";
+ string exp_rsp = "Invalid IPv4 address specified: 2001:db8:1::1";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // This is way off
+ cmd =
+ "{\n"
+ " \"command\": \"lease4-get\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"221B Baker St.\""
+ " }\n"
+ "}";
+ exp_rsp = "Failed to convert string to address '221B Baker St.': Invalid argument";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease4CmdsTest::testLease4GetByAddrNotFound() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ // Invalid
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-get\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"192.0.2.5\","
+ " \"subnet-id\": 44"
+ " }\n"
+ "}";
+ string exp_rsp = "Lease not found.";
+
+ // Note the status expected is empty. The query completed correctly,
+ // just didn't found the lease.
+ testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
+}
+
+void Lease4CmdsTest::testLease4GetByAddr() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-get\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"192.0.2.1\""
+ " }\n"
+ "}";
+ string exp_rsp = "IPv4 lease found.";
+
+ // The status expected is success. The lease should be returned.
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ // Now check that the lease parameters were indeed returned.
+ ASSERT_TRUE(rsp);
+
+ ConstElementPtr lease = rsp->get("arguments");
+ ASSERT_TRUE(lease);
+
+ // Now check that the lease was indeed returned.
+ checkLease4(lease, "192.0.2.1", 44, "08:08:08:08:08:08", true);
+}
+
+void Lease4CmdsTest::testLease4GetByHWAddrNotFound() {
+ // Initialize lease manager (false = v4, false = don't add leases)
+ initLeaseMgr(false, false);
+
+ // No such lease.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-get\",\n"
+ " \"arguments\": {"
+ " \"identifier-type\": \"hw-address\","
+ " \"identifier\": \"01:02:03:04:05:06\","
+ " \"subnet-id\": 44"
+ " }\n"
+ "}";
+ string exp_rsp = "Lease not found.";
+ testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
+}
+
+void Lease4CmdsTest::testLease4GetByHWAddr() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-get\",\n"
+ " \"arguments\": {"
+ " \"identifier-type\": \"hw-address\","
+ " \"identifier\": \"08:08:08:08:08:08\","
+ " \"subnet-id\": 44"
+ " }\n"
+ "}";
+ string exp_rsp = "IPv4 lease found.";
+
+ // The status expected is success. The lease should be returned.
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ // Now check that the lease parameters were indeed returned.
+ ASSERT_TRUE(rsp);
+
+ ConstElementPtr lease = rsp->get("arguments");
+ ASSERT_TRUE(lease);
+
+ // Now check that the lease was indeed returned.
+ checkLease4(lease, "192.0.2.1", 44, "08:08:08:08:08:08", false);
+}
+
+void Lease4CmdsTest::testLease4GetByClientIdNotFound() {
+ // Initialize lease manager (false = v4, false = don't add leases)
+ initLeaseMgr(false, false);
+
+ // No such lease.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-get\",\n"
+ " \"arguments\": {"
+ " \"identifier-type\": \"client-id\","
+ " \"identifier\": \"01:02:03:04\","
+ " \"subnet-id\": 44"
+ " }\n"
+ "}";
+ string exp_rsp = "Lease not found.";
+ testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
+}
+
+void Lease4CmdsTest::testLease4GetByClientId() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-get\",\n"
+ " \"arguments\": {"
+ " \"identifier-type\": \"client-id\","
+ " \"identifier\": \"42:42:42:42:42:42:42:42\","
+ " \"subnet-id\": 44"
+ " }\n"
+ "}";
+ string exp_rsp = "IPv4 lease found.";
+
+ // The status expected is success. The lease should be returned.
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ // Now check that the lease parameters were indeed returned.
+ ASSERT_TRUE(rsp);
+
+ ConstElementPtr lease = rsp->get("arguments");
+ ASSERT_TRUE(lease);
+
+ // Now check that the lease was indeed returned.
+ checkLease4(lease, "192.0.2.1", 44, "08:08:08:08:08:08", false);
+}
+
+void Lease4CmdsTest::testLease4GetAll() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ // Query for all leases.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-get-all\"\n"
+ "}";
+ string exp_rsp = "4 IPv4 lease(s) found.";
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ // Now check that the lease parameters were indeed returned.
+ ASSERT_TRUE(rsp);
+
+ ConstElementPtr args = rsp->get("arguments");
+ ASSERT_TRUE(args);
+ ASSERT_EQ(Element::map, args->getType());
+
+ ConstElementPtr leases = args->get("leases");
+ ASSERT_TRUE(leases);
+ ASSERT_EQ(Element::list, leases->getType());
+
+ // Let's check if the response contains desired leases.
+ checkLease4(leases, "192.0.2.1", 44, "08:08:08:08:08:08", true);
+ checkLease4(leases, "192.0.2.2", 44, "09:09:09:09:09:09", true, 5);
+ checkLease4(leases, "192.0.3.1", 88, "08:08:08:08:08:08", true);
+ checkLease4(leases, "192.0.3.2", 88, "09:09:09:09:09:09", true);
+}
+
+void Lease4CmdsTest::testLease4GetAllNoLeases() {
+ // Initialize lease manager (false = v4, false = don't add leases)
+ initLeaseMgr(false, false);
+
+ // Query for all leases.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-get-all\"\n"
+ "}";
+ string exp_rsp = "0 IPv4 lease(s) found.";
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
+
+ // Now check that the lease parameters were indeed returned.
+ ASSERT_TRUE(rsp);
+
+ ConstElementPtr args = rsp->get("arguments");
+ ASSERT_TRUE(args);
+ ASSERT_EQ(Element::map, args->getType());
+
+ ConstElementPtr leases = args->get("leases");
+ ASSERT_TRUE(leases);
+ ASSERT_EQ(Element::list, leases->getType());
+
+ EXPECT_EQ(0, leases->size());
+}
+
+void Lease4CmdsTest::testLease4GetAllBySubnetId() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ // Query for leases from subnet 44. Subnet 127 will be ignored because
+ // it doesn't contain any leases.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-get-all\",\n"
+ " \"arguments\": {\n"
+ " \"subnets\": [ 44, 127 ]"
+ " }\n"
+ "}";
+ string exp_rsp = "2 IPv4 lease(s) found.";
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ // Now check that the lease parameters were indeed returned.
+ ASSERT_TRUE(rsp);
+
+ ConstElementPtr args = rsp->get("arguments");
+ ASSERT_TRUE(args);
+ ASSERT_EQ(Element::map, args->getType());
+
+ ConstElementPtr leases = args->get("leases");
+ ASSERT_TRUE(leases);
+ ASSERT_EQ(Element::list, leases->getType());
+
+ // Let's check if the response contains desired leases.
+ checkLease4(leases, "192.0.2.1", 44, "08:08:08:08:08:08", true);
+ checkLease4(leases, "192.0.2.2", 44, "09:09:09:09:09:09", true, 5);
+}
+
+void Lease4CmdsTest::testLease4GetAllBySubnetIdNoLeases() {
+ // Initialize lease manager (false = v4, false = don't add leases)
+ initLeaseMgr(false, false);
+
+ // Query for leases from subnet 44. Subnet 127 will be ignored because
+ // it doesn't contain any leases.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-get-all\",\n"
+ " \"arguments\": {\n"
+ " \"subnets\": [ 44, 127 ]"
+ " }\n"
+ "}";
+ string exp_rsp = "0 IPv4 lease(s) found.";
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
+
+ // Now check that the lease parameters were indeed returned.
+ ASSERT_TRUE(rsp);
+
+ ConstElementPtr args = rsp->get("arguments");
+ ASSERT_TRUE(args);
+ ASSERT_EQ(Element::map, args->getType());
+
+ ConstElementPtr leases = args->get("leases");
+ ASSERT_TRUE(leases);
+ ASSERT_EQ(Element::list, leases->getType());
+
+ EXPECT_EQ(0, leases->size());
+}
+
+void Lease4CmdsTest::testLease4GetAllByMultipleSubnetIds() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ // Query for leases from subnet 44 and 88.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-get-all\",\n"
+ " \"arguments\": {\n"
+ " \"subnets\": [ 44, 88 ]"
+ " }\n"
+ "}";
+ string exp_rsp = "4 IPv4 lease(s) found.";
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ // Now check that the lease parameters were indeed returned.
+ ASSERT_TRUE(rsp);
+
+ ConstElementPtr args = rsp->get("arguments");
+ ASSERT_TRUE(args);
+ ASSERT_EQ(Element::map, args->getType());
+
+ ConstElementPtr leases = args->get("leases");
+ ASSERT_TRUE(leases);
+ ASSERT_EQ(Element::list, leases->getType());
+
+ // Let's check if the response contains desired leases.
+ checkLease4(leases, "192.0.2.1", 44, "08:08:08:08:08:08", true);
+ checkLease4(leases, "192.0.2.2", 44, "09:09:09:09:09:09", true, 5);
+ checkLease4(leases, "192.0.3.1", 88, "08:08:08:08:08:08", true);
+ checkLease4(leases, "192.0.3.2", 88, "09:09:09:09:09:09", true);
+}
+
+void Lease4CmdsTest::testLease4GetBySubnetIdInvalidArguments() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ // Subnets not specified in arguments.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-get-all\",\n"
+ " \"arguments\": {"
+ " \"foo\": 1\n"
+ " }\n"
+ "}";
+ string exp_rsp = "'subnets' parameter not specified";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Subnets are not a list.
+ cmd =
+ "{\n"
+ " \"command\": \"lease4-get-all\",\n"
+ " \"arguments\": {"
+ " \"subnets\": 1\n"
+ " }\n"
+ "}";
+ exp_rsp = "'subnets' parameter must be a list";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Subnets list must contain numbers.
+ cmd =
+ "{\n"
+ " \"command\": \"lease4-get-all\",\n"
+ " \"arguments\": {"
+ " \"subnets\": [ \"x\", \"y\" ]\n"
+ " }\n"
+ "}";
+ exp_rsp = "listed subnet identifiers must be numbers";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease4CmdsTest::testLease4GetPaged() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ // Gather all returned addresses to verify that all were returned.
+ std::set<std::string> lease_addresses;
+
+ // Keyword start indicates that we want to retrieve the first page.
+ std::string last_address = "start";
+
+ // There are 4 leases in the database, so the first two pages should
+ // include leases and the 3 page should be empty.
+ for (auto i = 0; i < 3; ++i) {
+ // Query for a page of leases.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-get-page\",\n"
+ " \"arguments\": {"
+ " \"from\": \"" + last_address + "\","
+ " \"limit\": 2"
+ " }"
+ "}";
+
+ // For the first two pages we should get success. For the last
+ // one an empty status code.
+ ConstElementPtr rsp;
+ if (i < 2) {
+ string exp_rsp = "2 IPv4 lease(s) found.";
+ rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ } else {
+ string exp_rsp = "0 IPv4 lease(s) found.";
+ rsp = testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
+
+ }
+
+ // Now check that the lease parameters were indeed returned.
+ ASSERT_TRUE(rsp);
+
+ // Arguments must exist.
+ ConstElementPtr args = rsp->get("arguments");
+ ASSERT_TRUE(args);
+ ASSERT_EQ(Element::map, args->getType());
+
+ // For convenience, we return the number of returned leases,
+ // so as the client can check whether there was anything returned
+ // before parsing the leases structure.
+ ConstElementPtr page_count = args->get("count");
+ ASSERT_TRUE(page_count);
+ ASSERT_EQ(Element::integer, page_count->getType());
+
+ // leases must exist, but may be empty.
+ ConstElementPtr leases = args->get("leases");
+ ASSERT_TRUE(leases);
+ ASSERT_EQ(Element::list, leases->getType());
+
+ if (!leases->empty()) {
+ EXPECT_EQ(2, page_count->intValue());
+
+ // Go over each lease and verify its correctness.
+ for (ConstElementPtr lease : leases->listValue()) {
+ ASSERT_EQ(Element::map, lease->getType());
+ ASSERT_TRUE(lease->contains("ip-address"));
+ ConstElementPtr ip_address = lease->get("ip-address");
+ ASSERT_EQ(Element::string, ip_address->getType());
+ last_address = ip_address->stringValue();
+
+ lease_addresses.insert(last_address);
+
+ // The easiest way to retrieve the subnet id and HW address is to
+ // ask the Lease Manager.
+ Lease4Ptr from_mgr = LeaseMgrFactory::instance().getLease4(IOAddress(last_address));
+ ASSERT_TRUE(from_mgr);
+ uint32_t pool_id = 0;
+ if (last_address == "192.0.2.2") {
+ pool_id = 5;
+ }
+ checkLease4(leases, last_address, from_mgr->subnet_id_,
+ from_mgr->hwaddr_->toText(false), true, pool_id);
+ }
+
+ } else {
+ // In the third iteration the page should be empty.
+ EXPECT_EQ(0, page_count->intValue());
+ }
+ }
+
+ // Check if all addresses were returned.
+ EXPECT_EQ(1, lease_addresses.count("192.0.2.1"));
+ EXPECT_EQ(1, lease_addresses.count("192.0.2.2"));
+ EXPECT_EQ(1, lease_addresses.count("192.0.3.1"));
+ EXPECT_EQ(1, lease_addresses.count("192.0.3.2"));
+}
+
+void Lease4CmdsTest::testLease4GetPagedZeroAddress() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ // Query for a page of leases.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-get-page\",\n"
+ " \"arguments\": {"
+ " \"from\": \"0.0.0.0\","
+ " \"limit\": 2"
+ " }"
+ "}";
+
+ string exp_rsp = "2 IPv4 lease(s) found.";
+ testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+}
+
+void Lease4CmdsTest::testLease4GetPagedIPv6Address() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ // Query for a page of leases.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-get-page\",\n"
+ " \"arguments\": {"
+ " \"from\": \"2001:db8::1\","
+ " \"limit\": 2"
+ " }"
+ "}";
+
+ string exp_rsp = "'from' parameter value 2001:db8::1 is not an IPv4 address";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease4CmdsTest::testLease4GetPagedInvalidFrom() {
+ // Initialize lease manager (false = v6, true = add leases)
+ initLeaseMgr(false, true);
+
+ // Query for a page of leases.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-get-page\",\n"
+ " \"arguments\": {"
+ " \"from\": \"foo\","
+ " \"limit\": 2"
+ " }"
+ "}";
+
+ string exp_rsp = "'from' parameter value is neither 'start' keyword "
+ "nor a valid IPv4 address";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease4CmdsTest::testLease4GetPagedNoLimit() {
+ // Initialize lease manager (false = v6, true = add leases)
+ initLeaseMgr(false, true);
+
+ // Query for a page of leases.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-get-page\",\n"
+ " \"arguments\": {"
+ " \"from\": \"start\""
+ " }"
+ "}";
+
+ string exp_rsp = "'limit' parameter not specified";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease4CmdsTest::testLease4GetPagedLimitNotNumber() {
+ // Initialize lease manager (false = v6, true = add leases)
+ initLeaseMgr(false, true);
+
+ // Query for a page of leases.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-get-page\",\n"
+ " \"arguments\": {"
+ " \"from\": \"start\","
+ " \"limit\": false"
+ " }"
+ "}";
+
+ string exp_rsp = "'limit' parameter must be a number";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease4CmdsTest::testLease4GetPagedLimitIsZero() {
+ // Initialize lease manager (false = v6, true = add leases)
+ initLeaseMgr(false, true);
+
+ // Query for a page of leases.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-get-page\",\n"
+ " \"arguments\": {"
+ " \"from\": \"start\","
+ " \"limit\": 0"
+ " }"
+ "}";
+
+ string exp_rsp = "page size of retrieved leases must not be 0";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease4CmdsTest::testLease4GetByHwAddressParams() {
+ // No parameters whatsoever.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-get-by-hw-address\",\n"
+ " \"arguments\": {"
+ " }\n"
+ "}";
+ string exp_rsp = "'hw-address' parameter not specified";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // hw-address must be a string.
+ cmd =
+ "{\n"
+ " \"command\": \"lease4-get-by-hw-address\",\n"
+ " \"arguments\": {"
+ " \"hw-address\": 1234\n"
+ " }\n"
+ "}";
+ exp_rsp = "'hw-address' parameter must be a string";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Simply bad value.
+ cmd =
+ "{\n"
+ " \"command\": \"lease4-get-by-hw-address\",\n"
+ " \"arguments\": {"
+ " \"hw-address\": \"00::01:00:bc:0d:67\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "two consecutive separators (':') specified in a decoded string";
+ exp_rsp += " '00::01:00:bc:0d:67'";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease4CmdsTest::testLease4GetByHwAddressFind0() {
+ // Initialize lease manager (false = v4, false = don't add leases)
+ initLeaseMgr(false, false);
+
+ // No such lease.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-get-by-hw-address\",\n"
+ " \"arguments\": {"
+ " \"hw-address\": \"01:02:03:04:05:06\"\n"
+ " }\n"
+ "}";
+ string exp_rsp = "0 IPv4 lease(s) found.";
+ testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
+}
+
+void Lease4CmdsTest::testLease4GetByHwAddressFind2() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ // Get the lease.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-get-by-hw-address\",\n"
+ " \"arguments\": {"
+ " \"hw-address\": \"08:08:08:08:08:08\"\n"
+ " }\n"
+ "}";
+ string exp_rsp = "2 IPv4 lease(s) found.";
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ // Now check that the lease parameters were indeed returned.
+ ASSERT_TRUE(rsp);
+ ConstElementPtr map = rsp->get("arguments");
+ ASSERT_TRUE(map);
+ ASSERT_EQ(Element::map, map->getType());
+ ConstElementPtr leases = map->get("leases");
+ ASSERT_TRUE(leases);
+ ASSERT_EQ(Element::list, leases->getType());
+ ASSERT_EQ(2, leases->size());
+
+ // Let's check if the response makes any sense.
+ ConstElementPtr lease = leases->get(0);
+ ASSERT_TRUE(lease);
+ checkLease4(lease, "192.0.2.1", 44, "08:08:08:08:08:08", false);
+ lease = leases->get(1);
+ ASSERT_TRUE(lease);
+ checkLease4(lease, "192.0.3.1", 88, "08:08:08:08:08:08", false);
+}
+
+void Lease4CmdsTest::testLease4GetByClientIdParams() {
+ // No parameters whatsoever.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-get-by-client-id\",\n"
+ " \"arguments\": {"
+ " }\n"
+ "}";
+ string exp_rsp = "'client-id' parameter not specified";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // client-id must be a string.
+ cmd =
+ "{\n"
+ " \"command\": \"lease4-get-by-client-id\",\n"
+ " \"arguments\": {"
+ " \"client-id\": 1234\n"
+ " }\n"
+ "}";
+ exp_rsp = "'client-id' parameter must be a string";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Simply bad value.
+ cmd =
+ "{\n"
+ " \"command\": \"lease4-get-by-client-id\",\n"
+ " \"arguments\": {"
+ " \"client-id\": \"00::01:00:bc:0d:67\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "two consecutive separators (':') specified in a decoded string";
+ exp_rsp += " '00::01:00:bc:0d:67'";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease4CmdsTest::testLease4GetByClientIdFind0() {
+ // Initialize lease manager (false = v4, false = don't add leases)
+ initLeaseMgr(false, false);
+
+ // No such lease.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-get-by-client-id\",\n"
+ " \"arguments\": {"
+ " \"client-id\": \"01:02:03:04\"\n"
+ " }\n"
+ "}";
+ string exp_rsp = "0 IPv4 lease(s) found.";
+ testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
+}
+
+void Lease4CmdsTest::testLease4GetByClientIdFind2() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ // Get the lease.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-get-by-client-id\",\n"
+ " \"arguments\": {"
+ " \"client-id\": \"42:42:42:42:42:42:42:42\"\n"
+ " }\n"
+ "}";
+ string exp_rsp = "2 IPv4 lease(s) found.";
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ // Now check that the lease parameters were indeed returned.
+ ASSERT_TRUE(rsp);
+ ConstElementPtr map = rsp->get("arguments");
+ ASSERT_TRUE(map);
+ ASSERT_EQ(Element::map, map->getType());
+ ConstElementPtr leases = map->get("leases");
+ ASSERT_TRUE(leases);
+ ASSERT_EQ(Element::list, leases->getType());
+ ASSERT_EQ(2, leases->size());
+
+ // Let's check if the response makes any sense.
+ ConstElementPtr lease = leases->get(0);
+ ASSERT_TRUE(lease);
+ checkLease4(lease, "192.0.2.1", 44, "08:08:08:08:08:08", false);
+ lease = leases->get(1);
+ ASSERT_TRUE(lease);
+ checkLease4(lease, "192.0.3.1", 88, "08:08:08:08:08:08", false);
+}
+
+void Lease4CmdsTest::testLease4GetByHostnameParams() {
+ // No parameters whatsoever.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-get-by-hostname\",\n"
+ " \"arguments\": {"
+ " }\n"
+ "}";
+ string exp_rsp = "'hostname' parameter not specified";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // hostname must be a string.
+ cmd =
+ "{\n"
+ " \"command\": \"lease4-get-by-hostname\",\n"
+ " \"arguments\": {"
+ " \"hostname\": 1234\n"
+ " }\n"
+ "}";
+ exp_rsp = "'hostname' parameter must be a string";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // hostname must be not empty.
+ cmd =
+ "{\n"
+ " \"command\": \"lease4-get-by-hostname\",\n"
+ " \"arguments\": {"
+ " \"hostname\": \"\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "'hostname' parameter is empty";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease4CmdsTest::testLease4GetByHostnameFind0() {
+ // Initialize lease manager (false = v4, false = don't add leases)
+ initLeaseMgr(false, false);
+
+ // No such lease.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-get-by-hostname\",\n"
+ " \"arguments\": {"
+ " \"hostname\": \"foo.bar\"\n"
+ " }\n"
+ "}";
+ string exp_rsp = "0 IPv4 lease(s) found.";
+ testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
+}
+
+void Lease4CmdsTest::testLease4GetByHostnameFind2() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ // Get the lease.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-get-by-hostname\",\n"
+ " \"arguments\": {"
+ " \"hostname\": \"Myhost.Example.Com.\"\n"
+ " }\n"
+ "}";
+ string exp_rsp = "4 IPv4 lease(s) found.";
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ // Now check that the lease parameters were indeed returned.
+ ASSERT_TRUE(rsp);
+ ConstElementPtr map = rsp->get("arguments");
+ ASSERT_TRUE(map);
+ ASSERT_EQ(Element::map, map->getType());
+ ConstElementPtr leases = map->get("leases");
+ ASSERT_TRUE(leases);
+ ASSERT_EQ(Element::list, leases->getType());
+ ASSERT_EQ(4, leases->size());
+
+ // Let's check if the response makes any sense.
+ ConstElementPtr lease = leases->get(0);
+ ASSERT_TRUE(lease);
+ checkLease4(lease, "192.0.2.1", 44, "08:08:08:08:08:08", false);
+ lease = leases->get(2);
+ ASSERT_TRUE(lease);
+ checkLease4(lease, "192.0.3.1", 88, "08:08:08:08:08:08", false);
+}
+
+void Lease4CmdsTest::testLease4UpdateMissingParams() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ // Everything missing. What sort of nonsense is that?
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-update\",\n"
+ " \"arguments\": {"
+ " }\n"
+ "}";
+ string exp_rsp = "missing parameter 'ip-address' (<string>:3:19)";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Just ip is not enough (subnet-id and hwaddr missing, although
+ // Kea should be able to figure out the subnet-id on its own).
+ txt =
+ "{\n"
+ " \"command\": \"lease4-update\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"192.0.2.123\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "missing parameter 'hw-address' (<string>:3:19)";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Better, but still no luck. (hwaddr missing).
+ txt =
+ "{\n"
+ " \"command\": \"lease4-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44,\n"
+ " \"ip-address\": \"192.0.2.202\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "missing parameter 'hw-address' (<string>:3:19)";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Close, but no cigars. (ip-address missing).
+ txt =
+ "{\n"
+ " \"command\": \"lease4-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44,\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "missing parameter 'ip-address' (<string>:3:19)";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease4CmdsTest::testLease4UpdateBadParams() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ // All params are there, but there's no subnet-id 123 configured.
+ // (initLeaseMgr initialized subnet-id 44 for v4 and subnet-id 66 for v6).
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 123,\n"
+ " \"ip-address\": \"192.0.2.202\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\"\n"
+ " }\n"
+ "}";
+ string exp_rsp = "Invalid subnet-id: No IPv4 subnet with subnet-id=123 currently configured.";
+ testCommand(txt, CONTROL_RESULT_CONFLICT, exp_rsp);
+
+ // This time the new IP address does not belong to the subnet.
+ txt =
+ "{\n"
+ " \"command\": \"lease4-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44,\n"
+ " \"ip-address\": \"10.0.0.1\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "The address 10.0.0.1 does not belong to subnet 192.0.2.0/24, subnet-id=44";
+ testCommand(txt, CONTROL_RESULT_CONFLICT, exp_rsp);
+
+ // We don't use any of that bleeding edge nonsense in this museum. v4 only.
+ txt =
+ "{\n"
+ " \"command\": \"lease4-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44,\n"
+ " \"ip-address\": \"2001:db8:1::1\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "Non-IPv4 address specified: 2001:db8:1::1";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Bad user context: not a map.
+ txt =
+ "{\n"
+ " \"command\": \"lease4-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44,\n"
+ " \"ip-address\": \"192.0.2.1\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"user-context\": \"bad value\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "Invalid user context '\"bad value\"' is not a JSON map.";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Duplicated comment.
+ txt =
+ "{\n"
+ " \"command\": \"lease4-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44,\n"
+ " \"ip-address\": \"192.0.2.1\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"user-context\": { \"comment\": \"in user context\" },\n"
+ " \"comment\": \"direct\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "Duplicated comment entry '\"direct\"' in user context "
+ "'{ \"comment\": \"in user context\" }'";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease4CmdsTest::testLease4UpdateNoLease() {
+ // Initialize lease manager (false = v4, false = don't add leases)
+ initLeaseMgr(false, false);
+
+ checkLease4Stats(44, 0, 0);
+
+ checkLease4Stats(88, 0, 0);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44,\n"
+ " \"ip-address\": \"192.0.2.1\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"hostname\": \"newhostname.example.org\""
+ " }\n"
+ "}";
+ string exp_rsp = "failed to update the lease with address 192.0.2.1 "
+ "either because the lease has been deleted or it has changed in the "
+ "database, in both cases a retry might succeed";
+ testCommand(txt, CONTROL_RESULT_CONFLICT, exp_rsp);
+
+ checkLease4Stats(44, 0, 0);
+
+ checkLease4Stats(88, 0, 0);
+}
+
+void Lease4CmdsTest::testLease4Update() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ checkLease4Stats(44, 2, 0);
+
+ checkLease4Stats(88, 2, 0);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44,\n"
+ " \"ip-address\": \"192.0.2.1\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"pool-id\": 3,\n"
+ " \"hostname\": \"newhostname.example.org\""
+ " }\n"
+ "}";
+ string exp_rsp = "IPv4 lease updated.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease4Stats(44, 2, 0);
+
+ checkLease4Stats(88, 2, 0);
+
+ // Now check that the lease is really there.
+ Lease4Ptr l = lmptr_->getLease4(IOAddress("192.0.2.1"));
+ ASSERT_TRUE(l);
+
+ // Make sure the lease has been updated.
+ ASSERT_TRUE(l->hwaddr_);
+ EXPECT_EQ("1a:1b:1c:1d:1e:1f", l->hwaddr_->toText(false));
+ EXPECT_EQ(3, l->pool_id_);
+ EXPECT_EQ("newhostname.example.org", l->hostname_);
+ EXPECT_FALSE(l->getContext());
+}
+
+void Lease4CmdsTest::testLease4UpdateDeclinedLeases() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true, true);
+
+ checkLease4Stats(44, 2, 2);
+
+ checkLease4Stats(88, 2, 2);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44,\n"
+ " \"ip-address\": \"192.0.2.1\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"pool-id\": 3,\n"
+ " \"hostname\": \"newhostname.example.org\""
+ " }\n"
+ "}";
+ string exp_rsp = "IPv4 lease updated.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease4Stats(44, 2, 1);
+
+ checkLease4Stats(88, 2, 2);
+
+ // Now check that the lease is still there.
+ Lease4Ptr l = lmptr_->getLease4(IOAddress("192.0.2.1"));
+ ASSERT_TRUE(l);
+
+ // Make sure the lease has been updated.
+ ASSERT_TRUE(l->hwaddr_);
+ EXPECT_EQ("1a:1b:1c:1d:1e:1f", l->hwaddr_->toText(false));
+ EXPECT_EQ(3, l->pool_id_);
+ EXPECT_EQ("newhostname.example.org", l->hostname_);
+ EXPECT_FALSE(l->getContext());
+}
+
+void Lease4CmdsTest::testLease4UpdateNoSubnetId() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ checkLease4Stats(44, 2, 0);
+
+ checkLease4Stats(88, 2, 0);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-update\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"192.0.2.1\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"hostname\": \"newhostname.example.org\""
+ " }\n"
+ "}";
+ string exp_rsp = "IPv4 lease updated.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease4Stats(44, 2, 0);
+
+ checkLease4Stats(88, 2, 0);
+
+ // Now check that the lease is still there.
+ Lease4Ptr l = lmptr_->getLease4(IOAddress("192.0.2.1"));
+ ASSERT_TRUE(l);
+
+ // Make sure the subnet-id is correct.
+ EXPECT_EQ(44, l->subnet_id_);
+
+ // Make sure the lease has been updated.
+ ASSERT_TRUE(l->hwaddr_);
+ EXPECT_EQ("1a:1b:1c:1d:1e:1f", l->hwaddr_->toText(false));
+ EXPECT_EQ("newhostname.example.org", l->hostname_);
+ EXPECT_FALSE(l->getContext());
+}
+
+void Lease4CmdsTest::testLease4UpdateNoSubnetIdDeclinedLeases() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true, true);
+
+ checkLease4Stats(44, 2, 2);
+
+ checkLease4Stats(88, 2, 2);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-update\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"192.0.2.1\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"hostname\": \"newhostname.example.org\""
+ " }\n"
+ "}";
+ string exp_rsp = "IPv4 lease updated.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease4Stats(44, 2, 1);
+
+ checkLease4Stats(88, 2, 2);
+
+ // Now check that the lease is really there.
+ Lease4Ptr l = lmptr_->getLease4(IOAddress("192.0.2.1"));
+ ASSERT_TRUE(l);
+
+ // Make sure the subnet-id is correct.
+ EXPECT_EQ(44, l->subnet_id_);
+
+ // Make sure the lease has been updated.
+ ASSERT_TRUE(l->hwaddr_);
+ EXPECT_EQ("1a:1b:1c:1d:1e:1f", l->hwaddr_->toText(false));
+ EXPECT_EQ("newhostname.example.org", l->hostname_);
+ EXPECT_FALSE(l->getContext());
+}
+
+void Lease4CmdsTest::testLease4UpdateForceCreate() {
+ // Initialize lease manager (false = v4, false = don't add leases)
+ initLeaseMgr(false, false);
+
+ checkLease4Stats(44, 0, 0);
+
+ checkLease4Stats(88, 0, 0);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44,\n"
+ " \"ip-address\": \"192.0.2.1\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"hostname\": \"newhostname.example.org\","
+ " \"force-create\": true"
+ " }\n"
+ "}";
+ string exp_rsp = "IPv4 lease added.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease4Stats(44, 1, 0);
+
+ checkLease4Stats(88, 0, 0);
+
+ // Now check that the lease is really there.
+ Lease4Ptr l = lmptr_->getLease4(IOAddress("192.0.2.1"));
+ ASSERT_TRUE(l);
+
+ // Make sure the lease is correct.
+ ASSERT_TRUE(l->hwaddr_);
+ EXPECT_EQ("1a:1b:1c:1d:1e:1f", l->hwaddr_->toText(false));
+ EXPECT_EQ("newhostname.example.org", l->hostname_);
+ EXPECT_FALSE(l->getContext());
+}
+
+void Lease4CmdsTest::testLease4UpdateForceCreateNoSubnetId() {
+ // Initialize lease manager (false = v4, false = don't add leases)
+ initLeaseMgr(false, false);
+
+ checkLease4Stats(44, 0, 0);
+
+ checkLease4Stats(88, 0, 0);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-update\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"192.0.2.1\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"hostname\": \"newhostname.example.org\","
+ " \"force-create\": true"
+ " }\n"
+ "}";
+ string exp_rsp = "IPv4 lease added.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease4Stats(44, 1, 0);
+
+ checkLease4Stats(88, 0, 0);
+
+ // Now check that the lease is really there.
+ Lease4Ptr l = lmptr_->getLease4(IOAddress("192.0.2.1"));
+ ASSERT_TRUE(l);
+
+ // Make sure the subnet-id is figured out correctly.
+ EXPECT_EQ(44, l->subnet_id_);
+
+ // Make sure the lease is correct.
+ ASSERT_TRUE(l->hwaddr_);
+ EXPECT_EQ("1a:1b:1c:1d:1e:1f", l->hwaddr_->toText(false));
+ EXPECT_EQ("newhostname.example.org", l->hostname_);
+ EXPECT_FALSE(l->getContext());
+}
+
+void Lease4CmdsTest::testLease4UpdateDoNotForceCreate() {
+ // Initialize lease manager (false = v4, false = don't add leases)
+ initLeaseMgr(false, false);
+
+ checkLease4Stats(44, 0, 0);
+
+ checkLease4Stats(88, 0, 0);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44,\n"
+ " \"ip-address\": \"192.0.2.1\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"hostname\": \"newhostname.example.org\","
+ " \"force-create\": false"
+ " }\n"
+ "}";
+ string exp_rsp = "failed to update the lease with address 192.0.2.1 "
+ "either because the lease has been deleted or it has changed in the "
+ "database, in both cases a retry might succeed";
+ testCommand(txt, CONTROL_RESULT_CONFLICT, exp_rsp);
+
+ checkLease4Stats(44, 0, 0);
+
+ checkLease4Stats(88, 0, 0);
+}
+
+void Lease4CmdsTest::testLease4UpdateComment() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ checkLease4Stats(44, 2, 0);
+
+ checkLease4Stats(88, 2, 0);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44,\n"
+ " \"ip-address\": \"192.0.2.1\",\n"
+ " \"hw-address\": \"42:42:42:42:42:42:42:42\",\n"
+ " \"comment\": \"a comment\",\n"
+ " \"user-context\": { \"foobar\": true }\n"
+ " }\n"
+ "}";
+ string exp_rsp = "IPv4 lease updated.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease4Stats(44, 2, 0);
+
+ checkLease4Stats(88, 2, 0);
+
+ // Now check that the lease is really there.
+ Lease4Ptr l = lmptr_->getLease4(IOAddress("192.0.2.1"));
+ ASSERT_TRUE(l);
+
+ // Make sure the lease has been updated.
+ ASSERT_TRUE(l->hwaddr_);
+ EXPECT_EQ("42:42:42:42:42:42:42:42", l->hwaddr_->toText(false));
+
+ // Check user context.
+ ConstElementPtr ctx = l->getContext();
+ ASSERT_TRUE(ctx);
+ EXPECT_EQ(2, ctx->size());
+ ASSERT_TRUE(ctx->contains("comment"));
+ EXPECT_EQ("\"a comment\"", ctx->get("comment")->str());
+ ASSERT_TRUE(ctx->contains("foobar"));
+ EXPECT_EQ("true", ctx->get("foobar")->str());
+}
+
+void Lease4CmdsTest::testLease4UpdateExtendedInfo() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ checkLease4Stats(44, 2, 0);
+
+ checkLease4Stats(88, 2, 0);
+
+ Lease4Collection leases;
+ const vector<uint8_t> relay_id = { 0xaa, 0xbb, 0xcc };
+ leases = lmptr_->getLeases4ByRelayId(relay_id,
+ IOAddress::IPV4_ZERO_ADDRESS(),
+ LeasePageSize(10));
+ EXPECT_TRUE(leases.empty());
+ const vector<uint8_t> remote_id = { 1, 2, 3 };
+ leases = lmptr_->getLeases4ByRemoteId(remote_id,
+ IOAddress::IPV4_ZERO_ADDRESS(),
+ LeasePageSize(10));
+ EXPECT_TRUE(leases.empty());
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44,\n"
+ " \"ip-address\": \"192.0.2.1\",\n"
+ " \"hw-address\": \"42:42:42:42:42:42:42:42\",\n"
+ " \"user-context\": { \"ISC\": { \"relay-agent-info\": {\n"
+ " \"sub-options\": \"0x02030102030C03AABBCC\",\n"
+ " \"remote-id\": \"010203\",\n"
+ " \"relay-id\": \"AABBCC\"\n"
+ " } } }\n"
+ " }\n"
+ "}";
+ string exp_rsp = "IPv4 lease updated.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease4Stats(44, 2, 0);
+
+ checkLease4Stats(88, 2, 0);
+
+ // Now check that the lease is really there.
+ Lease4Ptr l = lmptr_->getLease4(IOAddress("192.0.2.1"));
+ ASSERT_TRUE(l);
+
+ // Make sure the lease has been updated.
+ ASSERT_TRUE(l->hwaddr_);
+ EXPECT_EQ("42:42:42:42:42:42:42:42", l->hwaddr_->toText(false));
+
+ // Check the user context / extended info too.
+ ConstElementPtr ctx = l->getContext();
+ ASSERT_TRUE(ctx);
+ string expected = "{ \"ISC\": { \"relay-agent-info\": ";
+ expected += "{ \"relay-id\": \"AABBCC\", ";
+ expected += "\"remote-id\": \"010203\", ";
+ expected += "\"sub-options\": \"0x02030102030C03AABBCC\" } } }";
+ EXPECT_EQ(expected, ctx->str());
+ EXPECT_EQ(relay_id, l->relay_id_);
+ EXPECT_EQ(remote_id, l->remote_id_);
+
+ // Check the lease can be retrieved by its relay or remote id too.
+ leases = lmptr_->getLeases4ByRelayId(relay_id,
+ IOAddress::IPV4_ZERO_ADDRESS(),
+ LeasePageSize(10));
+ ASSERT_EQ(1, leases.size());
+ EXPECT_EQ(*l, *leases[0]);
+ leases = lmptr_->getLeases4ByRemoteId(remote_id,
+ IOAddress::IPV4_ZERO_ADDRESS(),
+ LeasePageSize(10));
+ ASSERT_EQ(1, leases.size());
+ EXPECT_EQ(*l, *leases[0]);
+}
+
+void Lease4CmdsTest::testLease4DelMissingParams() {
+ // No parameters whatsoever. You want just a lease, any lease?
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-del\",\n"
+ " \"arguments\": {"
+ " }\n"
+ "}";
+ string exp_rsp = "Mandatory 'subnet-id' parameter missing.";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Just the subnet-id won't cut it, either.
+ cmd =
+ "{\n"
+ " \"command\": \"lease4-del\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 123"
+ " }\n"
+ "}";
+ exp_rsp = "No 'ip-address' provided and 'identifier-type' is either missing or not a string.";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // We can't identify your laptop by color. Sorry, buddy.
+ cmd =
+ "{\n"
+ " \"command\": \"lease4-del\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 123,\n"
+ " \"identifier-type\": \"color\",\n"
+ " \"identifier\": \"blue\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "Incorrect identifier type: color, the only supported values are: "
+ "address, hw-address, duid";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Query by DUID is not supported in v4. Sorry.
+ cmd =
+ "{\n"
+ " \"command\": \"lease4-del\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 123,\n"
+ " \"identifier-type\": \"duid\",\n"
+ " \"identifier\": \"01:01:01:01:01:01\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "Delete by duid is not allowed in v4.";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Identifier value is missing.
+ cmd =
+ "{\n"
+ " \"command\": \"lease4-del\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 123,\n"
+ " \"identifier-type\": \"hw-address\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "No 'ip-address' provided and 'identifier' is either missing or not a string.";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Identifier-type is missing.
+ cmd =
+ "{\n"
+ " \"command\": \"lease4-del\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 123,\n"
+ " \"identifier\": \"01:02:03:04:05\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "No 'ip-address' provided and 'identifier-type' is either missing or not a string.";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease4CmdsTest::testLease4DelByAddrNotFound() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ checkLease4Stats(44, 2, 0);
+
+ checkLease4Stats(88, 2, 0);
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-del\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"192.0.2.5\","
+ " \"subnet-id\": 44"
+ " }\n"
+ "}";
+ string exp_rsp = "IPv4 lease not found.";
+
+ // Note the status expected is empty. The query completed correctly,
+ // just didn't found the lease.
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
+
+ checkLease4Stats(44, 2, 0);
+
+ checkLease4Stats(88, 2, 0);
+}
+
+void Lease4CmdsTest::testLease4DelByAddr() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ checkLease4Stats(44, 2, 0);
+
+ checkLease4Stats(88, 2, 0);
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-del\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"192.0.2.1\""
+ " }\n"
+ "}";
+ string exp_rsp = "IPv4 lease deleted.";
+
+ // The status expected is success. The lease should be deleted.
+ testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease4Stats(44, 1, 0);
+
+ checkLease4Stats(88, 2, 0);
+
+ // Make sure the lease is really gone.
+ EXPECT_FALSE(lmptr_->getLease4(IOAddress("192.0.2.1")));
+}
+
+void Lease4CmdsTest::testLease4DelByAddrDeclinedLeases() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true, true);
+
+ checkLease4Stats(44, 2, 2);
+
+ checkLease4Stats(88, 2, 2);
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-del\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"192.0.2.1\""
+ " }\n"
+ "}";
+ string exp_rsp = "IPv4 lease deleted.";
+
+ // The status expected is success. The lease should be deleted.
+ testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease4Stats(44, 1, 1);
+
+ checkLease4Stats(88, 2, 2);
+
+ // Make sure the lease is really gone.
+ EXPECT_FALSE(lmptr_->getLease4(IOAddress("192.0.2.1")));
+}
+
+void Lease4CmdsTest::testLease4DelByAddrBadParam() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ checkLease4Stats(44, 2, 0);
+
+ checkLease4Stats(88, 2, 0);
+
+ // Invalid family
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-del\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"2001:db8:1::1\""
+ " }\n"
+ "}";
+ string exp_rsp = "Invalid IPv4 address specified: 2001:db8:1::1";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ checkLease4Stats(44, 2, 0);
+
+ checkLease4Stats(88, 2, 0);
+
+ // This is way off
+ cmd =
+ "{\n"
+ " \"command\": \"lease6-del\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"221B Baker St.\""
+ " }\n"
+ "}";
+ exp_rsp = "Failed to convert string to address '221B Baker St.': Invalid argument";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease4CmdsTest::testLease4DelByHWAddrNotFound() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ checkLease4Stats(44, 2, 0);
+
+ checkLease4Stats(88, 2, 0);
+
+ // No such lease.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-del\",\n"
+ " \"arguments\": {"
+ " \"identifier-type\": \"hw-address\","
+ " \"identifier\": \"01:02:03:04:05:06\","
+ " \"subnet-id\": 44"
+ " }\n"
+ "}";
+ string exp_rsp = "IPv4 lease not found.";
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
+
+ checkLease4Stats(44, 2, 0);
+
+ checkLease4Stats(88, 2, 0);
+
+ // Make sure the lease is still there.
+ EXPECT_TRUE(lmptr_->getLease4(IOAddress("192.0.2.1")));
+}
+
+void Lease4CmdsTest::testLease4DelByHWAddr() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ checkLease4Stats(44, 2, 0);
+
+ checkLease4Stats(88, 2, 0);
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-del\",\n"
+ " \"arguments\": {"
+ " \"identifier-type\": \"hw-address\","
+ " \"identifier\": \"08:08:08:08:08:08\","
+ " \"subnet-id\": 44"
+ " }\n"
+ "}";
+ string exp_rsp = "IPv4 lease deleted.";
+
+ // The status expected is success. The lease should be deleted.
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease4Stats(44, 1, 0);
+
+ checkLease4Stats(88, 2, 0);
+
+ // Make sure the lease is really gone.
+ EXPECT_FALSE(lmptr_->getLease4(IOAddress("192.0.2.1")));
+}
+
+void Lease4CmdsTest::testLease4DelByClientIdNotFound() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ checkLease4Stats(44, 2, 0);
+
+ checkLease4Stats(88, 2, 0);
+
+ // No such lease.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-del\",\n"
+ " \"arguments\": {"
+ " \"identifier-type\": \"client-id\","
+ " \"identifier\": \"01:02:03:04\","
+ " \"subnet-id\": 44"
+ " }\n"
+ "}";
+ string exp_rsp = "IPv4 lease not found.";
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
+
+ checkLease4Stats(44, 2, 0);
+
+ checkLease4Stats(88, 2, 0);
+
+ // Make sure the lease is still there.
+ EXPECT_TRUE(lmptr_->getLease4(IOAddress("192.0.2.1")));
+}
+
+void Lease4CmdsTest::testLease4DelByClientId() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ checkLease4Stats(44, 2, 0);
+
+ checkLease4Stats(88, 2, 0);
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-del\",\n"
+ " \"arguments\": {"
+ " \"identifier-type\": \"client-id\","
+ " \"identifier\": \"42:42:42:42:42:42:42:42\","
+ " \"subnet-id\": 44"
+ " }\n"
+ "}";
+ string exp_rsp = "IPv4 lease deleted.";
+
+ // The status expected is success. The lease should be deleted.
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease4Stats(44, 1, 0);
+
+ checkLease4Stats(88, 2, 0);
+
+ // Make sure the lease is really gone.
+ EXPECT_FALSE(lmptr_->getLease4(IOAddress("192.0.2.1")));
+}
+
+void Lease4CmdsTest::testLease4Wipe() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ checkLease4Stats(44, 2, 0);
+
+ checkLease4Stats(88, 2, 0);
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-wipe\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44"
+ " }\n"
+ "}";
+ string exp_rsp = "Deleted 2 IPv4 lease(s) from subnet(s) 44";
+
+ // The status expected is success. The lease should be deleted.
+ testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease4Stats(44, 0, 0);
+
+ checkLease4Stats(88, 2, 0);
+
+ // Make sure the leases in subnet 44 are really gone.
+ EXPECT_FALSE(lmptr_->getLease4(IOAddress("192.0.2.1")));
+ EXPECT_FALSE(lmptr_->getLease4(IOAddress("192.0.2.2")));
+
+ // Make sure the leases from subnet 88 are still there.
+ EXPECT_TRUE(lmptr_->getLease4(IOAddress("192.0.3.1")));
+ EXPECT_TRUE(lmptr_->getLease4(IOAddress("192.0.3.2")));
+}
+
+void Lease4CmdsTest::testLease4WipeAll() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ checkLease4Stats(44, 2, 0);
+
+ checkLease4Stats(88, 2, 0);
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-wipe\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 0"
+ " }\n"
+ "}";
+ string exp_rsp = "Deleted 4 IPv4 lease(s) from subnet(s) 44 88";
+
+ // The status expected is success. The lease should be deleted.
+ testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease4Stats(44, 0, 0);
+
+ checkLease4Stats(88, 0, 0);
+
+ // Make sure the leases in subnet 44 are really gone.
+ EXPECT_FALSE(lmptr_->getLease4(IOAddress("192.0.2.1")));
+ EXPECT_FALSE(lmptr_->getLease4(IOAddress("192.0.2.2")));
+
+ // Make sure the leases from subnet 88 are gone, too.
+ EXPECT_FALSE(lmptr_->getLease4(IOAddress("192.0.3.1")));
+ EXPECT_FALSE(lmptr_->getLease4(IOAddress("192.0.3.2")));
+}
+
+void Lease4CmdsTest::testLease4WipeAllNoArgs() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ checkLease4Stats(44, 2, 0);
+
+ checkLease4Stats(88, 2, 0);
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-wipe\"\n"
+ "}";
+ string exp_rsp = "Deleted 4 IPv4 lease(s) from subnet(s) 44 88";
+
+ // The status expected is success. The lease should be deleted.
+ testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease4Stats(44, 0, 0);
+
+ checkLease4Stats(88, 0, 0);
+
+ // Make sure the leases in subnet 44 are really gone.
+ EXPECT_FALSE(lmptr_->getLease4(IOAddress("192.0.2.1")));
+ EXPECT_FALSE(lmptr_->getLease4(IOAddress("192.0.2.2")));
+
+ // Make sure the leases from subnet 88 are gone, too.
+ EXPECT_FALSE(lmptr_->getLease4(IOAddress("192.0.3.1")));
+ EXPECT_FALSE(lmptr_->getLease4(IOAddress("192.0.3.2")));
+}
+
+void Lease4CmdsTest::testLease4WipeNoLeases() {
+ // Initialize lease manager (false = v4, false = don't add leases)
+ initLeaseMgr(false, false);
+
+ checkLease4Stats(44, 0, 0);
+
+ checkLease4Stats(88, 0, 0);
+
+ // Query for valid, existing lease.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-wipe\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44"
+ " }\n"
+ "}";
+ string exp_rsp = "Deleted 0 IPv4 lease(s) from subnet(s) 44";
+ testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
+
+ checkLease4Stats(44, 0, 0);
+
+ checkLease4Stats(88, 0, 0);
+}
+
+void Lease4CmdsTest::testLease4WipeNoLeasesAll() {
+ // Initialize lease manager (false = v4, false = don't add leases)
+ initLeaseMgr(false, false);
+
+ checkLease4Stats(44, 0, 0);
+
+ checkLease4Stats(88, 0, 0);
+
+ // Query for valid, existing lease.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-wipe\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 0"
+ " }\n"
+ "}";
+ string exp_rsp = "Deleted 0 IPv4 lease(s) from subnet(s) 44 88";
+ testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
+
+ checkLease4Stats(44, 0, 0);
+
+ checkLease4Stats(88, 0, 0);
+}
+
+void Lease4CmdsTest::testLease4BrokenUpdate() {
+ // Initialize lease manager (false = v4, false = don't add leases)
+ initLeaseMgr(false, false);
+
+ // Set the sanity checks level.
+ CfgMgr::instance().getCurrentCfg()->getConsistency()
+ ->setLeaseSanityCheck(CfgConsistency::LEASE_CHECK_FIX);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 444,\n"
+ " \"ip-address\": \"192.0.2.202\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"force-create\": true\n"
+ " }\n"
+ "}";
+ string exp_rsp = "Invalid subnet-id: No IPv4 subnet with "
+ "subnet-id=444 currently configured.";
+ testCommand(txt, CONTROL_RESULT_CONFLICT, exp_rsp);
+}
+
+void Lease4CmdsTest::testLease4ResendDdnsBadParam() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ // Missing address parameter.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-resend-ddns\",\n"
+ " \"arguments\": {\n"
+ " }\n"
+ "}\n";
+
+ string exp_rsp = "'ip-address' parameter is missing.";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Invalid address family.
+ cmd =
+ "{\n"
+ " \"command\": \"lease4-resend-ddns\",\n"
+ " \"arguments\": {\n"
+ " \"ip-address\": \"2001:db8:1::1\"\n"
+ " }\n"
+ "}\n";
+
+ exp_rsp = "Invalid IPv4 address specified: 2001:db8:1::1";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // ip-address is not an address at all.
+ cmd =
+ "{\n"
+ " \"command\": \"lease4-resend-ddns\",\n"
+ " \"arguments\": {\n"
+ " \"ip-address\": \"221B Baker St.\"\n"
+ " }\n"
+ "}\n";
+
+ exp_rsp = "'221B Baker St.' is not a valid IP address.";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease4CmdsTest::testLease4ResendDdnsDisabled() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ // Disable DDNS updating.
+ disableD2();
+
+ // Query for valid, existing lease.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-resend-ddns\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"192.0.2.5\""
+ " }\n"
+ "}";
+
+ string exp_rsp = "DDNS updating is not enabled";
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_CONFLICT, exp_rsp);
+ // With D2 disabled there is no queue, size should come back as -1.
+ EXPECT_EQ(ncrQueueSize(), -1);
+}
+
+void Lease4CmdsTest::testLease4ResendDdnsNoLease() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ // Invalid
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-resend-ddns\",\n"
+ " \"arguments\": {\n"
+ " \"ip-address\": \"192.0.2.5\"\n"
+ " }\n"
+ "}\n";
+ string exp_rsp = "No lease found for: 192.0.2.5";
+ testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
+}
+
+void Lease4CmdsTest::testLease4ResendNoHostname() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ // NCR sender queue should be empty.
+ ASSERT_EQ(ncrQueueSize(), 0);
+
+ // Fetch the lease so we can replace the hostname with "".
+ Lease4Ptr lease = lmptr_->getLease4(IOAddress("192.0.2.1"));
+ ASSERT_TRUE(lease);
+ lease->hostname_ = "";
+ lmptr_->updateLease4(lease);
+
+ // Query for valid, existing lease.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-resend-ddns\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"192.0.2.1\""
+ " }\n"
+ "}";
+
+ string exp_rsp = "Lease for: 192.0.2.1, has no hostname, nothing to update";
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_CONFLICT, exp_rsp);
+
+ // There should not any NCRs queued.
+ EXPECT_EQ(ncrQueueSize(), 0);
+}
+
+void Lease4CmdsTest::testLease4ResendNoDirectionsEnabled() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ // NCR sender queue should be empty.
+ ASSERT_EQ(ncrQueueSize(), 0);
+
+ // Fetch the lease so we can replace the hostname with "".
+ Lease4Ptr lease = lmptr_->getLease4(IOAddress("192.0.2.1"));
+ ASSERT_TRUE(lease);
+ lease->fqdn_fwd_ = false;
+ lease->fqdn_rev_ = false;
+ lmptr_->updateLease4(lease);
+
+ // Query for valid, existing lease.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-resend-ddns\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"192.0.2.1\""
+ " }\n"
+ "}";
+
+ string exp_rsp = "Neither forward nor reverse updates enabled for lease for: 192.0.2.1";
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_CONFLICT, exp_rsp);
+
+ // There should not any NCRs queued.
+ EXPECT_EQ(ncrQueueSize(), 0);
+}
+
+void Lease4CmdsTest::testLease4ResendDdnsEnabled() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ // Structure detailing a test scenario.
+ struct Scenario {
+ std::string description_;
+ bool fqdn_fwd_;
+ bool fqdn_rev_;
+ };
+
+ // Three test scenarios to verify each combination of true flags.
+ std::vector<Scenario> scenarios = {
+ { "fwd_only", true, false },
+ { "rev_only", false, true},
+ { "both", true, true},
+ };
+
+ // Query for valid, existing lease.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-resend-ddns\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"192.0.2.1\""
+ " }\n"
+ "}";
+
+ // Expected response string.
+ string exp_rsp = "NCR generated for: 192.0.2.1, hostname: myhost.example.com.";
+
+ for (auto scenario : scenarios) {
+ SCOPED_TRACE(scenario.description_);
+
+ // Fetch the lease so we can update the DDNS direction flags.
+ Lease4Ptr lease = lmptr_->getLease4(IOAddress("192.0.2.1"));
+ ASSERT_TRUE(lease);
+ lease->fqdn_rev_ = scenario.fqdn_rev_;
+ lease->fqdn_fwd_ = scenario.fqdn_fwd_;
+ lmptr_->updateLease4(lease);
+
+ // Queue should be empty.
+ ASSERT_EQ(ncrQueueSize(), 0);
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ // We should have one entry in the queue.
+ ASSERT_EQ(ncrQueueSize(), 1);
+ verifyNameChangeRequest(CHG_ADD, scenario.fqdn_rev_, scenario.fqdn_fwd_,
+ "192.0.2.1", "myhost.example.com.");
+ }
+}
+
+void Lease4CmdsTest::testLease4DnsRemoveD2Enabled() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ // Structure detailing a test scenario.
+ struct Scenario {
+ std::string description_;
+ std::string hostname_;
+ bool fqdn_fwd_;
+ bool fqdn_rev_;
+ std::string update_ddns_;
+ bool exp_ncr_;
+ };
+
+ bool fwd = true;
+ bool rev = true;
+ bool ncr = true;
+
+ // Three test scenarios to verify each combination of true flags.
+ std::vector<Scenario> scenarios = {
+ {
+ "no_host",
+ "",
+ fwd, rev,
+ "\"update-ddns\": true",
+ !ncr
+ },
+ {
+ "no directions",
+ "myhost.example.com.",
+ !fwd, !rev,
+ "\"update-ddns\": true",
+ !ncr
+ },
+ {
+ "fwd_only",
+ "myhost.example.com.",
+ fwd, !rev,
+ "\"update-ddns\": true",
+ ncr
+ },
+ {
+ "rev_only",
+ "myhost.example.com.",
+ !fwd, rev,
+ "\"update-ddns\": true",
+ ncr
+ },
+ {
+ "both directions",
+ "myhost.example.com.",
+ fwd, rev,
+ "\"update-ddns\": true",
+ ncr
+ },
+ {
+ "default update-ddns",
+ "myhost.example.com.",
+ fwd, rev,
+ "",
+ !ncr
+ },
+ {
+ "update-ddns = false",
+ "myhost.example.com.",
+ fwd, rev,
+ "\"update-ddns\": false",
+ !ncr
+ },
+ };
+
+ for (auto scenario : scenarios) {
+ SCOPED_TRACE(scenario.description_);
+
+ // Let's create a lease with scenario attributes.
+ Lease4Ptr lease = createLease4("192.0.2.8", 44, 0x08, 0x42);
+ lease->hostname_ = scenario.hostname_;
+ lease->fqdn_rev_ = scenario.fqdn_rev_;
+ lease->fqdn_fwd_ = scenario.fqdn_fwd_;
+ ASSERT_TRUE(lmptr_->addLease(lease));
+
+ // NCR Queue should be empty.
+ ASSERT_EQ(ncrQueueSize(), 0);
+
+ // Build the command
+ std::stringstream cmd;
+ cmd <<
+ "{"
+ " \"command\": \"lease4-del\","
+ " \"arguments\": {"
+ " \"ip-address\": \"192.0.2.8\"";
+
+ if (!scenario.update_ddns_.empty()) {
+ cmd << "," << scenario.update_ddns_;
+ }
+
+ cmd << "}}";
+
+ // Execute the delete command.
+ static_cast<void>(testCommand(cmd.str(), CONTROL_RESULT_SUCCESS, "IPv4 lease deleted."));
+
+ if (!scenario.exp_ncr_) {
+ // Should not have an ncr.
+ ASSERT_EQ(ncrQueueSize(), 0);
+ } else {
+ // We should have an ncr, verify it.
+ ASSERT_EQ(ncrQueueSize(), 1);
+ verifyNameChangeRequest(CHG_REMOVE, scenario.fqdn_rev_, scenario.fqdn_fwd_,
+ lease->addr_.toText(), lease->hostname_);
+ }
+
+ // Lease should have been deleted.
+ lease = lmptr_->getLease4(lease->addr_);
+ ASSERT_FALSE(lease);
+ }
+}
+
+void Lease4CmdsTest::testLease4DnsRemoveD2Disabled() {
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ disableD2();
+
+ // Delete for valid, existing lease.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-del\",\n"
+ " \"arguments\": {\n"
+ " \"ip-address\": \"192.0.2.8\",\n"
+ " \"update-ddns\": true\n"
+ " }\n"
+ "}";
+
+ // Let's create a lease with scenario attributes.
+ Lease4Ptr lease = createLease4("192.0.2.8", 44, 0x08, 0x42);
+ lease->hostname_ = "myhost.example.com.";
+ lease->fqdn_rev_ = true;
+ lease->fqdn_fwd_ = true;
+ ASSERT_TRUE(lmptr_->addLease(lease));
+
+ // NCR Queue is not enabled.
+ ASSERT_EQ(ncrQueueSize(), -1);
+
+ // Execute the delete command.
+ static_cast<void>(testCommand(cmd, CONTROL_RESULT_SUCCESS, "IPv4 lease deleted."));
+
+ // NCR Queue is not enabled.
+ ASSERT_EQ(ncrQueueSize(), -1);
+
+ // Lease should have been deleted.
+ lease = lmptr_->getLease4(lease->addr_);
+ ASSERT_FALSE(lease);
+}
+
+// Verify that v4 lease add handles conflict as expected.
+void Lease4CmdsTest::testLease4ConflictingAdd() {
+ MultiThreadingTest mt(true);
+
+ // Initialize lease manager (false = v4, false = don't add leases)
+ initLeaseMgr(false, false);
+
+ // Make sure the lease doesn't exist.
+ IOAddress addr("192.0.2.1");
+ Lease4Ptr lease = lmptr_->getLease4(addr);
+ ASSERT_FALSE(lease);
+
+ // Verify stats show no leases.
+ checkLease4Stats(44, 0, 0);
+
+ // Lock the address.
+ ResourceHandler4 resource_handler;
+ ASSERT_TRUE(resource_handler.tryLock4(addr));
+
+ // Now let's try to add the lease.
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44,\n"
+ " \"ip-address\": \"192.0.2.1\",\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"comment\": \"a comment\"\n"
+ " }\n"
+ "}";
+
+ string exp_rsp = "ResourceBusy: IP address:192.0.2.1 could not be added.";
+ testCommand(txt, CONTROL_RESULT_CONFLICT, exp_rsp);
+
+ // Lease should not have been added.
+ lease = lmptr_->getLease4(addr);
+ ASSERT_FALSE(lease);
+
+ // Stats should not have changed.
+ checkLease4Stats(44, 0, 0);
+}
+
+void Lease4CmdsTest::testLease4ConflictingUpdate() {
+ MultiThreadingTest mt(true);
+
+ // Initialize lease manager (false = v4, true = add leases)
+ initLeaseMgr(false, true);
+
+ // Verify stats show no leases.
+ checkLease4Stats(44, 2, 0);
+
+ // Make sure the lease exists.
+ IOAddress addr("192.0.2.1");
+ Lease4Ptr lease = lmptr_->getLease4(addr);
+ ASSERT_TRUE(lease);
+ // Save a copy of the original lease.
+ Lease4 original_lease = *lease;
+
+ // Lock the address.
+ ResourceHandler4 resource_handler;
+ ASSERT_TRUE(resource_handler.tryLock4(addr));
+
+ // Now let's try to update the lease.
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 44,\n"
+ " \"ip-address\": \"192.0.2.1\",\n"
+ " \"hw-address\": \"2a:2b:2c:2d:2e:2f\",\n"
+ " \"comment\": \"a comment\"\n"
+ " }\n"
+ "}";
+
+ string exp_rsp = "ResourceBusy: IP address:192.0.2.1 could not be updated.";
+ testCommand(txt, CONTROL_RESULT_CONFLICT, exp_rsp);
+
+ // Fetch the lease again.
+ lease = lmptr_->getLease4(addr);
+ ASSERT_TRUE(lease);
+
+ // Lease should not have been changed.
+ EXPECT_EQ(original_lease, *lease);
+}
+
+void Lease4CmdsTest::testLease4Write() {
+ // lease4-write negative tests. Positive tests are in the
+ // memfile_lease_mgr_unittest.cc file.
+
+ // Initialize lease manager (false = v4, false = don't add leases)
+ initLeaseMgr(false, false);
+
+ // Parameter is missing.
+ string txt =
+ "{\n"
+ " \"command\": \"lease4-write\",\n"
+ " \"arguments\": {"
+ " }\n"
+ "}";
+ string exp_rsp = "'filename' parameter not specified";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Filename must be a string.
+ txt =
+ "{\n"
+ " \"command\": \"lease4-write\",\n"
+ " \"arguments\": {"
+ " \"filename\": 0\n"
+ " }\n"
+ "}";
+ exp_rsp = "'filename' parameter must be a string";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Filename must be not empty.
+ txt =
+ "{\n"
+ " \"command\": \"lease4-write\",\n"
+ " \"arguments\": {"
+ " \"filename\": \"\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "'filename' parameter is empty";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+TEST_F(Lease4CmdsTest, lease4AddMissingParams) {
+ testLease4AddMissingParams();
+}
+
+TEST_F(Lease4CmdsTest, lease4AddMissingParamsMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4AddMissingParams();
+}
+
+TEST_F(Lease4CmdsTest, lease4AddBadParams) {
+ testLease4AddBadParams();
+}
+
+TEST_F(Lease4CmdsTest, lease4AddBadParamsMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4AddBadParams();
+}
+
+TEST_F(Lease4CmdsTest, lease4Add) {
+ testLease4Add();
+}
+
+TEST_F(Lease4CmdsTest, lease4AddMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4Add();
+}
+
+TEST_F(Lease4CmdsTest, lease4AddDeclinedLeases) {
+ testLease4AddDeclinedLeases();
+}
+
+TEST_F(Lease4CmdsTest, lease4AddDeclinedLeasesMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4AddDeclinedLeases();
+}
+
+TEST_F(Lease4CmdsTest, lease4AddExisting) {
+ testLease4AddExisting();
+}
+
+TEST_F(Lease4CmdsTest, lease4AddExistingMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4AddExisting();
+}
+
+TEST_F(Lease4CmdsTest, lease4AddSubnetIdMissing) {
+ testLease4AddSubnetIdMissing();
+}
+
+TEST_F(Lease4CmdsTest, lease4AddSubnetIdMissingMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4AddSubnetIdMissing();
+}
+
+TEST_F(Lease4CmdsTest, lease4AddSubnetIdMissingDeclinedLeases) {
+ testLease4AddSubnetIdMissingDeclinedLeases();
+}
+
+TEST_F(Lease4CmdsTest, lease4AddSubnetIdMissingDeclinedLeasesMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4AddSubnetIdMissingDeclinedLeases();
+}
+
+TEST_F(Lease4CmdsTest, lease4AddSubnetIdMissingBadAddr) {
+ testLease4AddSubnetIdMissingBadAddr();
+}
+
+TEST_F(Lease4CmdsTest, lease4AddSubnetIdMissingBadAddrMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4AddSubnetIdMissingBadAddr();
+}
+
+TEST_F(Lease4CmdsTest, lease4AddNegativeExpireTime) {
+ testLease4AddNegativeExpireTime();
+}
+
+TEST_F(Lease4CmdsTest, lease4AddNegativeExpireTimeMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4AddNegativeExpireTime();
+}
+
+TEST_F(Lease4CmdsTest, lease4AddNegativeCltt) {
+ testLease4AddNegativeCltt();
+}
+
+TEST_F(Lease4CmdsTest, lease4AddNegativeClttMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4AddNegativeCltt();
+}
+
+TEST_F(Lease4CmdsTest, lease4AddFullAddr) {
+ testLease4AddFullAddr();
+}
+
+TEST_F(Lease4CmdsTest, lease4AddFullAddrMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4AddFullAddr();
+}
+
+TEST_F(Lease4CmdsTest, lease4AddComment) {
+ testLease4AddComment();
+}
+
+TEST_F(Lease4CmdsTest, lease4AddCommentMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4AddComment();
+}
+
+TEST_F(Lease4CmdsTest, lease4AddExtendedInfo) {
+ testLease4AddExtendedInfo();
+}
+
+TEST_F(Lease4CmdsTest, lease4AddExtendedInfoMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4AddExtendedInfo();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetMissingParams) {
+ testLease4GetMissingParams();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetMissingParamsMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4GetMissingParams();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByAddrBadParam) {
+ testLease4GetByAddrBadParam();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByAddrBadParamMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4GetByAddrBadParam();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByAddrNotFound) {
+ testLease4GetByAddrNotFound();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByAddrNotFoundMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4GetByAddrNotFound();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByAddr) {
+ testLease4GetByAddr();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByAddrMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4GetByAddr();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByHWAddrNotFound) {
+ testLease4GetByHWAddrNotFound();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByHWAddrNotFoundMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4GetByHWAddrNotFound();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByHWAddr) {
+ testLease4GetByHWAddr();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByHWAddrMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4GetByHWAddr();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByClientIdNotFound) {
+ testLease4GetByClientIdNotFound();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByClientIdNotFoundMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4GetByClientIdNotFound();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByClientId) {
+ testLease4GetByClientId();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByClientIdMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4GetByClientId();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetAll) {
+ testLease4GetAll();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetAllMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4GetAll();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetAllNoLeases) {
+ testLease4GetAllNoLeases();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetAllNoLeasesMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4GetAllNoLeases();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetAllBySubnetId) {
+ testLease4GetAllBySubnetId();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetAllBySubnetIdMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4GetAllBySubnetId();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetAllBySubnetIdNoLeases) {
+ testLease4GetAllBySubnetIdNoLeases();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetAllBySubnetIdNoLeasesMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4GetAllBySubnetIdNoLeases();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetAllByMultipleSubnetIds) {
+ testLease4GetAllByMultipleSubnetIds();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetAllByMultipleSubnetIdsMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4GetAllByMultipleSubnetIds();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetBySubnetIdInvalidArguments) {
+ testLease4GetBySubnetIdInvalidArguments();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetBySubnetIdInvalidArgumentsMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4GetBySubnetIdInvalidArguments();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetPaged) {
+ testLease4GetPaged();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetPagedMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4GetPaged();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetPagedZeroAddress) {
+ testLease4GetPagedZeroAddress();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetPagedZeroAddressMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4GetPagedZeroAddress();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetPagedIPv6Address) {
+ testLease4GetPagedIPv6Address();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetPagedIPv6AddressMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4GetPagedIPv6Address();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetPagedInvalidFrom) {
+ testLease4GetPagedInvalidFrom();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetPagedInvalidFromMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4GetPagedInvalidFrom();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetPagedNoLimit) {
+ testLease4GetPagedNoLimit();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetPagedNoLimitMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4GetPagedNoLimit();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetPagedLimitNotNumber) {
+ testLease4GetPagedLimitNotNumber();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetPagedLimitNotNumberMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4GetPagedLimitNotNumber();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetPagedLimitIsZero) {
+ testLease4GetPagedLimitIsZero();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetPagedLimitIsZeroMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4GetPagedLimitIsZero();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByHwAddressParams) {
+ testLease4GetByHwAddressParams();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByHwAddressParamsMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4GetByHwAddressParams();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByHwAddressFind0) {
+ testLease4GetByHwAddressFind0();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByHwAddressFind0MultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4GetByHwAddressFind0();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByHwAddressFind2) {
+ testLease4GetByHwAddressFind2();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByHwAddressFind2MultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4GetByHwAddressFind2();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByClientIdParams) {
+ testLease4GetByClientIdParams();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByClientIdParamsMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4GetByClientIdParams();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByClientIdFind0) {
+ testLease4GetByClientIdFind0();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByClientIdFind0MultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4GetByClientIdFind0();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByClientIdFind2) {
+ testLease4GetByClientIdFind2();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByClientIdFind2MultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4GetByClientIdFind2();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByHostnameParams) {
+ testLease4GetByHostnameParams();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByHostnameParamsMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4GetByHostnameParams();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByHostnameFind0) {
+ testLease4GetByHostnameFind0();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByHostnameFind0MultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4GetByHostnameFind0();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByHostnameFind2) {
+ testLease4GetByHostnameFind2();
+}
+
+TEST_F(Lease4CmdsTest, lease4GetByHostnameFind2MultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4GetByHostnameFind2();
+}
+
+TEST_F(Lease4CmdsTest, lease4UpdateMissingParams) {
+ testLease4UpdateMissingParams();
+}
+
+TEST_F(Lease4CmdsTest, lease4UpdateMissingParamsMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4UpdateMissingParams();
+}
+
+TEST_F(Lease4CmdsTest, lease4UpdateBadParams) {
+ testLease4UpdateBadParams();
+}
+
+TEST_F(Lease4CmdsTest, lease4UpdateBadParamsMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4UpdateBadParams();
+}
+
+TEST_F(Lease4CmdsTest, lease4UpdateNoLease) {
+ testLease4UpdateNoLease();
+}
+
+TEST_F(Lease4CmdsTest, lease4UpdateNoLeaseMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4UpdateNoLease();
+}
+
+TEST_F(Lease4CmdsTest, lease4Update) {
+ testLease4Update();
+}
+
+TEST_F(Lease4CmdsTest, lease4UpdateMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4Update();
+}
+
+TEST_F(Lease4CmdsTest, lease4UpdateDeclinedLeases) {
+ testLease4UpdateDeclinedLeases();
+}
+
+TEST_F(Lease4CmdsTest, lease4UpdateDeclinedLeasesMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4UpdateDeclinedLeases();
+}
+
+TEST_F(Lease4CmdsTest, lease4UpdateNoSubnetId) {
+ testLease4UpdateNoSubnetId();
+}
+
+TEST_F(Lease4CmdsTest, lease4UpdateNoSubnetIdMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4UpdateNoSubnetId();
+}
+
+TEST_F(Lease4CmdsTest, lease4UpdateNoSubnetIdDeclinedLeases) {
+ testLease4UpdateNoSubnetIdDeclinedLeases();
+}
+
+TEST_F(Lease4CmdsTest, lease4UpdateNoSubnetIdDeclinedLeasesMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4UpdateNoSubnetIdDeclinedLeases();
+}
+
+TEST_F(Lease4CmdsTest, lease4UpdateComment) {
+ testLease4UpdateComment();
+}
+
+TEST_F(Lease4CmdsTest, lease4UpdateCommentMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4UpdateComment();
+}
+
+TEST_F(Lease4CmdsTest, lease4UpdateExtendedInfo) {
+ testLease4UpdateExtendedInfo();
+}
+
+TEST_F(Lease4CmdsTest, lease4UpdateExtendedInfoMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4UpdateExtendedInfo();
+}
+
+TEST_F(Lease4CmdsTest, lease4UpdateForceCreate) {
+ testLease4UpdateForceCreate();
+}
+
+TEST_F(Lease4CmdsTest, lease4UpdateForceCreateMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4UpdateForceCreate();
+}
+
+TEST_F(Lease4CmdsTest, lease4UpdateForceCreateNoSubnetId) {
+ testLease4UpdateForceCreateNoSubnetId();
+}
+
+TEST_F(Lease4CmdsTest, lease4UpdateForceCreateNoSubnetIdMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4UpdateForceCreateNoSubnetId();
+}
+
+TEST_F(Lease4CmdsTest, lease4UpdateDoNotForceCreate) {
+ testLease4UpdateDoNotForceCreate();
+}
+
+TEST_F(Lease4CmdsTest, lease4UpdateDoNotForceCreateMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4UpdateDoNotForceCreate();
+}
+
+TEST_F(Lease4CmdsTest, lease4DelMissingParams) {
+ testLease4DelMissingParams();
+}
+
+TEST_F(Lease4CmdsTest, lease4DelMissingParamsMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4DelMissingParams();
+}
+
+TEST_F(Lease4CmdsTest, lease4DelByAddrNotFound) {
+ testLease4DelByAddrNotFound();
+}
+
+TEST_F(Lease4CmdsTest, lease4DelByAddrNotFoundMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4DelByAddrNotFound();
+}
+
+TEST_F(Lease4CmdsTest, lease4DelByAddr) {
+ testLease4DelByAddr();
+}
+
+TEST_F(Lease4CmdsTest, lease4DelByAddrMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4DelByAddr();
+}
+
+TEST_F(Lease4CmdsTest, lease4DelByAddrDeclinedLeases) {
+ testLease4DelByAddrDeclinedLeases();
+}
+
+TEST_F(Lease4CmdsTest, lease4DelByAddrDeclinedLeasesMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4DelByAddrDeclinedLeases();
+}
+
+TEST_F(Lease4CmdsTest, lease4DelByAddrBadParam) {
+ testLease4DelByAddrBadParam();
+}
+
+TEST_F(Lease4CmdsTest, lease4DelByAddrBadParamMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4DelByAddrBadParam();
+}
+
+TEST_F(Lease4CmdsTest, lease4DelByHWAddrNotFound) {
+ testLease4DelByHWAddrNotFound();
+}
+
+TEST_F(Lease4CmdsTest, lease4DelByHWAddrNotFoundMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4DelByHWAddrNotFound();
+}
+
+TEST_F(Lease4CmdsTest, lease4DelByHWAddr) {
+ testLease4DelByHWAddr();
+}
+
+TEST_F(Lease4CmdsTest, lease4DelByHWAddrMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4DelByHWAddr();
+}
+
+TEST_F(Lease4CmdsTest, lease4DelByClientIdNotFound) {
+ testLease4DelByClientIdNotFound();
+}
+
+TEST_F(Lease4CmdsTest, lease4DelByClientIdNotFoundMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4DelByClientIdNotFound();
+}
+
+TEST_F(Lease4CmdsTest, lease4DelByClientId) {
+ testLease4DelByClientId();
+}
+
+TEST_F(Lease4CmdsTest, lease4DelByClientIdMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4DelByClientId();
+}
+
+TEST_F(Lease4CmdsTest, lease4Wipe) {
+ testLease4Wipe();
+}
+
+TEST_F(Lease4CmdsTest, lease4WipeMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4Wipe();
+}
+
+TEST_F(Lease4CmdsTest, lease4WipeAll) {
+ testLease4WipeAll();
+}
+
+TEST_F(Lease4CmdsTest, lease4WipeAllMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4WipeAll();
+}
+
+TEST_F(Lease4CmdsTest, lease4WipeAllNoArgs) {
+ testLease4WipeAllNoArgs();
+}
+
+TEST_F(Lease4CmdsTest, lease4WipeAllNoArgsMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4WipeAllNoArgs();
+}
+
+TEST_F(Lease4CmdsTest, lease4WipeNoLeases) {
+ testLease4WipeNoLeases();
+}
+
+TEST_F(Lease4CmdsTest, lease4WipeNoLeasesMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4WipeNoLeases();
+}
+
+TEST_F(Lease4CmdsTest, lease4WipeNoLeasesAll) {
+ testLease4WipeNoLeasesAll();
+}
+
+TEST_F(Lease4CmdsTest, lease4WipeNoLeasesAllMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4WipeNoLeasesAll();
+}
+
+TEST_F(Lease4CmdsTest, lease4BrokenUpdate) {
+ testLease4BrokenUpdate();
+}
+
+TEST_F(Lease4CmdsTest, lease4BrokenUpdateMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4BrokenUpdate();
+}
+
+TEST_F(Lease4CmdsTest, lease4ResendDdnsBadParam) {
+ testLease4ResendDdnsBadParam();
+}
+
+TEST_F(Lease4CmdsTest, lease4ResendDdnsBadParamMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4ResendDdnsBadParam();
+}
+
+TEST_F(Lease4CmdsTest, lease4ResendDdnsDisabled) {
+ testLease4ResendDdnsDisabled();
+}
+
+TEST_F(Lease4CmdsTest, lease4ResendDdnsDisabledMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4ResendDdnsDisabled();
+}
+
+TEST_F(Lease4CmdsTest, lease4ResendDdnsNoLease) {
+ testLease4ResendDdnsNoLease();
+}
+
+TEST_F(Lease4CmdsTest, lease4ResendDdnsNoLeaseMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4ResendDdnsNoLease();
+}
+
+TEST_F(Lease4CmdsTest, lease4ResendNoHostname) {
+ testLease4ResendNoHostname();
+}
+
+TEST_F(Lease4CmdsTest, lease4ResendNoHostnameMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4ResendNoHostname();
+}
+
+TEST_F(Lease4CmdsTest, lease4ResendNoDirectionsEnabled) {
+ testLease4ResendNoDirectionsEnabled();
+}
+
+TEST_F(Lease4CmdsTest, lease4ResendNoDirectionsEnabledMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4ResendNoDirectionsEnabled();
+}
+
+TEST_F(Lease4CmdsTest, lease4ResendDdnsEnabled) {
+ testLease4ResendDdnsEnabled();
+}
+
+TEST_F(Lease4CmdsTest, lease4ResendDdnsEnabledMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4ResendDdnsEnabled();
+}
+
+TEST_F(Lease4CmdsTest, lease4DnsRemoveD2Enabled) {
+ testLease4DnsRemoveD2Enabled();
+}
+
+TEST_F(Lease4CmdsTest, lease4DnsRemoveD2EnabledMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4DnsRemoveD2Enabled();
+}
+
+TEST_F(Lease4CmdsTest, lease4DnsRemoveD2Disabled) {
+ testLease4DnsRemoveD2Disabled();
+}
+
+TEST_F(Lease4CmdsTest, lease4DnsRemoveD2DisabledMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4DnsRemoveD2Disabled();
+}
+
+TEST_F(Lease4CmdsTest, lease4ConflictingAddMultiThreading) {
+ testLease4ConflictingAdd();
+}
+
+TEST_F(Lease4CmdsTest, lease4ConflictingUpdateMultiThreading) {
+ testLease4ConflictingUpdate();
+}
+
+TEST_F(Lease4CmdsTest, lease4Write) {
+ testLease4Write();
+}
+
+TEST_F(Lease4CmdsTest, lease4WriteMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4Write();
+}
+
+} // end of anonymous namespace
diff --git a/src/hooks/dhcp/lease_cmds/tests/lease_cmds6_unittest.cc b/src/hooks/dhcp/lease_cmds/tests/lease_cmds6_unittest.cc
new file mode 100644
index 0000000..9b95b5e
--- /dev/null
+++ b/src/hooks/dhcp/lease_cmds/tests/lease_cmds6_unittest.cc
@@ -0,0 +1,4962 @@
+// Copyright (C) 2017-2023 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 <exceptions/exceptions.h>
+#include <hooks/hooks_manager.h>
+#include <config/command_mgr.h>
+#include <dhcpsrv/lease_mgr.h>
+#include <dhcpsrv/lease_mgr_factory.h>
+#include <dhcpsrv/ncr_generator.h>
+#include <dhcpsrv/cfgmgr.h>
+#include <dhcpsrv/resource_handler.h>
+#include <cc/command_interpreter.h>
+#include <cc/data.h>
+#include <lease_cmds_unittest.h>
+#include <stats/stats_mgr.h>
+#include <testutils/user_context_utils.h>
+#include <testutils/multi_threading_utils.h>
+
+#include <gtest/gtest.h>
+
+#include <errno.h>
+#include <set>
+
+using namespace std;
+using namespace isc;
+using namespace isc::hooks;
+using namespace isc::config;
+using namespace isc::data;
+using namespace isc::dhcp;
+using namespace isc::dhcp_ddns;
+using namespace isc::asiolink;
+using namespace isc::stats;
+using namespace isc::test;
+
+namespace {
+
+/// @brief Class dedicated to testing v6 part of lease_cmds library.
+///
+/// Provides convenience methods for loading, testing all commands and
+/// unloading the lease_cmds library.
+class Lease6CmdsTest : public LeaseCmdsTest {
+public:
+ /// @brief Constructor.
+ Lease6CmdsTest() {
+ setFamily(AF_INET6);
+ }
+
+ /// @brief Checks if specified response contains IPv6 lease
+ ///
+ /// @param lease Element tree that represents a lease
+ /// @param ip expected IP address (or prefix)
+ /// @param prefixlen prefix length (0 = expect address)
+ /// @param subnet_id expected subnet-id
+ /// @param duid expected value of DUID
+ /// @param hwaddr_required true if hwaddr is expected
+ /// @param pool_id expected pool-id (if value is 0 the parameter pool-id should not be present)
+ void checkLease6(isc::data::ConstElementPtr l, std::string ip,
+ uint8_t prefixlen, uint32_t subnet_id, std::string duid,
+ bool hwaddr_required, uint32_t pool_id = 0) {
+ ASSERT_TRUE(l);
+
+ // If the element is a list we need to retrieve the lease that
+ // we're interested in.
+ if (l->getType() == isc::data::Element::list) {
+ std::vector<isc::data::ElementPtr> e = l->listValue();
+ for (auto it = e.begin(); it != e.end(); ++it) {
+ isc::data::ConstElementPtr ip_address = (*it)->get("ip-address");
+ if (ip_address && ip_address->stringValue() == ip) {
+ l = (*it);
+ break;
+ }
+ }
+
+ ASSERT_TRUE(l);
+ }
+
+ ASSERT_TRUE(l->get("ip-address"));
+ EXPECT_EQ(ip, l->get("ip-address")->stringValue());
+ if (prefixlen != 0) {
+ ASSERT_TRUE(l->get("prefix-len"));
+ EXPECT_EQ(prefixlen, l->get("prefix-len")->intValue());
+ }
+
+ ASSERT_TRUE(l->get("subnet-id"));
+ EXPECT_EQ(subnet_id, l->get("subnet-id")->intValue());
+
+ ASSERT_TRUE(l->get("duid"));
+ EXPECT_EQ(duid, l->get("duid")->stringValue());
+
+ // hwaddr may or may not appear
+ if (hwaddr_required) {
+ EXPECT_TRUE(l->get("hwaddr"));
+ }
+
+ if (pool_id) {
+ ASSERT_TRUE(l->get("pool-id"));
+ EXPECT_EQ(pool_id, l->get("pool-id")->intValue());
+ } else {
+ EXPECT_FALSE(l->get("pool-id"));
+ }
+
+ // Check that all expected fields are there.
+ ASSERT_TRUE(l->contains("preferred-lft"));
+ ASSERT_TRUE(l->contains("valid-lft"));
+ ASSERT_TRUE(l->contains("cltt"));
+ ASSERT_TRUE(l->contains("subnet-id"));
+ ASSERT_TRUE(l->contains("fqdn-fwd"));
+ ASSERT_TRUE(l->contains("fqdn-rev"));
+ ASSERT_TRUE(l->contains("hostname"));
+ ASSERT_TRUE(l->contains("state"));
+
+ // Check that there are no v4 specific fields.
+ ASSERT_FALSE(l->contains("client-id"));
+
+ // Assuming that these values were used to create the lease.
+ // If we ever want to test different values they will need to
+ // be added as parameters to this function.
+ EXPECT_EQ(HIGH_VALID_LIFETIME,
+ static_cast<uint32_t>(l->get("valid-lft")->intValue()));
+ EXPECT_EQ(DEC_2030_TIME, l->get("cltt")->intValue());
+ }
+
+ /// @brief Check lease6 statistics.
+ ///
+ /// @param id Subnet id of the stats to check.
+ /// @assigned_nas The expected value of assigned nas addresses in subnet.
+ /// @declined The expected value of declined addresses in subnet.
+ /// @assigned_pds The expected value of assigned pds addresses in subnet.
+ void checkLease6Stats(isc::dhcp::SubnetID id, int32_t assigned_nas,
+ int32_t declined, int32_t assigned_pds) {
+ ASSERT_EQ(isc::stats::StatsMgr::instance().getObservation(
+ isc::stats::StatsMgr::generateName("subnet", id,
+ "assigned-nas"))->getInteger().first, assigned_nas);
+
+ ASSERT_EQ(isc::stats::StatsMgr::instance().getObservation(
+ isc::stats::StatsMgr::generateName("subnet", id,
+ "declined-addresses"))->getInteger().first, declined);
+
+ ASSERT_EQ(isc::stats::StatsMgr::instance().getObservation(
+ isc::stats::StatsMgr::generateName("subnet", id,
+ "assigned-pds"))->getInteger().first, assigned_pds);
+ }
+
+ /// @brief Check that lease6-add with missing parameters will fail.
+ void testLease6AddMissingParams();
+
+ /// @brief Verify that lease6-add can be rejected if parameters are
+ /// specified, but have incorrect values.
+ void testLease6AddBadParams();
+
+ /// @brief Check that a simple, well formed lease6 can be added.
+ void testLease6Add();
+
+ /// @brief Check that a simple, well formed lease6 can be added.
+ void testLease6AddDeclinedLeases();
+
+ /// @brief Check that a lease6 is not added when it already exists.
+ void testLease6AddExisting();
+
+ /// @brief Check that subnet-id is optional. If not specified, Kea should
+ /// select it on its own.
+ void testLease6AddSubnetIdMissing();
+
+ /// @brief Check that subnet-id is optional. If not specified, Kea should
+ /// select it on its own.
+ void testLease6AddSubnetIdMissingDeclinedLeases();
+
+ /// @brief Check that subnet-id is optional. If not specified, Kea should
+ /// select it on its own, but if there's no subnet for address being added,
+ /// it should fail.
+ void testLease6AddSubnetIdMissingBadAddr();
+
+ /// @brief Check that the lease with negative expiration time is rejected.
+ void testLease6AddNegativeExpireTime();
+
+ /// @brief Check that the lease with negative cltt is rejected.
+ void testLease6AddNegativeCltt();
+
+ /// @brief Check that a simple, well formed prefix lease can be added.
+ void testLease6AddPrefix();
+
+ /// @brief Check that a well formed lease6 with tons of parameters can be
+ /// added.
+ void testLease6AddFullAddr();
+
+ /// @brief Check that a well formed lease6 with a comment can be added.
+ void testLease6AddComment();
+
+ /// @brief Check that a well formed lease6 with relay and remote ids
+ /// can be added.
+ void testLease6AddExtendedInfo();
+
+ /// @brief Check that lease6-get can handle a situation when the query is
+ /// broken (some required parameters are missing).
+ void testLease6GetMissingParams();
+
+ /// @brief Check that lease6-get sanitizes its input.
+ void testLease6GetByAddrBadParam();
+
+ /// @brief Check that lease6-get can handle a situation when the query is
+ /// correctly formed, but the lease is not there.
+ void testLease6GetByAddrNotFound();
+
+ /// @brief Check that lease6-get can return a lease by address.
+ void testLease6GetByAddr();
+
+ /// @brief Check that lease6-get can return a lease by prefix.
+ void testLease6GetByAddrPrefix();
+
+ /// @brief Check that lease6-get rejects queries by client-id.
+ void testLease6GetByClientIdInvalidType();
+
+ /// @brief Check that lease6-get can handle a situation when the query is
+ /// correctly formed, but the lease is not there.
+ void testLease6GetByDuidNotFound();
+
+ /// @brief Check that lease6-get can find a lease by duid.
+ void testLease6GetByDuid();
+
+ /// @brief Check that lease6-get-all returns all leases.
+ void testLease6GetAll();
+
+ /// @brief Check that lease6-get-all returns empty set if no leases are
+ /// found.
+ void testLease6GetAllNoLeases();
+
+ /// @brief Check that lease6-get-all returns all leases for a subnet.
+ void testLease6GetAllBySubnetId();
+
+ /// @brief Check that lease6-get-all returns empty set when no leases are
+ /// found.
+ void testLease6GetAllBySubnetIdNoLeases();
+
+ /// @brief Check that lease6-get-all returns leases from multiple subnets.
+ void testLease6GetAllByMultipleSubnetIds();
+
+ /// @brief Check that lease6-get-all checks its input arguments.
+ void testLease6GetBySubnetIdInvalidArguments();
+
+ /// @brief Check that multiple calls to lease6-get-page return all leases.
+ void testLease6GetPaged();
+
+ /// @brief Verifies that first page of IPv6 leases can be retrieved by
+ /// specifying zero IPv6 address.
+ void testLease6GetPagedZeroAddress();
+
+ /// @brief Verifies that IPv4 address as a start address is rejected.
+ void testLease6GetPagedIPv4Address();
+
+ /// @brief Verifies that value of 'from' parameter other than 'start' or an
+ /// IPv6 address is rejected.
+ void testLease6GetPagedInvalidFrom();
+
+ /// @brief Verifies that limit is mandatory.
+ void testLease6GetPagedNoLimit();
+
+ /// @brief Verifies that the limit must be a number.
+ void testLease6GetPagedLimitNotNumber();
+
+ /// @brief Verifies that the limit of 0 is rejected.
+ void testLease6GetPagedLimitIsZero();
+
+ /// @brief Check that lease6-get-by-duid can handle a situation when the
+ /// query is broken (required parameter is missing).
+ void testLease6GetByDuidParams();
+
+ /// @brief Check that lease6-get-by-duid works as expected (find no lease).
+ void testLease6GetByDuidFind0();
+
+ /// @brief Check that lease6-get-by-duid works as expected (find two
+ /// leases).
+ void testLease6GetByDuidFind2();
+
+ /// @brief Check that lease6-get-by-hostname can handle a situation when
+ /// the query is broken (required parameter is missing).
+ void testLease6GetByHostnameParams();
+
+ /// @brief Check that lease6-get-by-hostname works as expected (find no
+ /// lease).
+ void testLease6GetByHostnameFind0();
+
+ /// @brief Check that lease6-get-by-hostname works as expected (find two
+ /// leases).
+ void testLease6GetByHostnameFind2();
+
+ /// @brief Test checks if lease6-update handler refuses calls with missing
+ /// parameters.
+ void testLease6UpdateMissingParams();
+
+ /// @brief Verify that lease6-update can be rejected if parameters are
+ /// specified, but have incorrect values.
+ void testLease6UpdateBadParams();
+
+ /// @brief Check that lease6-update correctly handles case when there is no
+ /// lease to be updated.
+ void testLease6UpdateNoLease();
+
+ /// @brief Check that a lease6 can be updated. We're changing hw-address and
+ /// a hostname.
+ void testLease6Update();
+
+ /// @brief Check that a lease6 can be updated. We're changing hw-address and
+ /// a hostname.
+ void testLease6UpdateDeclinedLeases();
+
+ /// @brief Check that a lease6 can be updated. We're changing hw-address and
+ /// a hostname. The subnet-id is not specified.
+ void testLease6UpdateNoSubnetId();
+
+ /// @brief Check that a lease6 can be updated. We're changing hw-address and
+ /// a hostname. The subnet-id is not specified.
+ void testLease6UpdateNoSubnetIdDeclinedLeases();
+
+ /// @brief Check that a lease6 is created if it doesn't exist during the
+ /// update. To trigger this behavior 'force-create' boolean parameter must
+ /// be included in the command.
+ void testLease6UpdateForceCreate();
+
+ /// @brief Check that a lease6 is created if it doesn't exist during the
+ /// update. To trigger this behavior 'force-create' boolean parameter must
+ /// be included in the command. The subnet-id is not specified, Kea will
+ /// figure it out.
+ void testLease6UpdateForceCreateNoSubnetId();
+
+ /// @brief Check that lease6-update correctly handles case when the
+ /// 'force-create' parameter is explicitly set to false.
+ void testLease6UpdateDoNotForceCreate();
+
+ /// @brief Check that a lease6 can be updated. We're adding a comment and an
+ /// user context.
+ void testLease6UpdateComment();
+
+ /// @brief Check that a lease6 can be updated. We're changing hw-address,
+ /// hostname and extended info.
+ void testLease6UpdateExtendedInfo();
+
+ /// @brief Check that lease6-del can handle a situation when the query is
+ /// broken (some required parameters are missing).
+ void testLease6DelMissingParams();
+
+ /// @brief Check that lease6-del(subnet-id, addr6) can handle a situation
+ /// when the query is correctly formed, but the lease is not there.
+ void testLease6DelByAddrNotFound();
+
+ /// @brief Check that lease6-del sanitizes its input.
+ void testLease6DelByAddrBadParam();
+
+ /// @brief Check that lease6-del(subnet-id, addr6) can handle a situation
+ /// when the query is correctly formed and the lease is deleted.
+ void testLease6DelByAddr();
+
+ /// @brief Check that lease6-del(subnet-id, addr6) can handle a situation
+ /// when the query is correctly formed and the lease is deleted.
+ void testLease6DelByAddrDeclinedLeases();
+
+ /// @brief Check that lease6-del(type, addr6) can handle a
+ /// situation when the query is correctly formed and the lease is deleted.
+ void testLease6DelByAddrPrefix();
+
+ /// @brief Check that lease6-del(subnet-id, addr) can handle a situation
+ /// when the query is correctly formed, but the lease is not there.
+ void testLease6DelByDuidNotFound();
+
+ /// @brief Check that lease6-del(subnet-id, iaid, identifier-type,
+ /// identifier) can find and delete a lease by duid.
+ void testLease6DelByDuid();
+
+ /// @brief Check that lease6-wipe can remove leases.
+ void testLease6Wipe();
+
+ /// @brief Check that lease6-wipe can remove leases from all subnets at
+ /// once.
+ void testLease6WipeAll();
+
+ /// @brief Check that lease6-wipe can remove leases from all subnets at
+ /// once (when no parameters are specified).
+ void testLease6WipeAllNoArgs();
+
+ /// @brief Check that lease6-wipe properly reports when no leases were
+ /// deleted.
+ void testLease6WipeNoLeases();
+
+ /// @brief Check that lease6-wipe properly reports when no leases were
+ /// deleted.
+ void testLease6WipeNoLeasesAll();
+
+ /// @brief Check that an attempt to update a lease (set incorrect
+ /// subnet-id) will fail.
+ void testLease6BrokenUpdate();
+
+ /// @brief This test verifies that it is possible to add two leases and
+ /// delete two leases as a result of the single lease6-bulk-apply command.
+ void testLease6BulkApply();
+
+ /// @brief This test verifies that the lease parameters are checked when
+ /// adding new leases only with the lease6-bulk-apply.
+ void testLease6BulkApplyAddsOnlyBadParam();
+
+ /// @brief This test verifies that it is possible to send new leases only
+ /// with the lease6-bulk-apply.
+ void testLease6BulkApplyAddsOnly();
+
+ /// @brief This test verifies that the lease parameters are checked when
+ /// updating leases only with the lease6-bulk-apply.
+ void testLease6BulkApplyUpdatesOnlyBadParam();
+
+ /// @brief This test verifies that it is possible to update leases with the
+ /// lease6-bulk-apply.
+ void testLease6BulkApplyUpdatesOnly();
+
+ /// @brief This test verifies that it is possible to update leases with
+ /// extended info with the lease6-bulk-apply.
+ void testLease6BulkApplyUpdatesOnlyExtendedInfo();
+
+ /// @brief This test verifies that it is possible to only delete leases with
+ /// the lease6-bulk-apply.
+ void testLease6BulkApplyDeletesOnly();
+
+ /// @brief This test verifies that deleting non existing leases returns an
+ /// 'empty' result.
+ void testLease6BulkApplyDeleteNonExiting();
+
+ /// @brief Check that changes for other leases are not applied if one of the
+ /// leases is malformed.
+ void testLease6BulkApplyRollback();
+
+ /// @brief Check that lease6-resend-ddns sanitizes its input.
+ void testLease6ResendDdnsBadParam();
+
+ /// @brief Check that lease6-resend-ddns does not generate an NCR for given
+ /// lease when DDNS updating is disabled.
+ void testLease6ResendDdnsDisabled();
+
+ /// @brief Check that lease6-resend-ddns does not generate an NCR for when
+ /// there is no matching lease.
+ void testLease6ResendDdnsNoLease();
+
+ /// @brief Check that lease6-resend-ddns does not generate an NCR for given
+ /// lease when updates are enabled but Lease::hostname_ is blank.
+ void testLease6ResendNoHostname();
+
+ /// @brief Check that lease6-resend-ddns does not generate an NCR for given
+ /// lease when updates are enabled, Lease::hostname_ is not blank, but both
+ /// Lease::fqdn_fwd_ and fdqn_rev_ are false.
+ void testLease6ResendNoDirectionsEnabled();
+
+ /// @brief Check that lease6-resend-ddns can generate an NCR for given
+ /// lease when updates are enabled, Lease::hostname_ is not blank, and at
+ /// least one of Lease::fqdn_fwd_ or fdqn_rev_ are true.
+ void testLease6ResendDdnsEnabled();
+
+ /// @brief Check that lease6-del does (or does not) generate an NCR to
+ /// remove DNS for a given lease based on lease content when DDNS updates
+ /// are enabled.
+ void testLease6DnsRemoveD2Enabled();
+
+ /// @brief Check that lease6-del does not generate an NCR to remove DNS for
+ /// a given lease based on lease content when DDNS updates are disabled.
+ void testLease6DnsRemoveD2Disabled();
+
+ /// @brief Verify that v6 lease add handles conflict as expected.
+ void testLease6ConflictingAdd();
+
+ /// @brief Verify that v6 lease update handles conflict as expected.
+ void testLease6ConflictingUpdate();
+
+ /// @brief Verify that v6 lease bulk update handles conflict as expected.
+ void testLease6ConflictingBulkApplyAdd();
+
+ /// @brief Check that lease6-write works as expected.
+ void testLease6Write();
+};
+
+void Lease6CmdsTest::testLease6AddMissingParams() {
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ // Everything missing. What sort of nonsense is that?
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " }\n"
+ "}";
+ string exp_rsp = "missing parameter 'ip-address' (<string>:3:19)";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Just ip is not enough (subnet-id and duid missing, although
+ // subnet-id can now be figured out by Kea code)
+ txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"2001:db8:1::3\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "missing parameter 'duid' (<string>:3:19)";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Just subnet-id and ip is not enough (duid missing).
+ txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::3\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "missing parameter 'duid' (<string>:3:19)";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Just subnet-id and duid is not enough (ip, iaid missing).
+ txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "missing parameter 'ip-address' (<string>:3:19)";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Just subnet-id, duid and iaid is not enough (ip missing).
+ txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"iaid\": 1234\n"
+ " }\n"
+ "}";
+ exp_rsp = "missing parameter 'ip-address' (<string>:3:19)";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Close, but no cigars. Still missing iaid.
+ txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"ip-address\": \"2001:db8:1::3\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "missing parameter 'iaid' (<string>:3:19)";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease6CmdsTest::testLease6AddBadParams() {
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ // All params are there, but there's no subnet-id 123 configured.
+ // (initLeaseMgr initialized subnet-id 44 for v4 and subnet-id 66 for v6).
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 123,\n"
+ " \"ip-address\": \"2001:db8:1::3\",\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"iaid\": 1234\n"
+ " }\n"
+ "}";
+ string exp_rsp = "Invalid subnet-id: No IPv6 subnet with subnet-id=123 currently configured.";
+ testCommand(txt, CONTROL_RESULT_CONFLICT, exp_rsp);
+
+ // This time the IP address does not belong to the subnet.
+ txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"3000::3\",\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"iaid\": 1234\n"
+ " }\n"
+ "}";
+ exp_rsp = "The address 3000::3 does not belong to subnet 2001:db8:1::/48, subnet-id=66";
+ testCommand(txt, CONTROL_RESULT_CONFLICT, exp_rsp);
+
+ // v4? You're a time traveler from early 80s or what?
+ txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"192.0.2.1\",\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"iaid\": 1234\n"
+ " }\n"
+ "}";
+ exp_rsp = "Non-IPv6 address specified: 192.0.2.1";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Invalid state: the only supported values are 0,1,2.
+ txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::1\",\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"iaid\": 1234\n,"
+ " \"state\": 123\n"
+ " }\n"
+ "}";
+ exp_rsp = "Invalid state value: 123, supported values are: 0 (default), 1 "
+ "(declined) and 2 (expired-reclaimed)";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Bad user context: not a map.
+ txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::1\",\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"iaid\": 1234\n,"
+ " \"user-context\": \"bad value\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "Invalid user context '\"bad value\"' is not a JSON map.";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Duplicated comment.
+ txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::1\",\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"iaid\": 1234\n,"
+ " \"user-context\": { \"comment\": \"in user context\" },\n"
+ " \"comment\": \"direct\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "Duplicated comment entry '\"direct\"' in user context "
+ "'{ \"comment\": \"in user context\" }'";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Negative expiration time.
+ txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::1\",\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"iaid\": 1234\n,"
+ " \"user-context\": { \"comment\": \"in user context\" },\n"
+ " \"expire\": -6218189367\n"
+ " }\n"
+ "}";
+ exp_rsp = "expiration time must be positive for address 2001:db8:1::1";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Negative cltt
+ txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::1\",\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"iaid\": 1234\n,"
+ " \"user-context\": { \"comment\": \"in user context\" },\n"
+ " \"expire\": 123456,\n"
+ " \"valid-lft\": 123457"
+ " }\n"
+ "}";
+ exp_rsp = "expiration time must be greater than valid lifetime for address "
+ "2001:db8:1::1";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Invalid declined state (1) for PD prefix.
+ txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::\",\n"
+ " \"prefix-len\": 48,\n"
+ " \"type\": \"IA_PD\",\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"iaid\": 1234,\n"
+ " \"state\": 1"
+ " }\n"
+ "}";
+ exp_rsp = "Invalid declined state for PD prefix.";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Invalid prefix len for PD prefix.
+ txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::1\",\n"
+ " \"prefix-len\": 48,\n"
+ " \"type\": \"IA_PD\",\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"iaid\": 1234\n"
+ " }\n"
+ "}";
+ exp_rsp = "Prefix address: 2001:db8:1::1 exceeds prefix/prefix-len pair: 2001:db8:1::/48";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease6CmdsTest::testLease6Add() {
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::3\",\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"iaid\": 1234\n"
+ " }\n"
+ "}";
+ string exp_rsp = "Lease for address 2001:db8:1::3, subnet-id 66 added.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease6Stats(66, 1, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Now check that the lease is really there.
+ Lease6Ptr l = lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::3"));
+ ASSERT_TRUE(l);
+
+ // Make sure the lease has proper value set.
+ ASSERT_TRUE(l->duid_);
+ EXPECT_EQ("1a:1b:1c:1d:1e:1f", l->duid_->toText());
+ EXPECT_EQ(4, l->valid_lft_); // taken from subnet configuration
+ EXPECT_FALSE(l->fqdn_fwd_);
+ EXPECT_FALSE(l->fqdn_rev_);
+ EXPECT_EQ("", l->hostname_);
+ EXPECT_FALSE(l->getContext());
+
+ // Test execution is fast. The cltt should be set to now. In some rare
+ // cases we could have the seconds counter to tick, so having a value off
+ // by one is ok.
+ EXPECT_LE(abs(l->cltt_ - time(NULL)), 1);
+ EXPECT_EQ(0, l->state_);
+}
+
+void Lease6CmdsTest::testLease6AddDeclinedLeases() {
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::3\",\n"
+ " \"state\": 1,\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"iaid\": 1234\n"
+ " }\n"
+ "}";
+ string exp_rsp = "Lease for address 2001:db8:1::3, subnet-id 66 added.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease6Stats(66, 1, 1, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Now check that the lease is really there.
+ Lease6Ptr l = lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::3"));
+ ASSERT_TRUE(l);
+
+ // Make sure the lease has proper value set.
+ ASSERT_TRUE(l->duid_);
+ EXPECT_EQ("1a:1b:1c:1d:1e:1f", l->duid_->toText());
+ EXPECT_EQ(4, l->valid_lft_); // taken from subnet configuration
+ EXPECT_FALSE(l->fqdn_fwd_);
+ EXPECT_FALSE(l->fqdn_rev_);
+ EXPECT_EQ("", l->hostname_);
+ EXPECT_FALSE(l->getContext());
+
+ // Test execution is fast. The cltt should be set to now. In some rare
+ // cases we could have the seconds counter to tick, so having a value off
+ // by one is ok.
+ EXPECT_LE(abs(l->cltt_ - time(NULL)), 1);
+ EXPECT_EQ(1, l->state_);
+}
+
+void Lease6CmdsTest::testLease6AddExisting() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::1\",\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"iaid\": 1234\n"
+ " }\n"
+ "}";
+ string exp_rsp = "IPv6 lease already exists.";
+ testCommand(txt, CONTROL_RESULT_CONFLICT, exp_rsp);
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+}
+
+void Lease6CmdsTest::testLease6AddSubnetIdMissing() {
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Now send the command without subnet-id. Kea should select
+ // the subnet id on its own.
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"2001:db8:1::3\",\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"iaid\": 1234\n"
+ " }\n"
+ "}";
+ string exp_rsp = "Lease for address 2001:db8:1::3, subnet-id 66 added.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease6Stats(66, 1, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Now check that the lease is really there and has correct subnet-id.
+ Lease6Ptr l = lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::3"));
+ ASSERT_TRUE(l);
+ EXPECT_EQ(66, l->subnet_id_);
+}
+
+void Lease6CmdsTest::testLease6AddSubnetIdMissingDeclinedLeases() {
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Now send the command without subnet-id. Kea should select
+ // the subnet id on its own.
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"2001:db8:1::3\",\n"
+ " \"state\": 1,\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"iaid\": 1234\n"
+ " }\n"
+ "}";
+ string exp_rsp = "Lease for address 2001:db8:1::3, subnet-id 66 added.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease6Stats(66, 1, 1, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Now check that the lease is really there and has correct subnet-id.
+ Lease6Ptr l = lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::3"));
+ ASSERT_TRUE(l);
+ EXPECT_EQ(66, l->subnet_id_);
+}
+
+void Lease6CmdsTest::testLease6AddSubnetIdMissingBadAddr() {
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Now send the command without subnet-id. Kea should select
+ // the subnet id on its own.
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"2001:ffff::1\",\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"iaid\": 1234\n"
+ " }\n"
+ "}";
+ string exp_rsp = "subnet-id not specified and failed to find a subnet for "
+ "address 2001:ffff::1";
+ testCommand(txt, CONTROL_RESULT_CONFLICT, exp_rsp);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Now check that the lease was not added.
+ Lease6Ptr l = lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:ffff::1"));
+ ASSERT_FALSE(l);
+}
+
+void Lease6CmdsTest::testLease6AddNegativeExpireTime() {
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Add a lease with negative expiration time.
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::3\",\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"iaid\": 1234,\n"
+ " \"expire\": -6218189367\n"
+ " }\n"
+ "}";
+ string exp_rsp = "expiration time must be positive for address 2001:db8:1::3";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Now check that the lease was not added.
+ Lease6Ptr l = lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::3"));
+ ASSERT_FALSE(l);
+}
+
+void Lease6CmdsTest::testLease6AddNegativeCltt() {
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Add a lease with negative cltt (expiration time - valid lifetime)
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::3\",\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"expire\": 123456,\n"
+ " \"iaid\": 1234,\n"
+ " \"valid-lft\": 123457"
+ " }\n"
+ "}";
+ string exp_rsp = "expiration time must be greater than valid lifetime for "
+ "address 2001:db8:1::3";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Now check that the lease was not added.
+ Lease6Ptr l = lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::3"));
+ ASSERT_FALSE(l);
+}
+
+void Lease6CmdsTest::testLease6AddPrefix() {
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:abcd::\",\n"
+ " \"prefix-len\": 48,\n"
+ " \"type\": \"IA_PD\",\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"iaid\": 1234\n"
+ " }\n"
+ "}";
+ string exp_rsp = "Lease for prefix 2001:db8:abcd::/48, subnet-id 66 added.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease6Stats(66, 0, 0, 1);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Now check that the lease is really there.
+ Lease6Ptr l = lmptr_->getLease6(Lease::TYPE_PD, IOAddress("2001:db8:abcd::"));
+ ASSERT_TRUE(l);
+ EXPECT_EQ(Lease::TYPE_PD, l->type_);
+ EXPECT_EQ(48, l->prefixlen_);
+ EXPECT_EQ("", l->hostname_);
+ EXPECT_FALSE(l->getContext());
+}
+
+void Lease6CmdsTest::testLease6AddFullAddr() {
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::3\",\n"
+ " \"duid\": \"01:02:03:04:05:06:07:08\",\n"
+ " \"iaid\": 1234,\n"
+ " \"hw-address\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"preferred-lft\": 500,\n"
+ " \"valid-lft\": 1000,\n"
+ " \"expire\": 6218189367,\n"
+ " \"fqdn-fwd\": true,\n"
+ " \"fqdn-rev\": true,\n"
+ " \"hostname\": \"urania.example.org\",\n"
+ " \"pool-id\": 5,\n"
+ " \"user-context\": { \"foobar\": true }\n"
+ " }\n"
+ "}";
+ string exp_rsp = "Lease for address 2001:db8:1::3, subnet-id 66 added.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease6Stats(66, 1, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Now check that the lease is really there.
+ Lease6Ptr l = lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::3"));
+ ASSERT_TRUE(l);
+ EXPECT_EQ(Lease::TYPE_NA, l->type_);
+ EXPECT_EQ("2001:db8:1::3", l->addr_.toText());
+ ASSERT_TRUE(l->hwaddr_);
+ EXPECT_EQ("1a:1b:1c:1d:1e:1f", l->hwaddr_->toText(false));
+ ASSERT_TRUE(l->duid_);
+ EXPECT_EQ("01:02:03:04:05:06:07:08", l->duid_->toText());
+ // expire (6218189367) - valid_lft(1000)
+ EXPECT_EQ(static_cast<time_t>(6218189367 - 1000), l->cltt_);
+ EXPECT_EQ(true, l->fqdn_fwd_);
+ EXPECT_EQ(true, l->fqdn_rev_);
+ EXPECT_EQ("urania.example.org", l->hostname_);
+ EXPECT_EQ(5, l->pool_id_);
+ ASSERT_TRUE(l->getContext());
+ EXPECT_EQ("{ \"foobar\": true }", l->getContext()->str());
+}
+
+void Lease6CmdsTest::testLease6AddComment() {
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::3\",\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"iaid\": 1234,\n"
+ " \"comment\": \"a comment\"\n"
+ " }\n"
+ "}";
+ string exp_rsp = "Lease for address 2001:db8:1::3, subnet-id 66 added.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease6Stats(66, 1, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Now check that the lease is really there.
+ Lease6Ptr l = lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::3"));
+ ASSERT_TRUE(l);
+
+ // Make sure the lease has proper value set.
+ ASSERT_TRUE(l->duid_);
+ EXPECT_EQ("1a:1b:1c:1d:1e:1f", l->duid_->toText());
+ ASSERT_TRUE(l->getContext());
+ EXPECT_EQ("{ \"comment\": \"a comment\" }", l->getContext()->str());
+}
+
+void Lease6CmdsTest::testLease6AddExtendedInfo() {
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ Lease6Collection leases;
+ vector<uint8_t> remote_id = { 1, 2, 3, 4, 5, 6 };
+ leases = lmptr_->getLeases6ByRemoteId(remote_id,
+ IOAddress::IPV6_ZERO_ADDRESS(),
+ 0,
+ IOAddress::IPV6_ZERO_ADDRESS(),
+ LeasePageSize(10));
+ EXPECT_TRUE(leases.empty());
+ vector<uint8_t> relay_bin(8, 0x64);
+ DuidPtr relay_id(new DUID(relay_bin));
+ leases = lmptr_->getLeases6ByRelayId(*relay_id,
+ IOAddress::IPV6_ZERO_ADDRESS(),
+ 0,
+ IOAddress::IPV6_ZERO_ADDRESS(),
+ LeasePageSize(10));
+ EXPECT_TRUE(leases.empty());
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::1\",\n"
+ " \"iaid\": 7654321,\n"
+ " \"duid\": \"88:88:88:88:88:88:88:88\",\n"
+ " \"hostname\": \"newhostname.example.org\",\n"
+ " \"user-context\": { \"ISC\": { \"relay-info\": [ {\n"
+ " \"remote-id\": \"010203040506\",\n"
+ " \"relay-id\": \"6464646464646464\" } ] } }\n"
+ " }\n"
+ "}";
+ string exp_rsp = "Lease for address 2001:db8:1::1, subnet-id 66 added.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease6Stats(66, 1, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Now check that the lease is really there.
+ Lease6Ptr l = lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1"));
+ ASSERT_TRUE(l);
+
+ // Make sure the lease has proper value set.
+ ASSERT_TRUE(l->duid_);
+ EXPECT_EQ("88:88:88:88:88:88:88:88", l->duid_->toText());
+ EXPECT_EQ("newhostname.example.org", l->hostname_);
+ EXPECT_EQ(7654321, l->iaid_);
+
+ // Check the user context / extended info too.
+ ConstElementPtr ctx = l->getContext();
+ ASSERT_TRUE(ctx);
+ string expected = "{ \"ISC\": { \"relay-info\": ";
+ expected += "[ { \"relay-id\": \"6464646464646464\", ";
+ expected += "\"remote-id\": \"010203040506\" } ] } }";
+ EXPECT_EQ(expected, ctx->str());
+
+ // Check that BLQ tables were updated.
+ leases = lmptr_->getLeases6ByRemoteId(remote_id,
+ IOAddress::IPV6_ZERO_ADDRESS(),
+ 0,
+ IOAddress::IPV6_ZERO_ADDRESS(),
+ LeasePageSize(10));
+ // The lease must be retrieved from the remote id table.
+ ASSERT_EQ(1, leases.size());
+ Lease6Ptr lx = leases[0];
+ ASSERT_TRUE(lx);
+ EXPECT_EQ(IOAddress("2001:db8:1::1"), lx->addr_);
+ EXPECT_EQ(*l, *lx);
+
+ // The lease must be retrieved from the relay id table.
+ leases = lmptr_->getLeases6ByRelayId(*relay_id,
+ IOAddress::IPV6_ZERO_ADDRESS(),
+ 0,
+ IOAddress::IPV6_ZERO_ADDRESS(),
+ LeasePageSize(10));
+ ASSERT_EQ(1, leases.size());
+ lx = leases[0];
+ ASSERT_TRUE(lx);
+ EXPECT_EQ(IOAddress("2001:db8:1::1"), lx->addr_);
+ EXPECT_EQ(*l, *lx);
+}
+
+void Lease6CmdsTest::testLease6GetMissingParams() {
+ // No parameters whatsoever. You want just a lease, any lease?
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-get\",\n"
+ " \"arguments\": {"
+ " }\n"
+ "}";
+ string exp_rsp = "Mandatory 'subnet-id' parameter missing.";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Just the subnet-id won't cut it, either.
+ cmd =
+ "{\n"
+ " \"command\": \"lease6-get\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 123"
+ " }\n"
+ "}";
+ exp_rsp = "No 'ip-address' provided and 'identifier-type' is either missing or not a string.";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // We can't identify your laptop by color. Sorry, buddy.
+ cmd =
+ "{\n"
+ " \"command\": \"lease6-get\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 123,\n"
+ " \"identifier-type\": \"color\",\n"
+ " \"identifier\": \"blue\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "Incorrect identifier type: color, the only supported values are: "
+ "address, hw-address, duid";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Query by hw-address is not supported in v6. Sorry.
+ cmd =
+ "{\n"
+ " \"command\": \"lease6-get\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 123,\n"
+ " \"identifier-type\": \"hw-address\",\n"
+ " \"identifier\": \"01:01:01:01:01:01\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "Query by hw-address is not allowed in v6.";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Identifier value is missing.
+ cmd =
+ "{\n"
+ " \"command\": \"lease6-get\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 123,\n"
+ " \"identifier-type\": \"duid\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "No 'ip-address' provided and 'identifier' is either missing or not a string.";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Identifier-type is missing.
+ cmd =
+ "{\n"
+ " \"command\": \"lease6-get\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 123,\n"
+ " \"identifier\": \"01:02:03:04:05\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "No 'ip-address' provided and 'identifier-type' is either missing or not a string.";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease6CmdsTest::testLease6GetByAddrBadParam() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ // Invalid family
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-get\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"192.0.2.1\""
+ " }\n"
+ "}";
+ string exp_rsp = "Invalid IPv6 address specified: 192.0.2.1";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // This is way off
+ cmd =
+ "{\n"
+ " \"command\": \"lease6-get\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"221B Baker St.\""
+ " }\n"
+ "}";
+ exp_rsp = "Failed to convert string to address '221B Baker St.': Invalid argument";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease6CmdsTest::testLease6GetByAddrNotFound() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ // Invalid
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-get\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 1,\n"
+ " \"ip-address\": \"2001:db8:1::10\"\n"
+ " }\n"
+ "}";
+ string exp_rsp = "Lease not found.";
+
+ // Note the status expected is empty. The query completed correctly,
+ // just didn't found the lease.
+ testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
+}
+
+void Lease6CmdsTest::testLease6GetByClientIdInvalidType() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ // client-id query is allowed in v4 only.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-get\",\n"
+ " \"arguments\": {"
+ " \"identifier-type\": \"client-id\","
+ " \"identifier\": \"01:02:03:04\","
+ " \"subnet-id\": 44"
+ " }\n"
+ "}";
+ string exp_rsp = "Query by client-id is not allowed in v6.";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease6CmdsTest::testLease6GetByDuidNotFound() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-get\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 1,\n"
+ " \"identifier-type\": \"duid\","
+ " \"identifier\": \"00:01:02:03:04:05:06:07\"\n"
+ " }\n"
+ "}";
+ string exp_rsp = "Lease not found.";
+
+ // Note the status expected is empty. The query completed correctly,
+ // just didn't found the lease.
+ testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
+}
+
+void Lease6CmdsTest::testLease6GetByAddr() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-get\",\n"
+ " \"arguments\": {\n"
+ " \"ip-address\": \"2001:db8:1::1\"\n"
+ " }\n"
+ "}";
+ string exp_rsp = "IPv6 lease found.";
+
+ // The status expected is success. The lease should be returned.
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ // Now check that the lease parameters were indeed returned.
+ ASSERT_TRUE(rsp);
+
+ ConstElementPtr lease = rsp->get("arguments");
+ ASSERT_TRUE(lease);
+
+ // Now check that the lease was indeed returned.
+ checkLease6(lease, "2001:db8:1::1", 0, 66, "42:42:42:42:42:42:42:42", false);
+}
+void Lease6CmdsTest::testLease6GetByAddrPrefix() {
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ // We need to get a prefix lease. We need to create it by hand.
+ // Let's start with regular address lease and make it a prefix lease.
+ Lease6Ptr l = createLease6("2001:db8:1::1", 66, 0x77);
+ l->addr_ = IOAddress("2001:db8:1234:ab::");
+ l->type_ = Lease::TYPE_PD;
+ l->prefixlen_ = 56;
+ lmptr_->addLease(l);
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-get\",\n"
+ " \"arguments\": {"
+ " \"type\": \"IA_PD\","
+ " \"ip-address\": \"2001:db8:1234:ab::\""
+ " }\n"
+ "}";
+ string exp_rsp = "IPv6 lease found.";
+
+ // The status expected is success. The lease should be returned.
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ // Now check that the lease parameters were indeed returned.
+ ASSERT_TRUE(rsp);
+
+ ConstElementPtr lease = rsp->get("arguments");
+ ASSERT_TRUE(lease);
+
+ // Now check that the lease was indeed returned.
+ checkLease6(lease, "2001:db8:1234:ab::", 56, 66, "77:77:77:77:77:77:77:77", false);
+}
+
+void Lease6CmdsTest::testLease6GetByDuid() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-get\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"iaid\": 42,"
+ " \"identifier-type\": \"duid\","
+ " \"identifier\": \"42:42:42:42:42:42:42:42\"\n"
+ " }\n"
+ "}";
+ string exp_rsp = "IPv6 lease found.";
+
+ // The status expected is success. The lease should be returned.
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ // Now check that the lease parameters were indeed returned.
+ ASSERT_TRUE(rsp);
+
+ ConstElementPtr lease = rsp->get("arguments");
+ ASSERT_TRUE(lease);
+
+ // Now check that the lease was indeed returned.
+ checkLease6(lease, "2001:db8:1::1", 0, 66, "42:42:42:42:42:42:42:42", false);
+}
+
+void Lease6CmdsTest::testLease6GetAll() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ // Query for all leases.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-get-all\"\n"
+ "}";
+ string exp_rsp = "4 IPv6 lease(s) found.";
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ // Now check that the lease parameters were indeed returned.
+ ASSERT_TRUE(rsp);
+
+ ConstElementPtr args = rsp->get("arguments");
+ ASSERT_TRUE(args);
+ ASSERT_EQ(Element::map, args->getType());
+
+ ConstElementPtr leases = args->get("leases");
+ ASSERT_TRUE(leases);
+ ASSERT_EQ(Element::list, leases->getType());
+
+ // Let's check if the response contains desired leases.
+ checkLease6(leases, "2001:db8:1::1", 0, 66, "42:42:42:42:42:42:42:42", false);
+ checkLease6(leases, "2001:db8:1::2", 0, 66, "56:56:56:56:56:56:56:56", false, 5);
+ checkLease6(leases, "2001:db8:2::1", 0, 99, "42:42:42:42:42:42:42:42", false);
+ checkLease6(leases, "2001:db8:2::2", 0, 99, "56:56:56:56:56:56:56:56", false);
+}
+
+void Lease6CmdsTest::testLease6GetAllNoLeases() {
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ // Query for all leases.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-get-all\"\n"
+ "}";
+ string exp_rsp = "0 IPv6 lease(s) found.";
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
+
+ // Now check that the lease parameters were indeed returned.
+ ASSERT_TRUE(rsp);
+
+ ConstElementPtr args = rsp->get("arguments");
+ ASSERT_TRUE(args);
+ ASSERT_EQ(Element::map, args->getType());
+
+ ConstElementPtr leases = args->get("leases");
+ ASSERT_TRUE(leases);
+ ASSERT_EQ(Element::list, leases->getType());
+
+ EXPECT_EQ(0, leases->size());
+}
+
+void Lease6CmdsTest::testLease6GetAllBySubnetId() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ // Query for leases from subnet 66. Subnet 127 will be ignored because
+ // it doesn't contain any leases.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-get-all\",\n"
+ " \"arguments\": {\n"
+ " \"subnets\": [ 66, 127 ]"
+ " }\n"
+ "}";
+ string exp_rsp = "2 IPv6 lease(s) found.";
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ // Now check that the lease parameters were indeed returned.
+ ASSERT_TRUE(rsp);
+
+ ConstElementPtr args = rsp->get("arguments");
+ ASSERT_TRUE(args);
+ ASSERT_EQ(Element::map, args->getType());
+
+ ConstElementPtr leases = args->get("leases");
+ ASSERT_TRUE(leases);
+ ASSERT_EQ(Element::list, leases->getType());
+
+ // Let's check if the response contains desired leases.
+ checkLease6(leases, "2001:db8:1::1", 0, 66, "42:42:42:42:42:42:42:42", false);
+ checkLease6(leases, "2001:db8:1::2", 0, 66, "56:56:56:56:56:56:56:56", false, 5);
+}
+
+void Lease6CmdsTest::testLease6GetAllBySubnetIdNoLeases() {
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ // Query for leases from subnet 66. Subnet 127 will be ignored because
+ // it doesn't contain any leases.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-get-all\",\n"
+ " \"arguments\": {\n"
+ " \"subnets\": [ 66, 127 ]"
+ " }\n"
+ "}";
+ string exp_rsp = "0 IPv6 lease(s) found.";
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
+
+ // Now check that the lease parameters were indeed returned.
+ ASSERT_TRUE(rsp);
+
+ ConstElementPtr args = rsp->get("arguments");
+ ASSERT_TRUE(args);
+ ASSERT_EQ(Element::map, args->getType());
+
+ ConstElementPtr leases = args->get("leases");
+ ASSERT_TRUE(leases);
+ ASSERT_EQ(Element::list, leases->getType());
+
+ EXPECT_EQ(0, leases->size());
+}
+
+void Lease6CmdsTest::testLease6GetAllByMultipleSubnetIds() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ // Query for leases from subnet 66 and 99.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-get-all\",\n"
+ " \"arguments\": {\n"
+ " \"subnets\": [ 66, 99 ]"
+ " }\n"
+ "}";
+ string exp_rsp = "4 IPv6 lease(s) found.";
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ // Now check that the lease parameters were indeed returned.
+ ASSERT_TRUE(rsp);
+
+ ConstElementPtr args = rsp->get("arguments");
+ ASSERT_TRUE(args);
+ ASSERT_EQ(Element::map, args->getType());
+
+ ConstElementPtr leases = args->get("leases");
+ ASSERT_TRUE(leases);
+ ASSERT_EQ(Element::list, leases->getType());
+
+ // Let's check if the response contains desired leases.
+ checkLease6(leases, "2001:db8:1::1", 0, 66, "42:42:42:42:42:42:42:42", false);
+ checkLease6(leases, "2001:db8:1::2", 0, 66, "56:56:56:56:56:56:56:56", false, 5);
+ checkLease6(leases, "2001:db8:2::1", 0, 99, "42:42:42:42:42:42:42:42", false);
+ checkLease6(leases, "2001:db8:2::2", 0, 99, "56:56:56:56:56:56:56:56", false);
+}
+
+void Lease6CmdsTest::testLease6GetBySubnetIdInvalidArguments() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ // Subnets not specified in arguments.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-get-all\",\n"
+ " \"arguments\": {"
+ " \"foo\": 1\n"
+ " }\n"
+ "}";
+ string exp_rsp = "'subnets' parameter not specified";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Subnets are not a list.
+ cmd =
+ "{\n"
+ " \"command\": \"lease6-get-all\",\n"
+ " \"arguments\": {"
+ " \"subnets\": 1\n"
+ " }\n"
+ "}";
+ exp_rsp = "'subnets' parameter must be a list";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Subnets list must contain numbers.
+ cmd =
+ "{\n"
+ " \"command\": \"lease6-get-all\",\n"
+ " \"arguments\": {"
+ " \"subnets\": [ \"x\", \"y\" ]\n"
+ " }\n"
+ "}";
+ exp_rsp = "listed subnet identifiers must be numbers";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease6CmdsTest::testLease6GetPaged() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ // Gather all returned addresses to verify that all were returned.
+ std::set<std::string> lease_addresses;
+
+ // Keyword start indicates that we want to retrieve the first page.
+ std::string last_address = "start";
+
+ // There are 4 leases in the database, so the first two pages should
+ // include leases and the 3 page should be empty.
+ for (auto i = 0; i < 3; ++i) {
+ // Query for a page of leases.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-get-page\",\n"
+ " \"arguments\": {"
+ " \"from\": \"" + last_address + "\","
+ " \"limit\": 2"
+ " }"
+ "}";
+
+ // For the first two pages we should get success. For the last
+ // one an empty status code.
+ ConstElementPtr rsp;
+ if (i < 2) {
+ string exp_rsp = "2 IPv6 lease(s) found.";
+ rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ } else {
+ string exp_rsp = "0 IPv6 lease(s) found.";
+ rsp = testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
+
+ }
+
+ // Now check that the lease parameters were indeed returned.
+ ASSERT_TRUE(rsp);
+
+ // Arguments must exist.
+ ConstElementPtr args = rsp->get("arguments");
+ ASSERT_TRUE(args);
+ ASSERT_EQ(Element::map, args->getType());
+
+ // For convenience, we return the number of returned leases,
+ // so as the client can check whether there was anything returned
+ // before parsing the leases structure.
+ ConstElementPtr page_count = args->get("count");
+ ASSERT_TRUE(page_count);
+ ASSERT_EQ(Element::integer, page_count->getType());
+
+ // leases must exist, but may be empty.
+ ConstElementPtr leases = args->get("leases");
+ ASSERT_TRUE(leases);
+ ASSERT_EQ(Element::list, leases->getType());
+
+ if (!leases->empty()) {
+ EXPECT_EQ(2, page_count->intValue());
+
+ // Go over each lease and verify its correctness.
+ for (ConstElementPtr lease : leases->listValue()) {
+ ASSERT_EQ(Element::map, lease->getType());
+ ASSERT_TRUE(lease->contains("ip-address"));
+ ConstElementPtr ip_address = lease->get("ip-address");
+ ASSERT_EQ(Element::string, ip_address->getType());
+ last_address = ip_address->stringValue();
+
+ lease_addresses.insert(last_address);
+
+ // The easiest way to retrieve the subnet id and HW address is to
+ // ask the Lease Manager.
+ Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
+ IOAddress(last_address));
+ ASSERT_TRUE(from_mgr);
+ uint32_t pool_id = 0;
+ if (last_address == "2001:db8:1::2") {
+ pool_id = 5;
+ }
+ checkLease6(leases, last_address, 0, from_mgr->subnet_id_,
+ from_mgr->duid_->toText(), false, pool_id);
+ }
+
+ } else {
+ // In the third iteration the page should be empty.
+ EXPECT_EQ(0, page_count->intValue());
+ }
+ }
+
+ // Check if all addresses were returned.
+ EXPECT_EQ(1, lease_addresses.count("2001:db8:1::1"));
+ EXPECT_EQ(1, lease_addresses.count("2001:db8:1::2"));
+ EXPECT_EQ(1, lease_addresses.count("2001:db8:2::1"));
+ EXPECT_EQ(1, lease_addresses.count("2001:db8:2::2"));
+}
+
+void Lease6CmdsTest::testLease6GetPagedZeroAddress() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ // Query for a page of leases.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-get-page\",\n"
+ " \"arguments\": {"
+ " \"from\": \"::\","
+ " \"limit\": 2"
+ " }"
+ "}";
+
+ string exp_rsp = "2 IPv6 lease(s) found.";
+ testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+}
+
+void Lease6CmdsTest::testLease6GetPagedIPv4Address() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ // Query for a page of leases.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-get-page\",\n"
+ " \"arguments\": {"
+ " \"from\": \"192.0.2.3\","
+ " \"limit\": 2"
+ " }"
+ "}";
+
+ string exp_rsp = "'from' parameter value 192.0.2.3 is not an IPv6 address";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease6CmdsTest::testLease6GetPagedInvalidFrom() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ // Query for a page of leases.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-get-page\",\n"
+ " \"arguments\": {"
+ " \"from\": \"foo\","
+ " \"limit\": 2"
+ " }"
+ "}";
+
+ string exp_rsp = "'from' parameter value is neither 'start' keyword "
+ "nor a valid IPv6 address";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease6CmdsTest::testLease6GetPagedNoLimit() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ // Query for a page of leases.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-get-page\",\n"
+ " \"arguments\": {"
+ " \"from\": \"start\""
+ " }"
+ "}";
+
+ string exp_rsp = "'limit' parameter not specified";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease6CmdsTest::testLease6GetPagedLimitNotNumber() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ // Query for a page of leases.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-get-page\",\n"
+ " \"arguments\": {"
+ " \"from\": \"start\","
+ " \"limit\": false"
+ " }"
+ "}";
+
+ string exp_rsp = "'limit' parameter must be a number";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease6CmdsTest::testLease6GetPagedLimitIsZero() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ // Query for a page of leases.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-get-page\",\n"
+ " \"arguments\": {"
+ " \"from\": \"start\","
+ " \"limit\": 0"
+ " }"
+ "}";
+
+ string exp_rsp = "page size of retrieved leases must not be 0";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease6CmdsTest::testLease6GetByDuidParams() {
+ // No parameters whatsoever.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-get-by-duid\",\n"
+ " \"arguments\": {"
+ " }\n"
+ "}";
+ string exp_rsp = "'duid' parameter not specified";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // duid must be a string.
+ cmd =
+ "{\n"
+ " \"command\": \"lease6-get-by-duid\",\n"
+ " \"arguments\": {"
+ " \"duid\": 1234\n"
+ " }\n"
+ "}";
+ exp_rsp = "'duid' parameter must be a string";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Simply bad value.
+ cmd =
+ "{\n"
+ " \"command\": \"lease6-get-by-duid\",\n"
+ " \"arguments\": {"
+ " \"duid\": \"00::01:00:bc:0d:67\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "two consecutive separators (':') specified in a decoded string";
+ exp_rsp += " '00::01:00:bc:0d:67'";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease6CmdsTest::testLease6GetByDuidFind0() {
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ // No such lease.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-get-by-duid\",\n"
+ " \"arguments\": {"
+ " \"duid\": \"00:01:02:03:04:05:06:07\"\n"
+ " }\n"
+ "}";
+ string exp_rsp = "0 IPv6 lease(s) found.";
+ testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
+}
+
+void Lease6CmdsTest::testLease6GetByDuidFind2() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ // Get the lease.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-get-by-duid\",\n"
+ " \"arguments\": {"
+ " \"duid\": \"42:42:42:42:42:42:42:42\"\n"
+ " }\n"
+ "}";
+ string exp_rsp = "2 IPv6 lease(s) found.";
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ // Now check that the lease parameters were indeed returned.
+ ASSERT_TRUE(rsp);
+ ConstElementPtr map = rsp->get("arguments");
+ ASSERT_TRUE(map);
+ ASSERT_EQ(Element::map, map->getType());
+ ConstElementPtr leases = map->get("leases");
+ ASSERT_TRUE(leases);
+ ASSERT_EQ(Element::list, leases->getType());
+ ASSERT_EQ(2, leases->size());
+
+ // Let's check if the response makes any sense.
+ ConstElementPtr lease = leases->get(0);
+ ASSERT_TRUE(lease);
+ checkLease6(lease, "2001:db8:1::1", 0, 66, "42:42:42:42:42:42:42:42", false);
+ lease = leases->get(1);
+ ASSERT_TRUE(lease);
+ checkLease6(lease, "2001:db8:2::1", 0, 99, "42:42:42:42:42:42:42:42", false);
+}
+
+void Lease6CmdsTest::testLease6GetByHostnameParams() {
+ // No parameters whatsoever.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-get-by-hostname\",\n"
+ " \"arguments\": {"
+ " }\n"
+ "}";
+ string exp_rsp = "'hostname' parameter not specified";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // hostname must be a string.
+ cmd =
+ "{\n"
+ " \"command\": \"lease6-get-by-hostname\",\n"
+ " \"arguments\": {"
+ " \"hostname\": 1234\n"
+ " }\n"
+ "}";
+ exp_rsp = "'hostname' parameter must be a string";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // hostname must be not empty.
+ cmd =
+ "{\n"
+ " \"command\": \"lease6-get-by-hostname\",\n"
+ " \"arguments\": {"
+ " \"hostname\": \"\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "'hostname' parameter is empty";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease6CmdsTest::testLease6GetByHostnameFind0() {
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ // No such lease.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-get-by-hostname\",\n"
+ " \"arguments\": {"
+ " \"hostname\": \"foo.bar\"\n"
+ " }\n"
+ "}";
+ string exp_rsp = "0 IPv6 lease(s) found.";
+ testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
+}
+
+void Lease6CmdsTest::testLease6GetByHostnameFind2() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ // Get the lease.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-get-by-hostname\",\n"
+ " \"arguments\": {"
+ " \"hostname\": \"Myhost.Example.Com.\"\n"
+ " }\n"
+ "}";
+ string exp_rsp = "4 IPv6 lease(s) found.";
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ // Now check that the lease parameters were indeed returned.
+ ASSERT_TRUE(rsp);
+ ConstElementPtr map = rsp->get("arguments");
+ ASSERT_TRUE(map);
+ ASSERT_EQ(Element::map, map->getType());
+ ConstElementPtr leases = map->get("leases");
+ ASSERT_TRUE(leases);
+ ASSERT_EQ(Element::list, leases->getType());
+ ASSERT_EQ(4, leases->size());
+
+ // Let's check if the response makes any sense.
+ ConstElementPtr lease = leases->get(0);
+ ASSERT_TRUE(lease);
+ checkLease6(lease, "2001:db8:1::1", 0, 66, "42:42:42:42:42:42:42:42", false);
+ lease = leases->get(2);
+ ASSERT_TRUE(lease);
+ checkLease6(lease, "2001:db8:2::1", 0, 99, "42:42:42:42:42:42:42:42", false);
+}
+
+void Lease6CmdsTest::testLease6UpdateMissingParams() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ // Everything missing. What sort of nonsense is that?
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-update\",\n"
+ " \"arguments\": {"
+ " }\n"
+ "}";
+ string exp_rsp = "missing parameter 'ip-address' (<string>:3:19)";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Just ip is not enough (subnet-id and duid missing, although
+ // Kea should be able to figure out the subnet-id on its own.
+ txt =
+ "{\n"
+ " \"command\": \"lease6-update\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"2001:db8:1::1\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "missing parameter 'duid' (<string>:3:19)";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Better, but still no luck. (duid missing).
+ txt =
+ "{\n"
+ " \"command\": \"lease6-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::1\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "missing parameter 'duid' (<string>:3:19)";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // ip-address and identifier-type missing.
+ txt =
+ "{\n"
+ " \"command\": \"lease6-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "missing parameter 'ip-address' (<string>:3:19)";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Just subnet-id, duid and iaid is not enough (ip missing).
+ txt =
+ "{\n"
+ " \"command\": \"lease6-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"iaid\": 1234\n"
+ " }\n"
+ "}";
+ exp_rsp = "missing parameter 'ip-address' (<string>:3:19)";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Close, but no cigars. Still missing iaid.
+ txt =
+ "{\n"
+ " \"command\": \"lease6-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"ip-address\": \"2001:db8:1::1\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "missing parameter 'iaid' (<string>:3:19)";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease6CmdsTest::testLease6UpdateBadParams() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ // All params are there, but there's no subnet-id 123 configured.
+ // (initLeaseMgr initialized subnet-id 44 for v4 and subnet-id 66 for v6).
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 123,\n"
+ " \"ip-address\": \"2001:db8:1::1\",\n"
+ " \"duid\": \"88:88:88:88:88:88:88:88\"\n"
+ " }\n"
+ "}";
+ string exp_rsp = "Invalid subnet-id: No IPv6 subnet with subnet-id=123 currently configured.";
+ testCommand(txt, CONTROL_RESULT_CONFLICT, exp_rsp);
+
+ // This time the new IP address does not belong to the subnet.
+ txt =
+ "{\n"
+ " \"command\": \"lease6-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"3000::1\",\n"
+ " \"duid\": \"88:88:88:88:88:88:88:88\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "The address 3000::1 does not belong to subnet 2001:db8:1::/48, subnet-id=66";
+ testCommand(txt, CONTROL_RESULT_CONFLICT, exp_rsp);
+
+ // v4? You're a time traveler from early 80s or what?
+ txt =
+ "{\n"
+ " \"command\": \"lease6-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"192.0.2.1\",\n"
+ " \"duid\": \"88:88:88:88:88:88:88:88\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "Non-IPv6 address specified: 192.0.2.1";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Bad user context: not a map.
+ txt =
+ "{\n"
+ " \"command\": \"lease6-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::1\",\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"iaid\": 1234\n,"
+ " \"user-context\": \"bad value\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "Invalid user context '\"bad value\"' is not a JSON map.";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Duplicated comment.
+ txt =
+ "{\n"
+ " \"command\": \"lease6-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::1\",\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"iaid\": 1234\n,"
+ " \"user-context\": { \"comment\": \"in user context\" },\n"
+ " \"comment\": \"direct\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "Duplicated comment entry '\"direct\"' in user context "
+ "'{ \"comment\": \"in user context\" }'";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Invalid declined state (1) for PD prefix.
+ txt =
+ "{\n"
+ " \"command\": \"lease6-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::\",\n"
+ " \"prefix-len\": 48,\n"
+ " \"type\": \"IA_PD\",\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"iaid\": 1234,\n"
+ " \"state\": 1"
+ " }\n"
+ "}";
+ exp_rsp = "Invalid declined state for PD prefix.";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Invalid prefix len for PD prefix.
+ txt =
+ "{\n"
+ " \"command\": \"lease6-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::1\",\n"
+ " \"prefix-len\": 48,\n"
+ " \"type\": \"IA_PD\",\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"iaid\": 1234\n"
+ " }\n"
+ "}";
+ exp_rsp = "Prefix address: 2001:db8:1::1 exceeds prefix/prefix-len pair: 2001:db8:1::/48";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease6CmdsTest::testLease6UpdateNoLease() {
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::1\",\n"
+ " \"iaid\": 7654321,\n"
+ " \"duid\": \"88:88:88:88:88:88:88:88\",\n"
+ " \"hostname\": \"newhostname.example.org\""
+ " }\n"
+ "}";
+ string exp_rsp = "failed to update the lease with address 2001:db8:1::1 "
+ "either because the lease has been deleted or it has changed in the "
+ "database, in both cases a retry might succeed";
+ testCommand(txt, CONTROL_RESULT_CONFLICT, exp_rsp);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+}
+
+void Lease6CmdsTest::testLease6Update() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::1\",\n"
+ " \"iaid\": 7654321,\n"
+ " \"duid\": \"88:88:88:88:88:88:88:88\",\n"
+ " \"pool-id\": 3,\n"
+ " \"hostname\": \"newhostname.example.org\""
+ " }\n"
+ "}";
+ string exp_rsp = "IPv6 lease updated.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ // Now check that the lease is really there.
+ Lease6Ptr l = lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1"));
+ ASSERT_TRUE(l);
+
+ // Make sure the lease has been updated.
+ ASSERT_TRUE(l->duid_);
+ EXPECT_EQ("88:88:88:88:88:88:88:88", l->duid_->toText());
+ EXPECT_EQ(3, l->pool_id_);
+ EXPECT_EQ("newhostname.example.org", l->hostname_);
+ EXPECT_EQ(7654321, l->iaid_);
+ EXPECT_FALSE(l->getContext());
+}
+
+void Lease6CmdsTest::testLease6UpdateDeclinedLeases() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true, true);
+
+ checkLease6Stats(66, 2, 2, 0);
+
+ checkLease6Stats(99, 2, 2, 0);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::1\",\n"
+ " \"iaid\": 7654321,\n"
+ " \"duid\": \"88:88:88:88:88:88:88:88\",\n"
+ " \"pool-id\": 3,\n"
+ " \"hostname\": \"newhostname.example.org\""
+ " }\n"
+ "}";
+ string exp_rsp = "IPv6 lease updated.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease6Stats(66, 2, 1, 0);
+
+ checkLease6Stats(99, 2, 2, 0);
+
+ // Now check that the lease is still there.
+ Lease6Ptr l = lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1"));
+ ASSERT_TRUE(l);
+
+ // Make sure the lease has been updated.
+ ASSERT_TRUE(l->duid_);
+ EXPECT_EQ("88:88:88:88:88:88:88:88", l->duid_->toText());
+ EXPECT_EQ(3, l->pool_id_);
+ EXPECT_EQ("newhostname.example.org", l->hostname_);
+ EXPECT_EQ(7654321, l->iaid_);
+ EXPECT_FALSE(l->getContext());
+}
+
+void Lease6CmdsTest::testLease6UpdateNoSubnetId() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-update\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"2001:db8:1::1\",\n"
+ " \"iaid\": 7654321,\n"
+ " \"duid\": \"88:88:88:88:88:88:88:88\",\n"
+ " \"hostname\": \"newhostname.example.org\""
+ " }\n"
+ "}";
+ string exp_rsp = "IPv6 lease updated.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ // Now check that the lease is still there.
+ Lease6Ptr l = lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1"));
+ ASSERT_TRUE(l);
+
+ // Make sure the subnet-id is correct.
+ EXPECT_EQ(66, l->subnet_id_);
+
+ // Make sure the lease has been updated.
+ ASSERT_TRUE(l->duid_);
+ EXPECT_EQ("88:88:88:88:88:88:88:88", l->duid_->toText());
+ EXPECT_EQ("newhostname.example.org", l->hostname_);
+ EXPECT_EQ(7654321, l->iaid_);
+ EXPECT_FALSE(l->getContext());
+}
+
+void Lease6CmdsTest::testLease6UpdateNoSubnetIdDeclinedLeases() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true, true);
+
+ checkLease6Stats(66, 2, 2, 0);
+
+ checkLease6Stats(99, 2, 2, 0);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-update\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"2001:db8:1::1\",\n"
+ " \"iaid\": 7654321,\n"
+ " \"duid\": \"88:88:88:88:88:88:88:88\",\n"
+ " \"hostname\": \"newhostname.example.org\""
+ " }\n"
+ "}";
+ string exp_rsp = "IPv6 lease updated.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease6Stats(66, 2, 1, 0);
+
+ checkLease6Stats(99, 2, 2, 0);
+
+ // Now check that the lease is really there.
+ Lease6Ptr l = lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1"));
+ ASSERT_TRUE(l);
+
+ // Make sure the subnet-id is correct.
+ EXPECT_EQ(66, l->subnet_id_);
+
+ // Make sure the lease has been updated.
+ ASSERT_TRUE(l->duid_);
+ EXPECT_EQ("88:88:88:88:88:88:88:88", l->duid_->toText());
+ EXPECT_EQ("newhostname.example.org", l->hostname_);
+ EXPECT_EQ(7654321, l->iaid_);
+ EXPECT_FALSE(l->getContext());
+}
+
+void Lease6CmdsTest::testLease6UpdateForceCreate() {
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::1\",\n"
+ " \"iaid\": 7654321,\n"
+ " \"duid\": \"88:88:88:88:88:88:88:88\",\n"
+ " \"hostname\": \"newhostname.example.org\","
+ " \"force-create\": true"
+ " }\n"
+ "}";
+ string exp_rsp = "IPv6 lease added.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease6Stats(66, 1, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Now check that the lease is really there.
+ Lease6Ptr l = lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1"));
+ ASSERT_TRUE(l);
+
+ // Make sure the lease is correct.
+ ASSERT_TRUE(l->duid_);
+ EXPECT_EQ("88:88:88:88:88:88:88:88", l->duid_->toText());
+ EXPECT_EQ("newhostname.example.org", l->hostname_);
+ EXPECT_EQ(7654321, l->iaid_);
+ EXPECT_FALSE(l->getContext());
+}
+
+void Lease6CmdsTest::testLease6UpdateForceCreateNoSubnetId() {
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-update\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"2001:db8:1::1\",\n"
+ " \"iaid\": 7654321,\n"
+ " \"duid\": \"88:88:88:88:88:88:88:88\",\n"
+ " \"hostname\": \"newhostname.example.org\","
+ " \"force-create\": true"
+ " }\n"
+ "}";
+ string exp_rsp = "IPv6 lease added.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease6Stats(66, 1, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Now check that the lease is really there.
+ Lease6Ptr l = lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1"));
+ ASSERT_TRUE(l);
+
+ // Make sure the subnet-id is figured out correctly.
+ EXPECT_EQ(66, l->subnet_id_);
+
+ // Make sure the lease is correct.
+ ASSERT_TRUE(l->duid_);
+ EXPECT_EQ("88:88:88:88:88:88:88:88", l->duid_->toText());
+ EXPECT_EQ("newhostname.example.org", l->hostname_);
+ EXPECT_EQ(7654321, l->iaid_);
+ EXPECT_FALSE(l->getContext());
+}
+
+void Lease6CmdsTest::testLease6UpdateDoNotForceCreate() {
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::1\",\n"
+ " \"iaid\": 7654321,\n"
+ " \"duid\": \"88:88:88:88:88:88:88:88\",\n"
+ " \"hostname\": \"newhostname.example.org\","
+ " \"force-create\": false"
+ " }\n"
+ "}";
+ string exp_rsp = "failed to update the lease with address 2001:db8:1::1 "
+ "either because the lease has been deleted or it has changed in the "
+ "database, in both cases a retry might succeed";
+ testCommand(txt, CONTROL_RESULT_CONFLICT, exp_rsp);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+}
+
+void Lease6CmdsTest::testLease6UpdateComment() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::1\",\n"
+ " \"iaid\": 42,\n"
+ " \"duid\": \"42:42:42:42:42:42:42:42\",\n"
+ " \"comment\": \"a comment\",\n"
+ " \"user-context\": { \"foobar\": true }\n"
+ " }\n"
+ "}";
+ string exp_rsp = "IPv6 lease updated.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ // Now check that the lease is really there.
+ Lease6Ptr l = lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1"));
+ ASSERT_TRUE(l);
+
+ // Make sure the lease has been updated.
+ ASSERT_TRUE(l->duid_);
+ EXPECT_EQ("42:42:42:42:42:42:42:42", l->duid_->toText());
+
+ // Check user context.
+ ConstElementPtr ctx = l->getContext();
+ ASSERT_TRUE(ctx);
+ EXPECT_EQ(2, ctx->size());
+ ASSERT_TRUE(ctx->contains("comment"));
+ EXPECT_EQ("\"a comment\"", ctx->get("comment")->str());
+ ASSERT_TRUE(ctx->contains("foobar"));
+ EXPECT_EQ("true", ctx->get("foobar")->str());
+}
+
+void Lease6CmdsTest::testLease6UpdateExtendedInfo() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ Lease6Collection leases;
+ vector<uint8_t> remote_id = { 1, 2, 3, 4, 5, 6 };
+ leases = lmptr_->getLeases6ByRemoteId(remote_id,
+ IOAddress::IPV6_ZERO_ADDRESS(),
+ 0,
+ IOAddress::IPV6_ZERO_ADDRESS(),
+ LeasePageSize(10));
+ EXPECT_TRUE(leases.empty());
+ vector<uint8_t> relay_bin(8, 0x64);
+ DuidPtr relay_id(new DUID(relay_bin));
+ leases = lmptr_->getLeases6ByRelayId(*relay_id,
+ IOAddress::IPV6_ZERO_ADDRESS(),
+ 0,
+ IOAddress::IPV6_ZERO_ADDRESS(),
+ LeasePageSize(10));
+ EXPECT_TRUE(leases.empty());
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::1\",\n"
+ " \"iaid\": 7654321,\n"
+ " \"duid\": \"88:88:88:88:88:88:88:88\",\n"
+ " \"hostname\": \"newhostname.example.org\",\n"
+ " \"user-context\": { \"ISC\": { \"relay-info\": [ {\n"
+ " \"remote-id\": \"010203040506\",\n"
+ " \"relay-id\": \"6464646464646464\" } ] } }\n"
+ " }\n"
+ "}";
+ string exp_rsp = "IPv6 lease updated.";
+ testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ // Now check that the lease is really there.
+ Lease6Ptr l = lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1"));
+ ASSERT_TRUE(l);
+
+ // Make sure the lease has been updated.
+ ASSERT_TRUE(l->duid_);
+ EXPECT_EQ("88:88:88:88:88:88:88:88", l->duid_->toText());
+ EXPECT_EQ("newhostname.example.org", l->hostname_);
+ EXPECT_EQ(7654321, l->iaid_);
+
+ // Check the user context / extended info too.
+ ConstElementPtr ctx = l->getContext();
+ ASSERT_TRUE(ctx);
+ string expected = "{ \"ISC\": { \"relay-info\": ";
+ expected += "[ { \"relay-id\": \"6464646464646464\", ";
+ expected += "\"remote-id\": \"010203040506\" } ] } }";
+ EXPECT_EQ(expected, ctx->str());
+
+ // Check that BLQ tables were updated.
+ leases = lmptr_->getLeases6ByRemoteId(remote_id,
+ IOAddress::IPV6_ZERO_ADDRESS(),
+ 0,
+ IOAddress::IPV6_ZERO_ADDRESS(),
+ LeasePageSize(10));
+ // The lease must be retrieved from the remote id table.
+ ASSERT_EQ(1, leases.size());
+ Lease6Ptr lx = leases[0];
+ ASSERT_TRUE(lx);
+ EXPECT_EQ(IOAddress("2001:db8:1::1"), lx->addr_);
+ EXPECT_EQ(*l, *lx);
+
+ // The lease must be retrieved from the relay id table.
+ leases = lmptr_->getLeases6ByRelayId(*relay_id,
+ IOAddress::IPV6_ZERO_ADDRESS(),
+ 0,
+ IOAddress::IPV6_ZERO_ADDRESS(),
+ LeasePageSize(10));
+ ASSERT_EQ(1, leases.size());
+ lx = leases[0];
+ ASSERT_TRUE(lx);
+ EXPECT_EQ(IOAddress("2001:db8:1::1"), lx->addr_);
+ EXPECT_EQ(*l, *lx);
+}
+
+void Lease6CmdsTest::testLease6DelMissingParams() {
+ // No parameters whatsoever. You want just a lease, any lease?
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-del\",\n"
+ " \"arguments\": {"
+ " }\n"
+ "}";
+ string exp_rsp = "Mandatory 'subnet-id' parameter missing.";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Just the subnet-id won't cut it, either.
+ cmd =
+ "{\n"
+ " \"command\": \"lease6-del\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 123"
+ " }\n"
+ "}";
+ exp_rsp = "No 'ip-address' provided and 'identifier-type' is either missing or not a string.";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // We can't identify your laptop by color. Sorry, buddy.
+ cmd =
+ "{\n"
+ " \"command\": \"lease6-del\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 123,\n"
+ " \"identifier-type\": \"color\",\n"
+ " \"identifier\": \"blue\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "Incorrect identifier type: color, the only supported values are: "
+ "address, hw-address, duid";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Query by hw-address is not supported in v6. Sorry.
+ cmd =
+ "{\n"
+ " \"command\": \"lease6-del\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 123,\n"
+ " \"identifier-type\": \"hw-address\",\n"
+ " \"identifier\": \"01:01:01:01:01:01\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "Delete by hw-address is not allowed in v6.";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Identifier value is missing.
+ cmd =
+ "{\n"
+ " \"command\": \"lease6-del\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 123,\n"
+ " \"identifier-type\": \"hw-address\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "No 'ip-address' provided and 'identifier' is either missing or not a string.";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Identifier-type is missing.
+ cmd =
+ "{\n"
+ " \"command\": \"lease6-del\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 123,\n"
+ " \"identifier\": \"01:02:03:04:05\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "No 'ip-address' provided and 'identifier-type' is either missing or not a string.";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease6CmdsTest::testLease6DelByAddrNotFound() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-del\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 1,\n"
+ " \"ip-address\": \"2001:db8:1::10\"\n"
+ " }\n"
+ "}";
+ string exp_rsp = "IPv6 lease not found.";
+
+ // Note the status expected is empty. The query completed correctly,
+ // just didn't found the lease.
+ testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+}
+
+void Lease6CmdsTest::testLease6DelByDuidNotFound() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-del\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 1,\n"
+ " \"identifier-type\": \"duid\","
+ " \"identifier\": \"00:01:02:03:04:05:06:07\"\n"
+ " }\n"
+ "}";
+ string exp_rsp = "IPv6 lease not found.";
+
+ // Note the status expected is empty. The query completed correctly,
+ // just didn't found the lease.
+ testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ // Make sure the lease is still there.
+ EXPECT_TRUE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1")));
+}
+
+void Lease6CmdsTest::testLease6DelByAddr() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-del\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::1\""
+ " }\n"
+ "}";
+ string exp_rsp = "IPv6 lease deleted.";
+
+ // The status expected is success. The lease should be deleted.
+ testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease6Stats(66, 1, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ // Make sure the lease is really gone.
+ EXPECT_FALSE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1")));
+}
+
+void Lease6CmdsTest::testLease6DelByAddrDeclinedLeases() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true, true);
+
+ checkLease6Stats(66, 2, 2, 0);
+
+ checkLease6Stats(99, 2, 2, 0);
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-del\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::1\""
+ " }\n"
+ "}";
+ string exp_rsp = "IPv6 lease deleted.";
+
+ // The status expected is success. The lease should be deleted.
+ testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease6Stats(66, 1, 1, 0);
+
+ checkLease6Stats(99, 2, 2, 0);
+
+ // Make sure the lease is really gone.
+ EXPECT_FALSE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1")));
+}
+
+void Lease6CmdsTest::testLease6DelByAddrBadParam() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ // Invalid family
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-del\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"192.0.2.1\""
+ " }\n"
+ "}";
+ string exp_rsp = "Invalid IPv6 address specified: 192.0.2.1";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ // This is way off
+ cmd =
+ "{\n"
+ " \"command\": \"lease6-del\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"221B Baker St.\""
+ " }\n"
+ "}";
+ exp_rsp = "Failed to convert string to address '221B Baker St.': Invalid argument";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease6CmdsTest::testLease6DelByAddrPrefix() {
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Let's start with regular address lease and make it a prefix lease.
+ Lease6Ptr l = createLease6("2001:db8:1::1", 66, 0x77);
+ l->addr_ = IOAddress("2001:db8:1234:ab::");
+ l->type_ = Lease::TYPE_PD;
+ l->prefixlen_ = 56;
+ lmptr_->addLease(l);
+
+ StatsMgr::instance().setValue(StatsMgr::generateName("subnet", 66,
+ "assigned-pds" ),
+ int64_t(1));
+
+ checkLease6Stats(66, 0, 0, 1);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-del\",\n"
+ " \"arguments\": {"
+ " \"type\": \"IA_PD\","
+ " \"ip-address\": \"2001:db8:1234:ab::\""
+ " }\n"
+ "}";
+ string exp_rsp = "IPv6 lease deleted.";
+
+ // The status expected is success. The lease should be deleted.
+ testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Make sure the lease is really gone.
+ EXPECT_FALSE(lmptr_->getLease6(Lease::TYPE_PD, IOAddress("2001:db8:1234:ab::")));
+}
+
+void Lease6CmdsTest::testLease6DelByDuid() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-del\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"iaid\": 42,"
+ " \"identifier-type\": \"duid\","
+ " \"identifier\": \"42:42:42:42:42:42:42:42\"\n"
+ " }\n"
+ "}";
+ string exp_rsp = "IPv6 lease deleted.";
+
+ // The status expected is success. The lease should be deleted.
+ testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease6Stats(66, 1, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ // Make sure the lease is really gone.
+ EXPECT_FALSE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1")));
+}
+
+void Lease6CmdsTest::testLease6Wipe() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-wipe\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66\n"
+ " }\n"
+ "}";
+ string exp_rsp = "Deleted 2 IPv6 lease(s) from subnet(s) 66";
+
+ // The status expected is success. The lease should be deleted.
+ testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ // Make sure the leases in subnet 66 are really gone.
+ EXPECT_FALSE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1")));
+ EXPECT_FALSE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::2")));
+
+ // Make sure the leases from subnet 99 are still there.
+ EXPECT_TRUE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:2::1")));
+ EXPECT_TRUE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:2::2")));
+}
+
+void Lease6CmdsTest::testLease6WipeAll() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-wipe\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 0\n"
+ " }\n"
+ "}";
+ string exp_rsp = "Deleted 4 IPv6 lease(s) from subnet(s) 66 99";
+
+ // The status expected is success. The lease should be deleted.
+ testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Make sure the leases in subnet 66 are really gone.
+ EXPECT_FALSE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1")));
+ EXPECT_FALSE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::2")));
+
+ // Make sure the leases from subnet 99 are gone, too.
+ EXPECT_FALSE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:2::1")));
+ EXPECT_FALSE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:2::2")));
+}
+
+void Lease6CmdsTest::testLease6WipeAllNoArgs() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-wipe\"\n"
+ "}";
+ string exp_rsp = "Deleted 4 IPv6 lease(s) from subnet(s) 66 99";
+
+ // The status expected is success. The lease should be deleted.
+ testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Make sure the leases in subnet 66 are really gone.
+ EXPECT_FALSE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1")));
+ EXPECT_FALSE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::2")));
+
+ // Make sure the leases from subnet 99 are gone, too.
+ EXPECT_FALSE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:2::1")));
+ EXPECT_FALSE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:2::2")));
+}
+
+void Lease6CmdsTest::testLease6WipeNoLeases() {
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Query for valid, existing lease.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-wipe\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66"
+ " }\n"
+ "}";
+ string exp_rsp = "Deleted 0 IPv6 lease(s) from subnet(s) 66";
+ testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+}
+
+void Lease6CmdsTest::testLease6WipeNoLeasesAll() {
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Query for valid, existing lease.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-wipe\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 0"
+ " }\n"
+ "}";
+ string exp_rsp = "Deleted 0 IPv6 lease(s) from subnet(s) 66 99";
+ testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+}
+
+void Lease6CmdsTest::testLease6BrokenUpdate() {
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ // Set the sanity checks level.
+ CfgMgr::instance().getCurrentCfg()->getConsistency()
+ ->setLeaseSanityCheck(CfgConsistency::LEASE_CHECK_FIX);
+
+ // Now send the command.
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 444,\n"
+ " \"ip-address\": \"2001:db8:1::23\",\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"force-create\": true\n"
+ " }\n"
+ "}";
+ string exp_rsp = "Invalid subnet-id: No IPv6 subnet with "
+ "subnet-id=444 currently configured.";
+ testCommand(txt, CONTROL_RESULT_CONFLICT, exp_rsp);
+}
+
+void Lease6CmdsTest::testLease6BulkApply() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-bulk-apply\",\n"
+ " \"arguments\": {"
+ " \"deleted-leases\": ["
+ " {"
+ " \"ip-address\": \"2001:db8:1::1\","
+ " \"type\": \"IA_NA\""
+ " },"
+ " {"
+ " \"ip-address\": \"2001:db8:1::2\","
+ " \"type\": \"IA_NA\""
+ " }"
+ " ],"
+ " \"leases\": ["
+ " {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::123\",\n"
+ " \"duid\": \"11:11:11:11:11:11\",\n"
+ " \"iaid\": 1234\n"
+ " },"
+ " {"
+ " \"subnet-id\": 99,\n"
+ " \"ip-address\": \"2001:db8:2::123\",\n"
+ " \"duid\": \"22:22:22:22:22:22\",\n"
+ " \"iaid\": 1234\n"
+ " }"
+ " ]"
+ " }"
+ "}";
+ string exp_rsp = "Bulk apply of 4 IPv6 leases completed.";
+
+ // The status expected is success.
+ testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease6Stats(66, 1, 0, 0);
+
+ checkLease6Stats(99, 3, 0, 0);
+
+ // Check that the leases we inserted are stored.
+ EXPECT_TRUE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::123")));
+ EXPECT_TRUE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:2::123")));
+
+ // Check that the leases we deleted are gone,
+ EXPECT_FALSE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1")));
+ EXPECT_FALSE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::2")));
+}
+
+void Lease6CmdsTest::testLease6BulkApplyAddsOnlyBadParam() {
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ // Now send the command. The command uses an invalid state declined (1) for
+ // PD prefix.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-bulk-apply\",\n"
+ " \"arguments\": {"
+ " \"leases\": ["
+ " {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::\",\n"
+ " \"prefix-len\": 48,\n"
+ " \"type\": \"IA_PD\",\n"
+ " \"duid\": \"11:11:11:11:11:11\",\n"
+ " \"iaid\": 1234,\n"
+ " \"state\": 1"
+ " }"
+ " ]"
+ " }"
+ "}";
+ string exp_rsp = "Invalid declined state for PD prefix.";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Invalid prefix len for PD prefix.
+ cmd =
+ "{\n"
+ " \"command\": \"lease6-bulk-apply\",\n"
+ " \"arguments\": {"
+ " \"leases\": ["
+ " {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::123\",\n"
+ " \"prefix-len\": 48,\n"
+ " \"type\": \"IA_PD\",\n"
+ " \"duid\": \"11:11:11:11:11:11\",\n"
+ " \"iaid\": 1234\n"
+ " }"
+ " ]"
+ " }"
+ "}";
+ exp_rsp = "Prefix address: 2001:db8:1::123 exceeds prefix/prefix-len pair: 2001:db8:1::/48";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Check that the lease was not inserted.
+ EXPECT_FALSE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::123")));
+}
+
+void Lease6CmdsTest::testLease6BulkApplyAddsOnly() {
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-bulk-apply\",\n"
+ " \"arguments\": {"
+ " \"leases\": ["
+ " {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::123\",\n"
+ " \"duid\": \"11:11:11:11:11:11\",\n"
+ " \"iaid\": 1234\n"
+ " },"
+ " {"
+ " \"subnet-id\": 99,\n"
+ " \"ip-address\": \"2001:db8:2::123\",\n"
+ " \"duid\": \"22:22:22:22:22:22\",\n"
+ " \"iaid\": 1234\n"
+ " }"
+ " ]"
+ " }"
+ "}";
+ string exp_rsp = "Bulk apply of 2 IPv6 leases completed.";
+
+ // The status expected is success.
+ testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease6Stats(66, 1, 0, 0);
+
+ checkLease6Stats(99, 1, 0, 0);
+
+ // Check that the leases we inserted are stored.
+ EXPECT_TRUE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::123")));
+ EXPECT_TRUE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:2::123")));
+}
+
+void Lease6CmdsTest::testLease6BulkApplyUpdatesOnlyBadParam() {
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ // Let's start with regular address lease and make it a prefix lease.
+ Lease6Ptr l = createLease6("2001:db8:1::1", 66, 0x77);
+ l->addr_ = IOAddress("2001:db8:1234:ab::");
+ l->type_ = Lease::TYPE_PD;
+ l->prefixlen_ = 56;
+ lmptr_->addLease(l);
+
+ // Now send the command. The command uses an invalid state declined (1) for
+ // PD prefix.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-bulk-apply\",\n"
+ " \"arguments\": {"
+ " \"leases\": ["
+ " {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1234:ab::\",\n"
+ " \"prefix-len\": 64,\n"
+ " \"type\": \"IA_PD\",\n"
+ " \"duid\": \"77:77:77:77:77:77\",\n"
+ " \"iaid\": 1234,\n"
+ " \"state\": 1"
+ " }"
+ " ]"
+ " }"
+ "}";
+ string exp_rsp = "Invalid declined state for PD prefix.";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Invalid prefix len for PD prefix.
+ cmd =
+ "{\n"
+ " \"command\": \"lease6-bulk-apply\",\n"
+ " \"arguments\": {"
+ " \"leases\": ["
+ " {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1234:ab::\",\n"
+ " \"prefix-len\": 56,\n"
+ " \"type\": \"IA_PD\",\n"
+ " \"duid\": \"77:77:77:77:77:77\",\n"
+ " \"iaid\": 1234\n"
+ " }"
+ " ]"
+ " }"
+ "}";
+ exp_rsp = "Prefix address: 2001:db8:1234:ab:: exceeds prefix/prefix-len pair: 2001:db8:1234::/56";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Check that the lease we inserted is stored.
+ Lease6Ptr lease1 = lmptr_->getLease6(Lease::TYPE_PD, IOAddress("2001:db8:1234:ab::"));
+ ASSERT_TRUE(lease1);
+
+ // The IAID should have not been updated for the existing lease.
+ EXPECT_EQ(42, lease1->iaid_);
+}
+
+void Lease6CmdsTest::testLease6BulkApplyUpdatesOnly() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-bulk-apply\",\n"
+ " \"arguments\": {"
+ " \"leases\": ["
+ " {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::1\",\n"
+ " \"duid\": \"11:11:11:11:11:11\",\n"
+ " \"iaid\": 1234\n"
+ " },"
+ " {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::2\",\n"
+ " \"duid\": \"22:22:22:22:22:22\",\n"
+ " \"iaid\": 1234\n"
+ " }"
+ " ]"
+ " }"
+ "}";
+ string exp_rsp = "Bulk apply of 2 IPv6 leases completed.";
+
+ // The status expected is success.
+ testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ // Check that the leases we inserted are stored.
+ Lease6Ptr lease1 = lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1"));
+ Lease6Ptr lease2 = lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::2"));
+ ASSERT_TRUE(lease1);
+ ASSERT_TRUE(lease2);
+
+ // The IAIDs should have been updated for the existing leases.
+ EXPECT_EQ(1234, lease1->iaid_);
+ EXPECT_EQ(1234, lease2->iaid_);
+}
+
+void Lease6CmdsTest::testLease6BulkApplyUpdatesOnlyExtendedInfo() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ Lease6Collection leases;
+ vector<uint8_t> remote_id = { 1, 2, 3, 4, 5, 6 };
+ leases = lmptr_->getLeases6ByRemoteId(remote_id,
+ IOAddress::IPV6_ZERO_ADDRESS(),
+ 0,
+ IOAddress::IPV6_ZERO_ADDRESS(),
+ LeasePageSize(10));
+ EXPECT_TRUE(leases.empty());
+ vector<uint8_t> relay_bin(8, 0x64);
+ DuidPtr relay_id(new DUID(relay_bin));
+ leases = lmptr_->getLeases6ByRelayId(*relay_id,
+ IOAddress::IPV6_ZERO_ADDRESS(),
+ 0,
+ IOAddress::IPV6_ZERO_ADDRESS(),
+ LeasePageSize(10));
+ EXPECT_TRUE(leases.empty());
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-bulk-apply\",\n"
+ " \"arguments\": {"
+ " \"leases\": ["
+ " {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::1\",\n"
+ " \"duid\": \"11:11:11:11:11:11\",\n"
+ " \"iaid\": 1234\n"
+ " },"
+ " {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::2\",\n"
+ " \"duid\": \"22:22:22:22:22:22\",\n"
+ " \"iaid\": 1234\n,"
+ " \"user-context\": { \"ISC\": { \"relay-info\": [ {\n"
+ " \"remote-id\": \"010203040506\",\n"
+ " \"relay-id\": \"6464646464646464\" } ] } }\n"
+ " }"
+ " ]"
+ " }"
+ "}";
+ string exp_rsp = "Bulk apply of 2 IPv6 leases completed.";
+
+ // The status expected is success.
+ testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ // Check that the leases we inserted are stored.
+ Lease6Ptr lease1 = lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1"));
+ Lease6Ptr lease2 = lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::2"));
+ ASSERT_TRUE(lease1);
+ ASSERT_TRUE(lease2);
+
+ // The IAIDs should have been updated for the existing leases.
+ EXPECT_EQ(1234, lease1->iaid_);
+ EXPECT_EQ(1234, lease2->iaid_);
+
+ // The user context have been updated too.
+ EXPECT_FALSE(lease1->getContext());
+ ConstElementPtr ctx = lease2->getContext();
+ ASSERT_TRUE(ctx);
+ string expected = "{ \"ISC\": { \"relay-info\": ";
+ expected += "[ { \"relay-id\": \"6464646464646464\", ";
+ expected += "\"remote-id\": \"010203040506\" } ] } }";
+ EXPECT_EQ(expected, ctx->str());
+
+ // Check that BLQ tables were updated.
+ leases = lmptr_->getLeases6ByRemoteId(remote_id,
+ IOAddress::IPV6_ZERO_ADDRESS(),
+ 0,
+ IOAddress::IPV6_ZERO_ADDRESS(),
+ LeasePageSize(10));
+ ASSERT_EQ(1, leases.size());
+ Lease6Ptr lx = leases[0];
+ ASSERT_TRUE(lx);
+ EXPECT_EQ(IOAddress("2001:db8:1::2"), lx->addr_);
+ EXPECT_EQ(*lease2, *lx);
+ leases = lmptr_->getLeases6ByRelayId(*relay_id,
+ IOAddress::IPV6_ZERO_ADDRESS(),
+ 0,
+ IOAddress::IPV6_ZERO_ADDRESS(),
+ LeasePageSize(10));
+ ASSERT_EQ(1, leases.size());
+ lx = leases[0];
+ ASSERT_TRUE(lx);
+ EXPECT_EQ(IOAddress("2001:db8:1::2"), lx->addr_);
+ EXPECT_EQ(*lease2, *lx);
+}
+
+void Lease6CmdsTest::testLease6BulkApplyDeletesOnly() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-bulk-apply\",\n"
+ " \"arguments\": {"
+ " \"deleted-leases\": ["
+ " {"
+ " \"ip-address\": \"2001:db8:1::1\","
+ " \"type\": \"IA_NA\""
+ " },"
+ " {"
+ " \"ip-address\": \"2001:db8:1::2\","
+ " \"type\": \"IA_NA\""
+ " }"
+ " ]"
+ " }"
+ "}";
+ string exp_rsp = "Bulk apply of 2 IPv6 leases completed.";
+
+ // The status expected is success.
+ testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease6Stats(66, 0, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ // Check that the leases we deleted are gone,
+ EXPECT_FALSE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1")));
+ EXPECT_FALSE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::2")));
+}
+
+void Lease6CmdsTest::testLease6BulkApplyDeleteNonExiting() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-bulk-apply\",\n"
+ " \"arguments\": {"
+ " \"deleted-leases\": ["
+ " {"
+ " \"ip-address\": \"2001:db8:1::123\","
+ " \"type\": \"IA_NA\""
+ " },"
+ " {"
+ " \"ip-address\": \"2001:db8:1::234\","
+ " \"type\": \"IA_NA\""
+ " }"
+ " ]"
+ " }"
+ "}";
+ string exp_rsp = "Bulk apply of 0 IPv6 leases completed.";
+
+ // The status expected is success.
+ auto resp = testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
+ ASSERT_TRUE(resp);
+ ASSERT_EQ(Element::map, resp->getType());
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ auto args = resp->get("arguments");
+ ASSERT_TRUE(args);
+ ASSERT_EQ(Element::map, args->getType());
+
+ auto failed_deleted_leases = args->get("failed-deleted-leases");
+ ASSERT_TRUE(failed_deleted_leases);
+ ASSERT_EQ(Element::list, failed_deleted_leases->getType());
+ ASSERT_EQ(2, failed_deleted_leases->size());
+
+ {
+ SCOPED_TRACE("lease address 2001:db8:1::123");
+ checkFailedLease(failed_deleted_leases, "IA_NA", "2001:db8:1::123",
+ CONTROL_RESULT_EMPTY, "lease not found");
+ }
+
+ {
+ SCOPED_TRACE("lease address 2001:db8:1::234");
+ checkFailedLease(failed_deleted_leases, "IA_NA", "2001:db8:1::234",
+ CONTROL_RESULT_EMPTY, "lease not found");
+ }
+}
+
+void Lease6CmdsTest::testLease6BulkApplyRollback() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-bulk-apply\",\n"
+ " \"arguments\": {"
+ " \"deleted-leases\": ["
+ " {"
+ " \"ip-address\": \"2001:db8:1::1\","
+ " \"type\": \"IA_NA\""
+ " },"
+ " {"
+ " \"ip-address\": \"2001:db8:1::2\","
+ " \"type\": \"IA_NA\""
+ " }"
+ " ],"
+ " \"leases\": ["
+ " {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::123\","
+ " \"duid\": \"11:11:11:11:11:11\","
+ " \"iaid\": 1234\n"
+ " },"
+ " {"
+ " \"subnet-id\": -1,"
+ " \"ip-address\": \"2001:db8:2::123\","
+ " \"duid\": \"22:22:22:22:22:22\","
+ " \"iaid\": 1234"
+ " }"
+ " ]"
+ " }"
+ "}";
+ string exp_rsp = "out of range value (-1) specified for parameter 'subnet-id' (<string>:5:57)";
+
+ // The status expected is success.
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ checkLease6Stats(66, 2, 0, 0);
+
+ checkLease6Stats(99, 2, 0, 0);
+
+ EXPECT_FALSE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::123")));
+ EXPECT_FALSE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:2::123")));
+
+ EXPECT_TRUE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1")));
+ EXPECT_TRUE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::2")));
+}
+
+void Lease6CmdsTest::testLease6ResendDdnsBadParam() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ // Missing address parameter.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-resend-ddns\",\n"
+ " \"arguments\": {\n"
+ " }\n"
+ "}\n";
+
+ string exp_rsp = "'ip-address' parameter is missing.";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Invalid address family.
+ cmd =
+ "{\n"
+ " \"command\": \"lease6-resend-ddns\",\n"
+ " \"arguments\": {\n"
+ " \"ip-address\": \"192.0.2.1\"\n"
+ " }\n"
+ "}\n";
+
+ exp_rsp = "Invalid IPv6 address specified: 192.0.2.1";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // ip-address is not an address at all.
+ cmd =
+ "{\n"
+ " \"command\": \"lease6-resend-ddns\",\n"
+ " \"arguments\": {\n"
+ " \"ip-address\": \"221B Baker St.\"\n"
+ " }\n"
+ "}\n";
+
+ exp_rsp = "'221B Baker St.' is not a valid IP address.";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+void Lease6CmdsTest::testLease6ResendDdnsDisabled() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ // Disable DDNS updating.
+ disableD2();
+
+ // Query for valid, existing lease.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-resend-ddns\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"2001::dead:beef\"\n"
+ " }\n"
+ "}";
+
+ string exp_rsp = "DDNS updating is not enabled";
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_CONFLICT, exp_rsp);
+ // With D2 disabled there is no queue, size should come back as -1.
+ EXPECT_EQ(ncrQueueSize(), -1);
+}
+
+void Lease6CmdsTest::testLease6ResendDdnsNoLease() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ // Invalid
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-resend-ddns\",\n"
+ " \"arguments\": {\n"
+ " \"ip-address\": \"2001::dead:beef\"\n"
+ " }\n"
+ "}\n";
+ string exp_rsp = "No lease found for: 2001::dead:beef";
+ testCommand(cmd, CONTROL_RESULT_EMPTY, exp_rsp);
+}
+
+void Lease6CmdsTest::testLease6ResendNoHostname() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ // NCR sender queue should be empty.
+ ASSERT_EQ(ncrQueueSize(), 0);
+
+ // Fetch the lease so we can replace the hostname with "".
+ Lease6Ptr lease = lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1"));
+ ASSERT_TRUE(lease);
+ lease->hostname_ = "";
+ lmptr_->updateLease6(lease);
+
+ // Query for valid, existing lease.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-resend-ddns\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"2001:db8:1::1\""
+ " }\n"
+ "}";
+
+ string exp_rsp = "Lease for: 2001:db8:1::1, has no hostname, nothing to update";
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_CONFLICT, exp_rsp);
+
+ // There should not any NCRs queued.
+ EXPECT_EQ(ncrQueueSize(), 0);
+}
+
+void Lease6CmdsTest::testLease6ResendNoDirectionsEnabled() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ // NCR sender queue should be empty.
+ ASSERT_EQ(ncrQueueSize(), 0);
+
+ // Fetch the lease so we can replace the hostname with "".
+ Lease6Ptr lease = lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1"));
+ ASSERT_TRUE(lease);
+ lease->fqdn_fwd_ = false;
+ lease->fqdn_rev_ = false;
+ lmptr_->updateLease6(lease);
+
+ // Query for valid, existing lease.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-resend-ddns\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"2001:db8:1::1\""
+ " }\n"
+ "}";
+
+ string exp_rsp = "Neither forward nor reverse updates enabled for lease for: 2001:db8:1::1";
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_CONFLICT, exp_rsp);
+
+ // There should not any NCRs queued.
+ EXPECT_EQ(ncrQueueSize(), 0);
+}
+
+void Lease6CmdsTest::testLease6ResendDdnsEnabled() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ // Structure detailing a test scenario.
+ struct Scenario {
+ std::string description_;
+ bool fqdn_fwd_;
+ bool fqdn_rev_;
+ };
+
+ // Three test scenarios to verify each combination of true flags.
+ std::vector<Scenario> scenarios = {
+ { "fwd_only", true, false },
+ { "rev_only", false, true},
+ { "both", true, true},
+ };
+
+ // Query for valid, existing lease.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-resend-ddns\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"2001:db8:1::1\""
+ " }\n"
+ "}";
+
+ // Expected response string.
+ string exp_rsp = "NCR generated for: 2001:db8:1::1, hostname: myhost.example.com.";
+
+ for (auto scenario : scenarios) {
+ SCOPED_TRACE(scenario.description_);
+
+ // Fetch the lease so we can update the DDNS direction flags.
+ Lease6Ptr lease = lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1"));
+ ASSERT_TRUE(lease);
+ lease->fqdn_rev_ = scenario.fqdn_rev_;
+ lease->fqdn_fwd_ = scenario.fqdn_fwd_;
+ lmptr_->updateLease6(lease);
+
+ // Queue should be empty.
+ ASSERT_EQ(ncrQueueSize(), 0);
+ ConstElementPtr rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ // We should have one entry in the queue.
+ ASSERT_EQ(ncrQueueSize(), 1);
+ verifyNameChangeRequest(CHG_ADD, scenario.fqdn_rev_, scenario.fqdn_fwd_,
+ "2001:db8:1::1", "myhost.example.com.");
+ }
+}
+
+void Lease6CmdsTest::testLease6DnsRemoveD2Enabled() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ // Structure detailing a test scenario.
+ struct Scenario {
+ std::string description_;
+ std::string hostname_;
+ bool fqdn_fwd_;
+ bool fqdn_rev_;
+ std::string update_ddns_;
+ bool exp_ncr_;
+ };
+
+ bool fwd = true;
+ bool rev = true;
+ bool ncr = true;
+
+ // Three test scenarios to verify each combination of true flags.
+ std::vector<Scenario> scenarios = {
+ {
+ "no_host",
+ "",
+ fwd, rev,
+ "\"update-ddns\": true",
+ !ncr
+ },
+ {
+ "no directions",
+ "myhost.example.com.",
+ !fwd, !rev,
+ "\"update-ddns\": true",
+ !ncr
+ },
+ {
+ "fwd_only",
+ "myhost.example.com.",
+ fwd, !rev,
+ "\"update-ddns\": true",
+ ncr
+ },
+ {
+ "rev_only",
+ "myhost.example.com.",
+ !fwd, rev,
+ "\"update-ddns\": true",
+ ncr
+ },
+ {
+ "both directions",
+ "myhost.example.com.",
+ fwd, rev,
+ "\"update-ddns\": true",
+ ncr
+ },
+ {
+ "default update-ddns",
+ "myhost.example.com.",
+ fwd, rev,
+ "",
+ !ncr
+ },
+ {
+ "update-ddns = false",
+ "myhost.example.com.",
+ fwd, rev,
+ "\"update-ddns\": false",
+ !ncr
+ },
+ };
+
+ for (auto scenario : scenarios) {
+ SCOPED_TRACE(scenario.description_);
+
+ // Let's create a lease with scenario attributes.
+ Lease6Ptr lease = createLease6("2001:db8:1::8", 66, 0x77);
+ lease->hostname_ = scenario.hostname_;
+ lease->fqdn_rev_ = scenario.fqdn_rev_;
+ lease->fqdn_fwd_ = scenario.fqdn_fwd_;
+ ASSERT_TRUE(lmptr_->addLease(lease));
+
+ // NCR Queue should be empty.
+ ASSERT_EQ(ncrQueueSize(), 0);
+
+ // Build the command
+ std::stringstream cmd;
+ cmd <<
+ "{"
+ " \"command\": \"lease6-del\","
+ " \"arguments\": {"
+ " \"ip-address\": \"2001:db8:1::8\"\n";
+
+ if (!scenario.update_ddns_.empty()) {
+ cmd << "," << scenario.update_ddns_;
+ }
+
+ cmd << "}}";
+
+ // Execute the delete command.
+ static_cast<void>(testCommand(cmd.str(), CONTROL_RESULT_SUCCESS, "IPv6 lease deleted."));
+
+ if (!scenario.exp_ncr_) {
+ // Should not have an ncr.
+ ASSERT_EQ(ncrQueueSize(), 0);
+ } else {
+ // We should have an ncr, verify it.
+ ASSERT_EQ(ncrQueueSize(), 1);
+ verifyNameChangeRequest(CHG_REMOVE, scenario.fqdn_rev_, scenario.fqdn_fwd_,
+ lease->addr_.toText(), lease->hostname_);
+ }
+
+ // Lease should have been deleted.
+ lease = lmptr_->getLease6(Lease::TYPE_NA, lease->addr_);
+ ASSERT_FALSE(lease);
+ }
+}
+
+void Lease6CmdsTest::testLease6DnsRemoveD2Disabled() {
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ disableD2();
+
+ // Delete for valid, existing lease.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-del\",\n"
+ " \"arguments\": {\n"
+ " \"ip-address\": \"2001:db8:1::8\",\n"
+ " \"update-ddns\": true\n"
+ " }\n"
+ "}";
+
+ // Let's create a lease with scenario attributes.
+ Lease6Ptr lease = createLease6("2001:db8:1::8", 66, 0x77);
+ lease->hostname_ = "myhost.example.com.";
+ lease->fqdn_rev_ = true;
+ lease->fqdn_fwd_ = true;
+ ASSERT_TRUE(lmptr_->addLease(lease));
+
+ // NCR Queue is not enabled.
+ ASSERT_EQ(ncrQueueSize(), -1);
+
+ // Execute the delete command.
+ static_cast<void>(testCommand(cmd, CONTROL_RESULT_SUCCESS, "IPv6 lease deleted."));
+
+ // NCR Queue is not enabled.
+ ASSERT_EQ(ncrQueueSize(), -1);
+
+ // Lease should have been deleted.
+ lease = lmptr_->getLease6(Lease::TYPE_NA, lease->addr_);
+ ASSERT_FALSE(lease);
+}
+
+// Verify that v4 lease add handles conflict as expected.
+void Lease6CmdsTest::testLease6ConflictingAdd() {
+ MultiThreadingTest mt(true);
+
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ // Make sure the lease doesn't exist.
+ IOAddress addr("2001:db8:1::1");
+ Lease6Ptr lease = lmptr_->getLease6(Lease::TYPE_NA, addr);
+ ASSERT_FALSE(lease);
+
+ // Verify stats show no leases.
+ checkLease6Stats(66, 0, 0, 0);
+
+ // Lock the address.
+ ResourceHandler resource_handler;
+ ASSERT_TRUE(resource_handler.tryLock(Lease::TYPE_NA, addr));
+
+ // Now let's try to add the lease.
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-add\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::1\",\n"
+ " \"duid\": \"1a:1b:1c:1d:1e:1f\",\n"
+ " \"iaid\": 1234,\n"
+ " \"comment\": \"a comment\"\n"
+ " }\n"
+ "}";
+
+ string exp_rsp = "ResourceBusy: IP address:2001:db8:1::1 could not be added.";
+ testCommand(txt, CONTROL_RESULT_CONFLICT, exp_rsp);
+
+ // Lease should not have been added.
+ lease = lmptr_->getLease6(Lease::TYPE_NA, addr);
+ ASSERT_FALSE(lease);
+
+ // Stats should not have changed.
+ checkLease6Stats(66, 0, 0, 0);
+}
+
+void Lease6CmdsTest::testLease6ConflictingUpdate() {
+ MultiThreadingTest mt(true);
+
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, true);
+
+ // Verify stats show no leases.
+ checkLease6Stats(66, 2, 0, 0);
+
+ // Make sure the lease exists.
+ IOAddress addr("2001:db8:1::1");
+ Lease6Ptr lease = lmptr_->getLease6(Lease::TYPE_NA, addr);
+ ASSERT_TRUE(lease);
+ // Save a copy of the original lease.
+ Lease6 original_lease = *lease;
+
+ // Lock the address.
+ ResourceHandler resource_handler;
+ ASSERT_TRUE(resource_handler.tryLock(Lease::TYPE_NA, addr));
+
+ // Now let's try to update the lease.
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-update\",\n"
+ " \"arguments\": {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::1\",\n"
+ " \"duid\": \"2a:2b:2c:2d:2e:2f\",\n"
+ " \"iaid\": 1234,\n"
+ " \"comment\": \"a comment\"\n"
+ " }\n"
+ "}";
+
+ string exp_rsp = "ResourceBusy: IP address:2001:db8:1::1 could not be updated.";
+ testCommand(txt, CONTROL_RESULT_CONFLICT, exp_rsp);
+
+ // Fetch the lease again.
+ lease = lmptr_->getLease6(Lease::TYPE_NA, addr);
+ ASSERT_TRUE(lease);
+
+ // Lease should not have been changed.
+ EXPECT_EQ(original_lease, *lease);
+}
+
+void Lease6CmdsTest::testLease6ConflictingBulkApplyAdd() {
+ MultiThreadingTest mt(true);
+
+ // Initialize lease manager (true = v6, true = add leases)
+ initLeaseMgr(true, false);
+
+ checkLease6Stats(66, 0, 0, 0);
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Lock the address.
+ IOAddress locked_addr("2001:db8:2::77");
+ ResourceHandler resource_handler;
+ ASSERT_TRUE(resource_handler.tryLock(Lease::TYPE_NA, locked_addr));
+
+ // Now send the command.
+ string cmd =
+ "{\n"
+ " \"command\": \"lease6-bulk-apply\",\n"
+ " \"arguments\": {"
+ " \"leases\": ["
+ " {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::123\",\n"
+ " \"duid\": \"11:11:11:11:11:11\",\n"
+ " \"iaid\": 1234\n"
+ " },"
+ " {"
+ " \"subnet-id\": 99,\n"
+ " \"ip-address\": \"2001:db8:2::77\",\n"
+ " \"duid\": \"22:22:22:22:22:22\",\n"
+ " \"iaid\": 1234\n"
+ " },"
+ " {"
+ " \"subnet-id\": 66,\n"
+ " \"ip-address\": \"2001:db8:1::124\",\n"
+ " \"duid\": \"33:33:33:33:33:33\",\n"
+ " \"iaid\": 1234\n"
+ " },"
+ " ]"
+ " }"
+ "}";
+ string exp_rsp = "Bulk apply of 2 IPv6 leases completed.";
+
+ // The status expected is success.
+ auto rsp = testCommand(cmd, CONTROL_RESULT_SUCCESS, exp_rsp);
+
+ checkLease6Stats(66, 2, 0, 0);
+ checkLease6Stats(99, 0, 0, 0);
+
+ // Check that the leases we inserted are stored.
+ EXPECT_TRUE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::123")));
+ EXPECT_TRUE(lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::124")));
+
+ // Check that the lease for locked address was not added.
+ EXPECT_FALSE(lmptr_->getLease6(Lease::TYPE_NA, locked_addr));
+
+ auto args = rsp->get("arguments");
+ auto failed_leases = args->get("failed-leases");
+ ASSERT_TRUE(failed_leases);
+ ASSERT_EQ(Element::list, failed_leases->getType());
+ ASSERT_EQ(1, failed_leases->size());
+ checkFailedLease(failed_leases, "IA_NA", locked_addr.toText(),
+ CONTROL_RESULT_CONFLICT,
+ "ResourceBusy: IP address:2001:db8:2::77 could not be updated.");
+}
+
+void Lease6CmdsTest::testLease6Write() {
+ // lease4-write negative tests. Positive tests are in the
+ // memfile_lease_mgr_unittest.cc file.
+
+ // Initialize lease manager (true = v6, false = don't add leases)
+ initLeaseMgr(true, false);
+
+ // Parameter is missing.
+ string txt =
+ "{\n"
+ " \"command\": \"lease6-write\",\n"
+ " \"arguments\": {"
+ " }\n"
+ "}";
+ string exp_rsp = "'filename' parameter not specified";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Filename must be a string.
+ txt =
+ "{\n"
+ " \"command\": \"lease6-write\",\n"
+ " \"arguments\": {"
+ " \"filename\": 0\n"
+ " }\n"
+ "}";
+ exp_rsp = "'filename' parameter must be a string";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+
+ // Filename must be not empty.
+ txt =
+ "{\n"
+ " \"command\": \"lease6-write\",\n"
+ " \"arguments\": {"
+ " \"filename\": \"\"\n"
+ " }\n"
+ "}";
+ exp_rsp = "'filename' parameter is empty";
+ testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+TEST_F(Lease6CmdsTest, lease6AddMissingParams) {
+ testLease6AddMissingParams();
+}
+
+TEST_F(Lease6CmdsTest, lease6AddMissingParamsMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6AddMissingParams();
+}
+
+TEST_F(Lease6CmdsTest, lease6AddBadParams) {
+ testLease6AddBadParams();
+}
+
+TEST_F(Lease6CmdsTest, lease6AddBadParamsMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6AddBadParams();
+}
+
+TEST_F(Lease6CmdsTest, lease6Add) {
+ testLease6Add();
+}
+
+TEST_F(Lease6CmdsTest, lease6AddMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6Add();
+}
+
+TEST_F(Lease6CmdsTest, lease6AddDeclinedLeases) {
+ testLease6AddDeclinedLeases();
+}
+
+TEST_F(Lease6CmdsTest, lease6AddDeclinedLeasesMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6AddDeclinedLeases();
+}
+
+TEST_F(Lease6CmdsTest, lease6AddExisting) {
+ testLease6AddExisting();
+}
+
+TEST_F(Lease6CmdsTest, lease6AddExistingMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6AddExisting();
+}
+
+TEST_F(Lease6CmdsTest, lease6AddSubnetIdMissing) {
+ testLease6AddSubnetIdMissing();
+}
+
+TEST_F(Lease6CmdsTest, lease6AddSubnetIdMissingMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6AddSubnetIdMissing();
+}
+
+TEST_F(Lease6CmdsTest, lease6AddSubnetIdMissingDeclinedLeases) {
+ testLease6AddSubnetIdMissingDeclinedLeases();
+}
+
+TEST_F(Lease6CmdsTest, lease6AddSubnetIdMissingDeclinedLeasesMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6AddSubnetIdMissingDeclinedLeases();
+}
+
+TEST_F(Lease6CmdsTest, lease6AddSubnetIdMissingBadAddr) {
+ testLease6AddSubnetIdMissingBadAddr();
+}
+
+TEST_F(Lease6CmdsTest, lease6AddSubnetIdMissingBadAddrMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6AddSubnetIdMissingBadAddr();
+}
+
+TEST_F(Lease6CmdsTest, lease6AddNegativeExpireTime) {
+ testLease6AddNegativeExpireTime();
+}
+
+TEST_F(Lease6CmdsTest, lease6AddNegativeExpireTimeMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6AddNegativeExpireTime();
+}
+
+TEST_F(Lease6CmdsTest, lease6AddNegativeCltt) {
+ testLease6AddNegativeCltt();
+}
+
+TEST_F(Lease6CmdsTest, lease6AddNegativeClttMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6AddNegativeCltt();
+}
+
+TEST_F(Lease6CmdsTest, lease6AddPrefix) {
+ testLease6AddPrefix();
+}
+
+TEST_F(Lease6CmdsTest, lease6AddPrefixMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6AddPrefix();
+}
+
+TEST_F(Lease6CmdsTest, lease6AddFullAddr) {
+ testLease6AddFullAddr();
+}
+
+TEST_F(Lease6CmdsTest, lease6AddFullAddrMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6AddFullAddr();
+}
+
+TEST_F(Lease6CmdsTest, lease6AddComment) {
+ testLease6AddComment();
+}
+
+TEST_F(Lease6CmdsTest, lease6AddCommentMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6AddComment();
+}
+
+TEST_F(Lease6CmdsTest, lease6AddExtendedInfo) {
+ testLease6AddExtendedInfo();
+}
+
+TEST_F(Lease6CmdsTest, lease6AddExtendedInfoMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6AddExtendedInfo();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetMissingParams) {
+ testLease6GetMissingParams();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetMissingParamsMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6GetMissingParams();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetByAddrBadParam) {
+ testLease6GetByAddrBadParam();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetByAddrBadParamMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6GetByAddrBadParam();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetByAddrNotFound) {
+ testLease6GetByAddrNotFound();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetByAddrNotFoundMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6GetByAddrNotFound();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetByClientIdInvalidType) {
+ testLease6GetByClientIdInvalidType();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetByClientIdInvalidTypeMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6GetByClientIdInvalidType();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetByDuidNotFound) {
+ testLease6GetByDuidNotFound();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetByDuidNotFoundMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6GetByDuidNotFound();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetByAddr) {
+ testLease6GetByAddr();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetByAddrMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6GetByAddr();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetByAddrPrefix) {
+ testLease6GetByAddrPrefix();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetByAddrPrefixMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6GetByAddrPrefix();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetByDuid) {
+ testLease6GetByDuid();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetByDuidMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6GetByDuid();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetAll) {
+ testLease6GetAll();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetAllMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6GetAll();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetAllNoLeases) {
+ testLease6GetAllNoLeases();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetAllNoLeasesMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6GetAllNoLeases();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetAllBySubnetId) {
+ testLease6GetAllBySubnetId();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetAllBySubnetIdMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6GetAllBySubnetId();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetAllBySubnetIdNoLeases) {
+ testLease6GetAllBySubnetIdNoLeases();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetAllBySubnetIdNoLeasesMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6GetAllBySubnetIdNoLeases();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetAllByMultipleSubnetIds) {
+ testLease6GetAllByMultipleSubnetIds();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetAllByMultipleSubnetIdsMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6GetAllByMultipleSubnetIds();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetBySubnetIdInvalidArguments) {
+ testLease6GetBySubnetIdInvalidArguments();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetBySubnetIdInvalidArgumentsMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6GetBySubnetIdInvalidArguments();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetPaged) {
+ testLease6GetPaged();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetPagedMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6GetPaged();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetPagedZeroAddress) {
+ testLease6GetPagedZeroAddress();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetPagedZeroAddressMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6GetPagedZeroAddress();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetPagedIPv4Address) {
+ testLease6GetPagedIPv4Address();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetPagedIPv4AddressMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6GetPagedIPv4Address();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetPagedInvalidFrom) {
+ testLease6GetPagedInvalidFrom();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetPagedInvalidFromMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6GetPagedInvalidFrom();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetPagedNoLimit) {
+ testLease6GetPagedNoLimit();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetPagedNoLimitMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6GetPagedNoLimit();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetPagedLimitNotNumber) {
+ testLease6GetPagedLimitNotNumber();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetPagedLimitNotNumberMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6GetPagedLimitNotNumber();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetPagedLimitIsZero) {
+ testLease6GetPagedLimitIsZero();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetPagedLimitIsZeroMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6GetPagedLimitIsZero();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetByDuidParams) {
+ testLease6GetByDuidParams();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetByDuidParamsMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6GetByDuidParams();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetByDuidFind0) {
+ testLease6GetByDuidFind0();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetByDuidFind0MultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6GetByDuidFind0();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetByDuidFind2) {
+ testLease6GetByDuidFind2();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetByDuidFind2MultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6GetByDuidFind2();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetByHostnameParams) {
+ testLease6GetByHostnameParams();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetByHostnameParamsMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6GetByHostnameParams();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetByHostnameFind0) {
+ testLease6GetByHostnameFind0();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetByHostnameFind0MultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6GetByHostnameFind0();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetByHostnameFind2) {
+ testLease6GetByHostnameFind2();
+}
+
+TEST_F(Lease6CmdsTest, lease6GetByHostnameFind2MultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6GetByHostnameFind2();
+}
+
+TEST_F(Lease6CmdsTest, lease6UpdateMissingParams) {
+ testLease6UpdateMissingParams();
+}
+
+TEST_F(Lease6CmdsTest, lease6UpdateMissingParamsMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6UpdateMissingParams();
+}
+
+TEST_F(Lease6CmdsTest, lease6UpdateBadParams) {
+ testLease6UpdateBadParams();
+}
+
+TEST_F(Lease6CmdsTest, lease6UpdateBadParamsMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6UpdateBadParams();
+}
+
+TEST_F(Lease6CmdsTest, lease6UpdateNoLease) {
+ testLease6UpdateNoLease();
+}
+
+TEST_F(Lease6CmdsTest, lease6UpdateNoLeaseMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6UpdateNoLease();
+}
+
+TEST_F(Lease6CmdsTest, lease6Update) {
+ testLease6Update();
+}
+
+TEST_F(Lease6CmdsTest, lease6UpdateMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6Update();
+}
+
+TEST_F(Lease6CmdsTest, lease6UpdateDeclinedLeases) {
+ testLease6UpdateDeclinedLeases();
+}
+
+TEST_F(Lease6CmdsTest, lease6UpdateDeclinedLeasesMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6UpdateDeclinedLeases();
+}
+
+TEST_F(Lease6CmdsTest, lease6UpdateNoSubnetId) {
+ testLease6UpdateNoSubnetId();
+}
+
+TEST_F(Lease6CmdsTest, lease6UpdateNoSubnetIdMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6UpdateNoSubnetId();
+}
+
+TEST_F(Lease6CmdsTest, lease6UpdateNoSubnetIdDeclinedLeases) {
+ testLease6UpdateNoSubnetIdDeclinedLeases();
+}
+
+TEST_F(Lease6CmdsTest, lease6UpdateNoSubnetIdDeclinedLeasesMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6UpdateNoSubnetIdDeclinedLeases();
+}
+
+TEST_F(Lease6CmdsTest, lease6UpdateComment) {
+ testLease6UpdateComment();
+}
+
+TEST_F(Lease6CmdsTest, lease6UpdateCommentMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6UpdateComment();
+}
+
+TEST_F(Lease6CmdsTest, lease6UpdateExtendedInfo) {
+ testLease6UpdateExtendedInfo();
+}
+
+TEST_F(Lease6CmdsTest, lease6UpdateExtendedInfoMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6UpdateExtendedInfo();
+}
+
+TEST_F(Lease6CmdsTest, lease6UpdateForceCreate) {
+ testLease6UpdateForceCreate();
+}
+
+TEST_F(Lease6CmdsTest, lease6UpdateForceCreateMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6UpdateForceCreate();
+}
+
+TEST_F(Lease6CmdsTest, lease6UpdateForceCreateNoSubnetId) {
+ testLease6UpdateForceCreateNoSubnetId();
+}
+
+TEST_F(Lease6CmdsTest, lease6UpdateForceCreateNoSubnetIdMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6UpdateForceCreateNoSubnetId();
+}
+
+TEST_F(Lease6CmdsTest, lease6UpdateDoNotForceCreate) {
+ testLease6UpdateDoNotForceCreate();
+}
+
+TEST_F(Lease6CmdsTest, lease6UpdateDoNotForceCreateMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6UpdateDoNotForceCreate();
+}
+
+TEST_F(Lease6CmdsTest, lease6DelMissingParams) {
+ testLease6DelMissingParams();
+}
+
+TEST_F(Lease6CmdsTest, lease6DelMissingParamsMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6DelMissingParams();
+}
+
+TEST_F(Lease6CmdsTest, lease6DelByAddrNotFound) {
+ testLease6DelByAddrNotFound();
+}
+
+TEST_F(Lease6CmdsTest, lease6DelByAddrNotFoundMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6DelByAddrNotFound();
+}
+
+TEST_F(Lease6CmdsTest, lease6DelByDuidNotFound) {
+ testLease6DelByDuidNotFound();
+}
+
+TEST_F(Lease6CmdsTest, lease6DelByDuidNotFoundMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6DelByDuidNotFound();
+}
+
+TEST_F(Lease6CmdsTest, lease6DelByAddr) {
+ testLease6DelByAddr();
+}
+
+TEST_F(Lease6CmdsTest, lease6DelByAddrMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6DelByAddr();
+}
+
+TEST_F(Lease6CmdsTest, lease6DelByAddrDeclinedLeases) {
+ testLease6DelByAddrDeclinedLeases();
+}
+
+TEST_F(Lease6CmdsTest, lease6DelByAddrDeclinedLeasesMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6DelByAddrDeclinedLeases();
+}
+
+TEST_F(Lease6CmdsTest, lease6DelByAddrBadParam) {
+ testLease6DelByAddrBadParam();
+}
+
+TEST_F(Lease6CmdsTest, lease6DelByAddrBadParamMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6DelByAddrBadParam();
+}
+
+TEST_F(Lease6CmdsTest, lease6DelByAddrPrefix) {
+ testLease6DelByAddrPrefix();
+}
+
+TEST_F(Lease6CmdsTest, lease6DelByAddrPrefixMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6DelByAddrPrefix();
+}
+
+TEST_F(Lease6CmdsTest, lease6DelByDuid) {
+ testLease6DelByDuid();
+}
+
+TEST_F(Lease6CmdsTest, lease6DelByDuidMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6DelByDuid();
+}
+
+TEST_F(Lease6CmdsTest, lease6Wipe) {
+ testLease6Wipe();
+}
+
+TEST_F(Lease6CmdsTest, lease6WipeMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6Wipe();
+}
+
+TEST_F(Lease6CmdsTest, lease6WipeAll) {
+ testLease6WipeAll();
+}
+
+TEST_F(Lease6CmdsTest, lease6WipeAllMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6WipeAll();
+}
+
+TEST_F(Lease6CmdsTest, lease6WipeAllNoArgs) {
+ testLease6WipeAllNoArgs();
+}
+
+TEST_F(Lease6CmdsTest, lease6WipeAllNoArgsMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6WipeAllNoArgs();
+}
+
+TEST_F(Lease6CmdsTest, lease6WipeNoLeases) {
+ testLease6WipeNoLeases();
+}
+
+TEST_F(Lease6CmdsTest, lease6WipeNoLeasesMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6WipeNoLeases();
+}
+
+TEST_F(Lease6CmdsTest, lease6WipeNoLeasesAll) {
+ testLease6WipeNoLeasesAll();
+}
+
+TEST_F(Lease6CmdsTest, lease6WipeNoLeasesAllMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6WipeNoLeasesAll();
+}
+
+TEST_F(Lease6CmdsTest, lease6BrokenUpdate) {
+ testLease6BrokenUpdate();
+}
+
+TEST_F(Lease6CmdsTest, lease6BrokenUpdateMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6BrokenUpdate();
+}
+
+TEST_F(Lease6CmdsTest, lease6BulkApply) {
+ testLease6BulkApply();
+}
+
+TEST_F(Lease6CmdsTest, lease6BulkApplyMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6BulkApply();
+}
+
+TEST_F(Lease6CmdsTest, lease6BulkApplyAddsOnlyBadParam) {
+ testLease6BulkApplyAddsOnlyBadParam();
+}
+
+TEST_F(Lease6CmdsTest, lease6BulkApplyAddsOnlyBadParamMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6BulkApplyAddsOnlyBadParam();
+}
+
+TEST_F(Lease6CmdsTest, lease6BulkApplyAddsOnly) {
+ testLease6BulkApplyAddsOnly();
+}
+
+TEST_F(Lease6CmdsTest, lease6BulkApplyAddsOnlyMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6BulkApplyAddsOnly();
+}
+
+TEST_F(Lease6CmdsTest, lease6BulkApplyUpdatesOnlyBadParam) {
+ testLease6BulkApplyUpdatesOnlyBadParam();
+}
+
+TEST_F(Lease6CmdsTest, lease6BulkApplyUpdatesOnlyBadParamMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6BulkApplyUpdatesOnlyBadParam();
+}
+
+TEST_F(Lease6CmdsTest, lease6BulkApplyUpdatesOnly) {
+ testLease6BulkApplyUpdatesOnly();
+}
+
+TEST_F(Lease6CmdsTest, lease6BulkApplyUpdatesOnlyExtendedInfo) {
+ testLease6BulkApplyUpdatesOnlyExtendedInfo();
+}
+
+TEST_F(Lease6CmdsTest, lease6BulkApplyUpdatesOnlyMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6BulkApplyUpdatesOnly();
+}
+
+TEST_F(Lease6CmdsTest, lease6BulkApplyDeletesOnly) {
+ testLease6BulkApplyDeletesOnly();
+}
+
+TEST_F(Lease6CmdsTest, lease6BulkApplyDeletesOnlyMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6BulkApplyDeletesOnly();
+}
+
+TEST_F(Lease6CmdsTest, lease6BulkApplyDeleteNonExiting) {
+ testLease6BulkApplyDeleteNonExiting();
+}
+
+TEST_F(Lease6CmdsTest, lease6BulkApplyDeleteNonExitingMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6BulkApplyDeleteNonExiting();
+}
+
+TEST_F(Lease6CmdsTest, lease6BulkApplyRollback) {
+ testLease6BulkApplyRollback();
+}
+
+TEST_F(Lease6CmdsTest, lease6BulkApplyRollbackMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6BulkApplyRollback();
+}
+
+TEST_F(Lease6CmdsTest, lease6ResendDdnsBadParam) {
+ testLease6ResendDdnsBadParam();
+}
+
+TEST_F(Lease6CmdsTest, lease6ResendDdnsBadParamMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6ResendDdnsBadParam();
+}
+
+TEST_F(Lease6CmdsTest, lease6ResendDdnsDisabled) {
+ testLease6ResendDdnsDisabled();
+}
+
+TEST_F(Lease6CmdsTest, lease6ResendDdnsDisabledMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6ResendDdnsDisabled();
+}
+
+TEST_F(Lease6CmdsTest, lease6ResendDdnsNoLease) {
+ testLease6ResendDdnsNoLease();
+}
+
+TEST_F(Lease6CmdsTest, lease6ResendDdnsNoLeaseMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6ResendDdnsNoLease();
+}
+
+TEST_F(Lease6CmdsTest, lease6ResendNoHostname) {
+ testLease6ResendNoHostname();
+}
+
+TEST_F(Lease6CmdsTest, lease6ResendNoHostnameMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6ResendNoHostname();
+}
+
+TEST_F(Lease6CmdsTest, lease6ResendNoDirectionsEnabled) {
+ testLease6ResendNoDirectionsEnabled();
+}
+
+TEST_F(Lease6CmdsTest, lease6ResendNoDirectionsEnabledMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6ResendNoDirectionsEnabled();
+}
+
+TEST_F(Lease6CmdsTest, lease6ResendDdnsEnabled) {
+ testLease6ResendDdnsEnabled();
+}
+
+TEST_F(Lease6CmdsTest, lease6ResendDdnsEnabledMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6ResendDdnsEnabled();
+}
+
+TEST_F(Lease6CmdsTest, lease6DnsRemoveD2Enabled) {
+ testLease6DnsRemoveD2Enabled();
+}
+
+TEST_F(Lease6CmdsTest, lease6DnsRemoveD2EnabledMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6DnsRemoveD2Enabled();
+}
+
+TEST_F(Lease6CmdsTest, lease6DnsRemoveD2Disabled) {
+ testLease6DnsRemoveD2Disabled();
+}
+
+TEST_F(Lease6CmdsTest, lease6DnsRemoveD2DisabledMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6DnsRemoveD2Disabled();
+}
+
+TEST_F(Lease6CmdsTest, lease6ConflictingAddMultiThreading) {
+ testLease6ConflictingAdd();
+}
+
+TEST_F(Lease6CmdsTest, lease6ConflictingUpdateMultiThreading) {
+ testLease6ConflictingUpdate();
+}
+
+TEST_F(Lease6CmdsTest, lease6ConflictingBulkApplyAddMultiThreading) {
+ testLease6ConflictingBulkApplyAdd();
+}
+
+TEST_F(Lease6CmdsTest, lease6Write) {
+ testLease6Write();
+}
+
+TEST_F(Lease6CmdsTest, lease6WriteMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6Write();
+}
+
+} // end of anonymous namespace
diff --git a/src/hooks/dhcp/lease_cmds/tests/lease_cmds_unittest.cc b/src/hooks/dhcp/lease_cmds/tests/lease_cmds_unittest.cc
new file mode 100644
index 0000000..72f9451
--- /dev/null
+++ b/src/hooks/dhcp/lease_cmds/tests/lease_cmds_unittest.cc
@@ -0,0 +1,105 @@
+// Copyright (C) 2017-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 <exceptions/exceptions.h>
+#include <hooks/hooks_manager.h>
+#include <config/command_mgr.h>
+#include <dhcpsrv/lease_mgr.h>
+#include <dhcpsrv/lease_mgr_factory.h>
+#include <dhcpsrv/ncr_generator.h>
+#include <dhcpsrv/cfgmgr.h>
+#include <dhcpsrv/resource_handler.h>
+#include <cc/command_interpreter.h>
+#include <cc/data.h>
+#include <lease_cmds_unittest.h>
+#include <stats/stats_mgr.h>
+#include <testutils/user_context_utils.h>
+#include <testutils/multi_threading_utils.h>
+
+#include <gtest/gtest.h>
+
+#include <errno.h>
+#include <set>
+
+using namespace std;
+using namespace isc;
+using namespace isc::hooks;
+using namespace isc::config;
+using namespace isc::data;
+using namespace isc::dhcp;
+using namespace isc::dhcp_ddns;
+using namespace isc::asiolink;
+using namespace isc::stats;
+using namespace isc::test;
+
+namespace {
+
+// Simple test that checks the library really registers the commands.
+TEST_F(LeaseCmdsTest, commands) {
+ vector<string> cmds = {
+ "lease4-add", "lease6-add",
+ "lease4-get", "lease6-get",
+ "lease4-get-all", "lease6-get-all",
+ "lease4-get-page", "lease6-get-page",
+ "lease4-get-by-hw-address",
+ "lease4-get-by-client-id", "lease6-get-by-duid",
+ "lease4-get-by-hostname", "lease6-get-by-hostname",
+ "lease4-del", "lease6-del",
+ "lease4-update", "lease6-update",
+ "lease4-wipe", "lease6-wipe",
+ "lease4-resend-ddns", "lease6-resend-ddns"
+ };
+ setFamily(AF_INET);
+ testCommands(cmds);
+}
+
+void LeaseCmdsTest::testLeaseXDelBadUpdateDdnsParam() {
+ string cmd =
+ "{\n"
+ " \"command\": \"lease4-del\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"192.0.1.0\","
+ " \"update-ddns\": 77"
+ " }\n"
+ "}";
+
+ string exp_rsp = "'update-ddns' is not a boolean";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+
+ cmd =
+ "{\n"
+ " \"command\": \"lease6-del\",\n"
+ " \"arguments\": {"
+ " \"ip-address\": \"2001:db8:1::1\","
+ " \"update-ddns\": \"bogus\""
+ " }\n"
+ "}";
+
+ exp_rsp = "'update-ddns' is not a boolean";
+ testCommand(cmd, CONTROL_RESULT_ERROR, exp_rsp);
+}
+
+
+// Check that the library can be loaded and unloaded multiple times.
+TEST_F(LeaseCmdsTest, multipleLoads) {
+ setFamily(AF_INET);
+ testMultipleLoads();
+}
+
+TEST_F(LeaseCmdsTest, leaseXDelBadUpdateDdnsParam) {
+ setFamily(AF_INET);
+ testLeaseXDelBadUpdateDdnsParam();
+}
+
+TEST_F(LeaseCmdsTest, leaseXDelBadUpdateDdnsParamMultiThreading) {
+ MultiThreadingTest mt(true);
+ setFamily(AF_INET);
+ testLeaseXDelBadUpdateDdnsParam();
+}
+
+} // end of anonymous namespace
diff --git a/src/hooks/dhcp/lease_cmds/tests/lease_cmds_unittest.h b/src/hooks/dhcp/lease_cmds/tests/lease_cmds_unittest.h
new file mode 100644
index 0000000..57720f4
--- /dev/null
+++ b/src/hooks/dhcp/lease_cmds/tests/lease_cmds_unittest.h
@@ -0,0 +1,572 @@
+// Copyright (C) 2017-2023 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 <exceptions/exceptions.h>
+#include <hooks/hooks_manager.h>
+#include <config/command_mgr.h>
+#include <dhcpsrv/lease_mgr.h>
+#include <dhcpsrv/lease_mgr_factory.h>
+#include <dhcpsrv/ncr_generator.h>
+#include <dhcpsrv/cfgmgr.h>
+#include <dhcpsrv/resource_handler.h>
+#include <cc/command_interpreter.h>
+#include <cc/data.h>
+#include <process/daemon.h>
+#include <stats/stats_mgr.h>
+#include <testutils/user_context_utils.h>
+#include <testutils/multi_threading_utils.h>
+
+#include <gtest/gtest.h>
+
+#include <errno.h>
+#include <set>
+
+namespace {
+
+/// @brief High valid lifetime used for leases in the tests below.
+constexpr uint32_t HIGH_VALID_LIFETIME = 0xFFFFFFFE;
+
+/// @brief December 11th 2030 date used in the unit tests for cltt.
+constexpr time_t DEC_2030_TIME = 1923222072;
+
+/// @brief Test fixture for testing loading and unloading the flex-id library
+class LibLoadTest : public ::testing::Test {
+public:
+ /// @brief Constructor
+ LibLoadTest(std::string lib_filename)
+ : lib_name_(lib_filename) {
+ isc::config::CommandMgr::instance();
+ unloadLibs();
+ }
+
+ /// @brief Destructor
+ /// Removes files that may be left over from previous tests
+ virtual ~LibLoadTest() {
+ unloadLibs();
+ }
+
+ /// @brief Set family.
+ void setFamily(uint16_t family) {
+ isc::dhcp::CfgMgr::instance().setFamily(family);
+ if (family == AF_INET) {
+ isc::process::Daemon::setProcName("kea-dhcp4");
+ } else {
+ isc::process::Daemon::setProcName("kea-dhcp6");
+ }
+ }
+
+ /// @brief Adds library/parameters to list of libraries to be loaded
+ void addLib(const std::string& lib, isc::data::ConstElementPtr params) {
+ libraries_.push_back(make_pair(lib, params));
+ }
+
+ /// @brief Load all specified libraries.
+ ///
+ /// The libraries are stored in libraries
+ void loadLibs() {
+ ASSERT_TRUE(isc::hooks::HooksManager::loadLibraries(libraries_))
+ << "library loading failed";
+ }
+
+ /// @brief Unloads all libraries.
+ void unloadLibs() {
+ ASSERT_NO_THROW(isc::hooks::HooksManager::unloadLibraries());
+ }
+
+ /// @brief Checks whether specified command is registered
+ ///
+ /// @param name name of the command to be checked
+ /// @param expect_true true - must be registered, false - must not be
+ void checkCommandRegistered(const std::string& name, bool expect_true) {
+ // First get the list of registered commands
+ isc::data::ConstElementPtr lst = isc::data::Element::fromJSON("{ \"command\": \"list-commands\" }");
+ isc::data::ConstElementPtr rsp = isc::config::CommandMgr::instance().processCommand(lst);
+
+ ASSERT_TRUE(rsp);
+
+ isc::data::ConstElementPtr args = rsp->get("arguments");
+ ASSERT_TRUE(args);
+
+ std::string args_txt = args->str();
+
+ if (expect_true) {
+ EXPECT_TRUE(args_txt.find(name) != std::string::npos);
+ } else {
+ EXPECT_TRUE(args_txt.find(name) == std::string::npos);
+ }
+ }
+
+ /// @brief tests specified command and verifies response
+ ///
+ /// This method loads the library, sends specific command,
+ /// then checks if the result is as expected, checks if text response
+ /// is ok (optional, check skipped if exp_txt is empty) and then returns
+ /// the response (for possible additional checks).
+ ///
+ /// @param cmd JSON command to be sent (must be valid JSON)
+ /// @param exp_result 0 - success, 1 - error, 2 - ...
+ /// @param exp_txt expected text response (optional)
+ /// @return full response returned by the command execution.
+ isc::data::ConstElementPtr testCommand(std::string cmd_txt, int exp_result,
+ std::string exp_txt) {
+ // Let's load the library first.
+ loadLib();
+
+ isc::data::ConstElementPtr cmd;
+ EXPECT_NO_THROW(cmd = isc::data::Element::fromJSON(cmd_txt));
+ if (!cmd) {
+ ADD_FAILURE() << cmd_txt << " is not a valid JSON, test broken";
+ return (isc::data::ConstElementPtr());
+ }
+
+ // Process the command and verify response.
+ isc::data::ConstElementPtr rsp = isc::config::CommandMgr::instance().processCommand(cmd);
+ checkAnswer(rsp, exp_result, exp_txt);
+
+ return (rsp);
+ }
+
+ /// @brief Compares the status in the given parse result to a given value.
+ ///
+ /// @param answer Element set containing an integer response and string
+ /// comment.
+ /// @param exp_status is an integer against which to compare the status.
+ /// @param exp_txt is expected text (not checked if "")
+ void checkAnswer(isc::data::ConstElementPtr answer,
+ int exp_status,
+ std::string exp_txt = "") {
+ int rcode = 0;
+ isc::data::ConstElementPtr comment;
+ comment = isc::config::parseAnswer(rcode, answer);
+
+ if (rcode != exp_status) {
+ ADD_FAILURE() << "Expected status code " << exp_status
+ << " but received " << rcode << ", comment: "
+ << (comment ? comment->str() : "(none)");
+ }
+
+ // Ok, parseAnswer interface is weird. If there are no arguments,
+ // it returns content of text. But if there is an argument,
+ // it returns the argument and it's not possible to retrieve
+ // "text" (i.e. comment).
+ if (comment->getType() != isc::data::Element::string) {
+ comment = answer->get("text");
+ }
+
+ if (!exp_txt.empty()) {
+ EXPECT_EQ(exp_txt, comment->stringValue());
+ }
+ }
+
+ /// @brief Loads the library specified by lib_name_
+ void loadLib() {
+ if (libraries_.empty()) {
+ isc::data::ElementPtr params = isc::data::Element::createMap();
+ addLib(lib_name_, params);
+ }
+ EXPECT_NO_THROW(loadLibs());
+ }
+
+ /// @brief Test checks if specified commands are provided by the library.
+ ///
+ /// @param cms a vector of string with command names
+ void testCommands(const std::vector<std::string> cmds) {
+ // The commands should not be registered yet.
+ for (auto cmd = cmds.begin(); cmd != cmds.end(); ++cmd) {
+ checkCommandRegistered(*cmd, false);
+ }
+
+ loadLib();
+
+ // The commands should be available after library was loaded.
+ for (auto cmd = cmds.begin(); cmd != cmds.end(); ++cmd) {
+ checkCommandRegistered(*cmd, true);
+ }
+
+ unloadLibs();
+
+ // and the commands should be gone now.
+ for (auto cmd = cmds.begin(); cmd != cmds.end(); ++cmd) {
+ checkCommandRegistered(*cmd, false);
+ }
+
+ }
+
+ // Check that the library can be loaded and unloaded multiple times.
+ void testMultipleLoads() {
+ EXPECT_NO_THROW(loadLib());
+ EXPECT_NO_THROW(unloadLibs());
+
+ EXPECT_NO_THROW(loadLib());
+ EXPECT_NO_THROW(unloadLibs());
+
+ EXPECT_NO_THROW(loadLib());
+ EXPECT_NO_THROW(unloadLibs());
+
+ EXPECT_NO_THROW(loadLib());
+ EXPECT_NO_THROW(unloadLibs());
+ }
+
+ /// @brief Verify that NameChangeRequest holds valid values.
+ ///
+ /// This function picks first NameChangeRequest from the internal server's
+ /// queue and checks that it holds valid parameters. The NameChangeRequest
+ /// is removed from the queue.
+ ///
+ /// @param type An expected type of the NameChangeRequest (Add or Remove).
+ /// @param reverse An expected setting of the reverse update flag.
+ /// @param forward An expected setting of the forward update flag.
+ /// @param addr A string representation of the IPv6 address held in the
+ /// NameChangeRequest.
+ /// @param fqdn The expected string value of the FQDN, if blank the
+ /// check is skipped
+ void verifyNameChangeRequest(const isc::dhcp_ddns::NameChangeType type,
+ const bool reverse, const bool forward,
+ const std::string& addr,
+ const std::string& fqdn = "") {
+ isc::dhcp_ddns::NameChangeRequestPtr ncr;
+ ASSERT_NO_THROW(ncr = isc::dhcp::CfgMgr::instance().getD2ClientMgr().peekAt(0));
+ ASSERT_TRUE(ncr);
+
+ EXPECT_EQ(type, ncr->getChangeType());
+ EXPECT_EQ(forward, ncr->isForwardChange());
+ EXPECT_EQ(reverse, ncr->isReverseChange());
+ EXPECT_EQ(addr, ncr->getIpAddress());
+
+ if (!fqdn.empty()) {
+ EXPECT_EQ(fqdn, ncr->getFqdn());
+ }
+
+ // Process the message off the queue
+ ASSERT_NO_THROW(isc::dhcp::CfgMgr::instance().getD2ClientMgr().runReadyIO());
+ }
+
+ /// List of libraries to be/being loaded (usually just one)
+ isc::hooks::HookLibsCollection libraries_;
+
+ /// Path to the library filename
+ std::string lib_name_;
+};
+
+/// @brief Class dedicated to testing lease_cmds library.
+///
+/// Provides convenience methods for loading, testing all commands and
+/// unloading the lease_cmds library.
+class LeaseCmdsTest : public LibLoadTest {
+public:
+
+ /// @brief Pointer to the lease manager
+ isc::dhcp::LeaseMgr* lmptr_;
+
+ /// @brief Reference to the D2 client manager.
+ isc::dhcp::D2ClientMgr& d2_mgr_;
+
+ /// @brief Constructor
+ ///
+ /// Sets the library filename and clears the lease manager pointer.
+ /// Also ensured there is no lease manager leftovers from previous
+ /// test.
+ LeaseCmdsTest()
+ : LibLoadTest(LEASE_CMDS_LIB_SO),
+ d2_mgr_(isc::dhcp::CfgMgr::instance().getD2ClientMgr()) {
+ isc::dhcp::LeaseMgrFactory::destroy();
+ enableD2();
+ lmptr_ = 0;
+ isc::stats::StatsMgr::instance().removeAll();
+ }
+
+ /// @brief Destructor
+ ///
+ /// Removes library (if any), destroys lease manager (if any).
+ virtual ~LeaseCmdsTest() {
+ // destroys lease manager first because the other order triggers
+ // a clang/boost bug
+ isc::dhcp::LeaseMgrFactory::destroy();
+ disableD2();
+ unloadLibs();
+ lmptr_ = 0;
+ isc::stats::StatsMgr::instance().removeAll();
+ }
+
+ /// @brief Creates an IPv4 lease
+ ///
+ /// Lease parameters: valid lifetime = 0xFFFFFFFE, cltt = 1923222072, fqdn-fwd = false,
+ /// fqdn-rev = true, hostname = myhost.example.com
+ ///
+ /// @param ip_address IP address for the lease.
+ /// @param subnet_id subnet identifier
+ /// @param hw_address_pattern value to be used for generating HW address by repeating
+ /// it 6 times.
+ /// @param client_id_pattern value to be used for generating client identifier by
+ /// repeating it 8 times.
+ /// @param declined controls whether the lease should be in declined state.
+ ///
+ /// @return Returns the lease created
+ isc::dhcp::Lease4Ptr createLease4(const std::string& ip_address,
+ const isc::dhcp::SubnetID& subnet_id,
+ const uint8_t hw_address_pattern,
+ const uint8_t client_id_pattern,
+ bool declined = false, uint32_t pool_id = 0) {
+ isc::dhcp::Lease4Ptr lease(new isc::dhcp::Lease4());
+
+ lease->addr_ = isc::asiolink::IOAddress(ip_address);
+
+ // Set other parameters. For historical reasons, address 0 is not used.
+ lease->hwaddr_.reset(new isc::dhcp::HWAddr(std::vector<uint8_t>(6, hw_address_pattern), isc::dhcp::HTYPE_ETHER));
+ lease->client_id_ = isc::dhcp::ClientIdPtr(new isc::dhcp::ClientId(std::vector<uint8_t>(8, client_id_pattern)));
+ // Purposely using high cltt and valid lifetime to test that
+ // expiration time is cast properly.
+ lease->valid_lft_ = HIGH_VALID_LIFETIME; // Very high valid lifetime
+ lease->cltt_ = DEC_2030_TIME; // December 11th 2030
+ lease->updateCurrentExpirationTime();
+ if (declined) {
+ lease->state_ = isc::dhcp::Lease::STATE_DECLINED;
+ }
+ lease->subnet_id_ = subnet_id;
+ lease->fqdn_fwd_ = false;
+ lease->fqdn_rev_ = true;
+ lease->hostname_ = "myhost.example.com.";
+ lease->pool_id_ = pool_id;
+
+ return (lease);
+ }
+
+ /// @brief Creates an IPv6 lease
+ ///
+ /// Lease parameters: cltt = 1923222072, fqdn-fwd = false, fqdn-rev = true,
+ /// hostname = myhost.example.com, preferred lifetime = 1800,
+ /// valid lifetime = 0xFFFFFFFE
+ ///
+ /// @param ip_address IP address for the lease.
+ /// @param subnet_id subnet identifier
+ /// @param duid_address_pattern value to be used for generating DUID by
+ /// repeating it 8 times
+ /// @param declined controls whether the lease should be in declined state.
+ ///
+ /// @return Returns the lease created
+ isc::dhcp::Lease6Ptr createLease6(const std::string& ip_address,
+ const isc::dhcp::SubnetID& subnet_id,
+ const uint8_t duid_pattern,
+ bool declined = false, uint32_t pool_id = 0) {
+ isc::dhcp::Lease6Ptr lease(new isc::dhcp::Lease6());
+
+ lease->addr_ = isc::asiolink::IOAddress(ip_address);
+ lease->type_ = isc::dhcp::Lease::TYPE_NA;
+ lease->prefixlen_ = 128;
+ lease->iaid_ = 42;
+ lease->duid_ = isc::dhcp::DuidPtr(new isc::dhcp::DUID(std::vector<uint8_t>(8, duid_pattern)));
+ lease->preferred_lft_ = 1800;
+ // Purposely using high cltt and valid lifetime to test that
+ // expiration time is cast properly.
+ lease->valid_lft_ = HIGH_VALID_LIFETIME; // Very high valid lifetime
+ lease->cltt_ = DEC_2030_TIME; // December 11th 2030
+ lease->updateCurrentExpirationTime();
+ if (declined) {
+ lease->state_ = isc::dhcp::Lease::STATE_DECLINED;
+ }
+ lease->subnet_id_ = subnet_id;
+ lease->fqdn_fwd_ = false;
+ lease->fqdn_rev_ = true;
+ lease->hostname_ = "myhost.example.com.";
+ lease->pool_id_ = pool_id;
+
+ return (lease);
+ }
+
+ /// @brief Initializes lease manager (and optionally populates it with a lease)
+ ///
+ /// Creates a lease manager (memfile, trimmed down to keep everything in memory
+ /// only) and optionally can create a lease, which is useful for leaseX-get and
+ /// leaseX-del type of tests. For lease details, see @ref createLease4 and
+ /// @ref createLease6.
+ ///
+ /// @param v6 true = v6, false = v4
+ /// @param insert_lease governs whether a lease should be pre-inserted
+ /// @param declined governs whether a lease should be in declined state
+ void initLeaseMgr(bool v6, bool insert_lease, bool declined = false) {
+ isc::dhcp::LeaseMgrFactory::destroy();
+ std::ostringstream s;
+ s << "type=memfile persist=false ";
+ if (v6) {
+ s << "universe=6 extended-info-tables=true";
+ } else {
+ s << "universe=4";
+ }
+ isc::dhcp::LeaseMgrFactory::create(s.str());
+
+ lmptr_ = &(isc::dhcp::LeaseMgrFactory::instance());
+ ASSERT_TRUE(lmptr_);
+
+ isc::dhcp::CfgMgr& cfg_mgr = isc::dhcp::CfgMgr::instance();
+ if (v6) {
+ isc::dhcp::Subnet6Ptr subnet66(new isc::dhcp::Subnet6(isc::asiolink::IOAddress("2001:db8:1::"), 48, 1, 2, 3, 4, 66));
+ isc::dhcp::Subnet6Ptr subnet99(new isc::dhcp::Subnet6(isc::asiolink::IOAddress("2001:db8:2::"), 48, 1, 2, 3, 4, 99));
+ isc::dhcp::CfgSubnets6Ptr subnets = cfg_mgr.getStagingCfg()->getCfgSubnets6();
+ subnets->add(subnet66);
+ subnets->add(subnet99);
+ cfg_mgr.commit();
+ } else {
+ isc::dhcp::Subnet4Ptr subnet44(new isc::dhcp::Subnet4(isc::asiolink::IOAddress("192.0.2.0"), 24, 1, 2, 3, 44));
+ isc::dhcp::Subnet4Ptr subnet88(new isc::dhcp::Subnet4(isc::asiolink::IOAddress("192.0.3.0"), 24, 1, 2, 3, 88));
+ isc::dhcp::CfgSubnets4Ptr subnets = cfg_mgr.getStagingCfg()->getCfgSubnets4();
+ subnets->add(subnet44);
+ subnets->add(subnet88);
+ cfg_mgr.commit();
+ }
+
+ if (insert_lease) {
+ if (v6) {
+ lmptr_->addLease(createLease6("2001:db8:1::1", 66, 0x42, declined));
+ lmptr_->addLease(createLease6("2001:db8:1::2", 66, 0x56, declined, 5));
+ lmptr_->addLease(createLease6("2001:db8:2::1", 99, 0x42, declined));
+ lmptr_->addLease(createLease6("2001:db8:2::2", 99, 0x56, declined));
+ if (declined) {
+ isc::stats::StatsMgr::instance().setValue(
+ isc::stats::StatsMgr::generateName("subnet", 66, "declined-addresses"),
+ int64_t(2));
+ isc::stats::StatsMgr::instance().setValue(
+ isc::stats::StatsMgr::generateName("subnet", 99, "declined-addresses"),
+ int64_t(2));
+ } else {
+ isc::stats::StatsMgr::instance().setValue(
+ isc::stats::StatsMgr::generateName("subnet", 66, "declined-addresses"),
+ int64_t(0));
+ isc::stats::StatsMgr::instance().setValue(
+ isc::stats::StatsMgr::generateName("subnet", 99, "declined-addresses"),
+ int64_t(0));
+ }
+ isc::stats::StatsMgr::instance().setValue(
+ isc::stats::StatsMgr::generateName("subnet", 66, "assigned-nas" ),
+ int64_t(2));
+ isc::stats::StatsMgr::instance().setValue(
+ isc::stats::StatsMgr::generateName("subnet", 99, "assigned-nas" ),
+ int64_t(2));
+ } else {
+ lmptr_->addLease(createLease4("192.0.2.1", 44, 0x08, 0x42, declined));
+ lmptr_->addLease(createLease4("192.0.2.2", 44, 0x09, 0x56, declined, 5));
+ lmptr_->addLease(createLease4("192.0.3.1", 88, 0x08, 0x42, declined));
+ lmptr_->addLease(createLease4("192.0.3.2", 88, 0x09, 0x56, declined));
+ if (declined) {
+ isc::stats::StatsMgr::instance().setValue(
+ isc::stats::StatsMgr::generateName("subnet", 44, "declined-addresses"),
+ int64_t(2));
+ isc::stats::StatsMgr::instance().setValue(
+ isc::stats::StatsMgr::generateName("subnet", 88, "declined-addresses"),
+ int64_t(2));
+ } else {
+ isc::stats::StatsMgr::instance().setValue(
+ isc::stats::StatsMgr::generateName("subnet", 44, "declined-addresses"),
+ int64_t(0));
+ isc::stats::StatsMgr::instance().setValue(
+ isc::stats::StatsMgr::generateName("subnet", 88, "declined-addresses"),
+ int64_t(0));
+ }
+ isc::stats::StatsMgr::instance().setValue(
+ isc::stats::StatsMgr::generateName("subnet", 44, "assigned-addresses"),
+ int64_t(2));
+ isc::stats::StatsMgr::instance().setValue(
+ isc::stats::StatsMgr::generateName("subnet", 88, "assigned-addresses"),
+ int64_t(2));
+ }
+ }
+ }
+
+ /// @brief This function checks that the JSON list contains an entry
+ /// indicating lease deletion, creation or update failure.
+ ///
+ /// @param failed_leases_list JSON list containing list of leases.
+ /// @param expected_type Expected lease type as text.
+ /// @param expected_ip_address Expected IP address.
+ /// @oaram expected_control_result Expected control result for the lease.
+ /// @param expected_error_msg Expected error message. Default is an empty
+ /// string which indicates that the error message should not be checked.
+ void checkFailedLease(const isc::data::ConstElementPtr& failed_leases_list,
+ const std::string& expected_type,
+ const std::string& expected_ip_address,
+ const int expected_control_result,
+ const std::string& expected_error_msg = "") {
+ ASSERT_TRUE(failed_leases_list);
+
+ for (auto i = 0; i < failed_leases_list->size(); ++i) {
+ auto failed_lease = failed_leases_list->get(i);
+ ASSERT_TRUE(failed_lease);
+ ASSERT_EQ(isc::data::Element::map, failed_lease->getType());
+
+ auto ip_address = failed_lease->get("ip-address");
+ ASSERT_TRUE(ip_address);
+ ASSERT_EQ(isc::data::Element::string, ip_address->getType());
+
+ if (ip_address->stringValue() == expected_ip_address) {
+ auto lease_type = failed_lease->get("type");
+ ASSERT_TRUE(lease_type);
+ ASSERT_EQ(isc::data::Element::string, lease_type->getType());
+ EXPECT_EQ(expected_type, lease_type->stringValue());
+
+ auto control_result = failed_lease->get("result");
+ ASSERT_TRUE(control_result);
+ ASSERT_EQ(isc::data::Element::integer, control_result->getType());
+ EXPECT_EQ(expected_control_result, control_result->intValue());
+
+ if (!expected_error_msg.empty()) {
+ auto error_msg = failed_lease->get("error-message");
+ ASSERT_TRUE(error_msg);
+ ASSERT_EQ(isc::data::Element::string, error_msg->getType());
+ EXPECT_EQ(expected_error_msg, error_msg->stringValue());
+ }
+
+ return;
+ }
+ }
+
+ ADD_FAILURE() << "expected lease not found";
+ }
+
+ /// @brief Enables DHCP-DDNS updates.
+ void enableD2() {
+ isc::dhcp::D2ClientConfigPtr cfg(new isc::dhcp::D2ClientConfig());
+ ASSERT_NO_THROW(cfg->enableUpdates(true));
+ ASSERT_NO_THROW(isc::dhcp::CfgMgr::instance().setD2ClientConfig(cfg));
+ d2_mgr_.startSender(std::bind(&LeaseCmdsTest::d2ErrorHandler, this,
+ std::placeholders::_1, std::placeholders::_2));
+ }
+
+ /// @brief Disables DHCP-DDNS updates.
+ void disableD2() {
+ d2_mgr_.stopSender();
+ // Default constructor creates a config with DHCP-DDNS updates
+ // disabled.
+ isc::dhcp::D2ClientConfigPtr cfg(new isc::dhcp::D2ClientConfig());
+ isc::dhcp::CfgMgr::instance().setD2ClientConfig(cfg);
+ }
+
+ /// @brief No-op error handler for D2.
+ void d2ErrorHandler(const isc::dhcp_ddns::NameChangeSender::Result,
+ isc::dhcp_ddns::NameChangeRequestPtr&) {
+ // no-op
+ }
+
+ /// @brief Fetches the number of entries in the NCR sender queue.
+ ///
+ /// @return The NCR queue size.
+ int ncrQueueSize() {
+ int size = -1;
+ try {
+ size = d2_mgr_.getQueueSize();
+ } catch (...) {
+ // If d2_mgr_ isn't in sending, it will throw.
+ // Swallow the exception and return -1.
+ }
+
+ return (size);
+ }
+
+ /// @brief Check that leaseX-del checks update-ddns input.
+ void testLeaseXDelBadUpdateDdnsParam();
+};
+
+} // end of anonymous namespace
diff --git a/src/hooks/dhcp/lease_cmds/tests/run_unittests.cc b/src/hooks/dhcp/lease_cmds/tests/run_unittests.cc
new file mode 100644
index 0000000..3b1baf9
--- /dev/null
+++ b/src/hooks/dhcp/lease_cmds/tests/run_unittests.cc
@@ -0,0 +1,19 @@
+// Copyright (C) 2017-2018 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);
+}