diff options
Diffstat (limited to 'src/lib/d2srv/testutils')
-rw-r--r-- | src/lib/d2srv/testutils/Makefile.am | 23 | ||||
-rw-r--r-- | src/lib/d2srv/testutils/Makefile.in | 876 | ||||
-rw-r--r-- | src/lib/d2srv/testutils/nc_test_utils.cc | 987 | ||||
-rw-r--r-- | src/lib/d2srv/testutils/nc_test_utils.h | 497 | ||||
-rw-r--r-- | src/lib/d2srv/testutils/stats_test_utils.cc | 41 | ||||
-rw-r--r-- | src/lib/d2srv/testutils/stats_test_utils.h | 48 |
6 files changed, 2472 insertions, 0 deletions
diff --git a/src/lib/d2srv/testutils/Makefile.am b/src/lib/d2srv/testutils/Makefile.am new file mode 100644 index 0000000..c7ae2ad --- /dev/null +++ b/src/lib/d2srv/testutils/Makefile.am @@ -0,0 +1,23 @@ +SUBDIRS = . + +AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib +AM_CPPFLAGS += $(BOOST_INCLUDES) + +AM_CXXFLAGS = $(KEA_CXXFLAGS) + +CLEANFILES = *.gcno *.gcda + +if HAVE_GTEST + +noinst_LTLIBRARIES = libd2srvtest.la + +libd2srvtest_la_SOURCES = nc_test_utils.cc nc_test_utils.h +libd2srvtest_la_SOURCES += stats_test_utils.cc stats_test_utils.h + +libd2srvtest_la_CXXFLAGS = $(AM_CXXFLAGS) +libd2srvtest_la_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) + +libd2srvtest_la_LIBADD = $(top_builddir)/src/lib/d2srv/libkea-d2srv.la +libd2srvtest_la_LIBADD += $(top_builddir)/src/lib/log/libkea-log.la + +endif diff --git a/src/lib/d2srv/testutils/Makefile.in b/src/lib/d2srv/testutils/Makefile.in new file mode 100644 index 0000000..c19494f --- /dev/null +++ b/src/lib/d2srv/testutils/Makefile.in @@ -0,0 +1,876 @@ +# 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@ +subdir = src/lib/d2srv/testutils +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 = +LTLIBRARIES = $(noinst_LTLIBRARIES) +@HAVE_GTEST_TRUE@libd2srvtest_la_DEPENDENCIES = $(top_builddir)/src/lib/d2srv/libkea-d2srv.la \ +@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/log/libkea-log.la +am__libd2srvtest_la_SOURCES_DIST = nc_test_utils.cc nc_test_utils.h \ + stats_test_utils.cc stats_test_utils.h +@HAVE_GTEST_TRUE@am_libd2srvtest_la_OBJECTS = \ +@HAVE_GTEST_TRUE@ libd2srvtest_la-nc_test_utils.lo \ +@HAVE_GTEST_TRUE@ libd2srvtest_la-stats_test_utils.lo +libd2srvtest_la_OBJECTS = $(am_libd2srvtest_la_OBJECTS) +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 = +libd2srvtest_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(libd2srvtest_la_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +@HAVE_GTEST_TRUE@am_libd2srvtest_la_rpath = +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)/libd2srvtest_la-nc_test_utils.Plo \ + ./$(DEPDIR)/libd2srvtest_la-stats_test_utils.Plo +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 = $(libd2srvtest_la_SOURCES) +DIST_SOURCES = $(am__libd2srvtest_la_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 +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 \ + $(BOOST_INCLUDES) +AM_CXXFLAGS = $(KEA_CXXFLAGS) +CLEANFILES = *.gcno *.gcda +@HAVE_GTEST_TRUE@noinst_LTLIBRARIES = libd2srvtest.la +@HAVE_GTEST_TRUE@libd2srvtest_la_SOURCES = nc_test_utils.cc \ +@HAVE_GTEST_TRUE@ nc_test_utils.h stats_test_utils.cc \ +@HAVE_GTEST_TRUE@ stats_test_utils.h +@HAVE_GTEST_TRUE@libd2srvtest_la_CXXFLAGS = $(AM_CXXFLAGS) +@HAVE_GTEST_TRUE@libd2srvtest_la_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) +@HAVE_GTEST_TRUE@libd2srvtest_la_LIBADD = $(top_builddir)/src/lib/d2srv/libkea-d2srv.la \ +@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/log/libkea-log.la +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/lib/d2srv/testutils/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib/d2srv/testutils/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-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libd2srvtest.la: $(libd2srvtest_la_OBJECTS) $(libd2srvtest_la_DEPENDENCIES) $(EXTRA_libd2srvtest_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libd2srvtest_la_LINK) $(am_libd2srvtest_la_rpath) $(libd2srvtest_la_OBJECTS) $(libd2srvtest_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libd2srvtest_la-nc_test_utils.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libd2srvtest_la-stats_test_utils.Plo@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 $@ $< + +libd2srvtest_la-nc_test_utils.lo: nc_test_utils.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libd2srvtest_la_CPPFLAGS) $(CPPFLAGS) $(libd2srvtest_la_CXXFLAGS) $(CXXFLAGS) -MT libd2srvtest_la-nc_test_utils.lo -MD -MP -MF $(DEPDIR)/libd2srvtest_la-nc_test_utils.Tpo -c -o libd2srvtest_la-nc_test_utils.lo `test -f 'nc_test_utils.cc' || echo '$(srcdir)/'`nc_test_utils.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libd2srvtest_la-nc_test_utils.Tpo $(DEPDIR)/libd2srvtest_la-nc_test_utils.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='nc_test_utils.cc' object='libd2srvtest_la-nc_test_utils.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libd2srvtest_la_CPPFLAGS) $(CPPFLAGS) $(libd2srvtest_la_CXXFLAGS) $(CXXFLAGS) -c -o libd2srvtest_la-nc_test_utils.lo `test -f 'nc_test_utils.cc' || echo '$(srcdir)/'`nc_test_utils.cc + +libd2srvtest_la-stats_test_utils.lo: stats_test_utils.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libd2srvtest_la_CPPFLAGS) $(CPPFLAGS) $(libd2srvtest_la_CXXFLAGS) $(CXXFLAGS) -MT libd2srvtest_la-stats_test_utils.lo -MD -MP -MF $(DEPDIR)/libd2srvtest_la-stats_test_utils.Tpo -c -o libd2srvtest_la-stats_test_utils.lo `test -f 'stats_test_utils.cc' || echo '$(srcdir)/'`stats_test_utils.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libd2srvtest_la-stats_test_utils.Tpo $(DEPDIR)/libd2srvtest_la-stats_test_utils.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='stats_test_utils.cc' object='libd2srvtest_la-stats_test_utils.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libd2srvtest_la_CPPFLAGS) $(CPPFLAGS) $(libd2srvtest_la_CXXFLAGS) $(CXXFLAGS) -c -o libd2srvtest_la-stats_test_utils.lo `test -f 'stats_test_utils.cc' || echo '$(srcdir)/'`stats_test_utils.cc + +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 + +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 +check: check-recursive +all-am: Makefile $(LTLIBRARIES) +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-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-recursive + -rm -f ./$(DEPDIR)/libd2srvtest_la-nc_test_utils.Plo + -rm -f ./$(DEPDIR)/libd2srvtest_la-stats_test_utils.Plo + -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)/libd2srvtest_la-nc_test_utils.Plo + -rm -f ./$(DEPDIR)/libd2srvtest_la-stats_test_utils.Plo + -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) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ + am--depfiles check check-am clean clean-generic clean-libtool \ + clean-noinstLTLIBRARIES 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/lib/d2srv/testutils/nc_test_utils.cc b/src/lib/d2srv/testutils/nc_test_utils.cc new file mode 100644 index 0000000..3903535 --- /dev/null +++ b/src/lib/d2srv/testutils/nc_test_utils.cc @@ -0,0 +1,987 @@ +// Copyright (C) 2013-2021 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 <asiolink/asio_wrapper.h> +#include <asiolink/udp_endpoint.h> +#include <d2srv/d2_cfg_mgr.h> +#include <d2srv/testutils/nc_test_utils.h> +#include <dns/messagerenderer.h> +#include <dns/opcode.h> +#include <util/encode/base64.h> + +#include <gtest/gtest.h> + +using namespace std; +using namespace isc; +using namespace isc::d2; +namespace ph = std::placeholders; + +namespace isc { +namespace d2 { + +const char* valid_d2_config = "{ " + "\"ip-address\" : \"127.0.0.1\" , " + "\"port\" : 5031, " + "\"tsig-keys\": [" + "{ \"name\": \"d2_key.example.com\" , " + " \"algorithm\": \"HMAC-MD5\" ," + " \"secret\": \"LSWXnfkKZjdPJI5QxlpnfQ==\" " + "} ]," + "\"forward-ddns\" : {" + "\"ddns-domains\": [ " + "{ \"name\": \"example.com.\" , " + " \"key-name\": \"d2_key.example.com\" , " + " \"dns-servers\" : [ " + " { \"ip-address\": \"127.0.0.101\" } " + "] } ] }, " + "\"reverse-ddns\" : {" + "\"ddns-domains\": [ " + "{ \"name\": \" 0.168.192.in.addr.arpa.\" , " + " \"key-name\": \"d2_key.example.com\" , " + " \"dns-servers\" : [ " + " { \"ip-address\": \"127.0.0.101\" , " + " \"port\": 100 } ] } " + "] } }"; + + +const char* TEST_DNS_SERVER_IP = "127.0.0.1"; +size_t TEST_DNS_SERVER_PORT = 5301; + +//const bool HAS_RDATA = true; +const bool NO_RDATA = false; + +//*************************** FauxServer class *********************** + +FauxServer::FauxServer(asiolink::IOService& io_service, + asiolink::IOAddress& address, size_t port) + :io_service_(io_service), address_(address), port_(port), + server_socket_(), receive_pending_(false), perpetual_receive_(true), + tsig_key_() { + + server_socket_.reset(new boost::asio::ip::udp::socket(io_service_.get_io_service(), + boost::asio::ip::udp::v4())); + server_socket_->set_option(boost::asio::socket_base::reuse_address(true)); + + isc::asiolink::UDPEndpoint endpoint(address_, port_); + server_socket_->bind(endpoint.getASIOEndpoint()); +} + +FauxServer::FauxServer(asiolink::IOService& io_service, + DnsServerInfo& server) + :io_service_(io_service), address_(server.getIpAddress()), + port_(server.getPort()), server_socket_(), receive_pending_(false), + perpetual_receive_(true), tsig_key_() { + server_socket_.reset(new boost::asio::ip::udp::socket(io_service_.get_io_service(), + boost::asio::ip::udp::v4())); + server_socket_->set_option(boost::asio::socket_base::reuse_address(true)); + isc::asiolink::UDPEndpoint endpoint(address_, port_); + server_socket_->bind(endpoint.getASIOEndpoint()); +} + + +FauxServer::~FauxServer() { +} + +void +FauxServer::receive (const ResponseMode& response_mode, + const dns::Rcode& response_rcode) { + if (receive_pending_) { + return; + } + + receive_pending_ = true; + server_socket_->async_receive_from(boost::asio::buffer(receive_buffer_, + sizeof(receive_buffer_)), + remote_, + std::bind(&FauxServer::requestHandler, + this, ph::_1, ph::_2, + response_mode, + response_rcode)); +} + +void +FauxServer::requestHandler(const boost::system::error_code& error, + std::size_t bytes_recvd, + const ResponseMode& response_mode, + const dns::Rcode& response_rcode) { + receive_pending_ = false; + // If we encountered an error or received no data then fail. + // We expect the client to send good requests. + if (error.value() != 0 || bytes_recvd < 1) { + ADD_FAILURE() << "FauxServer receive failed: " << error.message(); + return; + } + + // If TSIG key isn't NULL, create a context and use to verify the + // request and sign the response. + dns::TSIGContextPtr context; + if (tsig_key_) { + context.reset(new dns::TSIGContext(*tsig_key_)); + } + + // We have a successfully received data. We need to turn it into + // a request in order to build a proper response. + // Note D2UpdateMessage is geared towards making requests and + // reading responses. This is the opposite perspective so we have + // to a bit of roll-your-own here. + dns::Message request(dns::Message::PARSE); + util::InputBuffer request_buf(receive_buffer_, bytes_recvd); + try { + request.fromWire(request_buf); + + // If context is not NULL, then we need to verify the message. + if (context) { + dns::TSIGError error = context->verify(request.getTSIGRecord(), + receive_buffer_, + bytes_recvd); + if (error != dns::TSIGError::NOERROR()) { + isc_throw(TSIGVerifyError, "TSIG verification failed: " + << error.toText()); + } + } + } catch (const std::exception& ex) { + // If the request cannot be parsed, then fail the test. + // We expect the client to send good requests. + ADD_FAILURE() << "FauxServer request is corrupt:" << ex.what(); + return; + } + + // The request parsed OK, so let's build a response. + // We must use the QID we received in the response or IOFetch will + // toss the response out, resulting in eventual timeout. + // We fill in the zone with data we know is from the "server". + dns::Message response(dns::Message::RENDER); + response.setQid(request.getQid()); + dns::Question question(dns::Name("response.example.com"), + dns::RRClass::ANY(), dns::RRType::SOA()); + response.addQuestion(question); + response.setOpcode(dns::Opcode(dns::Opcode::UPDATE_CODE)); + response.setHeaderFlag(dns::Message::HEADERFLAG_QR, true); + + // Set the response Rcode to value passed in, default is NOERROR. + response.setRcode(response_rcode); + + // Render the response to a buffer. + dns::MessageRenderer renderer; + util::OutputBuffer response_buf(TEST_MSG_MAX); + renderer.setBuffer(&response_buf); + + if (response_mode == INVALID_TSIG) { + // Create a different key to sign the response. + std::string secret ("key that doesn't match"); + D2TsigKeyPtr key; + ASSERT_NO_THROW(key.reset(new + D2TsigKey(dns::Name("badkey"), + dns::TSIGKey::HMACMD5_NAME(), + secret.c_str(), secret.size()))); + context.reset(new dns::TSIGContext(*key)); + } + + response.toWire(renderer, context.get()); + + // If mode is to ship garbage, then stomp on part of the rendered + // message. + if (response_mode == CORRUPT_RESP) { + response_buf.writeUint16At(0xFFFF, 2); + } + + // Ship the response via synchronous send. + try { + int cnt = server_socket_->send_to(boost::asio:: + buffer(response_buf.getData(), + response_buf.getLength()), + remote_); + // Make sure we sent what we expect to send. + if (cnt != response_buf.getLength()) { + ADD_FAILURE() << "FauxServer sent: " << cnt << " expected: " + << response_buf.getLength(); + } + } catch (const std::exception& ex) { + ADD_FAILURE() << "FauxServer send failed: " << ex.what(); + } + + if (perpetual_receive_) { + // Schedule the next receive + receive (response_mode, response_rcode); + } +} + + + +//********************** TimedIO class *********************** + +TimedIO::TimedIO() + : io_service_(new isc::asiolink::IOService()), + timer_(*io_service_), run_time_(0) { +} + +TimedIO::~TimedIO() { +} + +int +TimedIO::runTimedIO(int run_time) { + run_time_ = run_time; + int cnt = io_service_->get_io_service().poll(); + if (cnt == 0) { + timer_.setup(std::bind(&TimedIO::timesUp, this), run_time_); + cnt = io_service_->get_io_service().run_one(); + timer_.cancel(); + } + + return (cnt); +} + +void +TimedIO::timesUp() { + io_service_->stop(); + FAIL() << "Test Time: " << run_time_ << " expired"; +} + +//********************** TransactionTest class *********************** + +const unsigned int TransactionTest::FORWARD_CHG = 0x01; +const unsigned int TransactionTest::REVERSE_CHG = 0x02; +const unsigned int TransactionTest::FWD_AND_REV_CHG = REVERSE_CHG | FORWARD_CHG; + +TransactionTest::TransactionTest() : ncr_(), cfg_mgr_(new D2CfgMgr()) { +} + +TransactionTest::~TransactionTest() { +} + +void +TransactionTest::setupForIPv4Transaction(dhcp_ddns::NameChangeType chg_type, + int change_mask, + const TSIGKeyInfoPtr& tsig_key_info) { + const char* msg_str = + "{" + " \"change-type\" : 0 , " + " \"forward-change\" : true , " + " \"reverse-change\" : true , " + " \"fqdn\" : \"my.forward.example.com.\" , " + " \"ip-address\" : \"192.168.2.1\" , " + " \"dhcid\" : \"0102030405060708\" , " + " \"lease-expires-on\" : \"20130121132405\" , " + " \"lease-length\" : 1300, " + " \"use-conflict-resolution\" : true " + "}"; + + // Create NameChangeRequest from JSON string. + ncr_ = dhcp_ddns::NameChangeRequest::fromJSON(msg_str); + + // Set the change type. + ncr_->setChangeType(chg_type); + + // If the change mask does not include a forward change clear the + // forward domain; otherwise create the domain and its servers. + if (!(change_mask & FORWARD_CHG)) { + ncr_->setForwardChange(false); + forward_domain_.reset(); + } else { + // Create the forward domain and then its servers. + forward_domain_ = makeDomain("example.com.", tsig_key_info); + addDomainServer(forward_domain_, "forward.example.com", + "127.0.0.1", 5301, tsig_key_info); + addDomainServer(forward_domain_, "forward2.example.com", + "127.0.0.1", 5302, tsig_key_info); + } + + // If the change mask does not include a reverse change clear the + // reverse domain; otherwise create the domain and its servers. + if (!(change_mask & REVERSE_CHG)) { + ncr_->setReverseChange(false); + reverse_domain_.reset(); + } else { + // Create the reverse domain and its server. + reverse_domain_ = makeDomain("2.168.192.in.addr.arpa.", tsig_key_info); + addDomainServer(reverse_domain_, "reverse.example.com", + "127.0.0.1", 5301, tsig_key_info); + addDomainServer(reverse_domain_, "reverse2.example.com", + "127.0.0.1", 5302, tsig_key_info); + } +} + +void +TransactionTest::setupForIPv4Transaction(dhcp_ddns::NameChangeType chg_type, + int change_mask, + const std::string& key_name) { + setupForIPv4Transaction(chg_type, change_mask, makeTSIGKeyInfo(key_name)); +} + +void +TransactionTest::setupForIPv6Transaction(dhcp_ddns::NameChangeType chg_type, + int change_mask, + const TSIGKeyInfoPtr& tsig_key_info) { + const char* msg_str = + "{" + " \"change-type\" : 0 , " + " \"forward-change\" : true , " + " \"reverse-change\" : true , " + " \"fqdn\" : \"my6.forward.example.com.\" , " + " \"ip-address\" : \"2001:1::100\" , " + " \"dhcid\" : \"0102030405060708\" , " + " \"lease-expires-on\" : \"20130121132405\" , " + " \"lease-length\" : 1300, " + " \"use-conflict-resolution\" : true " + "}"; + + // Create NameChangeRequest from JSON string. + ncr_ = makeNcrFromString(msg_str); + + // Set the change type. + ncr_->setChangeType(chg_type); + + // If the change mask does not include a forward change clear the + // forward domain; otherwise create the domain and its servers. + if (!(change_mask & FORWARD_CHG)) { + ncr_->setForwardChange(false); + forward_domain_.reset(); + } else { + // Create the forward domain and then its servers. + forward_domain_ = makeDomain("example.com.", tsig_key_info); + addDomainServer(forward_domain_, "fwd6-server.example.com", + "::1", 5301, tsig_key_info); + addDomainServer(forward_domain_, "fwd6-server2.example.com", + "::1", 5302, tsig_key_info); + } + + // If the change mask does not include a reverse change clear the + // reverse domain; otherwise create the domain and its servers. + if (!(change_mask & REVERSE_CHG)) { + ncr_->setReverseChange(false); + reverse_domain_.reset(); + } else { + // Create the reverse domain and its server. + reverse_domain_ = makeDomain("1.2001.ip6.arpa.", tsig_key_info); + addDomainServer(reverse_domain_, "rev6-server.example.com", + "::1", 5301, tsig_key_info); + addDomainServer(reverse_domain_, "rev6-server2.example.com", + "::1", 5302, tsig_key_info); + } +} + +void +TransactionTest::setupForIPv6Transaction(dhcp_ddns::NameChangeType chg_type, + int change_mask, + const std::string& key_name) { + setupForIPv6Transaction(chg_type, change_mask, makeTSIGKeyInfo(key_name)); +} + + +//********************** Functions **************************** + +void +checkRRCount(const D2UpdateMessagePtr& request, + D2UpdateMessage::UpdateMsgSection section, int count) { + dns::RRsetIterator rrset_it = request->beginSection(section); + dns::RRsetIterator rrset_end = request->endSection(section); + + ASSERT_EQ(count, std::distance(rrset_it, rrset_end)); +} + +void +checkZone(const D2UpdateMessagePtr& request, const std::string& exp_zone_name) { + // Verify the zone section info. + D2ZonePtr zone = request->getZone(); + EXPECT_TRUE(zone); + EXPECT_EQ(exp_zone_name, zone->getName().toText()); + EXPECT_EQ(dns::RRClass::IN().getCode(), zone->getClass().getCode()); +} + +void +checkRR(dns::RRsetPtr rrset, const std::string& exp_name, + const dns::RRClass& exp_class, const dns::RRType& exp_type, + unsigned int exp_ttl, dhcp_ddns::NameChangeRequestPtr ncr, + bool has_rdata) { + // Verify the FQDN/DHCID RR fields. + EXPECT_EQ(exp_name, rrset->getName().toText()); + EXPECT_EQ(exp_class.getCode(), rrset->getClass().getCode()); + EXPECT_EQ(exp_type.getCode(), rrset->getType().getCode()); + EXPECT_EQ(exp_ttl, rrset->getTTL().getValue()); + if ((!has_rdata) || + (exp_type == dns::RRType::ANY() || exp_class == dns::RRClass::ANY())) { + // ANY types do not have RData + ASSERT_EQ(0, rrset->getRdataCount()); + return; + } + + ASSERT_EQ(1, rrset->getRdataCount()); + dns::RdataIteratorPtr rdata_it = rrset->getRdataIterator(); + ASSERT_TRUE(rdata_it); + + if ((exp_type == dns::RRType::A()) || + (exp_type == dns::RRType::AAAA())) { + // should have lease rdata + EXPECT_EQ(ncr->getIpAddress(), rdata_it->getCurrent().toText()); + } else if (exp_type == dns::RRType::PTR()) { + // should have PTR rdata + EXPECT_EQ(ncr->getFqdn(), rdata_it->getCurrent().toText()); + } else if (exp_type == dns::RRType::DHCID()) { + // should have DHCID rdata + const std::vector<uint8_t>& ncr_dhcid = ncr->getDhcid().getBytes(); + util::InputBuffer buffer(ncr_dhcid.data(), ncr_dhcid.size()); + dns::rdata::in::DHCID rdata_ref(buffer, ncr_dhcid.size()); + EXPECT_EQ(0, rdata_ref.compare(rdata_it->getCurrent())); + } else { + // we got a problem + FAIL(); + } +} + +dns::RRsetPtr +getRRFromSection(const D2UpdateMessagePtr& request, + D2UpdateMessage::UpdateMsgSection section, int index) { + dns::RRsetIterator rrset_it = request->beginSection(section); + dns::RRsetIterator rrset_end = request->endSection(section); + + if (std::distance(rrset_it, rrset_end) <= index) { + // Return an empty pointer if index is out of range. + return (dns::RRsetPtr()); + } + + std::advance(rrset_it, index); + return (*rrset_it); +} + +dhcp_ddns::NameChangeRequestPtr +makeNcrFromString(const std::string& ncr_str) { + return (dhcp_ddns::NameChangeRequest::fromJSON(ncr_str)); +} + +DdnsDomainPtr +makeDomain(const std::string& zone_name, const std::string& key_name) { + DnsServerInfoStoragePtr servers(new DnsServerInfoStorage()); + DdnsDomainPtr domain(new DdnsDomain(zone_name, servers, key_name)); + return (domain); +} + +DdnsDomainPtr +makeDomain(const std::string& zone_name, const TSIGKeyInfoPtr &tsig_key_info) { + DdnsDomainPtr domain; + DnsServerInfoStoragePtr servers(new DnsServerInfoStorage()); + std::string key_name; + if (tsig_key_info) { + key_name = tsig_key_info->getName(); + } + domain.reset(new DdnsDomain(zone_name, servers, key_name)); + return (domain); +} + +TSIGKeyInfoPtr +makeTSIGKeyInfo(const std::string& key_name, const std::string& secret, + const std::string& algorithm) { + TSIGKeyInfoPtr key_info; + if (!key_name.empty()) { + if (!secret.empty()) { + key_info.reset(new TSIGKeyInfo(key_name, algorithm, secret)); + } else { + // Since secret was left blank, we'll convert key_name into a + // base64 encoded string and use that. + const uint8_t* bytes = reinterpret_cast<const uint8_t*> + (key_name.c_str()); + size_t len = key_name.size(); + const vector<uint8_t> key_name_v(bytes, bytes + len); + std::string key_name64 + = isc::util::encode::encodeBase64(key_name_v); + + // Now, make the TSIGKeyInfo with a real base64 secret. + key_info.reset(new TSIGKeyInfo(key_name, algorithm, key_name64)); + } + } + + return (key_info); +} + +void +addDomainServer(DdnsDomainPtr& domain, const std::string& name, + const std::string& ip, const size_t port, + const TSIGKeyInfoPtr &tsig_key_info) { + DnsServerInfoPtr server(new DnsServerInfo(name, asiolink::IOAddress(ip), + port, true, tsig_key_info)); + domain->getServers()->push_back(server); +} + +// Verifies that the contents of the given transaction's DNS update request +// is correct for adding a forward DNS entry +void +checkAddFwdAddressRequest(NameChangeTransaction& tran) { + const D2UpdateMessagePtr& request = tran.getDnsUpdateRequest(); + ASSERT_TRUE(request); + + // Safety check. + dhcp_ddns::NameChangeRequestPtr ncr = tran.getNcr(); + ASSERT_TRUE(ncr); + + std::string exp_zone_name = tran.getForwardDomain()->getName(); + std::string exp_fqdn = ncr->getFqdn(); + const dns::RRType& exp_ip_rr_type = tran.getAddressRRType(); + + // Verify the zone section. + checkZone(request, exp_zone_name); + + // Verify the PREREQUISITE SECTION + // Should be 1 which tests for FQDN does not exist. + dns::RRsetPtr rrset; + checkRRCount(request, D2UpdateMessage::SECTION_PREREQUISITE, 1); + ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage:: + SECTION_PREREQUISITE, 0)); + checkRR(rrset, exp_fqdn, dns::RRClass::NONE(), dns::RRType::ANY(), 0, ncr); + + // Verify the UPDATE SECTION + // Should be 2 RRs: 1 to add the FQDN/IP and one to add the DHCID RR + checkRRCount(request, D2UpdateMessage::SECTION_UPDATE, 2); + + // Fetch ttl. + uint32_t ttl = ncr->getLeaseLength(); + + // First, Verify the FQDN/IP add RR. + ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage:: + SECTION_UPDATE, 0)); + checkRR(rrset, exp_fqdn, dns::RRClass::IN(), exp_ip_rr_type, ttl, ncr); + + // Now, verify the DHCID add RR. + ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage:: + SECTION_UPDATE, 1)); + checkRR(rrset, exp_fqdn, dns::RRClass::IN(), dns::RRType::DHCID(), + ttl, ncr); + + // Verify there are no RRs in the ADDITIONAL Section. + checkRRCount(request, D2UpdateMessage::SECTION_ADDITIONAL, 0); + + // Verify that it will render toWire without throwing. + dns::MessageRenderer renderer; + ASSERT_NO_THROW(request->toWire(renderer)); +} + +// Verifies that the contents of the given transaction's DNS update request +// is correct for replacing a forward DNS entry +void +checkReplaceFwdAddressRequest(NameChangeTransaction& tran) { + const D2UpdateMessagePtr& request = tran.getDnsUpdateRequest(); + ASSERT_TRUE(request); + + // Safety check. + dhcp_ddns::NameChangeRequestPtr ncr = tran.getNcr(); + ASSERT_TRUE(ncr); + + std::string exp_zone_name = tran.getForwardDomain()->getName(); + std::string exp_fqdn = ncr->getFqdn(); + const dns::RRType& exp_ip_rr_type = tran.getAddressRRType(); + + // Verify the zone section. + checkZone(request, exp_zone_name); + + // Verify the PREREQUISITE SECTION + // Should be 2, 1 which tests for FQDN does exist and the other + // checks for a matching DHCID. + dns::RRsetPtr rrset; + checkRRCount(request, D2UpdateMessage::SECTION_PREREQUISITE, 2); + + // Verify the FQDN test RR. + ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage:: + SECTION_PREREQUISITE, 0)); + checkRR(rrset, exp_fqdn, dns::RRClass::ANY(), dns::RRType::ANY(), 0, ncr); + + // Verify the DHCID test RR. + ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage:: + SECTION_PREREQUISITE, 1)); + checkRR(rrset, exp_fqdn, dns::RRClass::IN(), dns::RRType::DHCID(), 0, ncr); + + // Verify the UPDATE SECTION + // Should be 2, 1 which deletes the existing FQDN/IP and one that + // adds the new one. + checkRRCount(request, D2UpdateMessage::SECTION_UPDATE, 2); + + // Fetch ttl. + uint32_t ttl = ncr->getLeaseLength(); + + // Verify the FQDN delete RR. + ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage:: + SECTION_UPDATE, 0)); + checkRR(rrset, exp_fqdn, dns::RRClass::ANY(), exp_ip_rr_type, 0, ncr); + + // Verify the FQDN/IP add RR. + ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage:: + SECTION_UPDATE, 1)); + checkRR(rrset, exp_fqdn, dns::RRClass::IN(), exp_ip_rr_type, ttl, ncr); + + // Verify there are no RRs in the ADDITIONAL Section. + checkRRCount(request, D2UpdateMessage::SECTION_ADDITIONAL, 0); + + // Verify that it will render toWire without throwing. + dns::MessageRenderer renderer; + ASSERT_NO_THROW(request->toWire(renderer)); +} + +// Verifies that the contents of the given transaction's DNS update request +// is correct for replacing a reverse DNS entry +void +checkReplaceRevPtrsRequest(NameChangeTransaction& tran) { + const D2UpdateMessagePtr& request = tran.getDnsUpdateRequest(); + ASSERT_TRUE(request); + + // Safety check. + dhcp_ddns::NameChangeRequestPtr ncr = tran.getNcr(); + ASSERT_TRUE(ncr); + + std::string exp_zone_name = tran.getReverseDomain()->getName(); + std::string exp_rev_addr = D2CfgMgr::reverseIpAddress(ncr->getIpAddress()); + + // Verify the zone section. + checkZone(request, exp_zone_name); + + // Verify there are no RRs in the PREREQUISITE Section. + checkRRCount(request, D2UpdateMessage::SECTION_PREREQUISITE, 0); + + // Fetch ttl. + uint32_t ttl = ncr->getLeaseLength(); + + // Verify the UPDATE Section. + // It should contain 4 RRs: + // 1. A delete all PTR RRs for the given IP + // 2. A delete of all DHCID RRs for the given IP + // 3. An add of the new PTR RR + // 4. An add of the new DHCID RR + dns::RRsetPtr rrset; + checkRRCount(request, D2UpdateMessage::SECTION_UPDATE, 4); + + // Verify the PTR delete RR. + ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage:: + SECTION_UPDATE, 0)); + checkRR(rrset, exp_rev_addr, dns::RRClass::ANY(), dns::RRType::PTR(), + 0, ncr); + + // Verify the DHCID delete RR. + ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage:: + SECTION_UPDATE, 1)); + checkRR(rrset, exp_rev_addr, dns::RRClass::ANY(), dns::RRType::DHCID(), + 0, ncr); + + // Verify the PTR add RR. + ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage:: + SECTION_UPDATE, 2)); + checkRR(rrset, exp_rev_addr, dns::RRClass::IN(), dns::RRType::PTR(), + ttl, ncr); + + // Verify the DHCID add RR. + ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage:: + SECTION_UPDATE, 3)); + checkRR(rrset, exp_rev_addr, dns::RRClass::IN(), dns::RRType::DHCID(), + ttl, ncr); + + // Verify there are no RRs in the ADDITIONAL Section. + checkRRCount(request, D2UpdateMessage::SECTION_ADDITIONAL, 0); + + // Verify that it will render toWire without throwing. + dns::MessageRenderer renderer; + ASSERT_NO_THROW(request->toWire(renderer)); +} + +void +checkRemoveFwdAddressRequest(NameChangeTransaction& tran) { + const D2UpdateMessagePtr& request = tran.getDnsUpdateRequest(); + ASSERT_TRUE(request); + + // Safety check. + dhcp_ddns::NameChangeRequestPtr ncr = tran.getNcr(); + ASSERT_TRUE(ncr); + + std::string exp_zone_name = tran.getForwardDomain()->getName(); + std::string exp_fqdn = ncr->getFqdn(); + + // Verify the zone section. + checkZone(request, exp_zone_name); + + // Verify there is 1 RR in the PREREQUISITE Section. + checkRRCount(request, D2UpdateMessage::SECTION_PREREQUISITE, 1); + + // Verify the DHCID matching assertion RR. + dns::RRsetPtr rrset; + ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage:: + SECTION_PREREQUISITE, 0)); + checkRR(rrset, exp_fqdn, dns::RRClass::IN(), dns::RRType::DHCID(), + 0, ncr); + + // Verify there is 1 RR in the UPDATE Section. + checkRRCount(request, D2UpdateMessage::SECTION_UPDATE, 1); + + // Verify the FQDN/IP delete RR. + const dns::RRType& exp_ip_rr_type = tran.getAddressRRType(); + ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage:: + SECTION_UPDATE, 0)); + checkRR(rrset, exp_fqdn, dns::RRClass::NONE(), exp_ip_rr_type, + 0, ncr); + + // Verify that it will render toWire without throwing. + dns::MessageRenderer renderer; + ASSERT_NO_THROW(request->toWire(renderer)); +} + +void +checkRemoveFwdRRsRequest(NameChangeTransaction& tran) { + const D2UpdateMessagePtr& request = tran.getDnsUpdateRequest(); + ASSERT_TRUE(request); + + // Safety check. + dhcp_ddns::NameChangeRequestPtr ncr = tran.getNcr(); + ASSERT_TRUE(ncr); + + std::string exp_zone_name = tran.getForwardDomain()->getName(); + std::string exp_fqdn = ncr->getFqdn(); + + // Verify the zone section. + checkZone(request, exp_zone_name); + + // Verify there is 1 RR in the PREREQUISITE Section. + checkRRCount(request, D2UpdateMessage::SECTION_PREREQUISITE, 3); + + // Verify the DHCID matches assertion. + dns::RRsetPtr rrset; + ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage:: + SECTION_PREREQUISITE, 0)); + checkRR(rrset, exp_fqdn, dns::RRClass::IN(), dns::RRType::DHCID(), + 0, ncr); + + // Verify the NO A RRs assertion. + ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage:: + SECTION_PREREQUISITE, 1)); + checkRR(rrset, exp_fqdn, dns::RRClass::NONE(), dns::RRType::A(), + 0, ncr, NO_RDATA); + + // Verify the NO AAAA RRs assertion. + ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage:: + SECTION_PREREQUISITE, 2)); + checkRR(rrset, exp_fqdn, dns::RRClass::NONE(), dns::RRType::AAAA(), + 0, ncr, NO_RDATA); + + // Verify there is 1 RR in the UPDATE Section. + checkRRCount(request, D2UpdateMessage::SECTION_UPDATE, 1); + + // Verify the delete all for the FQDN RR. + ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage:: + SECTION_UPDATE, 0)); + checkRR(rrset, exp_fqdn, dns::RRClass::ANY(), dns::RRType::ANY(), + 0, ncr); + + // Verify that it will render toWire without throwing. + dns::MessageRenderer renderer; + ASSERT_NO_THROW(request->toWire(renderer)); +} + +void +checkRemoveRevPtrsRequest(NameChangeTransaction& tran) { + const D2UpdateMessagePtr& request = tran.getDnsUpdateRequest(); + ASSERT_TRUE(request); + + // Safety check. + dhcp_ddns::NameChangeRequestPtr ncr = tran.getNcr(); + ASSERT_TRUE(ncr); + + std::string exp_zone_name = tran.getReverseDomain()->getName(); + std::string exp_rev_addr = D2CfgMgr::reverseIpAddress(ncr->getIpAddress()); + + // Verify the zone section. + checkZone(request, exp_zone_name); + + // Verify there is 1 RR in the PREREQUISITE Section. + checkRRCount(request, D2UpdateMessage::SECTION_PREREQUISITE, 1); + + // Verify the FQDN-PTRNAME assertion RR. + dns::RRsetPtr rrset; + ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage:: + SECTION_PREREQUISITE, 0)); + checkRR(rrset, exp_rev_addr, dns::RRClass::IN(), dns::RRType::PTR(), + 0, ncr); + + // Verify there is 1 RR in the UPDATE Section. + checkRRCount(request, D2UpdateMessage::SECTION_UPDATE, 1); + + // Verify the delete all for the FQDN RR. + ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage:: + SECTION_UPDATE, 0)); + checkRR(rrset, exp_rev_addr, dns::RRClass::ANY(), dns::RRType::ANY(), + 0, ncr); + + // Verify that it will render toWire without throwing. + dns::MessageRenderer renderer; + ASSERT_NO_THROW(request->toWire(renderer)); +} + +std::string +toHexText(const uint8_t* data, size_t len) { + std::ostringstream stream; + stream << "Data length is: " << len << std::endl; + for (int i = 0; i < len; ++i) { + if (i > 0 && ((i % 16) == 0)) { + stream << std::endl; + } + + stream << setfill('0') << setw(2) << setbase(16) + << static_cast<unsigned int>(data[i]) << " "; + } + + return (stream.str()); +} + +// Verifies that the contents of the given transaction's DNS update request +// is correct for replacing a forward DNS entry when not using conflict +// resolution. +void +checkSimpleReplaceFwdAddressRequest(NameChangeTransaction& tran) { + const D2UpdateMessagePtr& request = tran.getDnsUpdateRequest(); + ASSERT_TRUE(request); + + // Safety check. + dhcp_ddns::NameChangeRequestPtr ncr = tran.getNcr(); + ASSERT_TRUE(ncr); + + std::string exp_zone_name = tran.getForwardDomain()->getName(); + std::string exp_fqdn = ncr->getFqdn(); + const dns::RRType& exp_ip_rr_type = tran.getAddressRRType(); + + // Verify the zone section. + checkZone(request, exp_zone_name); + + // Verify the PREREQUISITE SECTION + // There should be no prerequisites. + dns::RRsetPtr rrset; + checkRRCount(request, D2UpdateMessage::SECTION_PREREQUISITE, 0); + + // Verify the UPDATE SECTION + // Should be 4 + // 1. delete of the FQDN/IP RR + // 2. delete of the DHCID RR + // 3. add of the FQDN/IP RR + // 4. add of the DHCID RR + checkRRCount(request, D2UpdateMessage::SECTION_UPDATE, 4); + + // Fetch ttl. + uint32_t ttl = ncr->getLeaseLength(); + + // Verify the FQDN delete RR. + ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage:: + SECTION_UPDATE, 0)); + checkRR(rrset, exp_fqdn, dns::RRClass::ANY(), exp_ip_rr_type, 0, ncr); + + // Verify the DHCID delete RR. + ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage:: + SECTION_UPDATE, 1)); + checkRR(rrset, exp_fqdn, dns::RRClass::ANY(), dns::RRType::DHCID(), + 0, ncr); + + // Verify the FQDN/IP add RR. + ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage:: + SECTION_UPDATE, 2)); + checkRR(rrset, exp_fqdn, dns::RRClass::IN(), exp_ip_rr_type, ttl, ncr); + + // Now, verify the DHCID add RR. + ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage:: + SECTION_UPDATE, 3)); + checkRR(rrset, exp_fqdn, dns::RRClass::IN(), dns::RRType::DHCID(), + ttl, ncr); + + // Verify there are no RRs in the ADDITIONAL Section. + checkRRCount(request, D2UpdateMessage::SECTION_ADDITIONAL, 0); + + // Verify that it will render toWire without throwing. + dns::MessageRenderer renderer; + ASSERT_NO_THROW(request->toWire(renderer)); +} + +void +checkSimpleRemoveFwdRRsRequest(NameChangeTransaction& tran) { + const D2UpdateMessagePtr& request = tran.getDnsUpdateRequest(); + ASSERT_TRUE(request); + + // Safety check. + dhcp_ddns::NameChangeRequestPtr ncr = tran.getNcr(); + ASSERT_TRUE(ncr); + + std::string exp_zone_name = tran.getForwardDomain()->getName(); + std::string exp_fqdn = ncr->getFqdn(); + const dns::RRType& exp_ip_rr_type = tran.getAddressRRType(); + + // Verify the zone section. + checkZone(request, exp_zone_name); + + // Verify there no prerequisites. + checkRRCount(request, D2UpdateMessage::SECTION_PREREQUISITE, 0); + + // Verify there are 2 RRs in the UPDATE Section. + checkRRCount(request, D2UpdateMessage::SECTION_UPDATE, 2); + + // Verify the FQDN delete RR. + dns::RRsetPtr rrset; + ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage:: + SECTION_UPDATE, 0)); + checkRR(rrset, exp_fqdn, dns::RRClass::ANY(), exp_ip_rr_type, 0, ncr); + + // Verify the DHCID delete RR. + ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage:: + SECTION_UPDATE, 1)); + checkRR(rrset, exp_fqdn, dns::RRClass::ANY(), dns::RRType::DHCID(), + 0, ncr); + + // Verify that it will render toWire without throwing. + dns::MessageRenderer renderer; + ASSERT_NO_THROW(request->toWire(renderer)); +} + +// Verifies that the contents of the given transaction's DNS update request +// is correct for removing a reverse DNS entry when not using conflict +// resolution. +void +checkSimpleRemoveRevPtrsRequest(NameChangeTransaction& tran) { + const D2UpdateMessagePtr& request = tran.getDnsUpdateRequest(); + ASSERT_TRUE(request); + + // Safety check. + dhcp_ddns::NameChangeRequestPtr ncr = tran.getNcr(); + ASSERT_TRUE(ncr); + + std::string exp_zone_name = tran.getReverseDomain()->getName(); + std::string exp_rev_addr = D2CfgMgr::reverseIpAddress(ncr->getIpAddress()); + + // Verify the zone section. + checkZone(request, exp_zone_name); + + // Verify there are no RRs in the PREREQUISITE Section. + checkRRCount(request, D2UpdateMessage::SECTION_PREREQUISITE, 0); + + // Verify there is 2 RRs in the UPDATE Section. + checkRRCount(request, D2UpdateMessage::SECTION_UPDATE, 2); + + // Verify the FQDN delete RR. + dns::RRsetPtr rrset; + ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage:: + SECTION_UPDATE, 0)); + checkRR(rrset, exp_rev_addr, dns::RRClass::ANY(), dns::RRType::PTR(), 0, ncr); + + // Verify the DHCID delete RR. + ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage:: + SECTION_UPDATE, 1)); + checkRR(rrset, exp_rev_addr, dns::RRClass::ANY(), dns::RRType::DHCID(), 0, ncr); + + // Verify that it will render toWire without throwing. + dns::MessageRenderer renderer; + ASSERT_NO_THROW(request->toWire(renderer)); +} + +// Verifies the current state and next event in a transaction +void +checkContext(NameChangeTransactionPtr trans, const int exp_state, + const int exp_evt, const std::string& file, int line) { + ASSERT_TRUE(trans); + ASSERT_TRUE(exp_state == trans->getCurrState() && exp_evt == trans->getNextEvent()) + << "expected state: " << trans->getStateLabel(exp_state) + << " event: " << trans->getEventLabel(exp_evt) + << ", actual context: " << trans->getContextStr() + << " at " << file << ":" << line; +} + +} // namespace isc::d2 +} // namespace isc diff --git a/src/lib/d2srv/testutils/nc_test_utils.h b/src/lib/d2srv/testutils/nc_test_utils.h new file mode 100644 index 0000000..73b6287 --- /dev/null +++ b/src/lib/d2srv/testutils/nc_test_utils.h @@ -0,0 +1,497 @@ +// Copyright (C) 2013-2021 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/. + +#ifndef NC_TEST_UTILS_H +#define NC_TEST_UTILS_H + +/// @file nc_test_utils.h prototypes for functions related transaction testing. + +#include <asiolink/io_service.h> +#include <asiolink/interval_timer.h> +#include <d2srv/d2_update_message.h> +#include <d2srv/nc_trans.h> + +#include <boost/asio/ip/udp.hpp> +#include <boost/asio/socket_base.hpp> +#include <gtest/gtest.h> + +namespace isc { +namespace d2 { + +extern const char* valid_d2_config; +extern const char* TEST_DNS_SERVER_IP; +extern size_t TEST_DNS_SERVER_PORT; + +// Not extern'ed to allow use as array size +const int TEST_MSG_MAX = 1024; + +typedef boost::shared_ptr<boost::asio::ip::udp::socket> SocketPtr; + +/// @brief This class simulates a DNS server. It is capable of performing +/// an asynchronous read, governed by an IOService, and responding to received +/// requests in a given manner. +class FauxServer { +public: + /// @brief The types of response generated by the server. + enum ResponseMode { + USE_RCODE, // Generate a response with a given RCODE + CORRUPT_RESP, // Generate a corrupt response + INVALID_TSIG // Generate a response with the wrong TSIG key + }; + + /// @brief Reference to IOService to use for IO processing. + asiolink::IOService& io_service_; + + /// @brief IP address at which to listen for requests. + const asiolink::IOAddress& address_; + + /// @brief Port on which to listen for requests. + size_t port_; + + /// @brief Socket on which listening is done. + SocketPtr server_socket_; + + /// @brief Stores the end point of requesting client. + boost::asio::ip::udp::endpoint remote_; + + /// @brief Buffer in which received packets are stuffed. + uint8_t receive_buffer_[TEST_MSG_MAX]; + + /// @brief Flag which indicates if a receive has been initiated but not yet + /// completed. + bool receive_pending_; + /// @brief Flag which indicates if server is in perpetual receive mode. + /// If true once a receive has been completed, a new one will be + /// automatically initiated. + bool perpetual_receive_; + + /// @brief TSIG Key to use to verify requests and sign responses. If it is + /// NULL TSIG is not used. + D2TsigKeyPtr tsig_key_; + + /// @brief Constructor + /// + /// @param io_service IOService to be used for socket IO. + /// @param address IP address at which the server should listen. + /// @param port Port number at which the server should listen. + FauxServer(asiolink::IOService& io_service, asiolink::IOAddress& address, + size_t port); + + /// @brief Constructor + /// + /// @param io_service IOService to be used for socket IO. + /// @param server DnsServerInfo of server the DNS server. This supplies the + /// server's ip address and port. + FauxServer(asiolink::IOService& io_service, DnsServerInfo& server); + + /// @brief Destructor + virtual ~FauxServer(); + + /// @brief Initiates an asynchronous receive + /// + /// Starts the server listening for requests. Upon completion of the + /// listen, the callback method, requestHandler, is invoked. + /// + /// @param response_mode Selects how the server responds to a request + /// @param response_rcode The Rcode value set in the response. Not used + /// for all modes. + void receive (const ResponseMode& response_mode, + const dns::Rcode& response_rcode=dns::Rcode::NOERROR()); + + /// @brief Socket IO Completion callback + /// + /// This method servers as the Server's UDP socket receive callback handler. + /// When the receive completes the handler is invoked with the parameters + /// listed. + /// + /// @param error result code of the receive (determined by asio layer) + /// @param bytes_recvd number of bytes received, if any + /// @param response_mode type of response the handler should produce + /// @param response_rcode value of Rcode in the response constructed by + /// handler + void requestHandler(const boost::system::error_code& error, + std::size_t bytes_recvd, + const ResponseMode& response_mode, + const dns::Rcode& response_rcode); + + /// @brief Returns true if a receive has been started but not completed. + bool isReceivePending() { + return receive_pending_; + } + + /// @brief Sets the TSIG key to the given value. + /// + /// @param tsig_key Pointer to the TSIG key to use. If the pointer is + /// empty, TSIG will not be used. + void setTSIGKey(const D2TsigKeyPtr& tsig_key) { + tsig_key_ = tsig_key; + } +}; + +/// @brief Provides a means to process IOService IO for a finite amount of time. +/// +/// This class instantiates an IOService provides a single method, runTimedIO +/// which will run the IOService for no more than a finite amount of time, +/// at least one event is executed or the IOService is stopped. +/// It provides an virtual handler for timer expiration event. It is +/// intended to be used as a base class for test fixtures that need to process +/// IO by providing them a consistent way to do so while retaining a safety +/// valve so tests do not hang. +class TimedIO { +public: + asiolink::IOServicePtr io_service_; + asiolink::IntervalTimer timer_; + int run_time_; + + /// @brief Constructor + TimedIO(); + + /// @brief Destructor + virtual ~TimedIO(); + + /// @brief IO Timer expiration handler + /// + /// Stops the IOService and fails the current test. + virtual void timesUp(); + + /// @brief Processes IO till time expires or at least one handler executes. + /// + /// This method first polls IOService to run any ready handlers. If no + /// handlers are ready, it starts the internal time to run for the given + /// amount of time and invokes service's run_one method. This method + /// blocks until at least one handler executes or the IO Service is stopped. + /// Upon completion of this method the timer is cancelled. Should the + /// timer expires prior to run_one returning, the timesUp handler will be + /// invoked which stops the IO service and fails the test. + /// + /// Note that this method closely mimics the runIO method in D2Process. + /// + /// @param run_time maximum length of time to run in milliseconds before + /// timing out. + /// + /// @return Returns the number of handlers executed or zero. A return of + /// zero indicates that the IOService has been stopped. + int runTimedIO(int run_time); + +}; + +/// @brief Base class Test fixture for testing transactions. +class TransactionTest : public TimedIO, public ::testing::Test { +public: + dhcp_ddns::NameChangeRequestPtr ncr_; + DdnsDomainPtr forward_domain_; + DdnsDomainPtr reverse_domain_; + D2CfgMgrPtr cfg_mgr_; + + /// @brief constants used to specify change directions for a transaction. + static const unsigned int FORWARD_CHG; // Only forward change. + static const unsigned int REVERSE_CHG; // Only reverse change. + static const unsigned int FWD_AND_REV_CHG; // Both forward and reverse. + + TransactionTest(); + virtual ~TransactionTest(); + + /// @brief Creates a transaction which requests an IPv4 DNS update. + /// + /// The transaction is constructed around a predefined (i.e. "canned") + /// IPv4 NameChangeRequest. The request has both forward and reverse DNS + /// changes requested. Based upon the change mask, the transaction + /// will have either the forward, reverse, or both domains populated. + /// + /// @param change_type selects the type of change requested, CHG_ADD or + /// CHG_REMOVE. + /// @param change_mask determines which change directions are requested + /// FORWARD_CHG, REVERSE_CHG, or FWD_AND_REV_CHG. + /// @param tsig_key_info pointer to the TSIGKeyInfo to assign to both + /// domains in the transaction. This will cause the transaction to + /// use TSIG. If the pointer is empty, TSIG will not be used. + void setupForIPv4Transaction(dhcp_ddns::NameChangeType change_type, + int change_mask, + const TSIGKeyInfoPtr& tsig_key_info = + TSIGKeyInfoPtr()); + + /// @brief Creates a transaction which requests an IPv4 DNS update. + /// + /// Convenience wrapper around the above method which accepts a string + /// key_name from which the TSIGKeyInfo is constructed. Note the string + /// may not be blank. + /// + /// @param change_type selects the type of change requested, CHG_ADD or + /// CHG_REMOVE. + /// @param change_mask determines which change directions are requested + /// FORWARD_CHG, REVERSE_CHG, or FWD_AND_REV_CHG. + /// @param key_name value to use to create TSIG key. The value may not + /// be blank. + void setupForIPv4Transaction(dhcp_ddns::NameChangeType change_type, + int change_mask, const std::string& key_name); + + /// @brief Creates a transaction which requests an IPv6 DNS update. + /// + /// The transaction is constructed around a predefined (i.e. "canned") + /// IPv6 NameChangeRequest. The request has both forward and reverse DNS + /// changes requested. Based upon the change mask, the transaction + /// will have either the forward, reverse, or both domains populated. + /// + /// @param change_type selects the type of change requested, CHG_ADD or + /// CHG_REMOVE. + /// @param change_mask determines which change directions are requested + /// FORWARD_CHG, REVERSE_CHG, or FWD_AND_REV_CHG. + /// @param tsig_key_info pointer to the TSIGKeyInfo to assign to both + /// domains in the transaction. This will cause the transaction to + /// use TSIG. If the pointer is empty, TSIG will not be used. + void setupForIPv6Transaction(dhcp_ddns::NameChangeType change_type, + int change_mask, + const TSIGKeyInfoPtr& tsig_key_info = + TSIGKeyInfoPtr()); + + /// @brief Creates a transaction which requests an IPv6 DNS update. + /// + /// Convenience wrapper around the above method which accepts a string + /// key_name from which the TSIGKeyInfo is constructed. Note the string + /// may not be blank. + /// + /// @param change_type selects the type of change requested, CHG_ADD or + /// CHG_REMOVE. + /// @param change_mask determines which change directions are requested + /// FORWARD_CHG, REVERSE_CHG, or FWD_AND_REV_CHG. + /// @param key_name value to use to create TSIG key, if blank TSIG will not + /// be used. + void setupForIPv6Transaction(dhcp_ddns::NameChangeType change_type, + int change_mask, const std::string& key_name); +}; + + +/// @brief Tests the number of RRs in a request section against a given count. +/// +/// This function actually returns the number of RRsetPtrs in a section. Since +/// D2 only uses RRsets with a single RData in each (i.e. 1 RR), it is used +/// as the number of RRs. The dns::Message::getRRCount() cannot be used for +/// this as it returns the number of RDatas in an RRSet which does NOT equate +/// to the number of RRs. RRs with no RData, those with class or type of ANY, +/// are not counted. +/// +/// @param request DNS update request to test +/// @param section enum value of the section to count +/// @param count the expected number of RRs +extern void checkRRCount(const D2UpdateMessagePtr& request, + D2UpdateMessage::UpdateMsgSection section, int count); + +/// @brief Tests the zone content of a given request. +/// +/// @param request DNS update request to validate +/// @param exp_zone_name expected value of the zone name in the zone section +extern void checkZone(const D2UpdateMessagePtr& request, + const std::string& exp_zone_name); + +/// @brief Tests the contents of an RRset +/// +/// @param rrset Pointer the RRset to test +/// @param exp_name expected value of RRset name (FQDN or reverse ip) +/// @param exp_class expected RRClass value of RRset +/// @param exp_typ expected RRType value of RRset +/// @param exp_ttl expected TTL value of RRset +/// @param ncr NameChangeRequest on which the RRset is based +/// @param has_rdata if true, RRset's rdata will be checked based on it's +/// RRType. Set this to false if the RRset's type supports Rdata but it does +/// not contain it. For instance, prerequisites of type NONE have no Rdata +/// where updates of type NONE may. +extern void checkRR(dns::RRsetPtr rrset, const std::string& exp_name, + const dns::RRClass& exp_class, const dns::RRType& exp_type, + unsigned int exp_ttl, dhcp_ddns::NameChangeRequestPtr ncr, + bool has_rdata=true); + +/// @brief Fetches an RR(set) from a given section of a request +/// +/// @param request DNS update request from which the RR should come +/// @param section enum value of the section from which the RR should come +/// @param index zero-based index of the RR of interest. +/// +/// @return Pointer to the RR of interest, empty pointer if the index is out +/// of range. +extern dns::RRsetPtr getRRFromSection(const D2UpdateMessagePtr& request, + D2UpdateMessage::UpdateMsgSection section, + int index); +/// @brief Creates a NameChangeRequest from a JSON string +/// +/// @param ncr_str JSON string form of a NameChangeRequest. Example: +/// @code +/// const char* msg_str = +/// "{" +/// " \"change-type\" : 0 , " +/// " \"forward-change\" : true , " +/// " \"reverse-change\" : true , " +/// " \"fqdn\" : \"my.example.com.\" , " +/// " \"ip-address\" : \"192.168.2.1\" , " +/// " \"dhcid\" : \"0102030405060708\" , " +/// " \"lease-expires-on\" : \"20130121132405\" , " +/// " \"lease-length\" : 1300 " +/// "}"; +/// +/// @endcode + +/// @brief Verifies a forward mapping addition DNS update request +/// +/// Tests that the DNS Update request for a given transaction, is correct for +/// adding a forward DNS mapping. +/// +/// @param tran Transaction containing the request to be verified. +extern void checkAddFwdAddressRequest(NameChangeTransaction& tran); + +/// @brief Verifies a forward mapping replacement DNS update request +/// +/// Tests that the DNS Update request for a given transaction, is correct for +/// replacing a forward DNS mapping. +/// +/// @param tran Transaction containing the request to be verified. +extern void checkReplaceFwdAddressRequest(NameChangeTransaction& tran); + +/// @brief Verifies a reverse mapping replacement DNS update request +/// +/// Tests that the DNS Update request for a given transaction, is correct for +/// replacing a reverse DNS mapping. +/// +/// @param tran Transaction containing the request to be verified. +extern void checkReplaceRevPtrsRequest(NameChangeTransaction& tran); + +/// @brief Verifies a forward address removal DNS update request +/// +/// Tests that the DNS Update request for a given transaction, is correct for +/// removing the forward address DNS entry. +/// +/// @param tran Transaction containing the request to be verified. +extern void checkRemoveFwdAddressRequest(NameChangeTransaction& tran); + +/// @brief Verifies a forward RR removal DNS update request +/// +/// Tests that the DNS Update request for a given transaction, is correct for +/// removing forward RR DNS entries. +/// +/// @param tran Transaction containing the request to be verified. +extern void checkRemoveFwdRRsRequest(NameChangeTransaction& tran); + +/// @brief Verifies a reverse mapping removal DNS update request +/// +/// Tests that the DNS Update request for a given transaction, is correct for +/// removing a reverse DNS mapping. +/// +/// @param tran Transaction containing the request to be verified. +extern void checkRemoveRevPtrsRequest(NameChangeTransaction& tran); + +/// @brief Verifies a simple forward mapping replacement DNS update request +/// +/// Tests that the DNS Update request for a given transaction, is correct for +/// replacing a forward DNS mapping when not using conflict resolution. +/// +/// @param tran Transaction containing the request to be verified. +extern void checkSimpleReplaceFwdAddressRequest(NameChangeTransaction& tran); + +/// @brief Verifies a simple forward RR removal DNS update request +/// +/// Tests that the DNS Update request for a given transaction, is correct for +/// removing forward RR DNS entries when not using conflict resolution. +/// +/// @param tran Transaction containing the request to be verified. +extern void checkSimpleRemoveFwdRRsRequest(NameChangeTransaction& tran); + +/// @brief Verifies a simple reverse RR removal DNS update request +/// +/// Tests that the DNS Update request for a given transaction, is correct for +/// removing reverse RR DNS entries when not using conflict resolution. +/// +/// @param tran Transaction containing the request to be verified. +extern void checkSimpleRemoveRevPtrsRequest(NameChangeTransaction& tran); + +/// @brief Creates a NameChangeRequest from JSON string. +/// +/// @param ncr_str string of JSON text from which to make the request. +/// +/// @return Pointer to newly created request. +/// +/// @throw Underlying methods may throw. +extern +dhcp_ddns::NameChangeRequestPtr makeNcrFromString(const std::string& ncr_str); + +/// @brief Creates a DdnsDomain with the one server. +/// +/// @param zone_name zone name of the domain +/// @param key_name TSIG key name of the TSIG key for this domain. It will +/// create a TSIGKeyInfo based on the key_name and assign it to the domain. +/// +/// @throw Underlying methods may throw. +extern DdnsDomainPtr makeDomain(const std::string& zone_name, + const std::string& key_name); + +/// @brief Creates a DdnsDomain with the one server. +/// +/// @param zone_name zone name of the domain +/// @param tsig_key_info pointer to the TSIGInfog key for this domain. +/// Defaults to an empty pointer, meaning this domain has no key. +/// +/// @throw Underlying methods may throw. +extern DdnsDomainPtr makeDomain(const std::string& zone_name, + const TSIGKeyInfoPtr& + tsig_key_info = TSIGKeyInfoPtr()); + +/// @brief Creates a TSIGKeyInfo +/// +/// @param key_name name of the key +/// @param secret key secret data as a base64 encoded string. If blank, +/// then the secret value will be generated from key_name. +/// @param algorithm algorithm to use. Defaults to MD5. +/// @return a TSIGKeyInfoPtr for the newly created key. If key_name is blank +/// the pointer will be empty. +/// @throw Underlying methods may throw. +extern +TSIGKeyInfoPtr makeTSIGKeyInfo(const std::string& key_name, + const std::string& secret = "", + const std::string& algorithm + = TSIGKeyInfo::HMAC_MD5_STR); + +/// @brief Creates a DnsServerInfo and adds it to the given DdnsDomain. +/// +/// The server is created and added to the domain, without duplicate entry +/// checking. +/// +/// @param domain DdnsDomain to which to add the server +/// @param name new server's host name of the server +/// @param ip new server's ip address +/// @param port new server's port +/// @param tsig_key_info pointer to the TSIGInfog key for this server. +/// Defaults to an empty pointer, meaning this server has no key. +/// +/// @throw Underlying methods may throw. +extern void addDomainServer(DdnsDomainPtr& domain, const std::string& name, + const std::string& ip = TEST_DNS_SERVER_IP, + const size_t port = TEST_DNS_SERVER_PORT, + const TSIGKeyInfoPtr& + tsig_key_info = TSIGKeyInfoPtr()); + +/// @brief Creates a hex text dump of the given data buffer. +/// +/// This method is not used for testing but is handy for debugging. It creates +/// a pleasantly formatted string of 2-digits per byte separated by spaces with +/// 16 bytes per line. +/// +/// @param data pointer to the data to dump +/// @param len size (in bytes) of data +extern std::string toHexText(const uint8_t* data, size_t len); + +/// @brief Verifies the current state and next event in a transaction +/// @param trans NameChangeTransaction to check +/// @param exp_state expected current state of the transaction +/// @param exp_event expected next event of the transaction +/// @param file source file name +/// @param line source line number +extern void checkContext(NameChangeTransactionPtr trans, const int exp_state, + const int exp_evt, const std::string& file, int line); + +/// @brief Macro for calling checkContext() that supplies invocation location +#define CHECK_CONTEXT(a,b,c) checkContext(a,b,c,__FILE__,__LINE__) + +} // namespace isc::d2 +} // namespace isc + +#endif diff --git a/src/lib/d2srv/testutils/stats_test_utils.cc b/src/lib/d2srv/testutils/stats_test_utils.cc new file mode 100644 index 0000000..262879b --- /dev/null +++ b/src/lib/d2srv/testutils/stats_test_utils.cc @@ -0,0 +1,41 @@ +// Copyright (C) 2021 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 <d2srv/d2_stats.h> +#include <d2srv/testutils/stats_test_utils.h> + +using namespace isc::data; +using namespace isc::stats; +using namespace std; + +namespace isc { +namespace d2 { +namespace test { + +D2StatTest::D2StatTest() { + StatsMgr::instance().removeAll(); + D2Stats::init(); +} + +D2StatTest::~D2StatTest() { + StatsMgr::instance().removeAll(); +} + +void +checkStats(const string& key_name, const StatMap& expected_stats) { + StatMap key_stats; + for (const auto& it : expected_stats) { + const string& stat_name = + StatsMgr::generateName("key", key_name, it.first); + key_stats[stat_name] = it.second; + } + checkStats(key_stats); +} + +} +} +} diff --git a/src/lib/d2srv/testutils/stats_test_utils.h b/src/lib/d2srv/testutils/stats_test_utils.h new file mode 100644 index 0000000..ccdad02 --- /dev/null +++ b/src/lib/d2srv/testutils/stats_test_utils.h @@ -0,0 +1,48 @@ +// Copyright (C) 2020-2021 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/. + +#ifndef D2_STATS_TEST_UTILS_H +#define D2_STATS_TEST_UTILS_H + +#include <cc/data.h> +#include <d2srv/d2_stats.h> +#include <d2srv/d2_tsig_key.h> +#include <stats/testutils/stats_test_utils.h> + +#include <gtest/gtest.h> + +namespace isc { +namespace d2 { +namespace test { + +/// @brief Import statistic test utils. +using isc::stats::test::StatMap; +using isc::stats::test::checkStat; +using isc::stats::test::checkStats; + +/// @brief Test class with utility functions to test statistics. +class D2StatTest { +public: + /// @brief Constructor. + D2StatTest(); + + /// @brief Destructor. + virtual ~D2StatTest(); +}; + +/// @brief Compares StatsMgr key statistics against expected values. +/// +/// Prepend key part of names before calling checkStats simpler variant. +/// +/// @param key_name Name of the key. +/// @param expected_stats Map of expected static names and values. +void checkStats(const std::string& key_name, const StatMap& expected_stats); + +} +} +} + +#endif // D2_STATS_TEST_UTILS_H |