diff options
Diffstat (limited to 'src/lib/hooks/tests')
25 files changed, 7753 insertions, 0 deletions
diff --git a/src/lib/hooks/tests/Makefile.am b/src/lib/hooks/tests/Makefile.am new file mode 100644 index 0000000..8cbe413 --- /dev/null +++ b/src/lib/hooks/tests/Makefile.am @@ -0,0 +1,152 @@ +SUBDIRS = . + +AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib +AM_CPPFLAGS += $(BOOST_INCLUDES) + +AM_CXXFLAGS = $(KEA_CXXFLAGS) + +# Kea libraries against which the test user libraries are linked. +HOOKS_LIB = $(top_builddir)/src/lib/hooks/libkea-hooks.la +LOG_LIB = $(top_builddir)/src/lib/log/libkea-log.la +UTIL_LIB = $(top_builddir)/src/lib/util/libkea-util.la +EXCEPTIONS_LIB = $(top_builddir)/src/lib/exceptions/libkea-exceptions.la + +ALL_LIBS = $(HOOKS_LIB) $(LOG_LIB) $(UTIL_LIB) $(EXCEPTIONS_LIB) $(LOG4CPLUS_LIBS) + +# Files to clean include the file created by testing. +CLEANFILES = *.gcno *.gcda $(builddir)/marker_file.dat + +# Files generated by configure +DISTCLEANFILES = marker_file.h test_libraries.h + +TESTS_ENVIRONMENT = $(LIBTOOL) --mode=execute $(VALGRIND_COMMAND) + +TESTS = +if HAVE_GTEST +# Build shared libraries for testing. The libtool way to create a shared library +# is to specify "-avoid-version -export-dynamic -module" in the library LDFLAGS +# (see http://www.gnu.org/software/libtool/manual/html_node/Link-mode.html). +# Use of these switches will guarantee that the .so files are created in the +# .libs folder and they can be dlopened. +# +# Note that the shared libraries with callouts should not be used together with +# the --enable-static-link option. With this option, the bind10 libraries are +# statically linked with the program and if the callout invokes the methods +# which belong to these libraries, the library with the callout will get its +# own copy of the static objects (e.g. logger, ServerHooks) and that will lead +# to unexpected errors. For this reason, the --enable-static-link option is +# ignored for unit tests built here. + +noinst_LTLIBRARIES = libnvl.la libivl.la libfxl.la libbcl.la liblcl.la +noinst_LTLIBRARIES += liblecl.la libucl.la libfcl.la libpcl.la libacl.la + +# -rpath /nowhere is a hack to trigger libtool to not create a +# convenience archive, resulting in shared modules + +# No version function +libnvl_la_SOURCES = no_version_library.cc +libnvl_la_CXXFLAGS = $(AM_CXXFLAGS) +libnvl_la_CPPFLAGS = $(AM_CPPFLAGS) +libnvl_la_LDFLAGS = -avoid-version -export-dynamic -module -rpath /nowhere + +# Incorrect version function +libivl_la_SOURCES = incorrect_version_library.cc +libivl_la_CXXFLAGS = $(AM_CXXFLAGS) +libivl_la_CPPFLAGS = $(AM_CPPFLAGS) +libivl_la_LDFLAGS = -avoid-version -export-dynamic -module -rpath /nowhere + +# All framework functions throw an exception +libfxl_la_SOURCES = framework_exception_library.cc +libfxl_la_CXXFLAGS = $(AM_CXXFLAGS) +libfxl_la_CPPFLAGS = $(AM_CPPFLAGS) +libfxl_la_LDFLAGS = -avoid-version -export-dynamic -module -rpath /nowhere + +# The basic callout library - contains standard callouts +libbcl_la_SOURCES = basic_callout_library.cc +libbcl_la_CXXFLAGS = $(AM_CXXFLAGS) +libbcl_la_CPPFLAGS = $(AM_CPPFLAGS) +libbcl_la_LDFLAGS = -avoid-version -export-dynamic -module -rpath /nowhere + +# The load callout library - contains a load function +liblcl_la_SOURCES = load_callout_library.cc +liblcl_la_CXXFLAGS = $(AM_CXXFLAGS) +liblcl_la_CPPFLAGS = $(AM_CPPFLAGS) +liblcl_la_LDFLAGS = -avoid-version -export-dynamic -module -rpath /nowhere + +# The load error callout library - contains a load function that returns +# an error. +liblecl_la_SOURCES = load_error_callout_library.cc +liblecl_la_CXXFLAGS = $(AM_CXXFLAGS) +liblecl_la_CPPFLAGS = $(AM_CPPFLAGS) +liblecl_la_LDFLAGS = -avoid-version -export-dynamic -module -rpath /nowhere + +# The unload callout library - contains an unload function that +# creates a marker file. +libucl_la_SOURCES = unload_callout_library.cc +libucl_la_CXXFLAGS = $(AM_CXXFLAGS) +libucl_la_CPPFLAGS = $(AM_CPPFLAGS) +libucl_la_LDFLAGS = -avoid-version -export-dynamic -module -rpath /nowhere + +# The full callout library - contains all three framework functions. +libfcl_la_SOURCES = full_callout_library.cc +libfcl_la_CXXFLAGS = $(AM_CXXFLAGS) +libfcl_la_CPPFLAGS = $(AM_CPPFLAGS) +libfcl_la_LDFLAGS = -avoid-version -export-dynamic -module -rpath /nowhere + +# The parameters checking callout library - expects +libpcl_la_SOURCES = callout_params_library.cc +libpcl_la_CXXFLAGS = $(AM_CXXFLAGS) +libpcl_la_CPPFLAGS = $(AM_CPPFLAGS) +libpcl_la_LDFLAGS = -avoid-version -export-dynamic -module -rpath /nowhere +libpcl_la_LDFLAGS += $(top_builddir)/src/lib/util/libkea-util.la + +# The async callout library - parks object for asynchronous task +libacl_la_SOURCES = async_callout_library.cc +libacl_la_CXXFLAGS = $(AM_CXXFLAGS) +libacl_la_CPPFLAGS = $(AM_CPPFLAGS) +libacl_la_LDFLAGS = -avoid-version -export-dynamic -module -rpath /nowhere + +TESTS += run_unittests +run_unittests_SOURCES = run_unittests.cc +run_unittests_SOURCES += callout_handle_unittest.cc +run_unittests_SOURCES += callout_handle_associate_unittest.cc +run_unittests_SOURCES += callout_manager_unittest.cc +run_unittests_SOURCES += common_test_class.h +run_unittests_SOURCES += handles_unittest.cc +run_unittests_SOURCES += hooks_manager_unittest.cc +run_unittests_SOURCES += library_manager_collection_unittest.cc +run_unittests_SOURCES += library_manager_unittest.cc +run_unittests_SOURCES += parking_lots_unittest.cc +run_unittests_SOURCES += server_hooks_unittest.cc + +nodist_run_unittests_SOURCES = marker_file.h +nodist_run_unittests_SOURCES += test_libraries.h + +run_unittests_CXXFLAGS = $(AM_CXXFLAGS) +run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) +run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS) +if USE_STATIC_LINK +run_unittests_LDFLAGS += -static -export-dynamic +endif + +run_unittests_LDADD = $(AM_LDADD) +run_unittests_LDADD += $(ALL_LIBS) +run_unittests_LDADD += $(top_builddir)/src/lib/cc/libkea-cc.la +run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la +run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.la +run_unittests_LDADD += $(GTEST_LDADD) $(LOG4CPLUS_LIBS) $(BOOST_LIBS) +# As noted in configure.ac, libtool doesn't work perfectly with Darwin: it +# embeds the final install path in dynamic libraries and loadable modules refer +# to that path even if its loaded within the source tree, so preventing tests +# from working - but only when linking statically. The solution used in other +# Makefiles (setting the path to the dynamic libraries via an environment +# variable) don't seem to work. What does work is to run the unit test using +# libtool and specifying paths via -dlopen switches. So... If running in an +# environment where we have to set the library path AND if linking statically, +# override the "check" target and run the unit tests ourselves. + +endif + +noinst_PROGRAMS = $(TESTS) + +EXTRA_DIST = marker_file.h.in test_libraries.h.in diff --git a/src/lib/hooks/tests/Makefile.in b/src/lib/hooks/tests/Makefile.in new file mode 100644 index 0000000..688124d --- /dev/null +++ b/src/lib/hooks/tests/Makefile.in @@ -0,0 +1,1547 @@ +# 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 = run_unittests +@HAVE_GTEST_TRUE@@USE_STATIC_LINK_TRUE@am__append_2 = -static -export-dynamic +noinst_PROGRAMS = $(am__EXEEXT_2) +subdir = src/lib/hooks/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 = marker_file.h test_libraries.h +CONFIG_CLEAN_VPATH_FILES = +@HAVE_GTEST_TRUE@am__EXEEXT_1 = run_unittests$(EXEEXT) +am__EXEEXT_2 = $(am__EXEEXT_1) +PROGRAMS = $(noinst_PROGRAMS) +LTLIBRARIES = $(noinst_LTLIBRARIES) +libacl_la_LIBADD = +am__libacl_la_SOURCES_DIST = async_callout_library.cc +@HAVE_GTEST_TRUE@am_libacl_la_OBJECTS = \ +@HAVE_GTEST_TRUE@ libacl_la-async_callout_library.lo +libacl_la_OBJECTS = $(am_libacl_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 = +libacl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(libacl_la_CXXFLAGS) \ + $(CXXFLAGS) $(libacl_la_LDFLAGS) $(LDFLAGS) -o $@ +@HAVE_GTEST_TRUE@am_libacl_la_rpath = +libbcl_la_LIBADD = +am__libbcl_la_SOURCES_DIST = basic_callout_library.cc +@HAVE_GTEST_TRUE@am_libbcl_la_OBJECTS = \ +@HAVE_GTEST_TRUE@ libbcl_la-basic_callout_library.lo +libbcl_la_OBJECTS = $(am_libbcl_la_OBJECTS) +libbcl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(libbcl_la_CXXFLAGS) \ + $(CXXFLAGS) $(libbcl_la_LDFLAGS) $(LDFLAGS) -o $@ +@HAVE_GTEST_TRUE@am_libbcl_la_rpath = +libfcl_la_LIBADD = +am__libfcl_la_SOURCES_DIST = full_callout_library.cc +@HAVE_GTEST_TRUE@am_libfcl_la_OBJECTS = \ +@HAVE_GTEST_TRUE@ libfcl_la-full_callout_library.lo +libfcl_la_OBJECTS = $(am_libfcl_la_OBJECTS) +libfcl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(libfcl_la_CXXFLAGS) \ + $(CXXFLAGS) $(libfcl_la_LDFLAGS) $(LDFLAGS) -o $@ +@HAVE_GTEST_TRUE@am_libfcl_la_rpath = +libfxl_la_LIBADD = +am__libfxl_la_SOURCES_DIST = framework_exception_library.cc +@HAVE_GTEST_TRUE@am_libfxl_la_OBJECTS = \ +@HAVE_GTEST_TRUE@ libfxl_la-framework_exception_library.lo +libfxl_la_OBJECTS = $(am_libfxl_la_OBJECTS) +libfxl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(libfxl_la_CXXFLAGS) \ + $(CXXFLAGS) $(libfxl_la_LDFLAGS) $(LDFLAGS) -o $@ +@HAVE_GTEST_TRUE@am_libfxl_la_rpath = +libivl_la_LIBADD = +am__libivl_la_SOURCES_DIST = incorrect_version_library.cc +@HAVE_GTEST_TRUE@am_libivl_la_OBJECTS = \ +@HAVE_GTEST_TRUE@ libivl_la-incorrect_version_library.lo +libivl_la_OBJECTS = $(am_libivl_la_OBJECTS) +libivl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(libivl_la_CXXFLAGS) \ + $(CXXFLAGS) $(libivl_la_LDFLAGS) $(LDFLAGS) -o $@ +@HAVE_GTEST_TRUE@am_libivl_la_rpath = +liblcl_la_LIBADD = +am__liblcl_la_SOURCES_DIST = load_callout_library.cc +@HAVE_GTEST_TRUE@am_liblcl_la_OBJECTS = \ +@HAVE_GTEST_TRUE@ liblcl_la-load_callout_library.lo +liblcl_la_OBJECTS = $(am_liblcl_la_OBJECTS) +liblcl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(liblcl_la_CXXFLAGS) \ + $(CXXFLAGS) $(liblcl_la_LDFLAGS) $(LDFLAGS) -o $@ +@HAVE_GTEST_TRUE@am_liblcl_la_rpath = +liblecl_la_LIBADD = +am__liblecl_la_SOURCES_DIST = load_error_callout_library.cc +@HAVE_GTEST_TRUE@am_liblecl_la_OBJECTS = \ +@HAVE_GTEST_TRUE@ liblecl_la-load_error_callout_library.lo +liblecl_la_OBJECTS = $(am_liblecl_la_OBJECTS) +liblecl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(liblecl_la_CXXFLAGS) \ + $(CXXFLAGS) $(liblecl_la_LDFLAGS) $(LDFLAGS) -o $@ +@HAVE_GTEST_TRUE@am_liblecl_la_rpath = +libnvl_la_LIBADD = +am__libnvl_la_SOURCES_DIST = no_version_library.cc +@HAVE_GTEST_TRUE@am_libnvl_la_OBJECTS = \ +@HAVE_GTEST_TRUE@ libnvl_la-no_version_library.lo +libnvl_la_OBJECTS = $(am_libnvl_la_OBJECTS) +libnvl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(libnvl_la_CXXFLAGS) \ + $(CXXFLAGS) $(libnvl_la_LDFLAGS) $(LDFLAGS) -o $@ +@HAVE_GTEST_TRUE@am_libnvl_la_rpath = +libpcl_la_LIBADD = +am__libpcl_la_SOURCES_DIST = callout_params_library.cc +@HAVE_GTEST_TRUE@am_libpcl_la_OBJECTS = \ +@HAVE_GTEST_TRUE@ libpcl_la-callout_params_library.lo +libpcl_la_OBJECTS = $(am_libpcl_la_OBJECTS) +libpcl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(libpcl_la_CXXFLAGS) \ + $(CXXFLAGS) $(libpcl_la_LDFLAGS) $(LDFLAGS) -o $@ +@HAVE_GTEST_TRUE@am_libpcl_la_rpath = +libucl_la_LIBADD = +am__libucl_la_SOURCES_DIST = unload_callout_library.cc +@HAVE_GTEST_TRUE@am_libucl_la_OBJECTS = \ +@HAVE_GTEST_TRUE@ libucl_la-unload_callout_library.lo +libucl_la_OBJECTS = $(am_libucl_la_OBJECTS) +libucl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(libucl_la_CXXFLAGS) \ + $(CXXFLAGS) $(libucl_la_LDFLAGS) $(LDFLAGS) -o $@ +@HAVE_GTEST_TRUE@am_libucl_la_rpath = +am__run_unittests_SOURCES_DIST = run_unittests.cc \ + callout_handle_unittest.cc \ + callout_handle_associate_unittest.cc \ + callout_manager_unittest.cc common_test_class.h \ + handles_unittest.cc hooks_manager_unittest.cc \ + library_manager_collection_unittest.cc \ + library_manager_unittest.cc parking_lots_unittest.cc \ + server_hooks_unittest.cc +@HAVE_GTEST_TRUE@am_run_unittests_OBJECTS = \ +@HAVE_GTEST_TRUE@ run_unittests-run_unittests.$(OBJEXT) \ +@HAVE_GTEST_TRUE@ run_unittests-callout_handle_unittest.$(OBJEXT) \ +@HAVE_GTEST_TRUE@ run_unittests-callout_handle_associate_unittest.$(OBJEXT) \ +@HAVE_GTEST_TRUE@ run_unittests-callout_manager_unittest.$(OBJEXT) \ +@HAVE_GTEST_TRUE@ run_unittests-handles_unittest.$(OBJEXT) \ +@HAVE_GTEST_TRUE@ run_unittests-hooks_manager_unittest.$(OBJEXT) \ +@HAVE_GTEST_TRUE@ run_unittests-library_manager_collection_unittest.$(OBJEXT) \ +@HAVE_GTEST_TRUE@ run_unittests-library_manager_unittest.$(OBJEXT) \ +@HAVE_GTEST_TRUE@ run_unittests-parking_lots_unittest.$(OBJEXT) \ +@HAVE_GTEST_TRUE@ run_unittests-server_hooks_unittest.$(OBJEXT) +nodist_run_unittests_OBJECTS = +run_unittests_OBJECTS = $(am_run_unittests_OBJECTS) \ + $(nodist_run_unittests_OBJECTS) +am__DEPENDENCIES_1 = +am__DEPENDENCIES_2 = $(HOOKS_LIB) $(LOG_LIB) $(UTIL_LIB) \ + $(EXCEPTIONS_LIB) $(am__DEPENDENCIES_1) +@HAVE_GTEST_TRUE@run_unittests_DEPENDENCIES = $(am__DEPENDENCIES_2) \ +@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/util/unittests/libutil_unittests.la \ +@HAVE_GTEST_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@HAVE_GTEST_TRUE@ $(am__DEPENDENCIES_1) +run_unittests_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(run_unittests_CXXFLAGS) $(CXXFLAGS) $(run_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)/libacl_la-async_callout_library.Plo \ + ./$(DEPDIR)/libbcl_la-basic_callout_library.Plo \ + ./$(DEPDIR)/libfcl_la-full_callout_library.Plo \ + ./$(DEPDIR)/libfxl_la-framework_exception_library.Plo \ + ./$(DEPDIR)/libivl_la-incorrect_version_library.Plo \ + ./$(DEPDIR)/liblcl_la-load_callout_library.Plo \ + ./$(DEPDIR)/liblecl_la-load_error_callout_library.Plo \ + ./$(DEPDIR)/libnvl_la-no_version_library.Plo \ + ./$(DEPDIR)/libpcl_la-callout_params_library.Plo \ + ./$(DEPDIR)/libucl_la-unload_callout_library.Plo \ + ./$(DEPDIR)/run_unittests-callout_handle_associate_unittest.Po \ + ./$(DEPDIR)/run_unittests-callout_handle_unittest.Po \ + ./$(DEPDIR)/run_unittests-callout_manager_unittest.Po \ + ./$(DEPDIR)/run_unittests-handles_unittest.Po \ + ./$(DEPDIR)/run_unittests-hooks_manager_unittest.Po \ + ./$(DEPDIR)/run_unittests-library_manager_collection_unittest.Po \ + ./$(DEPDIR)/run_unittests-library_manager_unittest.Po \ + ./$(DEPDIR)/run_unittests-parking_lots_unittest.Po \ + ./$(DEPDIR)/run_unittests-run_unittests.Po \ + ./$(DEPDIR)/run_unittests-server_hooks_unittest.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 = $(libacl_la_SOURCES) $(libbcl_la_SOURCES) \ + $(libfcl_la_SOURCES) $(libfxl_la_SOURCES) $(libivl_la_SOURCES) \ + $(liblcl_la_SOURCES) $(liblecl_la_SOURCES) \ + $(libnvl_la_SOURCES) $(libpcl_la_SOURCES) $(libucl_la_SOURCES) \ + $(run_unittests_SOURCES) $(nodist_run_unittests_SOURCES) +DIST_SOURCES = $(am__libacl_la_SOURCES_DIST) \ + $(am__libbcl_la_SOURCES_DIST) $(am__libfcl_la_SOURCES_DIST) \ + $(am__libfxl_la_SOURCES_DIST) $(am__libivl_la_SOURCES_DIST) \ + $(am__liblcl_la_SOURCES_DIST) $(am__liblecl_la_SOURCES_DIST) \ + $(am__libnvl_la_SOURCES_DIST) $(am__libpcl_la_SOURCES_DIST) \ + $(am__libucl_la_SOURCES_DIST) \ + $(am__run_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='[0;31m'; \ + grn='[0;32m'; \ + lgn='[1;32m'; \ + blu='[1;34m'; \ + mgn='[0;35m'; \ + brg='[1m'; \ + std='[m'; \ + fi; \ +} +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/marker_file.h.in \ + $(srcdir)/test_libraries.h.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) + +# Kea libraries against which the test user libraries are linked. +HOOKS_LIB = $(top_builddir)/src/lib/hooks/libkea-hooks.la +LOG_LIB = $(top_builddir)/src/lib/log/libkea-log.la +UTIL_LIB = $(top_builddir)/src/lib/util/libkea-util.la +EXCEPTIONS_LIB = $(top_builddir)/src/lib/exceptions/libkea-exceptions.la +ALL_LIBS = $(HOOKS_LIB) $(LOG_LIB) $(UTIL_LIB) $(EXCEPTIONS_LIB) $(LOG4CPLUS_LIBS) + +# Files to clean include the file created by testing. +CLEANFILES = *.gcno *.gcda $(builddir)/marker_file.dat + +# Files generated by configure +DISTCLEANFILES = marker_file.h test_libraries.h +TESTS_ENVIRONMENT = $(LIBTOOL) --mode=execute $(VALGRIND_COMMAND) +# Build shared libraries for testing. The libtool way to create a shared library +# is to specify "-avoid-version -export-dynamic -module" in the library LDFLAGS +# (see http://www.gnu.org/software/libtool/manual/html_node/Link-mode.html). +# Use of these switches will guarantee that the .so files are created in the +# .libs folder and they can be dlopened. +# +# Note that the shared libraries with callouts should not be used together with +# the --enable-static-link option. With this option, the bind10 libraries are +# statically linked with the program and if the callout invokes the methods +# which belong to these libraries, the library with the callout will get its +# own copy of the static objects (e.g. logger, ServerHooks) and that will lead +# to unexpected errors. For this reason, the --enable-static-link option is +# ignored for unit tests built here. +@HAVE_GTEST_TRUE@noinst_LTLIBRARIES = libnvl.la libivl.la libfxl.la \ +@HAVE_GTEST_TRUE@ libbcl.la liblcl.la liblecl.la libucl.la \ +@HAVE_GTEST_TRUE@ libfcl.la libpcl.la libacl.la + +# -rpath /nowhere is a hack to trigger libtool to not create a +# convenience archive, resulting in shared modules + +# No version function +@HAVE_GTEST_TRUE@libnvl_la_SOURCES = no_version_library.cc +@HAVE_GTEST_TRUE@libnvl_la_CXXFLAGS = $(AM_CXXFLAGS) +@HAVE_GTEST_TRUE@libnvl_la_CPPFLAGS = $(AM_CPPFLAGS) +@HAVE_GTEST_TRUE@libnvl_la_LDFLAGS = -avoid-version -export-dynamic -module -rpath /nowhere + +# Incorrect version function +@HAVE_GTEST_TRUE@libivl_la_SOURCES = incorrect_version_library.cc +@HAVE_GTEST_TRUE@libivl_la_CXXFLAGS = $(AM_CXXFLAGS) +@HAVE_GTEST_TRUE@libivl_la_CPPFLAGS = $(AM_CPPFLAGS) +@HAVE_GTEST_TRUE@libivl_la_LDFLAGS = -avoid-version -export-dynamic -module -rpath /nowhere + +# All framework functions throw an exception +@HAVE_GTEST_TRUE@libfxl_la_SOURCES = framework_exception_library.cc +@HAVE_GTEST_TRUE@libfxl_la_CXXFLAGS = $(AM_CXXFLAGS) +@HAVE_GTEST_TRUE@libfxl_la_CPPFLAGS = $(AM_CPPFLAGS) +@HAVE_GTEST_TRUE@libfxl_la_LDFLAGS = -avoid-version -export-dynamic -module -rpath /nowhere + +# The basic callout library - contains standard callouts +@HAVE_GTEST_TRUE@libbcl_la_SOURCES = basic_callout_library.cc +@HAVE_GTEST_TRUE@libbcl_la_CXXFLAGS = $(AM_CXXFLAGS) +@HAVE_GTEST_TRUE@libbcl_la_CPPFLAGS = $(AM_CPPFLAGS) +@HAVE_GTEST_TRUE@libbcl_la_LDFLAGS = -avoid-version -export-dynamic -module -rpath /nowhere + +# The load callout library - contains a load function +@HAVE_GTEST_TRUE@liblcl_la_SOURCES = load_callout_library.cc +@HAVE_GTEST_TRUE@liblcl_la_CXXFLAGS = $(AM_CXXFLAGS) +@HAVE_GTEST_TRUE@liblcl_la_CPPFLAGS = $(AM_CPPFLAGS) +@HAVE_GTEST_TRUE@liblcl_la_LDFLAGS = -avoid-version -export-dynamic -module -rpath /nowhere + +# The load error callout library - contains a load function that returns +# an error. +@HAVE_GTEST_TRUE@liblecl_la_SOURCES = load_error_callout_library.cc +@HAVE_GTEST_TRUE@liblecl_la_CXXFLAGS = $(AM_CXXFLAGS) +@HAVE_GTEST_TRUE@liblecl_la_CPPFLAGS = $(AM_CPPFLAGS) +@HAVE_GTEST_TRUE@liblecl_la_LDFLAGS = -avoid-version -export-dynamic -module -rpath /nowhere + +# The unload callout library - contains an unload function that +# creates a marker file. +@HAVE_GTEST_TRUE@libucl_la_SOURCES = unload_callout_library.cc +@HAVE_GTEST_TRUE@libucl_la_CXXFLAGS = $(AM_CXXFLAGS) +@HAVE_GTEST_TRUE@libucl_la_CPPFLAGS = $(AM_CPPFLAGS) +@HAVE_GTEST_TRUE@libucl_la_LDFLAGS = -avoid-version -export-dynamic -module -rpath /nowhere + +# The full callout library - contains all three framework functions. +@HAVE_GTEST_TRUE@libfcl_la_SOURCES = full_callout_library.cc +@HAVE_GTEST_TRUE@libfcl_la_CXXFLAGS = $(AM_CXXFLAGS) +@HAVE_GTEST_TRUE@libfcl_la_CPPFLAGS = $(AM_CPPFLAGS) +@HAVE_GTEST_TRUE@libfcl_la_LDFLAGS = -avoid-version -export-dynamic -module -rpath /nowhere + +# The parameters checking callout library - expects +@HAVE_GTEST_TRUE@libpcl_la_SOURCES = callout_params_library.cc +@HAVE_GTEST_TRUE@libpcl_la_CXXFLAGS = $(AM_CXXFLAGS) +@HAVE_GTEST_TRUE@libpcl_la_CPPFLAGS = $(AM_CPPFLAGS) +@HAVE_GTEST_TRUE@libpcl_la_LDFLAGS = -avoid-version -export-dynamic \ +@HAVE_GTEST_TRUE@ -module -rpath /nowhere \ +@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/util/libkea-util.la + +# The async callout library - parks object for asynchronous task +@HAVE_GTEST_TRUE@libacl_la_SOURCES = async_callout_library.cc +@HAVE_GTEST_TRUE@libacl_la_CXXFLAGS = $(AM_CXXFLAGS) +@HAVE_GTEST_TRUE@libacl_la_CPPFLAGS = $(AM_CPPFLAGS) +@HAVE_GTEST_TRUE@libacl_la_LDFLAGS = -avoid-version -export-dynamic -module -rpath /nowhere +@HAVE_GTEST_TRUE@run_unittests_SOURCES = run_unittests.cc \ +@HAVE_GTEST_TRUE@ callout_handle_unittest.cc \ +@HAVE_GTEST_TRUE@ callout_handle_associate_unittest.cc \ +@HAVE_GTEST_TRUE@ callout_manager_unittest.cc \ +@HAVE_GTEST_TRUE@ common_test_class.h handles_unittest.cc \ +@HAVE_GTEST_TRUE@ hooks_manager_unittest.cc \ +@HAVE_GTEST_TRUE@ library_manager_collection_unittest.cc \ +@HAVE_GTEST_TRUE@ library_manager_unittest.cc \ +@HAVE_GTEST_TRUE@ parking_lots_unittest.cc \ +@HAVE_GTEST_TRUE@ server_hooks_unittest.cc +@HAVE_GTEST_TRUE@nodist_run_unittests_SOURCES = marker_file.h \ +@HAVE_GTEST_TRUE@ test_libraries.h +@HAVE_GTEST_TRUE@run_unittests_CXXFLAGS = $(AM_CXXFLAGS) +@HAVE_GTEST_TRUE@run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) +@HAVE_GTEST_TRUE@run_unittests_LDFLAGS = $(AM_LDFLAGS) \ +@HAVE_GTEST_TRUE@ $(GTEST_LDFLAGS) $(am__append_2) +@HAVE_GTEST_TRUE@run_unittests_LDADD = $(AM_LDADD) $(ALL_LIBS) \ +@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/util/unittests/libutil_unittests.la \ +@HAVE_GTEST_TRUE@ $(GTEST_LDADD) $(LOG4CPLUS_LIBS) \ +@HAVE_GTEST_TRUE@ $(BOOST_LIBS) +EXTRA_DIST = marker_file.h.in test_libraries.h.in +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/hooks/tests/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib/hooks/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): +marker_file.h: $(top_builddir)/config.status $(srcdir)/marker_file.h.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +test_libraries.h: $(top_builddir)/config.status $(srcdir)/test_libraries.h.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +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 + +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}; \ + } + +libacl.la: $(libacl_la_OBJECTS) $(libacl_la_DEPENDENCIES) $(EXTRA_libacl_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libacl_la_LINK) $(am_libacl_la_rpath) $(libacl_la_OBJECTS) $(libacl_la_LIBADD) $(LIBS) + +libbcl.la: $(libbcl_la_OBJECTS) $(libbcl_la_DEPENDENCIES) $(EXTRA_libbcl_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libbcl_la_LINK) $(am_libbcl_la_rpath) $(libbcl_la_OBJECTS) $(libbcl_la_LIBADD) $(LIBS) + +libfcl.la: $(libfcl_la_OBJECTS) $(libfcl_la_DEPENDENCIES) $(EXTRA_libfcl_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libfcl_la_LINK) $(am_libfcl_la_rpath) $(libfcl_la_OBJECTS) $(libfcl_la_LIBADD) $(LIBS) + +libfxl.la: $(libfxl_la_OBJECTS) $(libfxl_la_DEPENDENCIES) $(EXTRA_libfxl_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libfxl_la_LINK) $(am_libfxl_la_rpath) $(libfxl_la_OBJECTS) $(libfxl_la_LIBADD) $(LIBS) + +libivl.la: $(libivl_la_OBJECTS) $(libivl_la_DEPENDENCIES) $(EXTRA_libivl_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libivl_la_LINK) $(am_libivl_la_rpath) $(libivl_la_OBJECTS) $(libivl_la_LIBADD) $(LIBS) + +liblcl.la: $(liblcl_la_OBJECTS) $(liblcl_la_DEPENDENCIES) $(EXTRA_liblcl_la_DEPENDENCIES) + $(AM_V_CXXLD)$(liblcl_la_LINK) $(am_liblcl_la_rpath) $(liblcl_la_OBJECTS) $(liblcl_la_LIBADD) $(LIBS) + +liblecl.la: $(liblecl_la_OBJECTS) $(liblecl_la_DEPENDENCIES) $(EXTRA_liblecl_la_DEPENDENCIES) + $(AM_V_CXXLD)$(liblecl_la_LINK) $(am_liblecl_la_rpath) $(liblecl_la_OBJECTS) $(liblecl_la_LIBADD) $(LIBS) + +libnvl.la: $(libnvl_la_OBJECTS) $(libnvl_la_DEPENDENCIES) $(EXTRA_libnvl_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libnvl_la_LINK) $(am_libnvl_la_rpath) $(libnvl_la_OBJECTS) $(libnvl_la_LIBADD) $(LIBS) + +libpcl.la: $(libpcl_la_OBJECTS) $(libpcl_la_DEPENDENCIES) $(EXTRA_libpcl_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libpcl_la_LINK) $(am_libpcl_la_rpath) $(libpcl_la_OBJECTS) $(libpcl_la_LIBADD) $(LIBS) + +libucl.la: $(libucl_la_OBJECTS) $(libucl_la_DEPENDENCIES) $(EXTRA_libucl_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libucl_la_LINK) $(am_libucl_la_rpath) $(libucl_la_OBJECTS) $(libucl_la_LIBADD) $(LIBS) + +run_unittests$(EXEEXT): $(run_unittests_OBJECTS) $(run_unittests_DEPENDENCIES) $(EXTRA_run_unittests_DEPENDENCIES) + @rm -f run_unittests$(EXEEXT) + $(AM_V_CXXLD)$(run_unittests_LINK) $(run_unittests_OBJECTS) $(run_unittests_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libacl_la-async_callout_library.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libbcl_la-basic_callout_library.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfcl_la-full_callout_library.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfxl_la-framework_exception_library.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libivl_la-incorrect_version_library.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblcl_la-load_callout_library.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblecl_la-load_error_callout_library.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnvl_la-no_version_library.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpcl_la-callout_params_library.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libucl_la-unload_callout_library.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-callout_handle_associate_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-callout_handle_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-callout_manager_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-handles_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-hooks_manager_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-library_manager_collection_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-library_manager_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-parking_lots_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-run_unittests.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-server_hooks_unittest.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 $@ $< + +libacl_la-async_callout_library.lo: async_callout_library.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libacl_la_CPPFLAGS) $(CPPFLAGS) $(libacl_la_CXXFLAGS) $(CXXFLAGS) -MT libacl_la-async_callout_library.lo -MD -MP -MF $(DEPDIR)/libacl_la-async_callout_library.Tpo -c -o libacl_la-async_callout_library.lo `test -f 'async_callout_library.cc' || echo '$(srcdir)/'`async_callout_library.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libacl_la-async_callout_library.Tpo $(DEPDIR)/libacl_la-async_callout_library.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='async_callout_library.cc' object='libacl_la-async_callout_library.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) $(libacl_la_CPPFLAGS) $(CPPFLAGS) $(libacl_la_CXXFLAGS) $(CXXFLAGS) -c -o libacl_la-async_callout_library.lo `test -f 'async_callout_library.cc' || echo '$(srcdir)/'`async_callout_library.cc + +libbcl_la-basic_callout_library.lo: basic_callout_library.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libbcl_la_CPPFLAGS) $(CPPFLAGS) $(libbcl_la_CXXFLAGS) $(CXXFLAGS) -MT libbcl_la-basic_callout_library.lo -MD -MP -MF $(DEPDIR)/libbcl_la-basic_callout_library.Tpo -c -o libbcl_la-basic_callout_library.lo `test -f 'basic_callout_library.cc' || echo '$(srcdir)/'`basic_callout_library.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libbcl_la-basic_callout_library.Tpo $(DEPDIR)/libbcl_la-basic_callout_library.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='basic_callout_library.cc' object='libbcl_la-basic_callout_library.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) $(libbcl_la_CPPFLAGS) $(CPPFLAGS) $(libbcl_la_CXXFLAGS) $(CXXFLAGS) -c -o libbcl_la-basic_callout_library.lo `test -f 'basic_callout_library.cc' || echo '$(srcdir)/'`basic_callout_library.cc + +libfcl_la-full_callout_library.lo: full_callout_library.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfcl_la_CPPFLAGS) $(CPPFLAGS) $(libfcl_la_CXXFLAGS) $(CXXFLAGS) -MT libfcl_la-full_callout_library.lo -MD -MP -MF $(DEPDIR)/libfcl_la-full_callout_library.Tpo -c -o libfcl_la-full_callout_library.lo `test -f 'full_callout_library.cc' || echo '$(srcdir)/'`full_callout_library.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libfcl_la-full_callout_library.Tpo $(DEPDIR)/libfcl_la-full_callout_library.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='full_callout_library.cc' object='libfcl_la-full_callout_library.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) $(libfcl_la_CPPFLAGS) $(CPPFLAGS) $(libfcl_la_CXXFLAGS) $(CXXFLAGS) -c -o libfcl_la-full_callout_library.lo `test -f 'full_callout_library.cc' || echo '$(srcdir)/'`full_callout_library.cc + +libfxl_la-framework_exception_library.lo: framework_exception_library.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfxl_la_CPPFLAGS) $(CPPFLAGS) $(libfxl_la_CXXFLAGS) $(CXXFLAGS) -MT libfxl_la-framework_exception_library.lo -MD -MP -MF $(DEPDIR)/libfxl_la-framework_exception_library.Tpo -c -o libfxl_la-framework_exception_library.lo `test -f 'framework_exception_library.cc' || echo '$(srcdir)/'`framework_exception_library.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libfxl_la-framework_exception_library.Tpo $(DEPDIR)/libfxl_la-framework_exception_library.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='framework_exception_library.cc' object='libfxl_la-framework_exception_library.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) $(libfxl_la_CPPFLAGS) $(CPPFLAGS) $(libfxl_la_CXXFLAGS) $(CXXFLAGS) -c -o libfxl_la-framework_exception_library.lo `test -f 'framework_exception_library.cc' || echo '$(srcdir)/'`framework_exception_library.cc + +libivl_la-incorrect_version_library.lo: incorrect_version_library.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libivl_la_CPPFLAGS) $(CPPFLAGS) $(libivl_la_CXXFLAGS) $(CXXFLAGS) -MT libivl_la-incorrect_version_library.lo -MD -MP -MF $(DEPDIR)/libivl_la-incorrect_version_library.Tpo -c -o libivl_la-incorrect_version_library.lo `test -f 'incorrect_version_library.cc' || echo '$(srcdir)/'`incorrect_version_library.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libivl_la-incorrect_version_library.Tpo $(DEPDIR)/libivl_la-incorrect_version_library.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='incorrect_version_library.cc' object='libivl_la-incorrect_version_library.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) $(libivl_la_CPPFLAGS) $(CPPFLAGS) $(libivl_la_CXXFLAGS) $(CXXFLAGS) -c -o libivl_la-incorrect_version_library.lo `test -f 'incorrect_version_library.cc' || echo '$(srcdir)/'`incorrect_version_library.cc + +liblcl_la-load_callout_library.lo: load_callout_library.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liblcl_la_CPPFLAGS) $(CPPFLAGS) $(liblcl_la_CXXFLAGS) $(CXXFLAGS) -MT liblcl_la-load_callout_library.lo -MD -MP -MF $(DEPDIR)/liblcl_la-load_callout_library.Tpo -c -o liblcl_la-load_callout_library.lo `test -f 'load_callout_library.cc' || echo '$(srcdir)/'`load_callout_library.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liblcl_la-load_callout_library.Tpo $(DEPDIR)/liblcl_la-load_callout_library.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='load_callout_library.cc' object='liblcl_la-load_callout_library.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) $(liblcl_la_CPPFLAGS) $(CPPFLAGS) $(liblcl_la_CXXFLAGS) $(CXXFLAGS) -c -o liblcl_la-load_callout_library.lo `test -f 'load_callout_library.cc' || echo '$(srcdir)/'`load_callout_library.cc + +liblecl_la-load_error_callout_library.lo: load_error_callout_library.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liblecl_la_CPPFLAGS) $(CPPFLAGS) $(liblecl_la_CXXFLAGS) $(CXXFLAGS) -MT liblecl_la-load_error_callout_library.lo -MD -MP -MF $(DEPDIR)/liblecl_la-load_error_callout_library.Tpo -c -o liblecl_la-load_error_callout_library.lo `test -f 'load_error_callout_library.cc' || echo '$(srcdir)/'`load_error_callout_library.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liblecl_la-load_error_callout_library.Tpo $(DEPDIR)/liblecl_la-load_error_callout_library.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='load_error_callout_library.cc' object='liblecl_la-load_error_callout_library.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) $(liblecl_la_CPPFLAGS) $(CPPFLAGS) $(liblecl_la_CXXFLAGS) $(CXXFLAGS) -c -o liblecl_la-load_error_callout_library.lo `test -f 'load_error_callout_library.cc' || echo '$(srcdir)/'`load_error_callout_library.cc + +libnvl_la-no_version_library.lo: no_version_library.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnvl_la_CPPFLAGS) $(CPPFLAGS) $(libnvl_la_CXXFLAGS) $(CXXFLAGS) -MT libnvl_la-no_version_library.lo -MD -MP -MF $(DEPDIR)/libnvl_la-no_version_library.Tpo -c -o libnvl_la-no_version_library.lo `test -f 'no_version_library.cc' || echo '$(srcdir)/'`no_version_library.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnvl_la-no_version_library.Tpo $(DEPDIR)/libnvl_la-no_version_library.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='no_version_library.cc' object='libnvl_la-no_version_library.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) $(libnvl_la_CPPFLAGS) $(CPPFLAGS) $(libnvl_la_CXXFLAGS) $(CXXFLAGS) -c -o libnvl_la-no_version_library.lo `test -f 'no_version_library.cc' || echo '$(srcdir)/'`no_version_library.cc + +libpcl_la-callout_params_library.lo: callout_params_library.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpcl_la_CPPFLAGS) $(CPPFLAGS) $(libpcl_la_CXXFLAGS) $(CXXFLAGS) -MT libpcl_la-callout_params_library.lo -MD -MP -MF $(DEPDIR)/libpcl_la-callout_params_library.Tpo -c -o libpcl_la-callout_params_library.lo `test -f 'callout_params_library.cc' || echo '$(srcdir)/'`callout_params_library.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpcl_la-callout_params_library.Tpo $(DEPDIR)/libpcl_la-callout_params_library.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='callout_params_library.cc' object='libpcl_la-callout_params_library.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) $(libpcl_la_CPPFLAGS) $(CPPFLAGS) $(libpcl_la_CXXFLAGS) $(CXXFLAGS) -c -o libpcl_la-callout_params_library.lo `test -f 'callout_params_library.cc' || echo '$(srcdir)/'`callout_params_library.cc + +libucl_la-unload_callout_library.lo: unload_callout_library.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libucl_la_CPPFLAGS) $(CPPFLAGS) $(libucl_la_CXXFLAGS) $(CXXFLAGS) -MT libucl_la-unload_callout_library.lo -MD -MP -MF $(DEPDIR)/libucl_la-unload_callout_library.Tpo -c -o libucl_la-unload_callout_library.lo `test -f 'unload_callout_library.cc' || echo '$(srcdir)/'`unload_callout_library.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libucl_la-unload_callout_library.Tpo $(DEPDIR)/libucl_la-unload_callout_library.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='unload_callout_library.cc' object='libucl_la-unload_callout_library.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) $(libucl_la_CPPFLAGS) $(CPPFLAGS) $(libucl_la_CXXFLAGS) $(CXXFLAGS) -c -o libucl_la-unload_callout_library.lo `test -f 'unload_callout_library.cc' || echo '$(srcdir)/'`unload_callout_library.cc + +run_unittests-run_unittests.o: run_unittests.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-run_unittests.o -MD -MP -MF $(DEPDIR)/run_unittests-run_unittests.Tpo -c -o run_unittests-run_unittests.o `test -f 'run_unittests.cc' || echo '$(srcdir)/'`run_unittests.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-run_unittests.Tpo $(DEPDIR)/run_unittests-run_unittests.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='run_unittests.cc' object='run_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) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-run_unittests.o `test -f 'run_unittests.cc' || echo '$(srcdir)/'`run_unittests.cc + +run_unittests-run_unittests.obj: run_unittests.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-run_unittests.obj -MD -MP -MF $(DEPDIR)/run_unittests-run_unittests.Tpo -c -o run_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)/run_unittests-run_unittests.Tpo $(DEPDIR)/run_unittests-run_unittests.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='run_unittests.cc' object='run_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) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-run_unittests.obj `if test -f 'run_unittests.cc'; then $(CYGPATH_W) 'run_unittests.cc'; else $(CYGPATH_W) '$(srcdir)/run_unittests.cc'; fi` + +run_unittests-callout_handle_unittest.o: callout_handle_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-callout_handle_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-callout_handle_unittest.Tpo -c -o run_unittests-callout_handle_unittest.o `test -f 'callout_handle_unittest.cc' || echo '$(srcdir)/'`callout_handle_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-callout_handle_unittest.Tpo $(DEPDIR)/run_unittests-callout_handle_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='callout_handle_unittest.cc' object='run_unittests-callout_handle_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) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-callout_handle_unittest.o `test -f 'callout_handle_unittest.cc' || echo '$(srcdir)/'`callout_handle_unittest.cc + +run_unittests-callout_handle_unittest.obj: callout_handle_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-callout_handle_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-callout_handle_unittest.Tpo -c -o run_unittests-callout_handle_unittest.obj `if test -f 'callout_handle_unittest.cc'; then $(CYGPATH_W) 'callout_handle_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/callout_handle_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-callout_handle_unittest.Tpo $(DEPDIR)/run_unittests-callout_handle_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='callout_handle_unittest.cc' object='run_unittests-callout_handle_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) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-callout_handle_unittest.obj `if test -f 'callout_handle_unittest.cc'; then $(CYGPATH_W) 'callout_handle_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/callout_handle_unittest.cc'; fi` + +run_unittests-callout_handle_associate_unittest.o: callout_handle_associate_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-callout_handle_associate_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-callout_handle_associate_unittest.Tpo -c -o run_unittests-callout_handle_associate_unittest.o `test -f 'callout_handle_associate_unittest.cc' || echo '$(srcdir)/'`callout_handle_associate_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-callout_handle_associate_unittest.Tpo $(DEPDIR)/run_unittests-callout_handle_associate_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='callout_handle_associate_unittest.cc' object='run_unittests-callout_handle_associate_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) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-callout_handle_associate_unittest.o `test -f 'callout_handle_associate_unittest.cc' || echo '$(srcdir)/'`callout_handle_associate_unittest.cc + +run_unittests-callout_handle_associate_unittest.obj: callout_handle_associate_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-callout_handle_associate_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-callout_handle_associate_unittest.Tpo -c -o run_unittests-callout_handle_associate_unittest.obj `if test -f 'callout_handle_associate_unittest.cc'; then $(CYGPATH_W) 'callout_handle_associate_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/callout_handle_associate_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-callout_handle_associate_unittest.Tpo $(DEPDIR)/run_unittests-callout_handle_associate_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='callout_handle_associate_unittest.cc' object='run_unittests-callout_handle_associate_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) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-callout_handle_associate_unittest.obj `if test -f 'callout_handle_associate_unittest.cc'; then $(CYGPATH_W) 'callout_handle_associate_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/callout_handle_associate_unittest.cc'; fi` + +run_unittests-callout_manager_unittest.o: callout_manager_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-callout_manager_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-callout_manager_unittest.Tpo -c -o run_unittests-callout_manager_unittest.o `test -f 'callout_manager_unittest.cc' || echo '$(srcdir)/'`callout_manager_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-callout_manager_unittest.Tpo $(DEPDIR)/run_unittests-callout_manager_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='callout_manager_unittest.cc' object='run_unittests-callout_manager_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) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-callout_manager_unittest.o `test -f 'callout_manager_unittest.cc' || echo '$(srcdir)/'`callout_manager_unittest.cc + +run_unittests-callout_manager_unittest.obj: callout_manager_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-callout_manager_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-callout_manager_unittest.Tpo -c -o run_unittests-callout_manager_unittest.obj `if test -f 'callout_manager_unittest.cc'; then $(CYGPATH_W) 'callout_manager_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/callout_manager_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-callout_manager_unittest.Tpo $(DEPDIR)/run_unittests-callout_manager_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='callout_manager_unittest.cc' object='run_unittests-callout_manager_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) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-callout_manager_unittest.obj `if test -f 'callout_manager_unittest.cc'; then $(CYGPATH_W) 'callout_manager_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/callout_manager_unittest.cc'; fi` + +run_unittests-handles_unittest.o: handles_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-handles_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-handles_unittest.Tpo -c -o run_unittests-handles_unittest.o `test -f 'handles_unittest.cc' || echo '$(srcdir)/'`handles_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-handles_unittest.Tpo $(DEPDIR)/run_unittests-handles_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='handles_unittest.cc' object='run_unittests-handles_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) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-handles_unittest.o `test -f 'handles_unittest.cc' || echo '$(srcdir)/'`handles_unittest.cc + +run_unittests-handles_unittest.obj: handles_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-handles_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-handles_unittest.Tpo -c -o run_unittests-handles_unittest.obj `if test -f 'handles_unittest.cc'; then $(CYGPATH_W) 'handles_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/handles_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-handles_unittest.Tpo $(DEPDIR)/run_unittests-handles_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='handles_unittest.cc' object='run_unittests-handles_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) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-handles_unittest.obj `if test -f 'handles_unittest.cc'; then $(CYGPATH_W) 'handles_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/handles_unittest.cc'; fi` + +run_unittests-hooks_manager_unittest.o: hooks_manager_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-hooks_manager_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-hooks_manager_unittest.Tpo -c -o run_unittests-hooks_manager_unittest.o `test -f 'hooks_manager_unittest.cc' || echo '$(srcdir)/'`hooks_manager_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-hooks_manager_unittest.Tpo $(DEPDIR)/run_unittests-hooks_manager_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='hooks_manager_unittest.cc' object='run_unittests-hooks_manager_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) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-hooks_manager_unittest.o `test -f 'hooks_manager_unittest.cc' || echo '$(srcdir)/'`hooks_manager_unittest.cc + +run_unittests-hooks_manager_unittest.obj: hooks_manager_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-hooks_manager_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-hooks_manager_unittest.Tpo -c -o run_unittests-hooks_manager_unittest.obj `if test -f 'hooks_manager_unittest.cc'; then $(CYGPATH_W) 'hooks_manager_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/hooks_manager_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-hooks_manager_unittest.Tpo $(DEPDIR)/run_unittests-hooks_manager_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='hooks_manager_unittest.cc' object='run_unittests-hooks_manager_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) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-hooks_manager_unittest.obj `if test -f 'hooks_manager_unittest.cc'; then $(CYGPATH_W) 'hooks_manager_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/hooks_manager_unittest.cc'; fi` + +run_unittests-library_manager_collection_unittest.o: library_manager_collection_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-library_manager_collection_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-library_manager_collection_unittest.Tpo -c -o run_unittests-library_manager_collection_unittest.o `test -f 'library_manager_collection_unittest.cc' || echo '$(srcdir)/'`library_manager_collection_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-library_manager_collection_unittest.Tpo $(DEPDIR)/run_unittests-library_manager_collection_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='library_manager_collection_unittest.cc' object='run_unittests-library_manager_collection_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) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-library_manager_collection_unittest.o `test -f 'library_manager_collection_unittest.cc' || echo '$(srcdir)/'`library_manager_collection_unittest.cc + +run_unittests-library_manager_collection_unittest.obj: library_manager_collection_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-library_manager_collection_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-library_manager_collection_unittest.Tpo -c -o run_unittests-library_manager_collection_unittest.obj `if test -f 'library_manager_collection_unittest.cc'; then $(CYGPATH_W) 'library_manager_collection_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/library_manager_collection_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-library_manager_collection_unittest.Tpo $(DEPDIR)/run_unittests-library_manager_collection_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='library_manager_collection_unittest.cc' object='run_unittests-library_manager_collection_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) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-library_manager_collection_unittest.obj `if test -f 'library_manager_collection_unittest.cc'; then $(CYGPATH_W) 'library_manager_collection_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/library_manager_collection_unittest.cc'; fi` + +run_unittests-library_manager_unittest.o: library_manager_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-library_manager_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-library_manager_unittest.Tpo -c -o run_unittests-library_manager_unittest.o `test -f 'library_manager_unittest.cc' || echo '$(srcdir)/'`library_manager_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-library_manager_unittest.Tpo $(DEPDIR)/run_unittests-library_manager_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='library_manager_unittest.cc' object='run_unittests-library_manager_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) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-library_manager_unittest.o `test -f 'library_manager_unittest.cc' || echo '$(srcdir)/'`library_manager_unittest.cc + +run_unittests-library_manager_unittest.obj: library_manager_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-library_manager_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-library_manager_unittest.Tpo -c -o run_unittests-library_manager_unittest.obj `if test -f 'library_manager_unittest.cc'; then $(CYGPATH_W) 'library_manager_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/library_manager_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-library_manager_unittest.Tpo $(DEPDIR)/run_unittests-library_manager_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='library_manager_unittest.cc' object='run_unittests-library_manager_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) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-library_manager_unittest.obj `if test -f 'library_manager_unittest.cc'; then $(CYGPATH_W) 'library_manager_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/library_manager_unittest.cc'; fi` + +run_unittests-parking_lots_unittest.o: parking_lots_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-parking_lots_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-parking_lots_unittest.Tpo -c -o run_unittests-parking_lots_unittest.o `test -f 'parking_lots_unittest.cc' || echo '$(srcdir)/'`parking_lots_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-parking_lots_unittest.Tpo $(DEPDIR)/run_unittests-parking_lots_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='parking_lots_unittest.cc' object='run_unittests-parking_lots_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) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-parking_lots_unittest.o `test -f 'parking_lots_unittest.cc' || echo '$(srcdir)/'`parking_lots_unittest.cc + +run_unittests-parking_lots_unittest.obj: parking_lots_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-parking_lots_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-parking_lots_unittest.Tpo -c -o run_unittests-parking_lots_unittest.obj `if test -f 'parking_lots_unittest.cc'; then $(CYGPATH_W) 'parking_lots_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/parking_lots_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-parking_lots_unittest.Tpo $(DEPDIR)/run_unittests-parking_lots_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='parking_lots_unittest.cc' object='run_unittests-parking_lots_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) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-parking_lots_unittest.obj `if test -f 'parking_lots_unittest.cc'; then $(CYGPATH_W) 'parking_lots_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/parking_lots_unittest.cc'; fi` + +run_unittests-server_hooks_unittest.o: server_hooks_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-server_hooks_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-server_hooks_unittest.Tpo -c -o run_unittests-server_hooks_unittest.o `test -f 'server_hooks_unittest.cc' || echo '$(srcdir)/'`server_hooks_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-server_hooks_unittest.Tpo $(DEPDIR)/run_unittests-server_hooks_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='server_hooks_unittest.cc' object='run_unittests-server_hooks_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) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-server_hooks_unittest.o `test -f 'server_hooks_unittest.cc' || echo '$(srcdir)/'`server_hooks_unittest.cc + +run_unittests-server_hooks_unittest.obj: server_hooks_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-server_hooks_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-server_hooks_unittest.Tpo -c -o run_unittests-server_hooks_unittest.obj `if test -f 'server_hooks_unittest.cc'; then $(CYGPATH_W) 'server_hooks_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/server_hooks_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-server_hooks_unittest.Tpo $(DEPDIR)/run_unittests-server_hooks_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='server_hooks_unittest.cc' object='run_unittests-server_hooks_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) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(run_unittests_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-server_hooks_unittest.obj `if test -f 'server_hooks_unittest.cc'; then $(CYGPATH_W) 'server_hooks_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/server_hooks_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) $(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) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +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 \ + clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-recursive + -rm -f ./$(DEPDIR)/libacl_la-async_callout_library.Plo + -rm -f ./$(DEPDIR)/libbcl_la-basic_callout_library.Plo + -rm -f ./$(DEPDIR)/libfcl_la-full_callout_library.Plo + -rm -f ./$(DEPDIR)/libfxl_la-framework_exception_library.Plo + -rm -f ./$(DEPDIR)/libivl_la-incorrect_version_library.Plo + -rm -f ./$(DEPDIR)/liblcl_la-load_callout_library.Plo + -rm -f ./$(DEPDIR)/liblecl_la-load_error_callout_library.Plo + -rm -f ./$(DEPDIR)/libnvl_la-no_version_library.Plo + -rm -f ./$(DEPDIR)/libpcl_la-callout_params_library.Plo + -rm -f ./$(DEPDIR)/libucl_la-unload_callout_library.Plo + -rm -f ./$(DEPDIR)/run_unittests-callout_handle_associate_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-callout_handle_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-callout_manager_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-handles_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-hooks_manager_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-library_manager_collection_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-library_manager_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-parking_lots_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-run_unittests.Po + -rm -f ./$(DEPDIR)/run_unittests-server_hooks_unittest.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)/libacl_la-async_callout_library.Plo + -rm -f ./$(DEPDIR)/libbcl_la-basic_callout_library.Plo + -rm -f ./$(DEPDIR)/libfcl_la-full_callout_library.Plo + -rm -f ./$(DEPDIR)/libfxl_la-framework_exception_library.Plo + -rm -f ./$(DEPDIR)/libivl_la-incorrect_version_library.Plo + -rm -f ./$(DEPDIR)/liblcl_la-load_callout_library.Plo + -rm -f ./$(DEPDIR)/liblecl_la-load_error_callout_library.Plo + -rm -f ./$(DEPDIR)/libnvl_la-no_version_library.Plo + -rm -f ./$(DEPDIR)/libpcl_la-callout_params_library.Plo + -rm -f ./$(DEPDIR)/libucl_la-unload_callout_library.Plo + -rm -f ./$(DEPDIR)/run_unittests-callout_handle_associate_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-callout_handle_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-callout_manager_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-handles_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-hooks_manager_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-library_manager_collection_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-library_manager_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-parking_lots_unittest.Po + -rm -f ./$(DEPDIR)/run_unittests-run_unittests.Po + -rm -f ./$(DEPDIR)/run_unittests-server_hooks_unittest.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-noinstLTLIBRARIES 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/lib/hooks/tests/async_callout_library.cc b/src/lib/hooks/tests/async_callout_library.cc new file mode 100644 index 0000000..5f40e52 --- /dev/null +++ b/src/lib/hooks/tests/async_callout_library.cc @@ -0,0 +1,153 @@ +// Copyright (C) 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/. + +/// @file +/// @brief Async callout library +/// +/// This is source of a test library for testing a "parking" feature, i.e. +/// the callouts can schedule asynchronous operation and indicate that the +/// packet should be parked until the asynchronous operation completes and +/// the hooks library indicates that packet processing should be resumed. + +#include <config.h> +#include <hooks/hooks.h> +#include <hooks/parking_lots.h> +#include <log/logger.h> +#include <log/macros.h> +#include <log/message_initializer.h> +#include <algorithm> +#include <functional> +#include <sstream> +#include <string> +#include <vector> + +using namespace isc::hooks; +using namespace isc::log; +using namespace std; + +namespace { + +/// @brief Logger used by the library. +isc::log::Logger logger("acl"); + +/// @brief Log messages. +const char* log_messages[] = { + "ACL_LOAD_START", "async callout load %1", + "ACL_LOAD_END", "async callout load end", + "ACL_LOAD_END", "duplicate of async callout load end", + NULL +}; + +/// @brief Initializer for log messages. +const MessageInitializer message_initializer(log_messages); + +/// @brief Simple callback which unparks parked object. +/// +/// @param parking_lot parking lot where the object is parked. +/// @param parked_object parked object. +void unpark(ParkingLotHandlePtr parking_lot, const std::string& parked_object) { + parking_lot->unpark(parked_object); +} + +} // end of anonymous namespace + +extern "C" { + +/// @brief Callout scheduling object parking and providing function to unpark +/// it. +/// +/// This callout is crafted to test the following scenario. The callout returns +/// status "park" to indicate that the packet should be parked. The callout +/// performs asynchronous operation and indicates that the packet should be +/// unparked when this operation completes. Unparking the packet triggers a +/// function associated with the parked packet, e.g. a function which continues +/// processing of this packet. +/// +/// This test callout "parks" a string object instead of a packet. It assumes +/// that there might be multiple callouts installed on this hook point, which +/// all trigger asynchronous operation. The object must be unparked when the +/// last asynchronous operation completes. Therefore, it calls the @c reference +/// function on the parking lot object to increase the reference count. The +/// object remains parked as long as the reference counter is greater than +/// 0. +/// +/// The callout returns 1 or more pointers to the functions which should be +/// called by the unit tests to simulate completion of the asynchronous tasks. +/// When the test calls those functions, @c unpark function is called, which +/// decreases reference count on the parked object, or actually unparks the +/// object when the reference count reaches 0. +/// +/// @param handle Reference to callout handle used to set/get arguments. +int +hookpt_one(CalloutHandle& handle) { + // Using a string as "parked" object. + std::string parked_object; + handle.getArgument("parked_object", parked_object); + + // Retrieve the parking lot handle for this hook point. It allows for + // increasing a reference count on the parked object and also for + // scheduling packet unparking. + ParkingLotHandlePtr parking_lot = handle.getParkingLotHandlePtr(); + + // Increase the reference count to indicate that this callout needs the + // object to remain parked until the asynchronous operation completes. + // Otherwise, other callouts could potentially call unpark and cause the + // packet processing to continue before the asynchronous operation + // completes. + parking_lot->reference(parked_object); + + // Create pointer to the function that the test should call to simulate + // completion of the asynchronous operation scheduled by this callout. + std::function<void()> unpark_trigger_func = + std::bind(unpark, parking_lot, parked_object); + + // Every callout (if multiple callouts installed on this hook point) should + // return the function pointer under unique name. The base name is + // "unpark_trigger" and the callouts append consecutive numbers to this + // base name, e.g. "unpark_trigger1", "unpark_trigger2" etc. + + std::string fun_name; + std::vector<std::string> args = handle.getArgumentNames(); + unsigned i = 1; + do { + std::ostringstream candidate_name; + candidate_name << "unpark_trigger" << i; + if (std::find(args.begin(), args.end(), candidate_name.str()) == + args.end()) { + fun_name = candidate_name.str(); + + } else { + ++i; + } + } while (fun_name.empty()); + + handle.setArgument(fun_name, unpark_trigger_func); + + handle.setStatus(CalloutHandle::NEXT_STEP_PARK); + + return (0); +} + +// Framework functions. + +int +version() { + return (KEA_HOOKS_VERSION); +} + +// load() initializes the user library if the main image was statically linked. +int +load(isc::hooks::LibraryHandle&) { +#ifdef USE_STATIC_LINK + hooksStaticLinkInit(); +#endif + LOG_INFO(logger, "ACL_LOAD_START").arg("argument"); + LOG_INFO(logger, "ACL_LOAD_END"); + return (0); +} + +} + diff --git a/src/lib/hooks/tests/basic_callout_library.cc b/src/lib/hooks/tests/basic_callout_library.cc new file mode 100644 index 0000000..bd80555 --- /dev/null +++ b/src/lib/hooks/tests/basic_callout_library.cc @@ -0,0 +1,145 @@ +// Copyright (C) 2013-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +/// @file +/// @brief Basic callout library +/// +/// This is source of a test library for various test (LibraryManager and +/// HooksManager). The characteristics of the library produced from this +/// file are: +/// +/// - Only the "version" framework function is supplied. +/// +/// - A context_create callout is supplied. +/// +/// - Three "standard" callouts are supplied corresponding to the hooks +/// "hookpt_one", "hookpt_two", "hookpt_three". All do some trivial +/// calculations on the arguments supplied to it and the context variables, +/// returning intermediate results through the "result" argument. The result +/// of executing all four callouts in order is: +/// +/// @f[ (10 + data_1) * data_2 - data_3 @f] +/// +/// ...where data_1, data_2 and data_3 are the values passed in arguments of +/// the same name to the three callouts (data_1 passed to hookpt_one, data_2 +/// to hookpt_two etc.) and the result is returned in the argument "result". +/// +/// - The logger instance is created and some log messages are defined. Some +/// log messages are duplicated purposely, to check that the logger handles +/// the duplicates correctly. + +#include <config.h> +#include <hooks/hooks.h> +#include <fstream> +#include <log/logger.h> +#include <log/macros.h> +#include <log/message_initializer.h> + +using namespace isc::hooks; +using namespace isc::log; +using namespace std; + +namespace { + +/// @brief Logger used by the library. +isc::log::Logger logger("bcl"); + +/// @brief Log messages. +const char* log_messages[] = { + "BCL_LOAD_START", "basic callout load %1", + "BCL_LOAD_END", "basic callout load end", + "BCL_LOAD_END", "duplicate of basic callout load end", + NULL +}; + +/// @brief Initializer for log messages. +const MessageInitializer message_initializer(log_messages); + +} + +extern "C" { + +// Callouts. All return their result through the "result" argument. + +int +context_create(CalloutHandle& handle) { + handle.setContext("result", static_cast<int>(10)); + handle.setArgument("result", static_cast<int>(10)); + return (0); +} + +// First callout adds the passed "data_1" argument to the initialized context +// value of 10. (Note that the value set by context_create is accessed through +// context and not the argument, so checking that context is correctly passed +// between callouts in the same library.) + +int +hookpt_one(CalloutHandle& handle) { + int data; + handle.getArgument("data_1", data); + + int result; + handle.getArgument("result", result); + + result += data; + handle.setArgument("result", result); + + return (0); +} + +// Second callout multiplies the current context value by the "data_2" +// argument. + +int +hookpt_two(CalloutHandle& handle) { + int data; + handle.getArgument("data_2", data); + + int result; + handle.getArgument("result", result); + + result *= data; + handle.setArgument("result", result); + + return (0); +} + +// Final callout subtracts the result in "data_3". + +int +hookpt_three(CalloutHandle& handle) { + int data; + handle.getArgument("data_3", data); + + int result; + handle.getArgument("result", result); + + result -= data; + handle.setArgument("result", result); + + return (0); +} + +// Framework functions. + +int +version() { + return (KEA_HOOKS_VERSION); +} + +// load() initializes the user library if the main image was statically linked. +int +load(isc::hooks::LibraryHandle&) { +#ifdef USE_STATIC_LINK + hooksStaticLinkInit(); +#endif + LOG_INFO(logger, "BCL_LOAD_START").arg("argument"); + LOG_INFO(logger, "BCL_LOAD_END"); + return (0); +} + +} + diff --git a/src/lib/hooks/tests/callout_handle_associate_unittest.cc b/src/lib/hooks/tests/callout_handle_associate_unittest.cc new file mode 100644 index 0000000..cf09388 --- /dev/null +++ b/src/lib/hooks/tests/callout_handle_associate_unittest.cc @@ -0,0 +1,35 @@ +// Copyright (C) 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 <hooks/callout_handle.h> +#include <hooks/callout_handle_associate.h> +#include <gtest/gtest.h> + +using namespace isc::hooks; + +namespace { + +// This test verifies that the callout handle can be created and +// retrieved from the CalloutHandleAssociate. +TEST(CalloutHandleAssociate, getCalloutHandle) { + CalloutHandleAssociate associate; + // The handle should be initialized and returned. + CalloutHandlePtr callout_handle = associate.getCalloutHandle(); + ASSERT_TRUE(callout_handle); + + // When calling the second time, the same handle should be returned. + CalloutHandlePtr callout_handle2 = associate.getCalloutHandle(); + EXPECT_TRUE(callout_handle == callout_handle2); + + // A different associate should produce a different handle. + CalloutHandleAssociate associate2; + callout_handle2 = associate2.getCalloutHandle(); + EXPECT_FALSE(callout_handle == callout_handle2); +} + +} // end of anonymous namespace diff --git a/src/lib/hooks/tests/callout_handle_unittest.cc b/src/lib/hooks/tests/callout_handle_unittest.cc new file mode 100644 index 0000000..bb20e0c --- /dev/null +++ b/src/lib/hooks/tests/callout_handle_unittest.cc @@ -0,0 +1,384 @@ +// Copyright (C) 2013-2020 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <hooks/callout_handle.h> +#include <hooks/callout_manager.h> +#include <hooks/library_handle.h> +#include <hooks/server_hooks.h> + +#include <boost/shared_ptr.hpp> + +#include <gtest/gtest.h> + +using namespace isc::hooks; +using namespace std; + +namespace { + +/// @file +/// @brief Holds the CalloutHandle argument tests +/// +/// Additional testing of the CalloutHandle - together with the interaction +/// of the LibraryHandle - is done in the handles_unittests set of tests. + +class CalloutHandleTest : public ::testing::Test { +public: + + /// @brief Constructor + /// + /// Sets up a callout manager to be referenced by the CalloutHandle in + /// these tests. (The "4" for the number of libraries in the + /// CalloutManager is arbitrary - it is not used in these tests.) + CalloutHandleTest() : manager_(new CalloutManager(4)) + {} + + /// Obtain hook manager + boost::shared_ptr<CalloutManager>& getCalloutManager() { + return (manager_); + } + +private: + /// Callout manager accessed by this CalloutHandle. + boost::shared_ptr<CalloutManager> manager_; +}; + +// *** Argument Tests *** +// +// The first set of tests check that the CalloutHandle can store and retrieve +// arguments. These are very similar to the LibraryHandle context tests. + +// Test that we can store multiple values of the same type and that they +// are distinct. + +TEST_F(CalloutHandleTest, ArgumentDistinctSimpleType) { + CalloutHandle handle(getCalloutManager()); + + // Store and retrieve an int (random value). + int a = 42; + handle.setArgument("integer1", a); + EXPECT_EQ(42, a); + + int b = 0; + handle.getArgument("integer1", b); + EXPECT_EQ(42, b); + + // Add another integer (another random value). + int c = 142; + handle.setArgument("integer2", c); + EXPECT_EQ(142, c); + + int d = 0; + handle.getArgument("integer2", d); + EXPECT_EQ(142, d); + + // Add a short (random value). + short e = -81; + handle.setArgument("short", e); + EXPECT_EQ(-81, e); + + short f = 0; + handle.getArgument("short", f); + EXPECT_EQ(-81, f); +} + +// Test that trying to get an unknown argument throws an exception. + +TEST_F(CalloutHandleTest, ArgumentUnknownName) { + CalloutHandle handle(getCalloutManager()); + + // Set an integer + int a = 42; + handle.setArgument("integer1", a); + EXPECT_EQ(42, a); + + // Check we can retrieve it + int b = 0; + handle.getArgument("integer1", b); + EXPECT_EQ(42, b); + + // Check that getting an unknown name throws an exception. + int c = 0; + EXPECT_THROW(handle.getArgument("unknown", c), NoSuchArgument); +} + +// Test that trying to get an argument with an incorrect type throws an +// exception. + +TEST_F(CalloutHandleTest, ArgumentIncorrectType) { + CalloutHandle handle(getCalloutManager()); + + // Set an integer + int a = 42; + handle.setArgument("integer1", a); + EXPECT_EQ(42, a); + + // Check we can retrieve it + long b = 0; + EXPECT_THROW(handle.getArgument("integer1", b), boost::bad_any_cast); +} + +// Now try with some very complex types. The types cannot be defined within +// the function and they should contain a copy constructor. For this reason, +// a simple "struct" is used. + +struct Alpha { + int a; + int b; + Alpha(int first = 0, int second = 0) : a(first), b(second) {} +}; + +struct Beta { + int c; + int d; + Beta(int first = 0, int second = 0) : c(first), d(second) {} +}; + +TEST_F(CalloutHandleTest, ComplexTypes) { + CalloutHandle handle(getCalloutManager()); + + // Declare two variables of different (complex) types. (Note as to the + // variable names: aleph and beth are the first two letters of the Hebrew + // alphabet.) + Alpha aleph(1, 2); + EXPECT_EQ(1, aleph.a); + EXPECT_EQ(2, aleph.b); + handle.setArgument("aleph", aleph); + + Beta beth(11, 22); + EXPECT_EQ(11, beth.c); + EXPECT_EQ(22, beth.d); + handle.setArgument("beth", beth); + + // Ensure we can extract the data correctly. + Alpha aleph2; + EXPECT_EQ(0, aleph2.a); + EXPECT_EQ(0, aleph2.b); + handle.getArgument("aleph", aleph2); + EXPECT_EQ(1, aleph2.a); + EXPECT_EQ(2, aleph2.b); + + Beta beth2; + EXPECT_EQ(0, beth2.c); + EXPECT_EQ(0, beth2.d); + handle.getArgument("beth", beth2); + EXPECT_EQ(11, beth2.c); + EXPECT_EQ(22, beth2.d); + + // Ensure that complex types also thrown an exception if we attempt to + // get a context element of the wrong type. + EXPECT_THROW(handle.getArgument("aleph", beth), boost::bad_any_cast); +} + +// Check that the context can store pointers. And also check that it respects +// that a "pointer to X" is not the same as a "pointer to const X". + +TEST_F(CalloutHandleTest, PointerTypes) { + CalloutHandle handle(getCalloutManager()); + + // Declare a couple of variables, const and non-const. + Alpha aleph(5, 10); + const Beta beth(15, 20); + + Alpha* pa = ℵ + const Beta* pcb = ℶ + + // Check pointers can be set and retrieved OK. + handle.setArgument("non_const_pointer", pa); + handle.setArgument("const_pointer", pcb); + + Alpha* pa2 = 0; + handle.getArgument("non_const_pointer", pa2); + EXPECT_TRUE(pa == pa2); + + const Beta* pcb2 = 0; + handle.getArgument("const_pointer", pcb2); + EXPECT_TRUE(pcb == pcb2); + + // Check that the "const" is protected in the context. + const Alpha* pca3; + EXPECT_THROW(handle.getArgument("non_const_pointer", pca3), + boost::bad_any_cast); + + Beta* pb3; + EXPECT_THROW(handle.getArgument("const_pointer", pb3), + boost::bad_any_cast); +} + +// Check that we can get the names of the arguments. + +TEST_F(CalloutHandleTest, ContextItemNames) { + CalloutHandle handle(getCalloutManager()); + + vector<string> expected_names; + + expected_names.push_back("faith"); + handle.setArgument("faith", 42); + expected_names.push_back("hope"); + handle.setArgument("hope", 43); + expected_names.push_back("charity"); + handle.setArgument("charity", 44); + + // Get the names and check against the expected names. We'll sort + // both arrays to simplify the checking. + vector<string> actual_names = handle.getArgumentNames(); + + sort(actual_names.begin(), actual_names.end()); + sort(expected_names.begin(), expected_names.end()); + EXPECT_TRUE(expected_names == actual_names); +} + +// Test that we can delete an argument. + +TEST_F(CalloutHandleTest, DeleteArgument) { + CalloutHandle handle(getCalloutManager()); + + int one = 1; + int two = 2; + int three = 3; + int four = 4; + int value; // Return value + + handle.setArgument("one", one); + handle.setArgument("two", two); + handle.setArgument("three", three); + handle.setArgument("four", four); + + // Delete "one". + handle.getArgument("one", value); + EXPECT_EQ(1, value); + handle.deleteArgument("one"); + + EXPECT_THROW(handle.getArgument("one", value), NoSuchArgument); + handle.getArgument("two", value); + EXPECT_EQ(2, value); + handle.getArgument("three", value); + EXPECT_EQ(3, value); + handle.getArgument("four", value); + EXPECT_EQ(4, value); + + // Delete "three". + handle.getArgument("three", value); + EXPECT_EQ(3, value); + handle.deleteArgument("three"); + + EXPECT_THROW(handle.getArgument("one", value), NoSuchArgument); + handle.getArgument("two", value); + EXPECT_EQ(2, value); + EXPECT_THROW(handle.getArgument("three", value), NoSuchArgument); + handle.getArgument("four", value); + EXPECT_EQ(4, value); +} + +// Test that we can delete all arguments. + +TEST_F(CalloutHandleTest, DeleteAllArguments) { + CalloutHandle handle(getCalloutManager()); + + int one = 1; + int two = 2; + int three = 3; + int four = 4; + int value; // Return value + + // Set the arguments. The previous test verifies that this works. + handle.setArgument("one", one); + handle.setArgument("two", two); + handle.setArgument("three", three); + handle.setArgument("four", four); + + // Delete all arguments... + handle.deleteAllArguments(); + + // ... and check that none are left. + EXPECT_THROW(handle.getArgument("one", value), NoSuchArgument); + EXPECT_THROW(handle.getArgument("two", value), NoSuchArgument); + EXPECT_THROW(handle.getArgument("three", value), NoSuchArgument); + EXPECT_THROW(handle.getArgument("four", value), NoSuchArgument); +} + +// Test the "status" field. +TEST_F(CalloutHandleTest, StatusField) { + CalloutHandle handle(getCalloutManager()); + + // Should be continue on construction. + EXPECT_EQ(CalloutHandle::NEXT_STEP_CONTINUE, handle.getStatus()); + + handle.setStatus(CalloutHandle::NEXT_STEP_SKIP); + EXPECT_EQ(CalloutHandle::NEXT_STEP_SKIP, handle.getStatus()); + + handle.setStatus(CalloutHandle::NEXT_STEP_DROP); + EXPECT_EQ(CalloutHandle::NEXT_STEP_DROP, handle.getStatus()); + + handle.setStatus(CalloutHandle::NEXT_STEP_CONTINUE); + EXPECT_EQ(CalloutHandle::NEXT_STEP_CONTINUE, handle.getStatus()); +} + +// Tests that ScopedCalloutHandleState object resets CalloutHandle state +// during construction and destruction. +TEST_F(CalloutHandleTest, scopedState) { + // Create pointer to the handle to be wrapped. + CalloutHandlePtr handle(new CalloutHandle(getCalloutManager())); + + // Set two arguments and the non-default status. + int one = 1; + int two = 2; + int three = 3; + handle->setArgument("one", one); + handle->setArgument("two", two); + handle->setContext("three", three); + handle->setStatus(CalloutHandle::NEXT_STEP_DROP); + + + int value = 0; + EXPECT_NO_THROW(handle->getArgument("one", value)); + EXPECT_NO_THROW(handle->getArgument("two", value)); + EXPECT_NO_THROW(handle->getContext("three", value)); + EXPECT_EQ(CalloutHandle::NEXT_STEP_DROP, handle->getStatus()); + + { + // Wrap the callout handle with the scoped state object, which should + // reset the state of the handle. + ScopedCalloutHandleState scoped_state(handle); + + // When state is reset, all arguments should be removed and the + // default status should be set. + EXPECT_THROW(handle->getArgument("one", value), NoSuchArgument); + EXPECT_THROW(handle->getArgument("two", value), NoSuchArgument); + EXPECT_EQ(CalloutHandle::NEXT_STEP_CONTINUE, handle->getStatus()); + + // Context should be intact. + ASSERT_NO_THROW(handle->getContext("three", value)); + EXPECT_EQ(three, value); + + // Set the arguments and status again prior to the destruction of + // the wrapper. + handle->setArgument("one", one); + handle->setArgument("two", two); + handle->setStatus(CalloutHandle::NEXT_STEP_DROP); + + EXPECT_NO_THROW(handle->getArgument("one", value)); + EXPECT_NO_THROW(handle->getArgument("two", value)); + EXPECT_EQ(CalloutHandle::NEXT_STEP_DROP, handle->getStatus()); + } + + // Arguments should be gone again and the status should be set to + // a default value. + EXPECT_THROW(handle->getArgument("one", value), NoSuchArgument); + EXPECT_THROW(handle->getArgument("two", value), NoSuchArgument); + EXPECT_EQ(CalloutHandle::NEXT_STEP_CONTINUE, handle->getStatus()); + + // Context should be intact. + ASSERT_NO_THROW(handle->getContext("three", value)); + EXPECT_EQ(three, value); +} + +// Further tests of the "skip" flag and tests of getting the name of the +// hook to which the current callout is attached is in the "handles_unittest" +// module. + +} // Anonymous namespace diff --git a/src/lib/hooks/tests/callout_manager_unittest.cc b/src/lib/hooks/tests/callout_manager_unittest.cc new file mode 100644 index 0000000..67ba83b --- /dev/null +++ b/src/lib/hooks/tests/callout_manager_unittest.cc @@ -0,0 +1,944 @@ +// Copyright (C) 2013-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/callout_handle.h> +#include <hooks/callout_manager.h> +#include <hooks/library_handle.h> +#include <hooks/server_hooks.h> + +#include <boost/scoped_ptr.hpp> +#include <gtest/gtest.h> + +#include <algorithm> +#include <climits> +#include <string> +#include <vector> + +/// @file +/// @brief CalloutManager and LibraryHandle tests +/// +/// These set of tests check the CalloutManager and LibraryHandle. They are +/// together in the same file because the LibraryHandle is little more than a +/// restricted interface to the CalloutManager, and a lot of the support +/// structure for the tests is common. + +using namespace isc; +using namespace isc::hooks; +using namespace std; + +namespace { + +class CalloutManagerTest : public ::testing::Test { +public: + /// @brief Constructor + /// + /// Sets up a collection of three LibraryHandle objects to use in the test. + CalloutManagerTest() { + + // Set up the server hooks. There is one singleton for all tests, + // so reset it and explicitly set up the hooks for the test. + ServerHooks& hooks = ServerHooks::getServerHooks(); + hooks.reset(); + alpha_index_ = hooks.registerHook("alpha"); + beta_index_ = hooks.registerHook("beta"); + gamma_index_ = hooks.registerHook("gamma"); + delta_index_ = hooks.registerHook("delta"); + + // Set up the callout manager with these hooks. Assume a maximum of + // four libraries. + callout_manager_.reset(new CalloutManager(10)); + + // Set up the callout handle. + callout_handle_.reset(new CalloutHandle(callout_manager_)); + + // Initialize the static variable. + callout_value_ = 0; + } + + /// @brief Return the callout handle + CalloutHandle& getCalloutHandle() { + return (*callout_handle_); + } + + /// @brief Return the callout manager + boost::shared_ptr<CalloutManager> getCalloutManager() { + return (callout_manager_); + } + + /// Static variable used for accumulating information + static int callout_value_; + + /// Hook indexes. These are somewhat ubiquitous, so are made public for + /// ease of reference instead of being accessible by a function. + int alpha_index_; + int beta_index_; + int gamma_index_; + int delta_index_; + +private: + /// Callout handle used in calls + boost::shared_ptr<CalloutHandle> callout_handle_; + + /// Callout manager used for the test + boost::shared_ptr<CalloutManager> callout_manager_; +}; + +// Definition of the static variable. +int CalloutManagerTest::callout_value_ = 0; + +// Callout definitions +// +// The callouts defined here are structured in such a way that it is possible +// to determine the order in which they are called and whether they are called +// at all. The method used is simple - after a sequence of callouts, the digits +// in the value, reading left to right, determines the order of the callouts +// called. For example, callout one followed by two followed by three followed +// by two followed by one results in a value of 12321. +// +// Functions return a zero to indicate success. + +extern "C" { +int callout_general(int number) { + CalloutManagerTest::callout_value_ = + 10 * CalloutManagerTest::callout_value_ + number; + return (0); +} + +int callout_one(CalloutHandle&) { + return (callout_general(1)); +} + +int callout_two(CalloutHandle&) { + return (callout_general(2)); +} + +int callout_three(CalloutHandle&) { + return (callout_general(3)); +} + +int callout_four(CalloutHandle&) { + return (callout_general(4)); +} + +int callout_five(CalloutHandle&) { + return (callout_general(5)); +} + +int callout_six(CalloutHandle&) { + return (callout_general(6)); +} + +int callout_seven(CalloutHandle&) { + return (callout_general(7)); +} + +// The next functions are duplicates of some of the above, but return an error. +int callout_one_error(CalloutHandle& handle) { + (void) callout_one(handle); + return (1); +} + +int callout_two_error(CalloutHandle& handle) { + (void) callout_two(handle); + return (1); +} + +int callout_three_error(CalloutHandle& handle) { + (void) callout_three(handle); + return (1); +} + +int callout_four_error(CalloutHandle& handle) { + (void) callout_four(handle); + return (1); +} + +// The next functions are duplicates of some of the above, but throw exceptions. +int callout_one_exception(CalloutHandle& handle) { + (void) callout_one(handle); + throw 0; + return (1); +} + +int callout_two_exception(CalloutHandle& handle) { + (void) callout_two(handle); + throw 0; + return (1); +} + +int callout_three_exception(CalloutHandle& handle) { + (void) callout_three(handle); + throw 0; + return (1); +} + +int callout_four_exception(CalloutHandle& handle) { + (void) callout_four(handle); + throw 0; + return (1); +} + +} // extern "C" + +// *** Callout Tests *** +// +// The next set of tests check that callouts can be called. + +// Constructor - check that we trap bad parameters. +TEST_F(CalloutManagerTest, BadConstructorParameters) { + boost::scoped_ptr<CalloutManager> cm; + + // Invalid number of libraries + EXPECT_THROW(cm.reset(new CalloutManager(-1)), BadValue); +} + +// Check the number of libraries is reported successfully. +TEST_F(CalloutManagerTest, NumberOfLibraries) { + boost::scoped_ptr<CalloutManager> cm; + + // Check two valid values of number of libraries to ensure that the + // GetNumLibraries() returns the value set. + EXPECT_NO_THROW(cm.reset(new CalloutManager())); + EXPECT_EQ(0, cm->getNumLibraries()); + + EXPECT_NO_THROW(cm.reset(new CalloutManager(0))); + EXPECT_EQ(0, cm->getNumLibraries()); + + EXPECT_NO_THROW(cm.reset(new CalloutManager(4))); + EXPECT_EQ(4, cm->getNumLibraries()); + + EXPECT_NO_THROW(cm.reset(new CalloutManager(42))); + EXPECT_EQ(42, cm->getNumLibraries()); +} + +// Check that we can only set the current library index to the correct values. +TEST_F(CalloutManagerTest, CheckLibraryIndex) { + // Check valid indexes. As the callout manager is sized for 10 libraries, + // we expect: + // + // -1 to be valid as it is the standard "invalid" value. + // 0 to be valid for the pre-user library callouts + // 1-10 to be valid for the user-library callouts + // INT_MAX to be valid for the post-user library callouts + // + // All other values to be invalid. + for (int i = -1; i < 11; ++i) { + EXPECT_NO_THROW(getCalloutManager()->setLibraryIndex(i)); + EXPECT_EQ(i, getCalloutManager()->getLibraryIndex()); + } + EXPECT_NO_THROW(getCalloutManager()->setLibraryIndex(INT_MAX)); + EXPECT_EQ(INT_MAX, getCalloutManager()->getLibraryIndex()); + + // Check invalid ones + EXPECT_THROW(getCalloutManager()->setLibraryIndex(-2), NoSuchLibrary); + EXPECT_THROW(getCalloutManager()->setLibraryIndex(11), NoSuchLibrary); +} + +// Check that we can only register callouts on valid hook names. +TEST_F(CalloutManagerTest, ValidHookNames) { + EXPECT_NO_THROW(getCalloutManager()->registerCallout("alpha", callout_one, 0)); + EXPECT_THROW(getCalloutManager()->registerCallout("unknown", callout_one, 0), + NoSuchHook); +} + +// Check we can register callouts appropriately. +TEST_F(CalloutManagerTest, RegisterCallout) { + // Ensure that no callouts are attached to any of the hooks. + EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_)); + + // Set up so that hooks "alpha" and "beta" have callouts attached from a + // different libraries. + getCalloutManager()->registerCallout("alpha", callout_one, 0); + getCalloutManager()->registerCallout("beta", callout_two, 1); + + // Check all is as expected. + EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_)); + EXPECT_TRUE(getCalloutManager()->calloutsPresent(beta_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_)); + + // Check that calling the callouts returns as expected. (This is also a + // test of the callCallouts method.) + callout_value_ = 0; + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(1, callout_value_); + + callout_value_ = 0; + getCalloutManager()->callCallouts(beta_index_, getCalloutHandle()); + EXPECT_EQ(2, callout_value_); + + // Register some more callouts from different libraries on hook "alpha". + getCalloutManager()->registerCallout("alpha", callout_three, 2); + getCalloutManager()->registerCallout("alpha", callout_four, 2); + getCalloutManager()->registerCallout("alpha", callout_five, 3); + + // Check it is as expected. + callout_value_ = 0; + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(1345, callout_value_); + + // ... and check the additional callouts were not registered on the "beta" + // hook. + callout_value_ = 0; + getCalloutManager()->callCallouts(beta_index_, getCalloutHandle()); + EXPECT_EQ(2, callout_value_); + + // Add another callout to hook "alpha" from library index 2 - this should + // appear at the end of the callout list for that library. + getCalloutManager()->registerCallout("alpha", callout_six, 2); + callout_value_ = 0; + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(13465, callout_value_); + + // Add a callout from library index 1 - this should appear between the + // callouts from library index 0 and library index 2. + getCalloutManager()->registerCallout("alpha", callout_seven, 1); + callout_value_ = 0; + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(173465, callout_value_); +} + +// Check the "calloutsPresent()" method. +TEST_F(CalloutManagerTest, CalloutsPresent) { + // Ensure that no callouts are attached to any of the hooks. + EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_)); + + // Set up so that hooks "alpha", "beta" and "delta" have callouts attached + // to them, and callout "gamma" does not. (In the statements below, the + // exact callouts attached to a hook are not relevant - only the fact + // that some callouts are). Chose the libraries for which the callouts + // are registered randomly. + getCalloutManager()->registerCallout("alpha", callout_one, 0); + getCalloutManager()->registerCallout("alpha", callout_two, 1); + getCalloutManager()->registerCallout("beta", callout_two, 1); + getCalloutManager()->registerCallout("alpha", callout_three, 3); + getCalloutManager()->registerCallout("delta", callout_four, 3); + + // Check all is as expected. + EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_)); + EXPECT_TRUE(getCalloutManager()->calloutsPresent(beta_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_)); + EXPECT_TRUE(getCalloutManager()->calloutsPresent(delta_index_)); + + // Check we fail on an invalid hook index. + EXPECT_THROW(getCalloutManager()->calloutsPresent(42), NoSuchHook); + EXPECT_THROW(getCalloutManager()->calloutsPresent(-1), NoSuchHook); +} + +// Test that calling a hook with no callouts on it returns success. +TEST_F(CalloutManagerTest, CallNoCallouts) { + // Ensure that no callouts are attached to any of the hooks. + EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_)); + + // Call the callouts on an arbitrary hook and ensure that nothing happens. + callout_value_ = 475; + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(475, callout_value_); // Unchanged +} + +// Test that the callouts are called in the correct order (i.e. the callouts +// from the first library in the order they were registered, then the callouts +// from the second library in the order they were registered etc.) +TEST_F(CalloutManagerTest, CallCalloutsSuccess) { + // Ensure that no callouts are attached to any of the hooks. + EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_)); + + // Each library contributes one callout on hook "alpha". + callout_value_ = 0; + getCalloutManager()->registerCallout("alpha", callout_one, 1); + getCalloutManager()->registerCallout("alpha", callout_two, 1); + getCalloutManager()->registerCallout("alpha", callout_three, 2); + getCalloutManager()->registerCallout("alpha", callout_four, 3); + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(1234, callout_value_); + + // Do a random selection of callouts on hook "beta". + callout_value_ = 0; + getCalloutManager()->registerCallout("beta", callout_one, 0); + getCalloutManager()->registerCallout("beta", callout_three, 0); + getCalloutManager()->registerCallout("beta", callout_two, 1); + getCalloutManager()->registerCallout("beta", callout_four, 3); + getCalloutManager()->callCallouts(beta_index_, getCalloutHandle()); + EXPECT_EQ(1324, callout_value_); + + // Ensure that calling the callouts on a hook with no callouts works. + callout_value_ = 0; + getCalloutManager()->callCallouts(gamma_index_, getCalloutHandle()); + EXPECT_EQ(0, callout_value_); +} + +// Test that the callouts are called in order, but that callouts occurring +// after a callout that returns an error are called. +// +// (Note: in this test, the callouts that return an error set the value of +// callout_value_ before they return the error code.) +TEST_F(CalloutManagerTest, CallCalloutsError) { + // Ensure that no callouts are attached to any of the hooks. + EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_)); + + // Each library contributing one callout on hook "alpha". The first callout + // returns an error (after adding its value to the result). + callout_value_ = 0; + getCalloutManager()->registerCallout("alpha", callout_one_error, 0); + getCalloutManager()->registerCallout("alpha", callout_two, 1); + getCalloutManager()->registerCallout("alpha", callout_three, 2); + getCalloutManager()->registerCallout("alpha", callout_four, 3); + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(1234, callout_value_); + + // Each library contributing multiple callouts on hook "beta". The last + // callout on the first library returns an error. + callout_value_ = 0; + getCalloutManager()->registerCallout("beta", callout_one, 0); + getCalloutManager()->registerCallout("beta", callout_one_error, 0); + getCalloutManager()->registerCallout("beta", callout_two, 1); + getCalloutManager()->registerCallout("beta", callout_two, 1); + getCalloutManager()->registerCallout("beta", callout_three, 1); + getCalloutManager()->registerCallout("beta", callout_three, 1); + getCalloutManager()->registerCallout("beta", callout_four, 3); + getCalloutManager()->registerCallout("beta", callout_four, 3); + getCalloutManager()->callCallouts(beta_index_, getCalloutHandle()); + EXPECT_EQ(11223344, callout_value_); + + // A callout in a random position in the callout list returns an error. + callout_value_ = 0; + getCalloutManager()->registerCallout("gamma", callout_one, 0); + getCalloutManager()->registerCallout("gamma", callout_one, 0); + getCalloutManager()->registerCallout("gamma", callout_two, 1); + getCalloutManager()->registerCallout("gamma", callout_two, 1); + getCalloutManager()->registerCallout("gamma", callout_four_error, 3); + getCalloutManager()->registerCallout("gamma", callout_four, 3); + getCalloutManager()->callCallouts(gamma_index_, getCalloutHandle()); + EXPECT_EQ(112244, callout_value_); + + // The last callout on a hook returns an error. + callout_value_ = 0; + getCalloutManager()->registerCallout("delta", callout_one, 0); + getCalloutManager()->registerCallout("delta", callout_one, 0); + getCalloutManager()->registerCallout("delta", callout_two, 1); + getCalloutManager()->registerCallout("delta", callout_two, 1); + getCalloutManager()->registerCallout("delta", callout_three, 2); + getCalloutManager()->registerCallout("delta", callout_three, 2); + getCalloutManager()->registerCallout("delta", callout_four, 3); + getCalloutManager()->registerCallout("delta", callout_four_error, 3); + getCalloutManager()->callCallouts(delta_index_, getCalloutHandle()); + EXPECT_EQ(11223344, callout_value_); +} + +// Test that the callouts are called in order, but that callouts occurring +// after a callout that throws exception are called. +// +// (Note: in this test, the callouts that return an error set the value of +// callout_value_ before they throw exception.) +TEST_F(CalloutManagerTest, CallCalloutsException) { + // Ensure that no callouts are attached to any of the hooks. + EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_)); + + // Each library contributing one callout on hook "alpha". The first callout + // returns an error (after adding its value to the result). + callout_value_ = 0; + getCalloutManager()->registerCallout("alpha", callout_one_exception, 0); + getCalloutManager()->registerCallout("alpha", callout_two, 1); + getCalloutManager()->registerCallout("alpha", callout_three, 2); + getCalloutManager()->registerCallout("alpha", callout_four, 3); + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(1234, callout_value_); + EXPECT_EQ(getCalloutHandle().getStatus(), CalloutHandle::NEXT_STEP_DROP); + + // Each library contributing multiple callouts on hook "beta". The last + // callout on the first library returns an error. + callout_value_ = 0; + getCalloutManager()->registerCallout("beta", callout_one, 0); + getCalloutManager()->registerCallout("beta", callout_one_exception, 0); + getCalloutManager()->registerCallout("beta", callout_two, 1); + getCalloutManager()->registerCallout("beta", callout_two, 1); + getCalloutManager()->registerCallout("beta", callout_three, 1); + getCalloutManager()->registerCallout("beta", callout_three, 1); + getCalloutManager()->registerCallout("beta", callout_four, 3); + getCalloutManager()->registerCallout("beta", callout_four, 3); + getCalloutManager()->callCallouts(beta_index_, getCalloutHandle()); + EXPECT_EQ(11223344, callout_value_); + EXPECT_EQ(getCalloutHandle().getStatus(), CalloutHandle::NEXT_STEP_DROP); + + // A callout in a random position in the callout list returns an error. + callout_value_ = 0; + getCalloutManager()->registerCallout("gamma", callout_one, 0); + getCalloutManager()->registerCallout("gamma", callout_one, 0); + getCalloutManager()->registerCallout("gamma", callout_two, 1); + getCalloutManager()->registerCallout("gamma", callout_two, 1); + getCalloutManager()->registerCallout("gamma", callout_four_exception, 3); + getCalloutManager()->registerCallout("gamma", callout_four, 3); + getCalloutManager()->callCallouts(gamma_index_, getCalloutHandle()); + EXPECT_EQ(112244, callout_value_); + EXPECT_EQ(getCalloutHandle().getStatus(), CalloutHandle::NEXT_STEP_DROP); + + // The last callout on a hook returns an error. + callout_value_ = 0; + getCalloutManager()->registerCallout("delta", callout_one, 0); + getCalloutManager()->registerCallout("delta", callout_one, 0); + getCalloutManager()->registerCallout("delta", callout_two, 1); + getCalloutManager()->registerCallout("delta", callout_two, 1); + getCalloutManager()->registerCallout("delta", callout_three, 2); + getCalloutManager()->registerCallout("delta", callout_three, 2); + getCalloutManager()->registerCallout("delta", callout_four, 3); + getCalloutManager()->registerCallout("delta", callout_four_exception, 3); + getCalloutManager()->callCallouts(delta_index_, getCalloutHandle()); + EXPECT_EQ(11223344, callout_value_); + EXPECT_EQ(getCalloutHandle().getStatus(), CalloutHandle::NEXT_STEP_DROP); +} + +// Now test that we can deregister a single callout on a hook. +TEST_F(CalloutManagerTest, DeregisterSingleCallout) { + // Ensure that no callouts are attached to any of the hooks. + EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_)); + + // Add a callout to hook "alpha" and check it is added correctly. + callout_value_ = 0; + getCalloutManager()->registerCallout("alpha", callout_two, 0); + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(2, callout_value_); + + // Remove it and check that the no callouts are present. We have to reset + // the current library index here as it was invalidated by the call + // to callCallouts(). + EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_)); + EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_two, 0)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_)); +} + +// Now test that we can deregister a single callout on a hook that has multiple +// callouts from the same library. +TEST_F(CalloutManagerTest, DeregisterSingleCalloutSameLibrary) { + // Ensure that no callouts are attached to any of the hooks. + EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_)); + + // Add multiple callouts to hook "alpha". + callout_value_ = 0; + getCalloutManager()->registerCallout("alpha", callout_one, 0); + getCalloutManager()->registerCallout("alpha", callout_two, 0); + getCalloutManager()->registerCallout("alpha", callout_three, 0); + getCalloutManager()->registerCallout("alpha", callout_four, 0); + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(1234, callout_value_); + + // Remove the callout_two callout. We have to reset the current library + // index here as it was invalidated by the call to callCallouts(). + EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_two, 0)); + callout_value_ = 0; + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(134, callout_value_); + + // Try removing it again. + EXPECT_FALSE(getCalloutManager()->deregisterCallout("alpha", callout_two, 0)); + callout_value_ = 0; + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(134, callout_value_); +} + +// Check we can deregister multiple callouts from the same library. +TEST_F(CalloutManagerTest, DeregisterMultipleCalloutsSameLibrary) { + // Ensure that no callouts are attached to any of the hooks. + EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_)); + + // Each library contributes one callout on hook "alpha". + callout_value_ = 0; + getCalloutManager()->registerCallout("alpha", callout_one, 0); + getCalloutManager()->registerCallout("alpha", callout_two, 0); + getCalloutManager()->registerCallout("alpha", callout_one, 0); + getCalloutManager()->registerCallout("alpha", callout_two, 0); + getCalloutManager()->registerCallout("alpha", callout_three, 0); + getCalloutManager()->registerCallout("alpha", callout_four, 0); + getCalloutManager()->registerCallout("alpha", callout_three, 0); + getCalloutManager()->registerCallout("alpha", callout_four, 0); + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(12123434, callout_value_); + + // Remove the callout_two callouts. We have to reset the current library + // index here as it was invalidated by the call to callCallouts(). + EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_two, 0)); + callout_value_ = 0; + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(113434, callout_value_); + + // Try removing multiple callouts that includes one at the end of the + // list of callouts. + EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_four, 0)); + callout_value_ = 0; + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(1133, callout_value_); + + // ... and from the start. + EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_one, 0)); + callout_value_ = 0; + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(33, callout_value_); + + // ... and the remaining callouts. + EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_three, 0)); + callout_value_ = 0; + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(0, callout_value_); + + EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_)); +} + +// Check we can deregister multiple callouts from multiple libraries. +TEST_F(CalloutManagerTest, DeregisterMultipleCalloutsMultipleLibraries) { + // Ensure that no callouts are attached to any of the hooks. + EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_)); + + // Each library contributes two callouts to hook "alpha". + callout_value_ = 0; + getCalloutManager()->registerCallout("alpha", callout_one, 0); + getCalloutManager()->registerCallout("alpha", callout_two, 0); + getCalloutManager()->registerCallout("alpha", callout_three, 1); + getCalloutManager()->registerCallout("alpha", callout_four, 1); + getCalloutManager()->registerCallout("alpha", callout_five, 2); + getCalloutManager()->registerCallout("alpha", callout_two, 2); + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(123452, callout_value_); + + // Remove the callout_two callout from library 0. It should not affect + // the second callout_two callout registered by library 2. + EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_two, 0)); + callout_value_ = 0; + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(13452, callout_value_); +} + +// Check we can deregister all callouts from a single library. +TEST_F(CalloutManagerTest, DeregisterAllCallouts) { + // Ensure that no callouts are attached to hook one. + EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_)); + + // Each library contributes two callouts to hook "alpha". + callout_value_ = 0; + getCalloutManager()->registerCallout("alpha", callout_one, 0); + getCalloutManager()->registerCallout("alpha", callout_two, 0); + getCalloutManager()->registerCallout("alpha", callout_three, 1); + getCalloutManager()->registerCallout("alpha", callout_four, 1); + getCalloutManager()->registerCallout("alpha", callout_five, 2); + getCalloutManager()->registerCallout("alpha", callout_six, 2); + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(123456, callout_value_); + + // Remove all callouts from library index 1. + EXPECT_TRUE(getCalloutManager()->deregisterAllCallouts("alpha", 1)); + callout_value_ = 0; + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(1256, callout_value_); + + // Remove all callouts from library index 2. + EXPECT_TRUE(getCalloutManager()->deregisterAllCallouts("alpha", 2)); + callout_value_ = 0; + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(12, callout_value_); +} + +// Check that we can register/deregister callouts on different libraries +// and different hooks, and that the callout instances are regarded as +// unique and do not affect one another. +TEST_F(CalloutManagerTest, MultipleCalloutsLibrariesHooks) { + // Ensure that no callouts are attached to any of the hooks. + EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_)); + + // Register callouts on the alpha hook. + callout_value_ = 0; + getCalloutManager()->registerCallout("alpha", callout_one, 0); + getCalloutManager()->registerCallout("alpha", callout_two, 0); + getCalloutManager()->registerCallout("alpha", callout_three, 1); + getCalloutManager()->registerCallout("alpha", callout_four, 1); + getCalloutManager()->registerCallout("alpha", callout_five, 2); + getCalloutManager()->registerCallout("alpha", callout_two, 2); + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(123452, callout_value_); + + // Register the same callouts on the beta hook, and check that those + // on the alpha hook are not affected. + callout_value_ = 0; + getCalloutManager()->registerCallout("beta", callout_five, 0); + getCalloutManager()->registerCallout("beta", callout_one, 0); + getCalloutManager()->registerCallout("beta", callout_four, 2); + getCalloutManager()->registerCallout("beta", callout_three, 2); + getCalloutManager()->callCallouts(beta_index_, getCalloutHandle()); + EXPECT_EQ(5143, callout_value_); + + // Check that the order of callouts on the alpha hook has not been affected. + callout_value_ = 0; + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(123452, callout_value_); + + // Remove callout four from beta and check that alpha is not affected. + EXPECT_TRUE(getCalloutManager()->deregisterCallout("beta", callout_four, 2)); + + callout_value_ = 0; + getCalloutManager()->callCallouts(beta_index_, getCalloutHandle()); + EXPECT_EQ(513, callout_value_); + + callout_value_ = 0; + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(123452, callout_value_); +} + +// Library handle tests. As by inspection the LibraryHandle can be seen to be +// little more than shell around CalloutManager, only a basic set of tests +// is done concerning registration and deregistration of functions. +// +// More extensive tests (i.e. checking that when a callout is called it can +// only register and deregister callouts within its library) require that +// the CalloutHandle object pass the appropriate LibraryHandle to the +// callout. These tests are done in the handles_unittest tests. +TEST_F(CalloutManagerTest, LibraryHandleRegistration) { + // Ensure that no callouts are attached to any of the hooks. + EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_)); + + // Set up so that hooks "alpha" and "beta" have callouts attached from a + // different libraries. + getCalloutManager()->setLibraryIndex(0); + getCalloutManager()->getLibraryHandle().registerCallout("alpha", callout_one); + getCalloutManager()->getLibraryHandle().registerCallout("alpha", callout_two); + getCalloutManager()->setLibraryIndex(1); + getCalloutManager()->getLibraryHandle().registerCallout("alpha", callout_three); + getCalloutManager()->getLibraryHandle().registerCallout("alpha", callout_four); + + // Check all is as expected. + EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_)); + + // Check that calling the callouts returns as expected. (This is also a + // test of the callCallouts method.) + callout_value_ = 0; + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(1234, callout_value_); + + // Deregister a callout on library index 0 (after we check we can't + // deregister it through library index 1). + EXPECT_FALSE(getCalloutManager()->deregisterCallout("alpha", callout_two, 1)); + callout_value_ = 0; + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(1234, callout_value_); + + EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_two, 0)); + callout_value_ = 0; + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(134, callout_value_); + + // Deregister all callouts on library index 1. + EXPECT_TRUE(getCalloutManager()->deregisterAllCallouts("alpha", 1)); + callout_value_ = 0; + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(1, callout_value_); +} + +// A repeat of the test above, but using the alternate constructor for the +// LibraryHandle. +TEST_F(CalloutManagerTest, LibraryHandleAlternateConstructor) { + // Ensure that no callouts are attached to any of the hooks. + EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_)); + + // Set up so that hooks "alpha" and "beta" have callouts attached from a + // different libraries. + LibraryHandle lh0(*getCalloutManager().get(), 0); + lh0.registerCallout("alpha", callout_one); + lh0.registerCallout("alpha", callout_two); + + LibraryHandle lh1(*getCalloutManager().get(), 1); + lh1.registerCallout("alpha", callout_three); + lh1.registerCallout("alpha", callout_four); + + // Check all is as expected. + EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_)); + + // Check that calling the callouts returns as expected. (This is also a + // test of the callCallouts method.) + callout_value_ = 0; + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(1234, callout_value_); + + // Deregister a callout on library index 0 (after we check we can't + // deregister it through library index 1). + EXPECT_FALSE(lh1.deregisterCallout("alpha", callout_two)); + callout_value_ = 0; + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(1234, callout_value_); + + EXPECT_TRUE(lh0.deregisterCallout("alpha", callout_two)); + callout_value_ = 0; + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(134, callout_value_); + + // Deregister all callouts on library index 1. + EXPECT_TRUE(lh1.deregisterAllCallouts("alpha")); + callout_value_ = 0; + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(1, callout_value_); +} + +// Check that the pre- and post- user callout library handles work +// appropriately with no user libraries. +TEST_F(CalloutManagerTest, LibraryHandlePrePostNoLibraries) { + // Create a local callout manager and callout handle to reflect no libraries + // being loaded. + boost::shared_ptr<CalloutManager> manager(new CalloutManager(0)); + CalloutHandle handle(manager); + + // Ensure that no callouts are attached to any of the hooks. + EXPECT_FALSE(manager->calloutsPresent(alpha_index_)); + + // Setup the pre-and post callouts. + manager->getPostLibraryHandle().registerCallout("alpha", callout_four); + manager->getPreLibraryHandle().registerCallout("alpha", callout_one); + // Check all is as expected. + EXPECT_TRUE(manager->calloutsPresent(alpha_index_)); + EXPECT_FALSE(manager->calloutsPresent(beta_index_)); + EXPECT_FALSE(manager->calloutsPresent(gamma_index_)); + EXPECT_FALSE(manager->calloutsPresent(delta_index_)); + + // Check that calling the callouts returns as expected. + callout_value_ = 0; + manager->callCallouts(alpha_index_, handle); + EXPECT_EQ(14, callout_value_); + + // Deregister the pre- library callout. + EXPECT_TRUE(manager->getPreLibraryHandle().deregisterAllCallouts("alpha")); + callout_value_ = 0; + manager->callCallouts(alpha_index_, handle); + EXPECT_EQ(4, callout_value_); +} + +// Repeat the tests with one user library. +TEST_F(CalloutManagerTest, LibraryHandlePrePostUserLibrary) { + + // Setup the pre-, library and post callouts. + getCalloutManager()->getPostLibraryHandle().registerCallout("alpha", + callout_four); + getCalloutManager()->getPreLibraryHandle().registerCallout("alpha", + callout_one); + + // ... and set up a callout in between, on library number 2. + LibraryHandle lh1(*getCalloutManager().get(), 2); + lh1.registerCallout("alpha", callout_five); + + // Check all is as expected. + EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_)); + EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_)); + + // Check that calling the callouts returns as expected. + callout_value_ = 0; + getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); + EXPECT_EQ(154, callout_value_); +} + +// Test that control command handlers can be installed as callouts. +TEST_F(CalloutManagerTest, LibraryHandleRegisterCommandHandler) { + CalloutHandle handle(getCalloutManager()); + + // Simulate creation of the two hook libraries. Fist library implements two + // handlers for the control command 'command-one'. Second library implements + // two control command handlers: one for the 'command-one', another one for + // 'command-two'. Each of the handlers for the 'command-one' must be called + // and they must be called in the appropriate order. Command handler for + // 'command-two' should also be called. + + getCalloutManager()->setLibraryIndex(0); + getCalloutManager()->getLibraryHandle().registerCommandCallout("command-one", callout_one); + getCalloutManager()->getLibraryHandle().registerCommandCallout("command-one", callout_four); + getCalloutManager()->setLibraryIndex(1); + getCalloutManager()->getLibraryHandle().registerCommandCallout("command-one", callout_two); + getCalloutManager()->getLibraryHandle().registerCommandCallout("command-two", callout_three); + + // Command handlers are installed for commands: 'command-one' and 'command-two'. + EXPECT_TRUE(getCalloutManager()->commandHandlersPresent("command-one")); + EXPECT_TRUE(getCalloutManager()->commandHandlersPresent("command-two")); + // There should be no handlers installed for 'command-three' and 'command-four'. + EXPECT_FALSE(getCalloutManager()->commandHandlersPresent("command-three")); + EXPECT_FALSE(getCalloutManager()->commandHandlersPresent("command-four")); + + // Call handlers for 'command-one'. There should be three handlers called in + // the following order: 1, 4, 2. + callout_value_ = 0; + ASSERT_NO_THROW(getCalloutManager()->callCommandHandlers("command-one", handle)); + EXPECT_EQ(142, callout_value_); + + // There should be one handler invoked for the 'command-two'. This handler has + // index of 3. + callout_value_ = 0; + ASSERT_NO_THROW(getCalloutManager()->callCommandHandlers("command-two", handle)); + EXPECT_EQ(3, callout_value_); + + // An attempt to call handlers for the commands for which no hook points + // were created should result in exception. + EXPECT_THROW(getCalloutManager()->callCommandHandlers("command-three", handle), + NoSuchHook); + EXPECT_THROW(getCalloutManager()->callCommandHandlers("command-four", handle), + NoSuchHook); +} + +// This test checks if the CalloutManager can adjust its own hook_vector_ size. +TEST_F(CalloutManagerTest, VectorSize) { + + size_t s = getCalloutManager()->getHookLibsVectorSize(); + + ServerHooks& hooks = ServerHooks::getServerHooks(); + + EXPECT_NO_THROW(hooks.registerHook("a_new_one")); + + // Now load a callout. Name of the hook point the new callout is installed + // on doesn't matter. CM should do sanity checks and adjust anyway. + getCalloutManager()->getPostLibraryHandle().registerCallout("alpha", + callout_four); + + // The vector size should have been increased by one, because there's + // one new hook point now. + EXPECT_EQ(s + 1, getCalloutManager()->getHookLibsVectorSize()); +} + +// The setting of the hook index is checked in the handles_unittest +// set of tests, as access restrictions mean it is not easily tested +// on its own. + +} // namespace diff --git a/src/lib/hooks/tests/callout_params_library.cc b/src/lib/hooks/tests/callout_params_library.cc new file mode 100644 index 0000000..d35fc00 --- /dev/null +++ b/src/lib/hooks/tests/callout_params_library.cc @@ -0,0 +1,129 @@ +// Copyright (C) 2016-2020 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +/// @file +/// @brief Callout Library +/// +/// This is the source of a test library for the DHCP parser tests that +/// specify parameters. It will attempt to obtain its own parameters. + +#include <config.h> +#include <hooks/hooks.h> +#include <iostream> + +using namespace std; +using namespace isc::hooks; +using namespace isc::data; + +extern "C" { + +// Framework functions +int +version() { + return (KEA_HOOKS_VERSION); +} + +/// @brief This method will be called when the hook library is loaded +/// +/// While its primary usage is for unit-testing, it also doubles as an +/// illustration referred to from Hooks Developer's Guide. As such, please +/// keep it simple, tidy and try to avoid referencing unnecessary code. +/// Parts of it can be used as copy-paste examples. +/// +/// @param handle passed by the hooks framework +/// @return 0 if load was successful, non-zero for errors +int load(LibraryHandle& handle) { + ConstElementPtr elems = handle.getParameters(); + ConstElementPtr string_elem = handle.getParameter("svalue"); + ConstElementPtr int_elem = handle.getParameter("ivalue"); + ConstElementPtr bool_elem = handle.getParameter("bvalue"); + ConstElementPtr nonexistent = handle.getParameter("nonexistent"); + vector<string> names = handle.getParameterNames(); + + // String handling example. + if (!string_elem) { + // Parameter was not specified at all. + return (1); + } + + if (string_elem->getType() != Element::string) { + // Parameter is specified, but it's not a string. + return (2); + } + + string str = string_elem->stringValue(); + if (str != "string value") { + // Parameter is specified, is a string, but has unexpected value. + // + // This library is used for testing, so it expects exact value of the + // parameter. Normal library would likely use whatever value user + // specified. + return (3); + } + + // Integer handling example + if (!int_elem) { + // Parameter was not specified at all. + return (4); + } + + if (int_elem->getType() != Element::integer) { + // Parameter is specified, but it's not an integer. + return (5); + } + + int int_value = int_elem->intValue(); + if (int_value != 42) { + // Parameter specified, is an integer, but has a value different than + // expected. + return (6); + } + + // Boolean handling example + if (!bool_elem) { + // Parameter was not specified at all. + return (7); + } + + if (bool_elem->getType() != Element::boolean) { + // Parameter is specified, but it's not a boolean. + return (8); + } + + bool flag = bool_elem->boolValue(); + if (flag != true) { + // Parameter specified, is a boolean, but has a value different than + // expected. + return (9); + } + + // Check names. As a side effect of what maps using strings are + // implemented names are sorted in alphabetical order. + if ((names.size() != 3) || (names[0] != "bvalue") || + (names[1] != "ivalue") || (names[2] != "svalue")) { + // Expect 3 names: bvalue, ivalue, svalue. + return (10); + } + + // Check elems map. + if (!elems) { + return (11); + } + string expected_str = "{ " + "\"bvalue\": true, " + "\"ivalue\": 42, " + "\"svalue\": \"string value\"" + " }"; + if (expected_str != elems->str()) { + return (12); + } + + // All validation steps were successful. The library has all the parameters + // it needs, so we should report a success. + return (0); +} + +} diff --git a/src/lib/hooks/tests/common_test_class.h b/src/lib/hooks/tests/common_test_class.h new file mode 100644 index 0000000..aa34bcf --- /dev/null +++ b/src/lib/hooks/tests/common_test_class.h @@ -0,0 +1,174 @@ +// 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 COMMON_HOOKS_TEST_CLASS_H +#define COMMON_HOOKS_TEST_CLASS_H + +#include <hooks/callout_handle.h> +#include <hooks/callout_manager.h> +#include <hooks/server_hooks.h> +#include <hooks/tests/marker_file.h> + +#include <boost/shared_ptr.hpp> +#include <gtest/gtest.h> + +/// @brief Common hooks test class +/// +/// This class is a shared parent of the test fixture class in the tests of the +/// higher-level hooks classes (LibraryManager, LibraryManagerCollection and +/// HooksManager). It +/// +/// - sets the ServerHooks object with three hooks and stores their +/// indexes. +/// - executes the callouts (which are assumed to perform a calculation) +/// and checks the results. + +class HooksCommonTestClass { +public: + /// @brief Constructor + HooksCommonTestClass() { + + // Set up the server hooks. ServerHooks is a singleton, so we reset it + // between each test. + isc::hooks::ServerHooks& hooks = + isc::hooks::ServerHooks::getServerHooks(); + hooks.reset(); + hookpt_one_index_ = hooks.registerHook("hookpt_one"); + hookpt_two_index_ = hooks.registerHook("hookpt_two"); + hookpt_three_index_ = hooks.registerHook("hookpt_three"); + } + + /// @brief Call callouts test + /// + /// All of the loaded libraries for which callouts are called register four + /// callouts: a context_create callout and three callouts that are attached + /// to hooks hookpt_one, hookpt_two and hookpt_three. These four callouts, + /// executed in sequence, perform a series of calculations. Data is passed + /// between callouts in the argument list, in a variable named "result". + /// + /// context_create initializes the calculation by setting a seed + /// value, called r0 here. This value is dependent on the library being + /// loaded. Prior to that, the argument "result" is initialized to -1, + /// the purpose being to avoid exceptions when running this test with no + /// libraries loaded. + /// + /// Callout hookpt_one is passed a value d1 and performs a simple arithmetic + /// operation on it and r0 yielding a result r1. Hence we can say that + /// @f[ r1 = hookpt_one(r0, d1) @f] + /// + /// Callout hookpt_two is passed a value d2 and performs another simple + /// arithmetic operation on it and d2, yielding r2, i.e. + /// @f[ r2 = hookpt_two(d1, d2) @f] + /// + /// hookpt_three does a similar operation giving + /// @f[ r3 = hookpt_three(r2, d3) @f]. + /// + /// The details of the operations hookpt_one, hookpt_two and hookpt_three + /// depend on the library, so the results obtained not only depend on + /// the data, but also on the library loaded. This method is passed both + /// data and expected results. It executes the three callouts in sequence, + /// checking the intermediate and final results. Only if the expected + /// library has been loaded correctly and the callouts in it registered + /// correctly will be the results be as expected. + /// + /// It is assumed that callout_manager_ has been set up appropriately. + /// + /// @note The CalloutHandle used in the calls is declared locally here. + /// The advantage of this (apart from scope reduction) is that on + /// exit, it is destroyed. This removes any references to memory + /// allocated by loaded libraries while they are still loaded. + /// + /// @param manager CalloutManager to use for the test + /// @param r0...r3, d1..d3 Data (dN) and expected results (rN) - both + /// intermediate and final. The arguments are ordered so that they + /// appear in the argument list in the order they are used. + void executeCallCallouts( + const boost::shared_ptr<isc::hooks::CalloutManager>& manager, + int r0, int d1, int r1, int d2, int r2, int d3, int r3) { + static const char* COMMON_TEXT = " callout returned the wrong value"; + static const char* RESULT = "result"; + + int result; + + // Set up a callout handle for the calls. + isc::hooks::CalloutHandle handle(manager); + + // Initialize the argument RESULT. This simplifies testing by + // eliminating the generation of an exception when we try the unload + // test. In that case, RESULT is unchanged. + handle.setArgument(RESULT, -1); + + // Seed the calculation. + manager->callCallouts(isc::hooks::ServerHooks::CONTEXT_CREATE, handle); + handle.getArgument(RESULT, result); + EXPECT_EQ(r0, result) << "context_create" << COMMON_TEXT; + + // Perform the first calculation. + handle.setArgument("data_1", d1); + manager->callCallouts(hookpt_one_index_, handle); + handle.getArgument(RESULT, result); + EXPECT_EQ(r1, result) << "hookpt_one" << COMMON_TEXT; + + // ... the second ... + handle.setArgument("data_2", d2); + manager->callCallouts(hookpt_two_index_, handle); + handle.getArgument(RESULT, result); + EXPECT_EQ(r2, result) << "hookpt_two" << COMMON_TEXT; + + // ... and the third. + handle.setArgument("data_3", d3); + manager->callCallouts(hookpt_three_index_, handle); + handle.getArgument(RESULT, result); + EXPECT_EQ(r3, result) << "hookpt_three" << COMMON_TEXT; + } + + /// @brief Call command handlers test. + /// + /// This test is similar to @c executeCallCallouts but it uses + /// @ref CalloutManager::callCommandHandlers to execute the command + /// handlers for the following commands: 'command-one' and 'command-two'. + /// + /// @param manager CalloutManager to use for the test + /// @param r1..r2, d1..d2 Data (dN) and expected results (rN). + void executeCallCommandHandlers( + const boost::shared_ptr<isc::hooks::CalloutManager>& manager, + int d1, int r1, int d2, int r2) { + static const char* COMMON_TEXT = " command handler returned the wrong value"; + static const char* RESULT = "result"; + + int result; + + // Set up a callout handle for the calls. + isc::hooks::CalloutHandle handle(manager); + + // Initialize the argument RESULT. This simplifies testing by + // eliminating the generation of an exception when we try the unload + // test. In that case, RESULT is unchanged. + handle.setArgument(RESULT, -1); + + // Perform the first calculation: it should assign the data to the + // result. + handle.setArgument("data_1", d1); + manager->callCommandHandlers("command-one", handle); + handle.getArgument(RESULT, result); + EXPECT_EQ(r1, result) << "command-one" << COMMON_TEXT; + + // Perform the second calculation: it should multiply the data by 10 + // and return in the result. + handle.setArgument("data_2", d2); + manager->callCommandHandlers("command-two", handle); + handle.getArgument(RESULT, result); + EXPECT_EQ(r2, result) << "command-two" << COMMON_TEXT; + } + + + /// Hook indexes. These are are made public for ease of reference. + int hookpt_one_index_; + int hookpt_two_index_; + int hookpt_three_index_; +}; + +#endif // COMMON_HOOKS_TEST_CLASS_H diff --git a/src/lib/hooks/tests/framework_exception_library.cc b/src/lib/hooks/tests/framework_exception_library.cc new file mode 100644 index 0000000..c60c3f8 --- /dev/null +++ b/src/lib/hooks/tests/framework_exception_library.cc @@ -0,0 +1,41 @@ +// Copyright (C) 2013-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +/// @file +/// @brief Framework exception library +/// +/// This is source of a test library for various test (LibraryManager and +/// HooksManager). The characteristics of the library produced from this +/// file are: +/// +/// - All three framework functions are supplied (version(), load() and +/// unload()) and all generate an exception. + +#include <config.h> + +#include <hooks/hooks.h> + +#include <exception> + +extern "C" { + +int +version() { + throw std::exception(); +} + +int +load(isc::hooks::LibraryHandle& /*handle*/) { + throw std::exception(); +} + +int +unload() { + throw std::exception(); +} + +}; + diff --git a/src/lib/hooks/tests/full_callout_library.cc b/src/lib/hooks/tests/full_callout_library.cc new file mode 100644 index 0000000..58ea8c7 --- /dev/null +++ b/src/lib/hooks/tests/full_callout_library.cc @@ -0,0 +1,177 @@ +// Copyright (C) 2013-2020 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +/// @file +/// @brief Full callout library +/// +/// This is source of a test library for various test (LibraryManager and +/// HooksManager). The characteristics of the library produced from this +/// file are: +/// +/// The characteristics of this library are: +/// +/// - All four framework functions are supplied (version(), load(), +/// unload() and multi_threading_compatible()), with unload() +/// creating a marker file. The test code checks for the presence +/// of this file, so verifying that unload() has been run. +/// +/// - One standard and two non-standard callouts are supplied, with the latter +/// being registered by the load() function. +/// +/// All callouts do trivial calculations, the result of all being called in +/// sequence being +/// +/// @f[ ((7 * data_1) - data_2) * data_3 @f] +/// +/// ...where data_1, data_2 and data_3 are the values passed in arguments of +/// the same name to the three callouts (data_1 passed to hookpt_one, data_2 +/// to hookpt_two etc.) and the result is returned in the argument "result". + +#include <config.h> + +#include <hooks/hooks.h> +#include <hooks/tests/marker_file.h> + +#include <fstream> + +using namespace isc::hooks; + +extern "C" { + +// Callouts + +int +context_create(CalloutHandle& handle) { + handle.setContext("result", static_cast<int>(7)); + handle.setArgument("result", static_cast<int>(7)); + return (0); +} + +// First callout adds the passed "data_1" argument to the initialized context +// value of 7. (Note that the value set by context_create is accessed through +// context and not the argument, so checking that context is correctly passed +// between callouts in the same library.) + +int +hookpt_one(CalloutHandle& handle) { + int data; + handle.getArgument("data_1", data); + + int result; + handle.getArgument("result", result); + + result *= data; + handle.setArgument("result", result); + + return (0); +} + +// Second callout subtracts the passed value of data_2 from the current +// running total. + +static int +hook_nonstandard_two(CalloutHandle& handle) { + int data; + handle.getArgument("data_2", data); + + int result; + handle.getArgument("result", result); + + result -= data; + handle.setArgument("result", result); + + return (0); +} + +// Final callout multiplies the current running total by data_3. + +static int +hook_nonstandard_three(CalloutHandle& handle) { + int data; + handle.getArgument("data_3", data); + + int result; + handle.getArgument("result", result); + + result *= data; + handle.setArgument("result", result); + + return (0); +} + +// First command handler assigns data to a result. + +static int +command_handler_one(CalloutHandle& handle) { + int data; + handle.getArgument("data_1", data); + + int result; + handle.getArgument("result", result); + + result = data; + handle.setArgument("result", result); + + return (0); +} + +// Second command handler multiples the result by data by 10. + +static int +command_handler_two(CalloutHandle& handle) { + int data; + handle.getArgument("data_2", data); + + int result; + handle.getArgument("result", result); + + result *= data * 10; + handle.setArgument("result", result); + + return (0); +} + +// Framework functions + +int +version() { + return (KEA_HOOKS_VERSION); +} + +int +load(LibraryHandle& handle) { + // Initialize if the main image was statically linked +#ifdef USE_STATIC_LINK + hooksStaticLinkInit(); +#endif + // Register the non-standard functions + handle.registerCallout("hookpt_two", hook_nonstandard_two); + handle.registerCallout("hookpt_three", hook_nonstandard_three); + + // Register command_handler_one as control command handler. + handle.registerCommandCallout("command-one", command_handler_one); + handle.registerCommandCallout("command-two", command_handler_two); + + return (0); +} + +int +unload() { + // Create the marker file. + std::fstream marker; + marker.open(MARKER_FILE, std::fstream::out); + marker.close(); + + return (0); +} + +int +multi_threading_compatible() { + return (1); +} + +}; + diff --git a/src/lib/hooks/tests/handles_unittest.cc b/src/lib/hooks/tests/handles_unittest.cc new file mode 100644 index 0000000..a9292d8 --- /dev/null +++ b/src/lib/hooks/tests/handles_unittest.cc @@ -0,0 +1,777 @@ +// Copyright (C) 2013-2020 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <hooks/callout_handle.h> +#include <hooks/callout_manager.h> +#include <hooks/library_handle.h> +#include <hooks/server_hooks.h> + +#include <boost/lexical_cast.hpp> +#include <boost/scoped_ptr.hpp> +#include <gtest/gtest.h> + +#include <algorithm> +#include <string> + +/// @file +/// CalloutHandle/LibraryHandle interaction tests +/// +/// This file holds unit tests checking the interaction between the +/// CalloutHandle/LibraryHandle and CalloutManager classes. In particular, +/// they check that: +/// +/// - A CalloutHandle's context is shared between callouts from the same +/// library, but there is a separate context for each library. +/// +/// - The various methods manipulating the items in the CalloutHandle's context +/// work correctly. +/// +/// - An active callout can only modify the registration of callouts registered +/// by its own library. + +using namespace isc::hooks; +using namespace std; + +namespace { + +class HandlesTest : public ::testing::Test { +public: + /// @brief Constructor + /// + /// Sets up the various elements used in each test. + HandlesTest() { + // Set up four hooks, although through gamma + ServerHooks& hooks = ServerHooks::getServerHooks(); + hooks.reset(); + alpha_index_ = hooks.registerHook("alpha"); + beta_index_ = hooks.registerHook("beta"); + gamma_index_ = hooks.registerHook("gamma"); + delta_index_ = hooks.registerHook("delta"); + + // Set up for three libraries. + manager_.reset(new CalloutManager(3)); + + // Initialize remaining variables. + common_string_ = ""; + } + + /// @brief Return callout manager + boost::shared_ptr<CalloutManager> getCalloutManager() { + return (manager_); + } + + /// Hook indexes - these are frequently accessed, so are accessed directly. + int alpha_index_; + int beta_index_; + int gamma_index_; + int delta_index_; + + /// String accessible by all callouts whatever the library + static std::string common_string_; + +private: + /// Callout manager. Declared static so that the callout functions can + /// access it. + boost::shared_ptr<CalloutManager> manager_; +}; + +/// Define the common string +std::string HandlesTest::common_string_; + + +// The next set of functions define the callouts used by the tests. They +// manipulate the data in such a way that callouts called - and the order in +// which they were called - can be determined. The functions also check that +// the "callout context" data areas are separate. +// +// Three libraries are assumed, and each supplies four callouts. All callouts +// manipulate two context elements the CalloutHandle, the elements being called +// "string" and "int" (which describe the type of data manipulated). +// +// For the string item, each callout shifts data to the left and inserts its own +// data. The data is a string of the form "nmc", where "n" is the number of +// the library, "m" is the callout number and "y" is the indication of what +// callout handle was passed as an argument ("1" or "2": "0" is used when no +// identification has been set in the callout handle). +// +// For simplicity, and to cut down the number of functions actually written, +// the callout indicator ("1" or "2") ) used in the in the CalloutHandle +// functions is passed via a CalloutArgument. The argument is named "string": +// use of a name the same as that of one of the context elements serves as a +// check that the argument name space and argument context space are separate. +// +// For integer data, the value starts at zero and an increment is added on each +// call. This increment is equal to: +// +// 100 * library number + 10 * callout number + callout handle +// +// Although this gives less information than the string value, the reasons for +// using it are: +// +// - It is a separate item in the context, so checks that the context can +// handle multiple items. +// - It provides an item that can be deleted by the context deletion +// methods. + + +// Values set in the CalloutHandle context. There are three libraries, so +// there are three contexts for the callout, one for each library. + +std::string& resultCalloutString(int index) { + static std::string result_callout_string[3]; + return (result_callout_string[index]); +} + +int& resultCalloutInt(int index) { + static int result_callout_int[3]; + return (result_callout_int[index]); +} + +// A simple function to zero the results. + +static void zero_results() { + for (int i = 0; i < 3; ++i) { + resultCalloutString(i) = ""; + resultCalloutInt(i) = 0; + } +} + + +// Library callouts. + +// Common code for setting the callout context values. + +int +execute(CalloutHandle& callout_handle, int library_num, int callout_num) { + + // Obtain the callout handle number + int handle_num = 0; + try { + callout_handle.getArgument("handle_num", handle_num); + } catch (const NoSuchArgument&) { + // handle_num argument not set: this is the case in the tests where + // the context_create hook check is tested. + handle_num = 0; + } + + // Create the basic data to be appended to the context value. + int idata = 100 * library_num + 10 * callout_num + handle_num; + string sdata = boost::lexical_cast<string>(idata); + + // Get the context data. As before, this will not exist for the first + // callout called. (In real life, the library should create it when the + // "context_create" hook gets called before any packet processing takes + // place.) + int int_value = 0; + try { + callout_handle.getContext("int", int_value); + } catch (const NoSuchCalloutContext&) { + int_value = 0; + } + + string string_value = ""; + try { + callout_handle.getContext("string", string_value); + } catch (const NoSuchCalloutContext&) { + string_value = ""; + } + + // Update the values and set them back in the callout context. + int_value += idata; + callout_handle.setContext("int", int_value); + + string_value += sdata; + callout_handle.setContext("string", string_value); + + return (0); +} + +// The following functions are the actual callouts - the name is of the +// form "callout_<library number>_<callout number>" + +int +callout11(CalloutHandle& callout_handle) { + return (execute(callout_handle, 1, 1)); +} + +int +callout12(CalloutHandle& callout_handle) { + return (execute(callout_handle, 1, 2)); +} + +int +callout13(CalloutHandle& callout_handle) { + return (execute(callout_handle, 1, 3)); +} + +int +callout21(CalloutHandle& callout_handle) { + return (execute(callout_handle, 2, 1)); +} + +int +callout22(CalloutHandle& callout_handle) { + return (execute(callout_handle, 2, 2)); +} + +int +callout23(CalloutHandle& callout_handle) { + return (execute(callout_handle, 2, 3)); +} + +int +callout31(CalloutHandle& callout_handle) { + return (execute(callout_handle, 3, 1)); +} + +int +callout32(CalloutHandle& callout_handle) { + return (execute(callout_handle, 3, 2)); +} + +int +callout33(CalloutHandle& callout_handle) { + return (execute(callout_handle, 3, 3)); +} + +// Common callout code for the fourth hook (which makes the data available for +// checking). It copies the library and callout context data to the global +// variables. + +int printExecute(CalloutHandle& callout_handle, int library_num) { + callout_handle.getContext("string", resultCalloutString(library_num - 1)); + callout_handle.getContext("int", resultCalloutInt(library_num - 1)); + + return (0); +} + +// These are the actual callouts. + +int +print1(CalloutHandle& callout_handle) { + return (printExecute(callout_handle, 1)); +} + +int +print2(CalloutHandle& callout_handle) { + return (printExecute(callout_handle, 2)); +} + +int +print3(CalloutHandle& callout_handle) { + return (printExecute(callout_handle, 3)); +} + +// This test checks the many-faced nature of the context for the CalloutContext. + +TEST_F(HandlesTest, ContextAccessCheck) { + // Register callouts for the different libraries. + CalloutHandle handle(getCalloutManager()); + + getCalloutManager()->registerCallout("alpha", callout11, 0); + getCalloutManager()->registerCallout("beta", callout12, 0); + getCalloutManager()->registerCallout("gamma", callout13, 0); + getCalloutManager()->registerCallout("delta", print1, 0); + + getCalloutManager()->registerCallout("alpha", callout21, 1); + getCalloutManager()->registerCallout("beta", callout22, 1); + getCalloutManager()->registerCallout("gamma", callout23, 1); + getCalloutManager()->registerCallout("delta", print2, 1); + + getCalloutManager()->registerCallout("alpha", callout31, 2); + getCalloutManager()->registerCallout("beta", callout32, 2); + getCalloutManager()->registerCallout("gamma", callout33, 2); + getCalloutManager()->registerCallout("delta", print3, 2); + + // Create the callout handles and distinguish them by setting the + // "handle_num" argument. + CalloutHandle callout_handle_1(getCalloutManager()); + callout_handle_1.setArgument("handle_num", static_cast<int>(1)); + + CalloutHandle callout_handle_2(getCalloutManager()); + callout_handle_2.setArgument("handle_num", static_cast<int>(2)); + + // Now call the callouts attached to the first three hooks. Each hook is + // called twice (once for each callout handle) before the next hook is + // called. + getCalloutManager()->callCallouts(alpha_index_, callout_handle_1); + getCalloutManager()->callCallouts(alpha_index_, callout_handle_2); + getCalloutManager()->callCallouts(beta_index_, callout_handle_1); + getCalloutManager()->callCallouts(beta_index_, callout_handle_2); + getCalloutManager()->callCallouts(gamma_index_, callout_handle_1); + getCalloutManager()->callCallouts(gamma_index_, callout_handle_2); + + // Get the results for each callout (the callout on hook "delta" copies + // the context values into a location the test can access). Explicitly + // zero the variables before getting the results so we are certain that + // the values are the results of the callouts. + + zero_results(); + + // To explain the expected callout context results. + // + // Each callout handle maintains a separate context for each library. When + // the first call to callCallouts() is made, "111" gets appended to + // the context for library 1 maintained by the first callout handle, "211" + // gets appended to the context maintained for library 2, and "311" to + // the context maintained for library 3. In each case, the first digit + // corresponds to the library number, the second to the callout number and + // the third to the "handle_num" of the callout handle. For the first call + // to callCallouts, handle 1 is used, so the last digit is always 1. + // + // The next call to callCallouts() calls the same callouts but for the + // second callout handle. It also maintains three contexts (one for + // each library) and they will get "112", "212", "312" appended to + // them. The explanation for the digits is the same as before, except that + // in this case, the callout handle is number 2, so the third digit is + // always 2. These additions don't affect the contexts maintained by + // callout handle 1. + // + // The process is then repeated for hooks "beta" and "gamma" which, for + // callout handle 1, append "121", "221" and "321" for hook "beta" and + // "311", "321" and "331" for hook "gamma". + // + // The expected integer values can be found by summing up the values + // corresponding to the elements of the strings. + + // At this point, we have only called the "print" function for callout + // handle "1", so the following results are checking the context values + // maintained in that callout handle. + + getCalloutManager()->callCallouts(delta_index_, callout_handle_1); + EXPECT_EQ("111121131", resultCalloutString(0)); + EXPECT_EQ("211221231", resultCalloutString(1)); + EXPECT_EQ("311321331", resultCalloutString(2)); + + EXPECT_EQ((111 + 121 + 131), resultCalloutInt(0)); + EXPECT_EQ((211 + 221 + 231), resultCalloutInt(1)); + EXPECT_EQ((311 + 321 + 331), resultCalloutInt(2)); + + // Repeat the checks for callout 2. + + zero_results(); + getCalloutManager()->callCallouts(delta_index_, callout_handle_2); + + EXPECT_EQ((112 + 122 + 132), resultCalloutInt(0)); + EXPECT_EQ((212 + 222 + 232), resultCalloutInt(1)); + EXPECT_EQ((312 + 322 + 332), resultCalloutInt(2)); + + EXPECT_EQ("112122132", resultCalloutString(0)); + EXPECT_EQ("212222232", resultCalloutString(1)); + EXPECT_EQ("312322332", resultCalloutString(2)); +} + +// Now repeat the test, but add a deletion callout to the list. The "beta" +// hook of library 2 will have an additional callout to delete the "int" +// element: the same hook for library 3 will delete both elements. In +// addition, the names of context elements for the libraries at this point +// will be printed. + +// List of context item names. + +vector<string>& +getItemNames(int index) { + static vector<string> context_items[3]; + return (context_items[index]); +} + +// Context item deletion functions. + +int +deleteIntContextItem(CalloutHandle& handle) { + handle.deleteContext("int"); + return (0); +} + +int +deleteAllContextItems(CalloutHandle& handle) { + handle.deleteAllContext(); + return (0); +} + +// Generic print function - copy names in sorted order. + +int +printContextNamesExecute(CalloutHandle& handle, int library_num) { + const int index = library_num - 1; + getItemNames(index) = handle.getContextNames(); + sort(getItemNames(index).begin(), getItemNames(index).end()); + return (0); +} + +int +printContextNames1(CalloutHandle& handle) { + return (printContextNamesExecute(handle, 1)); +} + +int +printContextNames2(CalloutHandle& handle) { + return (printContextNamesExecute(handle, 2)); +} + +int +printContextNames3(CalloutHandle& handle) { + return (printContextNamesExecute(handle, 3)); +} + +// Perform the test including deletion of context items. + +TEST_F(HandlesTest, ContextDeletionCheck) { + getCalloutManager()->registerCallout("alpha", callout11, 0); + getCalloutManager()->registerCallout("beta", callout12, 0); + getCalloutManager()->registerCallout("beta", printContextNames1, 0); + getCalloutManager()->registerCallout("gamma", callout13, 0); + getCalloutManager()->registerCallout("delta", print1, 0); + + getCalloutManager()->registerCallout("alpha", callout21, 1); + getCalloutManager()->registerCallout("beta", callout22, 1); + getCalloutManager()->registerCallout("beta", deleteIntContextItem, 1); + getCalloutManager()->registerCallout("beta", printContextNames2, 1); + getCalloutManager()->registerCallout("gamma", callout23, 1); + getCalloutManager()->registerCallout("delta", print2, 1); + + getCalloutManager()->registerCallout("alpha", callout31, 2); + getCalloutManager()->registerCallout("beta", callout32, 2); + getCalloutManager()->registerCallout("beta", deleteAllContextItems, 2); + getCalloutManager()->registerCallout("beta", printContextNames3, 2); + getCalloutManager()->registerCallout("gamma", callout33, 2); + getCalloutManager()->registerCallout("delta", print3, 2); + + // Create the callout handles and distinguish them by setting the "long" + // argument. + CalloutHandle callout_handle_1(getCalloutManager()); + callout_handle_1.setArgument("handle_num", static_cast<int>(1)); + + CalloutHandle callout_handle_2(getCalloutManager()); + callout_handle_2.setArgument("handle_num", static_cast<int>(2)); + + // Now call the callouts attached to the first three hooks. Each hook is + // called twice (once for each callout handle) before the next hook is + // called. + getCalloutManager()->callCallouts(alpha_index_, callout_handle_1); + getCalloutManager()->callCallouts(alpha_index_, callout_handle_2); + getCalloutManager()->callCallouts(beta_index_, callout_handle_1); + getCalloutManager()->callCallouts(beta_index_, callout_handle_2); + getCalloutManager()->callCallouts(gamma_index_, callout_handle_1); + getCalloutManager()->callCallouts(gamma_index_, callout_handle_2); + + // Get the results for each callout. Explicitly zero the variables before + // getting the results so we are certain that the values are the results + // of the callouts. + + zero_results(); + getCalloutManager()->callCallouts(delta_index_, callout_handle_1); + + // The logic by which the expected results are arrived at is described + // in the ContextAccessCheck test. The results here are different + // because context items have been modified along the way. + + EXPECT_EQ((111 + 121 + 131), resultCalloutInt(0)); + EXPECT_EQ(( 231), resultCalloutInt(1)); + EXPECT_EQ(( 331), resultCalloutInt(2)); + + EXPECT_EQ("111121131", resultCalloutString(0)); + EXPECT_EQ("211221231", resultCalloutString(1)); + EXPECT_EQ( "331", resultCalloutString(2)); + + // Repeat the checks for callout handle 2. + + zero_results(); + getCalloutManager()->callCallouts(delta_index_, callout_handle_2); + + EXPECT_EQ((112 + 122 + 132), resultCalloutInt(0)); + EXPECT_EQ(( 232), resultCalloutInt(1)); + EXPECT_EQ(( 332), resultCalloutInt(2)); + + EXPECT_EQ("112122132", resultCalloutString(0)); + EXPECT_EQ("212222232", resultCalloutString(1)); + EXPECT_EQ( "332", resultCalloutString(2)); + + // ... and check what the names of the context items are after the callouts + // for hook "beta". We know they are in sorted order. + + EXPECT_EQ(2, getItemNames(0).size()); + EXPECT_EQ(string("int"), getItemNames(0)[0]); + EXPECT_EQ(string("string"), getItemNames(0)[1]); + + EXPECT_EQ(1, getItemNames(1).size()); + EXPECT_EQ(string("string"), getItemNames(1)[0]); + + EXPECT_EQ(0, getItemNames(2).size()); +} + +// Tests that the CalloutHandle's constructor and destructor call the +// context_create and context_destroy callbacks (if registered). For +// simplicity, we'll use the same callout functions as used above. + +TEST_F(HandlesTest, ConstructionDestructionCallouts) { + + // Register context callouts. + getCalloutManager()->registerCallout("context_create", callout11, 0); + getCalloutManager()->registerCallout("context_create", print1, 0); + getCalloutManager()->registerCallout("context_destroy", callout12, 0); + getCalloutManager()->registerCallout("context_destroy", print1, 0); + + // Create the CalloutHandle and check that the constructor callout + // has run. + zero_results(); + boost::scoped_ptr<CalloutHandle> + callout_handle(new CalloutHandle(getCalloutManager())); + EXPECT_EQ("110", resultCalloutString(0)); + EXPECT_EQ(110, resultCalloutInt(0)); + + // Check that the destructor callout runs. Note that the "print1" callout + // didn't destroy the library context - it only copied it to where it + // could be examined. As a result, the destructor callout appends its + // elements to the constructor's values and the result is printed. + zero_results(); + callout_handle.reset(); + + EXPECT_EQ("110120", resultCalloutString(0)); + EXPECT_EQ((110 + 120), resultCalloutInt(0)); +} + +// Testing the operation of the "skip" flag. Callouts print the value +// they see in the flag and either leave it unchanged, set it or clear it. +int +calloutPrintSkip(CalloutHandle& handle) { + static const std::string YES("Y"); + static const std::string NO("N"); + static const std::string DROP("D"); + static const std::string PARK("P"); + + switch (handle.getStatus()) { + case CalloutHandle::NEXT_STEP_CONTINUE: + HandlesTest::common_string_ += NO; // skip = no + break; + case CalloutHandle::NEXT_STEP_SKIP: + HandlesTest::common_string_ += YES; // skip = yes + break; + case CalloutHandle::NEXT_STEP_DROP: + HandlesTest::common_string_ += DROP; // drop + break; + case CalloutHandle::NEXT_STEP_PARK: + HandlesTest::common_string_ += PARK; // park + break; + } + return (0); +} + +int +calloutSetSkip(CalloutHandle& handle) { + static_cast<void>(calloutPrintSkip(handle)); + handle.setStatus(CalloutHandle::NEXT_STEP_SKIP); + return (0); +} + +int +calloutClearSkip(CalloutHandle& handle) { + static_cast<void>(calloutPrintSkip(handle)); + handle.setStatus(CalloutHandle::NEXT_STEP_CONTINUE); + return (0); +} + +// Do a series of tests, returning with the skip flag set "true". + +TEST_F(HandlesTest, ReturnSkipSet) { + getCalloutManager()->registerCallout("alpha", calloutPrintSkip, 0); + getCalloutManager()->registerCallout("alpha", calloutSetSkip, 0); + getCalloutManager()->registerCallout("alpha", calloutSetSkip, 0); + getCalloutManager()->registerCallout("alpha", calloutClearSkip, 0); + + getCalloutManager()->registerCallout("alpha", calloutPrintSkip, 1); + getCalloutManager()->registerCallout("alpha", calloutSetSkip, 1); + getCalloutManager()->registerCallout("alpha", calloutSetSkip, 1); + getCalloutManager()->registerCallout("alpha", calloutClearSkip, 1); + getCalloutManager()->registerCallout("alpha", calloutClearSkip, 1); + + getCalloutManager()->registerCallout("alpha", calloutPrintSkip, 2); + getCalloutManager()->registerCallout("alpha", calloutSetSkip, 2); + getCalloutManager()->registerCallout("alpha", calloutClearSkip, 2); + getCalloutManager()->registerCallout("alpha", calloutSetSkip, 2); + + CalloutHandle callout_handle(getCalloutManager()); + getCalloutManager()->callCallouts(alpha_index_, callout_handle); + + // Check result. For ease of visual checking, the expected string is + // divided into sections corresponding to the blocks of callouts above. + EXPECT_EQ(std::string("NNYY" "NNYYN" "NNYN"), common_string_); + + // ... and check that the skip flag on exit from callCallouts is set. + EXPECT_EQ(CalloutHandle::NEXT_STEP_SKIP, callout_handle.getStatus()); +} + +// Repeat the test, returning with the skip flag clear. +TEST_F(HandlesTest, ReturnSkipClear) { + getCalloutManager()->registerCallout("alpha", calloutSetSkip, 0); + getCalloutManager()->registerCallout("alpha", calloutSetSkip, 0); + getCalloutManager()->registerCallout("alpha", calloutClearSkip, 0); + + getCalloutManager()->registerCallout("alpha", calloutPrintSkip, 1); + getCalloutManager()->registerCallout("alpha", calloutSetSkip, 1); + getCalloutManager()->registerCallout("alpha", calloutClearSkip, 1); + getCalloutManager()->registerCallout("alpha", calloutSetSkip, 1); + getCalloutManager()->registerCallout("alpha", calloutClearSkip, 1); + getCalloutManager()->registerCallout("alpha", calloutClearSkip, 1); + + getCalloutManager()->registerCallout("alpha", calloutClearSkip, 2); + getCalloutManager()->registerCallout("alpha", calloutPrintSkip, 2); + getCalloutManager()->registerCallout("alpha", calloutSetSkip, 2); + getCalloutManager()->registerCallout("alpha", calloutClearSkip, 2); + + CalloutHandle callout_handle(getCalloutManager()); + getCalloutManager()->callCallouts(alpha_index_, callout_handle); + + // Check result. For ease of visual checking, the expected string is + // divided into sections corresponding to the blocks of callouts above. + EXPECT_EQ(std::string("NYY" "NNYNYN" "NNNY"), common_string_); + + // ... and check that the skip flag on exit from callCallouts is set. + EXPECT_EQ(CalloutHandle::NEXT_STEP_CONTINUE, callout_handle.getStatus()); +} + +// Check that the skip flag is cleared when callouts are called - even if +// there are no callouts. + +TEST_F(HandlesTest, NoCalloutsSkipTest) { + // Note - no callouts are registered on any hook. + CalloutHandle callout_handle(getCalloutManager()); + + // Clear the skip flag and call a hook with no callouts. + callout_handle.setStatus(CalloutHandle::NEXT_STEP_CONTINUE); + getCalloutManager()->callCallouts(alpha_index_, callout_handle); + EXPECT_EQ(CalloutHandle::NEXT_STEP_CONTINUE, callout_handle.getStatus()); + + // Set the skip flag and call a hook with no callouts. + callout_handle.setStatus(CalloutHandle::NEXT_STEP_SKIP); + getCalloutManager()->callCallouts(alpha_index_, callout_handle); + EXPECT_EQ(CalloutHandle::NEXT_STEP_CONTINUE, callout_handle.getStatus()); +} + +// The next set of callouts do a similar thing to the above "skip" tests, +// but alter the value of a string argument. This is for testing that the +// a callout is able to change an argument and return it to the caller. + +const char* MODIFIED_ARG = "modified_arg"; + +int +calloutSetArgumentCommon(CalloutHandle& handle, const char* what) { + std::string modified_arg = ""; + + handle.getArgument(MODIFIED_ARG, modified_arg); + modified_arg = modified_arg + std::string(what); + handle.setArgument(MODIFIED_ARG, modified_arg); + return (0); +} + +int +calloutSetArgumentSkip(CalloutHandle& handle) { + return (calloutSetArgumentCommon(handle, "S")); +} + +int +calloutSetArgumentContinue(CalloutHandle& handle) { + return (calloutSetArgumentCommon(handle, "C")); +} + +int +calloutSetArgumentDrop(CalloutHandle& handle) { + return (calloutSetArgumentCommon(handle, "D")); +} + +int +calloutSetArgumentPark(CalloutHandle& handle) { + return (calloutSetArgumentCommon(handle, "P")); +} + +// ... and a callout to just copy the argument to the "common_string_" variable +// but otherwise not alter it. + +int +calloutPrintArgument(CalloutHandle& handle) { + handle.getArgument(MODIFIED_ARG, HandlesTest::common_string_); + return (0); +} + +// This test verifies that the next step status is processed appropriately. +// The test checks the following next step statuses: CONTINUE, SKIP, DROP. +TEST_F(HandlesTest, CheckModifiedArgument) { + getCalloutManager()->registerCallout("alpha", calloutSetArgumentSkip, 0); + getCalloutManager()->registerCallout("alpha", calloutSetArgumentContinue, 0); + getCalloutManager()->registerCallout("alpha", calloutSetArgumentContinue, 0); + + getCalloutManager()->registerCallout("alpha", calloutSetArgumentSkip, 1); + getCalloutManager()->registerCallout("alpha", calloutSetArgumentDrop, 1); + getCalloutManager()->registerCallout("alpha", calloutPrintArgument, 1); + getCalloutManager()->registerCallout("alpha", calloutSetArgumentDrop, 1); + getCalloutManager()->registerCallout("alpha", calloutSetArgumentContinue, 1); + + getCalloutManager()->registerCallout("alpha", calloutSetArgumentSkip, 2); + getCalloutManager()->registerCallout("alpha", calloutSetArgumentContinue, 2); + getCalloutManager()->registerCallout("alpha", calloutSetArgumentPark, 2); + getCalloutManager()->registerCallout("alpha", calloutSetArgumentSkip, 2); + getCalloutManager()->registerCallout("alpha", calloutSetArgumentPark, 2); + + // Create the argument with an initial empty string value. Then call the + // sequence of callouts above. + CalloutHandle callout_handle(getCalloutManager()); + std::string modified_arg = ""; + callout_handle.setArgument(MODIFIED_ARG, modified_arg); + getCalloutManager()->callCallouts(alpha_index_, callout_handle); + + // Check the intermediate and results. For visual checking, the expected + // string is divided into sections corresponding to the blocks of callouts + // above. + EXPECT_EQ(std::string("SCC" "SD"), common_string_); + + callout_handle.getArgument(MODIFIED_ARG, modified_arg); + EXPECT_EQ(std::string("SCC" "SDDC" "SCPSP"), modified_arg); +} + +// Test that the CalloutHandle provides the name of the hook to which the +// callout is attached. + +int +callout_hook_name(CalloutHandle& callout_handle) { + HandlesTest::common_string_ = callout_handle.getHookName(); + return (0); +} + +int +callout_hook_dummy(CalloutHandle&) { + return (0); +} + +TEST_F(HandlesTest, HookName) { + getCalloutManager()->registerCallout("alpha", callout_hook_name, 0); + getCalloutManager()->registerCallout("beta", callout_hook_name, 0); + + // Call alpha and beta callouts and check the hook to which they belong. + CalloutHandle callout_handle(getCalloutManager()); + + EXPECT_EQ(std::string(""), HandlesTest::common_string_); + + getCalloutManager()->callCallouts(alpha_index_, callout_handle); + EXPECT_EQ(std::string("alpha"), HandlesTest::common_string_); + + getCalloutManager()->callCallouts(beta_index_, callout_handle); + EXPECT_EQ(std::string("beta"), HandlesTest::common_string_); + + // Make sure that the callout accesses the name even if it is not the + // only callout in the list. + getCalloutManager()->registerCallout("gamma", callout_hook_dummy, 1); + getCalloutManager()->registerCallout("gamma", callout_hook_name, 1); + getCalloutManager()->registerCallout("gamma", callout_hook_dummy, 1); + + EXPECT_EQ(std::string("beta"), HandlesTest::common_string_); + getCalloutManager()->callCallouts(gamma_index_, callout_handle); + EXPECT_EQ(std::string("gamma"), HandlesTest::common_string_); +} + +} // Anonymous namespace + diff --git a/src/lib/hooks/tests/hooks_manager_unittest.cc b/src/lib/hooks/tests/hooks_manager_unittest.cc new file mode 100644 index 0000000..a36d42c --- /dev/null +++ b/src/lib/hooks/tests/hooks_manager_unittest.cc @@ -0,0 +1,1081 @@ +// 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 <hooks/callout_handle.h> +#include <hooks/hooks_manager.h> +#include <hooks/server_hooks.h> + +#include <hooks/tests/common_test_class.h> +#define TEST_ASYNC_CALLOUT +#include <hooks/tests/test_libraries.h> +#include <cc/data.h> + +#include <boost/shared_ptr.hpp> +#include <gtest/gtest.h> + +#include <algorithm> +#include <fstream> +#include <string> + +#include <unistd.h> + +using namespace isc; +using namespace isc::hooks; +using namespace isc::data; +using namespace std; + +namespace { + +/// @brief Hooks manager collection test class + +class HooksManagerTest : public ::testing::Test, + public HooksCommonTestClass { +public: + /// @brief Constructor + /// + /// Reset the hooks manager. The hooks manager is a singleton, so needs + /// to be reset for each test. + HooksManagerTest() { + HooksManager::setTestMode(false); + HooksManager::prepareUnloadLibraries(); + bool status = HooksManager::unloadLibraries(); + if (!status) { + cerr << "(fixture ctor) unloadLibraries failed" << endl; + } + // Ensure the marker file is not present at the start of a test. + static_cast<void>(remove(MARKER_FILE)); + } + + /// @brief Destructor + /// + /// Unload all libraries. + ~HooksManagerTest() { + static_cast<void>(remove(MARKER_FILE)); + HooksManager::setTestMode(false); + HooksManager::prepareUnloadLibraries(); + bool status = HooksManager::unloadLibraries(); + if (!status) { + cerr << "(fixture dtor) unloadLibraries failed" << endl; + } + } + + /// @brief Marker file present + /// + /// Convenience function to check whether a marker file is present. It + /// does this by opening the file. + /// + /// @return true if the marker file is present. + bool markerFilePresent() const { + + // Try to open it. + std::fstream marker; + marker.open(MARKER_FILE, std::fstream::in); + + // Check if it is open and close it if so. + bool exists = marker.is_open(); + if (exists) { + marker.close(); + } + + return (exists); + } + + /// @brief Call callouts test + /// + /// See the header for HooksCommonTestClass::execute for details. + /// + /// @param r0...r3, d1..d3 Values and intermediate values expected. They + /// are ordered so that the variables appear in the argument list in + /// the order they are used. + void executeCallCallouts(int r0, int d1, int r1, int d2, int r2, int d3, + int r3) { + static const char* COMMON_TEXT = " callout returned the wrong value"; + static const char* RESULT = "result"; + + // Get a CalloutHandle for the calculation. + CalloutHandlePtr handle = HooksManager::createCalloutHandle(); + + // Initialize the argument RESULT. This simplifies testing by + // eliminating the generation of an exception when we try the unload + // test. In that case, RESULT is unchanged. + int result = -1; + handle->setArgument(RESULT, result); + + // Seed the calculation. + HooksManager::callCallouts(isc::hooks::ServerHooks::CONTEXT_CREATE, + *handle); + handle->getArgument(RESULT, result); + EXPECT_EQ(r0, result) << "context_create" << COMMON_TEXT; + + // Perform the first calculation. + handle->setArgument("data_1", d1); + HooksManager::callCallouts(hookpt_one_index_, *handle); + handle->getArgument(RESULT, result); + EXPECT_EQ(r1, result) << "hookpt_one" << COMMON_TEXT; + + // ... the second ... + handle->setArgument("data_2", d2); + HooksManager::callCallouts(hookpt_two_index_, *handle); + handle->getArgument(RESULT, result); + EXPECT_EQ(r2, result) << "hookpt_two" << COMMON_TEXT; + + // ... and the third. + handle->setArgument("data_3", d3); + HooksManager::callCallouts(hookpt_three_index_, *handle); + handle->getArgument(RESULT, result); + EXPECT_EQ(r3, result) << "hookpt_three" << COMMON_TEXT; + } + + /// @brief Call command handlers test. + /// + /// This test is similar to @c executeCallCallouts but it uses + /// @ref HooksManager::callCommandHandlers to execute the command + /// handlers for the following commands: 'command-one' and 'command-two'. + /// + /// @param r1..r2, d1..d2 Data (dN) and expected results (rN). + void executeCallCommandHandlers(int d1, int r1, int d2, int r2) { + static const char* COMMON_TEXT = " command handler returned the wrong value"; + static const char* RESULT = "result"; + + int result; + + // Set up a callout handle for the calls. + CalloutHandlePtr handle = HooksManager::createCalloutHandle(); + + // Initialize the argument RESULT. This simplifies testing by + // eliminating the generation of an exception when we try the unload + // test. In that case, RESULT is unchanged. + handle->setArgument(RESULT, -1); + + // Perform the first calculation: it should assign the data to the + // result. + handle->setArgument("data_1", d1); + HooksManager::callCommandHandlers("command-one", *handle); + handle->getArgument(RESULT, result); + EXPECT_EQ(r1, result) << "command-one" << COMMON_TEXT; + + // Perform the second calculation: it should multiply the data by 10 + // and return in the result. + handle->setArgument("data_2", d2); + HooksManager::callCommandHandlers("command-two", *handle); + handle->getArgument(RESULT, result); + EXPECT_EQ(r2, result) << "command-two" << COMMON_TEXT; + } + +private: + /// To avoid unused variable errors + std::string dummy(int i) { + if (i == 0) { + return (LOAD_CALLOUT_LIBRARY); + } else { + return (LOAD_ERROR_CALLOUT_LIBRARY); + } + } +}; + +// This is effectively the same test as for LibraryManager, but using the +// HooksManager object. + +TEST_F(HooksManagerTest, LoadLibraries) { + + // Set up the list of libraries to be loaded. + HookLibsCollection library_names; + library_names.push_back(make_pair(std::string(FULL_CALLOUT_LIBRARY), + data::ConstElementPtr())); + library_names.push_back(make_pair(std::string(BASIC_CALLOUT_LIBRARY), + data::ConstElementPtr())); + + // Load the libraries. + EXPECT_TRUE(HooksManager::loadLibraries(library_names)); + + // Execute the callouts. The first library implements the calculation. + // + // r3 = (7 * d1 - d2) * d3 + // + // The last-loaded library implements the calculation + // + // r3 = (10 + d1) * d2 - d3 + // + // Putting the processing for each library together in the appropriate + // order, we get: + // + // r3 = ((10 * d1 + d1) - d2) * d2 * d3 - d3 + { + SCOPED_TRACE("Calculation with libraries loaded"); + executeCallCallouts(10, 3, 33, 2, 62, 3, 183); + } + + // r2 = 5 * 7 * 10 + { + SCOPED_TRACE("Calculation using command handlers"); + executeCallCommandHandlers(5, 5, 7, 350); + } + + // Try unloading the libraries. + EXPECT_NO_THROW(HooksManager::prepareUnloadLibraries()); + bool status = false; + EXPECT_NO_THROW(status = HooksManager::unloadLibraries()); + EXPECT_TRUE(status); + + // Re-execute the calculation - callouts can be called but as nothing + // happens, the result should always be -1. + { + SCOPED_TRACE("Calculation with libraries not loaded"); + executeCallCallouts(-1, 3, -1, 22, -1, 83, -1); + } +} + +// This is effectively the same test as above, but with a library generating +// an error when loaded. It is expected that the failing library will not be +// loaded, but others will be. + +TEST_F(HooksManagerTest, LoadLibrariesWithError) { + + // Set up the list of libraries to be loaded. + HookLibsCollection library_names; + library_names.push_back(make_pair(std::string(FULL_CALLOUT_LIBRARY), + data::ConstElementPtr())); + library_names.push_back(make_pair(std::string(INCORRECT_VERSION_LIBRARY), + data::ConstElementPtr())); + library_names.push_back(make_pair(std::string(BASIC_CALLOUT_LIBRARY), + data::ConstElementPtr())); + + // Load the libraries. We expect a failure return because one of the + // libraries fails to load. + EXPECT_FALSE(HooksManager::loadLibraries(library_names)); +} + +// Test that we can unload a set of libraries while we have a CalloutHandle +// created on them in existence, and can delete the handle afterwards. + +TEST_F(HooksManagerTest, CalloutHandleUnloadLibrary) { + + // Set up the list of libraries to be loaded. + HookLibsCollection library_names; + library_names.push_back(make_pair(std::string(FULL_CALLOUT_LIBRARY), + data::ConstElementPtr())); + + // Load the libraries. + EXPECT_TRUE(HooksManager::loadLibraries(library_names)); + + // Execute the callouts. This library implements: + // + // r3 = (7 * d1 - d2) * d3 + { + SCOPED_TRACE("Calculation with full callout library loaded"); + executeCallCallouts(7, 4, 28, 8, 20, 2, 40); + } + + // Get an outstanding callout handle on this library. + CalloutHandlePtr handle = HooksManager::createCalloutHandle(); + + // Execute once of the callouts again to ensure that the handle contains + // memory allocated by the library. + HooksManager::callCallouts(ServerHooks::CONTEXT_CREATE, *handle); + + // Unload the libraries. + HooksManager::prepareUnloadLibraries(); + EXPECT_FALSE(HooksManager::unloadLibraries()); + + // Deleting the callout handle should not cause a segmentation fault. + handle.reset(); + + // And allows unload. + EXPECT_TRUE(HooksManager::unloadLibraries()); +} + +// Test that we can load a new set of libraries while we have a CalloutHandle +// created on them in existence, and can delete the handle afterwards. + +TEST_F(HooksManagerTest, CalloutHandleLoadLibrary) { + + // Set up the list of libraries to be loaded. + HookLibsCollection library_names; + library_names.push_back(make_pair(std::string(FULL_CALLOUT_LIBRARY), + data::ConstElementPtr())); + + // Load the libraries. + EXPECT_TRUE(HooksManager::loadLibraries(library_names)); + + // Execute the callouts. This library implements: + // + // r3 = (7 * d1 - d2) * d3 + { + SCOPED_TRACE("Calculation with full callout library loaded"); + executeCallCallouts(7, 4, 28, 8, 20, 2, 40); + } + + // Get an outstanding callout handle on this library and execute one of + // the callouts again to ensure that the handle contains memory allocated + // by the library. + CalloutHandlePtr handle = HooksManager::createCalloutHandle(); + HooksManager::callCallouts(ServerHooks::CONTEXT_CREATE, *handle); + + // Load a new library that implements the calculation + // + // r3 = (10 + d1) * d2 - d3 + HookLibsCollection new_library_names; + new_library_names.push_back(make_pair(std::string(BASIC_CALLOUT_LIBRARY), + data::ConstElementPtr())); + + // Load the libraries. + EXPECT_THROW(HooksManager::loadLibraries(new_library_names), + LibrariesStillOpened); + + // Deleting the old callout handle should not cause a segmentation fault. + handle.reset(); + + // But it allows the load of the new library. + EXPECT_TRUE(HooksManager::loadLibraries(new_library_names)); + + // Execute the calculation. + { + SCOPED_TRACE("Calculation with basic callout library loaded"); + executeCallCallouts(10, 7, 17, 3, 51, 16, 35); + } +} + +// This is effectively the same test as the LoadLibraries test. + +TEST_F(HooksManagerTest, ReloadSameLibraries) { + + // Set up the list of libraries to be loaded. + HookLibsCollection library_names; + library_names.push_back(make_pair(std::string(FULL_CALLOUT_LIBRARY), + data::ConstElementPtr())); + library_names.push_back(make_pair(std::string(BASIC_CALLOUT_LIBRARY), + data::ConstElementPtr())); + + // Load the libraries. + EXPECT_TRUE(HooksManager::loadLibraries(library_names)); + + // Execute the callouts. See the LoadLibraries test for an explanation of + // the calculation. + { + SCOPED_TRACE("Calculation with libraries loaded"); + executeCallCallouts(10, 3, 33, 2, 62, 3, 183); + } + + // Try reloading the libraries and re-execute the calculation - we should + // get the same results. + EXPECT_NO_THROW(HooksManager::loadLibraries(library_names)); + { + SCOPED_TRACE("Calculation with libraries reloaded"); + executeCallCallouts(10, 3, 33, 2, 62, 3, 183); + } +} + +TEST_F(HooksManagerTest, ReloadLibrariesReverseOrder) { + + // Set up the list of libraries to be loaded and load them. + HookLibsCollection library_names; + library_names.push_back(make_pair(std::string(FULL_CALLOUT_LIBRARY), + data::ConstElementPtr())); + library_names.push_back(make_pair(std::string(BASIC_CALLOUT_LIBRARY), + data::ConstElementPtr())); + EXPECT_TRUE(HooksManager::loadLibraries(library_names)); + + // Execute the callouts. The first library implements the calculation. + // + // r3 = (7 * d1 - d2) * d3 + // + // The last-loaded library implements the calculation + // + // r3 = (10 + d1) * d2 - d3 + // + // Putting the processing for each library together in the given order + // gives. + // + // r3 = ((10 * d1 + d1) - d2) * d2 * d3 - d3 + { + SCOPED_TRACE("Calculation with libraries loaded"); + executeCallCallouts(10, 3, 33, 2, 62, 3, 183); + } + + // Reload the libraries in the reverse order. + std::reverse(library_names.begin(), library_names.end()); + EXPECT_TRUE(HooksManager::loadLibraries(library_names)); + + // The calculation in the reverse order gives: + // + // r3 = ((((7 + d1) * d1) * d2 - d2) - d3) * d3 + { + SCOPED_TRACE("Calculation with libraries loaded in reverse order"); + executeCallCallouts(7, 3, 30, 3, 87, 7, 560); + } +} + +// Local callouts for the test of server-registered callouts. + +namespace { + + int +testPreCallout(CalloutHandle& handle) { + handle.setArgument("result", static_cast<int>(1027)); + return (0); +} + +int +testPostCallout(CalloutHandle& handle) { + int result; + handle.getArgument("result", result); + result *= 2; + handle.setArgument("result", result); + return (0); +} + +} + +// The next test registers the pre and post- callouts above for hook hookpt_two, +// and checks they are called. + +TEST_F(HooksManagerTest, PrePostCalloutTest) { + + // Load a single library. + HookLibsCollection library_names; + library_names.push_back(make_pair(std::string(FULL_CALLOUT_LIBRARY), + data::ConstElementPtr())); + EXPECT_TRUE(HooksManager::loadLibraries(library_names)); + + // Load the pre- and post- callouts. + HooksManager::preCalloutsLibraryHandle().registerCallout("hookpt_two", + testPreCallout); + HooksManager::postCalloutsLibraryHandle().registerCallout("hookpt_two", + testPostCallout); + + // Execute the callouts. hookpt_two implements the calculation: + // + // "result - data_2" + // + // With the pre- and post- callouts above, the result expected is + // + // (1027 - data_2) * 2 + CalloutHandlePtr handle = HooksManager::createCalloutHandle(); + handle->setArgument("result", static_cast<int>(0)); + handle->setArgument("data_2", static_cast<int>(15)); + + HooksManager::callCallouts(hookpt_two_index_, *handle); + + int result = 0; + handle->getArgument("result", result); + EXPECT_EQ(2024, result); + + // Reset the handle to allow a reload. + handle.reset(); + + // ... and check that the pre- and post- callout functions don't survive a + // reload. + EXPECT_NO_THROW(HooksManager::prepareUnloadLibraries()); + bool status = false; + EXPECT_NO_THROW(status = HooksManager::unloadLibraries()); + EXPECT_TRUE(status); + EXPECT_TRUE(HooksManager::loadLibraries(library_names)); + handle = HooksManager::createCalloutHandle(); + + handle->setArgument("result", static_cast<int>(0)); + handle->setArgument("data_2", static_cast<int>(15)); + + HooksManager::callCallouts(hookpt_two_index_, *handle); + + result = 0; + handle->getArgument("result", result); + EXPECT_EQ(-15, result); +} + +// Test with test mode enabled and the pre- and post- callout functions survive +// a reload + +TEST_F(HooksManagerTest, TestModeEnabledPrePostSurviveLoad) { + + // Load a single library. + HookLibsCollection library_names; + library_names.push_back(make_pair(std::string(FULL_CALLOUT_LIBRARY), + data::ConstElementPtr())); + + // Load the pre- and post- callouts. + HooksManager::preCalloutsLibraryHandle().registerCallout("hookpt_two", + testPreCallout); + HooksManager::postCalloutsLibraryHandle().registerCallout("hookpt_two", + testPostCallout); + + HooksManager::setTestMode(true); + + // With the pre- and post- callouts above, the result expected is + // + // 1027 * 2 + CalloutHandlePtr handle = HooksManager::createCalloutHandle(); + handle->setArgument("result", static_cast<int>(0)); + handle->setArgument("data_2", static_cast<int>(15)); + + HooksManager::callCallouts(hookpt_two_index_, *handle); + + int result = 0; + handle->getArgument("result", result); + EXPECT_EQ(2054, result); + + // Reset the handle to allow a reload. + handle.reset(); + + // ... and check that the pre- and post- callout functions survive a + // reload. + EXPECT_NO_THROW(HooksManager::prepareUnloadLibraries()); + bool status = false; + EXPECT_NO_THROW(status = HooksManager::unloadLibraries()); + EXPECT_TRUE(status); + EXPECT_TRUE(HooksManager::loadLibraries(library_names)); + handle = HooksManager::createCalloutHandle(); + + handle->setArgument("result", static_cast<int>(0)); + handle->setArgument("data_2", static_cast<int>(15)); + + HooksManager::callCallouts(hookpt_two_index_, *handle); + + // Expect same value i.e. 1027 * 2 + result = 0; + handle->getArgument("result", result); + EXPECT_EQ(2054, result); +} + +// Test with test mode disabled and the pre- and post- callout functions do not +// survive a reload + +TEST_F(HooksManagerTest, TestModeDisabledPrePostDoNotSurviveLoad) { + + // Load a single library. + HookLibsCollection library_names; + library_names.push_back(make_pair(std::string(FULL_CALLOUT_LIBRARY), + data::ConstElementPtr())); + + // Load the pre- and post- callouts. + HooksManager::preCalloutsLibraryHandle().registerCallout("hookpt_two", + testPreCallout); + HooksManager::postCalloutsLibraryHandle().registerCallout("hookpt_two", + testPostCallout); + + HooksManager::setTestMode(false); + + // With the pre- and post- callouts above, the result expected is + // + // 1027 * 2 + CalloutHandlePtr handle = HooksManager::createCalloutHandle(); + handle->setArgument("result", static_cast<int>(0)); + handle->setArgument("data_2", static_cast<int>(15)); + + HooksManager::callCallouts(hookpt_two_index_, *handle); + + int result = 0; + handle->getArgument("result", result); + EXPECT_EQ(2054, result); + + // Reset the handle to allow a reload. + handle.reset(); + + // ... and check that the pre- and post- callout functions don't survive a + // reload. + EXPECT_NO_THROW(HooksManager::prepareUnloadLibraries()); + bool status = false; + EXPECT_NO_THROW(status = HooksManager::unloadLibraries()); + EXPECT_TRUE(status); + EXPECT_TRUE(HooksManager::loadLibraries(library_names)); + handle = HooksManager::createCalloutHandle(); + + handle->setArgument("result", static_cast<int>(0)); + handle->setArgument("data_2", static_cast<int>(15)); + + HooksManager::callCallouts(hookpt_two_index_, *handle); + + result = 0; + handle->getArgument("result", result); + EXPECT_EQ(-15, result); +} + +// Test with test mode enabled and the pre- and post- callout functions do not +// survive a reload if the test mode is set too late. + +TEST_F(HooksManagerTest, TestModeEnabledTooLatePrePostDoNotSurvive) { + + // Load a single library. + HookLibsCollection library_names; + library_names.push_back(make_pair(std::string(FULL_CALLOUT_LIBRARY), + data::ConstElementPtr())); + + // Load the pre- and post- callouts. + HooksManager::preCalloutsLibraryHandle().registerCallout("hookpt_two", + testPreCallout); + HooksManager::postCalloutsLibraryHandle().registerCallout("hookpt_two", + testPostCallout); + + // With the pre- and post- callouts above, the result expected is + // + // 1027 * 2 + CalloutHandlePtr handle = HooksManager::createCalloutHandle(); + handle->setArgument("result", static_cast<int>(0)); + handle->setArgument("data_2", static_cast<int>(15)); + + HooksManager::callCallouts(hookpt_two_index_, *handle); + + int result = 0; + handle->getArgument("result", result); + EXPECT_EQ(2054, result); + + // Reset the handle to allow a reload. + handle.reset(); + + // ... and check that the pre- and post- callout functions don't survive a + // reload. + EXPECT_NO_THROW(HooksManager::prepareUnloadLibraries()); + bool status = false; + EXPECT_NO_THROW(status = HooksManager::unloadLibraries()); + EXPECT_TRUE(status); + EXPECT_TRUE(HooksManager::loadLibraries(library_names)); + handle = HooksManager::createCalloutHandle(); + + HooksManager::setTestMode(true); + + handle->setArgument("result", static_cast<int>(0)); + handle->setArgument("data_2", static_cast<int>(15)); + + HooksManager::callCallouts(hookpt_two_index_, *handle); + + result = 0; + handle->getArgument("result", result); + EXPECT_EQ(-15, result); +} + +// Check that everything works even with no libraries loaded. First that +// calloutsPresent() always returns false. + +TEST_F(HooksManagerTest, NoLibrariesCalloutsPresent) { + // No callouts should be present on any hooks. + EXPECT_FALSE(HooksManager::calloutsPresent(hookpt_one_index_)); + EXPECT_FALSE(HooksManager::calloutsPresent(hookpt_two_index_)); + EXPECT_FALSE(HooksManager::calloutsPresent(hookpt_three_index_)); + EXPECT_FALSE(HooksManager::commandHandlersPresent("command-one")); + EXPECT_FALSE(HooksManager::commandHandlersPresent("command-two")); +} + +TEST_F(HooksManagerTest, NoLibrariesCallCallouts) { + executeCallCallouts(-1, 3, -1, 22, -1, 83, -1); +} + +// Test the encapsulation of the ServerHooks::registerHook() method. + +TEST_F(HooksManagerTest, RegisterHooks) { + ServerHooks::getServerHooks().reset(); + EXPECT_EQ(2, ServerHooks::getServerHooks().getCount()); + + // Check that the hook indexes are as expected. (Use temporary variables + // as it appears that Google test can't access the constants.) + int sh_cc = ServerHooks::CONTEXT_CREATE; + int hm_cc = HooksManager::CONTEXT_CREATE; + EXPECT_EQ(sh_cc, hm_cc); + + int sh_cd = ServerHooks::CONTEXT_DESTROY; + int hm_cd = HooksManager::CONTEXT_DESTROY; + EXPECT_EQ(sh_cd, hm_cd); + + // Register a few hooks and check we have the indexes as expected. + EXPECT_EQ(2, HooksManager::registerHook(string("alpha"))); + EXPECT_EQ(3, HooksManager::registerHook(string("beta"))); + EXPECT_EQ(4, HooksManager::registerHook(string("gamma"))); + + + // The code used to throw, but it now allows to register the same + // hook several times. It simply returns existing index. + //EXPECT_THROW(static_cast<void>(HooksManager::registerHook(string("alpha"))), + // DuplicateHook); + EXPECT_EQ(2, HooksManager::registerHook(string("alpha"))); + + // ... an check the hooks are as we expect. + EXPECT_EQ(5, ServerHooks::getServerHooks().getCount()); + vector<string> names = ServerHooks::getServerHooks().getHookNames(); + sort(names.begin(), names.end()); + + EXPECT_EQ(string("alpha"), names[0]); + EXPECT_EQ(string("beta"), names[1]); + EXPECT_EQ(string("context_create"), names[2]); + EXPECT_EQ(string("context_destroy"), names[3]); + EXPECT_EQ(string("gamma"), names[4]); +} + +// Check that we can get the names of the libraries. + +TEST_F(HooksManagerTest, LibraryNames) { + + // Set up the list of libraries to be loaded. + HookLibsCollection library_names; + library_names.push_back(make_pair(std::string(FULL_CALLOUT_LIBRARY), + data::ConstElementPtr())); + library_names.push_back(make_pair(std::string(BASIC_CALLOUT_LIBRARY), + data::ConstElementPtr())); + + // Check the names before the libraries are loaded. + std::vector<std::string> loaded_names = HooksManager::getLibraryNames(); + EXPECT_TRUE(loaded_names.empty()); + + // Load the libraries and check the names again. + EXPECT_TRUE(HooksManager::loadLibraries(library_names)); + loaded_names = HooksManager::getLibraryNames(); + EXPECT_TRUE(extractNames(library_names) == loaded_names); + + // Unload the libraries and check again. + EXPECT_NO_THROW(HooksManager::prepareUnloadLibraries()); + bool status = false; + EXPECT_NO_THROW(status = HooksManager::unloadLibraries()); + EXPECT_TRUE(status); + loaded_names = HooksManager::getLibraryNames(); + EXPECT_TRUE(loaded_names.empty()); +} + +// Test the library validation function. + +TEST_F(HooksManagerTest, validateLibraries) { + // Vector of libraries that failed validation + std::vector<std::string> failed; + + // Test different vectors of libraries. + + // No libraries should return a success. + std::vector<std::string> libraries; + + failed = HooksManager::validateLibraries(libraries); + EXPECT_TRUE(failed.empty()); + + // Single valid library should validate. + libraries.clear(); + libraries.push_back(BASIC_CALLOUT_LIBRARY); + + failed = HooksManager::validateLibraries(libraries); + EXPECT_TRUE(failed.empty()); + + // Multiple valid libraries should succeed. + libraries.clear(); + libraries.push_back(BASIC_CALLOUT_LIBRARY); + libraries.push_back(FULL_CALLOUT_LIBRARY); + libraries.push_back(UNLOAD_CALLOUT_LIBRARY); + + failed = HooksManager::validateLibraries(libraries); + EXPECT_TRUE(failed.empty()); + + // Single invalid library should fail. + libraries.clear(); + libraries.push_back(NOT_PRESENT_LIBRARY); + + failed = HooksManager::validateLibraries(libraries); + EXPECT_TRUE(failed == libraries); + + // Multiple invalid libraries should fail. + libraries.clear(); + libraries.push_back(INCORRECT_VERSION_LIBRARY); + libraries.push_back(NO_VERSION_LIBRARY); + libraries.push_back(FRAMEWORK_EXCEPTION_LIBRARY); + + failed = HooksManager::validateLibraries(libraries); + EXPECT_TRUE(failed == libraries); + + // Combination of valid and invalid (first one valid) should fail. + libraries.clear(); + libraries.push_back(FULL_CALLOUT_LIBRARY); + libraries.push_back(INCORRECT_VERSION_LIBRARY); + libraries.push_back(NO_VERSION_LIBRARY); + + std::vector<std::string> expected_failures; + expected_failures.push_back(INCORRECT_VERSION_LIBRARY); + expected_failures.push_back(NO_VERSION_LIBRARY); + + failed = HooksManager::validateLibraries(libraries); + EXPECT_TRUE(failed == expected_failures); + + // Combination of valid and invalid (first one invalid) should fail. + libraries.clear(); + libraries.push_back(NO_VERSION_LIBRARY); + libraries.push_back(FULL_CALLOUT_LIBRARY); + libraries.push_back(INCORRECT_VERSION_LIBRARY); + + expected_failures.clear(); + expected_failures.push_back(NO_VERSION_LIBRARY); + expected_failures.push_back(INCORRECT_VERSION_LIBRARY); + + failed = HooksManager::validateLibraries(libraries); + EXPECT_TRUE(failed == expected_failures); +} + +// This test verifies that unload is called by the prepare method. +TEST_F(HooksManagerTest, prepareUnload) { + + // Set up the list of libraries to be loaded and load them. + HookLibsCollection library_names; + library_names.push_back(make_pair(std::string(UNLOAD_CALLOUT_LIBRARY), + data::ConstElementPtr())); + EXPECT_TRUE(HooksManager::loadLibraries(library_names)); + + // Check that the marker file is not present. + EXPECT_FALSE(markerFilePresent()); + + // Prepare unload libraries runs unload functions. + HooksManager::prepareUnloadLibraries(); + + // Now the marker file is present. + EXPECT_TRUE(markerFilePresent()); +} + +// This test verifies that the specified parameters are accessed properly. +TEST_F(HooksManagerTest, LibraryParameters) { + + // Prepare parameters for the callout parameters library. + ElementPtr params = Element::createMap(); + params->set("svalue", Element::create("string value")); + params->set("ivalue", Element::create(42)); + params->set("bvalue", Element::create(true)); + + // Set up the list of libraries to be loaded. + HookLibsCollection library_names; + library_names.push_back(make_pair(std::string(BASIC_CALLOUT_LIBRARY), + data::ConstElementPtr())); + library_names.push_back(make_pair(std::string(CALLOUT_PARAMS_LIBRARY), + params)); + + // Load the libraries. Note that callout params library checks if + // all mandatory parameters are there, so if anything is missing, its + // load() function will return error, thus causing the library to not + // load. + EXPECT_TRUE(HooksManager::loadLibraries(library_names)); + + // Try unloading the libraries. + EXPECT_NO_THROW(HooksManager::prepareUnloadLibraries()); + bool status = false; + EXPECT_NO_THROW(status = HooksManager::unloadLibraries()); + EXPECT_TRUE(status); +} + +// This test verifies that an object can be parked in two different +// callouts and that it is unparked when the last callout calls the +// unpark function. +TEST_F(HooksManagerTest, Parking) { + // Load the same library twice. Both installed callouts will trigger + // asynchronous operation. + HookLibsCollection library_names; + library_names.push_back(make_pair(std::string(ASYNC_CALLOUT_LIBRARY), + data::ConstElementPtr())); + library_names.push_back(make_pair(std::string(ASYNC_CALLOUT_LIBRARY), + data::ConstElementPtr())); + + // Load the libraries. + EXPECT_TRUE(HooksManager::loadLibraries(library_names)); + + CalloutHandlePtr handle = HooksManager::createCalloutHandle(); + + // We could be parked any object. Typically it will be a pointer to the + // packet. In this case, however, it is simpler to just use a string. + std::string parked_object = "foo"; + handle->setArgument("parked_object", parked_object); + + // This boolean value will be set to true when the packet gets unparked. + bool unparked = false; + + // The callouts instruct us to park the object. We associated the callback + // function with the parked object, which sets "unparked" flag to true. We + // can later test the value of this flag to verify when exactly the packet + // got unparked. + ASSERT_NO_THROW( + HooksManager::park<std::string>("hookpt_one", "foo", + [&unparked] { + unparked = true; + }) + ); + + // Call both installed callouts. + HooksManager::callCallouts(hookpt_one_index_, *handle); + + // We have two callouts which should have returned pointers to the + // functions which we can call to simulate completion of asynchronous + // tasks. + std::function<void()> unpark_trigger_func1; + handle->getArgument("unpark_trigger1", unpark_trigger_func1); + // Call the first function. It should cause the hook library to call the + // "unpark" function. However, the object should not be unparked yet, + // because the other callout hasn't completed its scheduled asynchronous + // operation (keeps a reference on the parked object). + unpark_trigger_func1(); + EXPECT_FALSE(unparked); + + // Call the second function. This should decrease the reference count to + // 0 and the packet should be unparked. + std::function<void()> unpark_trigger_func2; + handle->getArgument("unpark_trigger2", unpark_trigger_func2); + unpark_trigger_func2(); + EXPECT_TRUE(unparked); + + // Resetting the handle makes return from test body to crash. + + // Try unloading the libraries. + EXPECT_NO_THROW(HooksManager::prepareUnloadLibraries()); + bool status = false; + EXPECT_NO_THROW(status = HooksManager::unloadLibraries()); + // Handle is still active. + EXPECT_FALSE(status); +} + +// This test verifies that the server can also unpark the packet. +TEST_F(HooksManagerTest, ServerUnpark) { + // Load the same library twice. Both installed callouts will trigger + // asynchronous operation. + HookLibsCollection library_names; + library_names.push_back(make_pair(std::string(ASYNC_CALLOUT_LIBRARY), + data::ConstElementPtr())); + library_names.push_back(make_pair(std::string(ASYNC_CALLOUT_LIBRARY), + data::ConstElementPtr())); + // Load libraries. + EXPECT_TRUE(HooksManager::loadLibraries(library_names)); + + CalloutHandlePtr handle = HooksManager::createCalloutHandle(); + + // We could be parked any object. Typically it will be a pointer to the + // packet. In this case, however, it is simpler to just use a string. + std::string parked_object = "foo"; + handle->setArgument("parked_object", parked_object); + + // This boolean value will be set to true when the packet gets unparked. + bool unparked = false; + + // The callouts instruct us to park the object. We associated the callback + // function with the parked object, which sets "unparked" flag to true. We + // can later test the value of this flag to verify when exactly the packet + // got unparked. + HooksManager::park<std::string>("hookpt_one", "foo", + [&unparked] { + unparked = true; + }); + + // It should be possible for the server to increase reference counter. + ASSERT_NO_THROW(HooksManager::reference<std::string>("hookpt_one", "foo")); + + // Call installed callout. + HooksManager::callCallouts(hookpt_one_index_, *handle); + + // Server can force unparking the object. + EXPECT_TRUE(HooksManager::unpark<std::string>("hookpt_one", "foo")); + + EXPECT_TRUE(unparked); + + // Reset the handle to allow unload. + handle.reset(); + + // Try unloading the libraries. + EXPECT_NO_THROW(HooksManager::prepareUnloadLibraries()); + bool status = false; + EXPECT_NO_THROW(status = HooksManager::unloadLibraries()); + EXPECT_TRUE(status); +} + +// This test verifies that the server can drop parked packet. +TEST_F(HooksManagerTest, ServerDropParked) { + // Load library. + HookLibsCollection library_names; + library_names.push_back(make_pair(std::string(ASYNC_CALLOUT_LIBRARY), + data::ConstElementPtr())); + EXPECT_TRUE(HooksManager::loadLibraries(library_names)); + + CalloutHandlePtr handle = HooksManager::createCalloutHandle(); + + // We could be parked any object. Typically it will be a pointer to the + // packet. In this case, however, it is simpler to just use a string. + std::string parked_object = "foo"; + handle->setArgument("parked_object", parked_object); + + // This boolean value will be set to true when the packet gets unparked. + bool unparked = false; + + // The callouts instruct us to park the object. We associated the callback + // function with the parked object, which sets "unparked" flag to true. We + // can later test the value of this flag to verify when exactly the packet + // got unparked. + HooksManager::park<std::string>("hookpt_one", "foo", + [&unparked] { + unparked = true; + }); + + // It should be possible for the server to increase reference counter. + ASSERT_NO_THROW(HooksManager::reference<std::string>("hookpt_one", "foo")); + + // Call installed callout. + HooksManager::callCallouts(hookpt_one_index_, *handle); + + // Drop the parked packet. The callback should not be called. + EXPECT_TRUE(HooksManager::drop<std::string>("hookpt_one", "foo")); + + EXPECT_FALSE(unparked); + + // An attempt to unpark the packet should return false, as this packet + // is not parked anymore. + EXPECT_FALSE(HooksManager::unpark<std::string>("hookpt_one", "foo")); + + // Reset the handle to allow unload. + handle.reset(); + + // Try unloading the libraries. + EXPECT_NO_THROW(HooksManager::prepareUnloadLibraries()); + bool status = false; + EXPECT_NO_THROW(status = HooksManager::unloadLibraries()); + EXPECT_TRUE(status); +} + +// This test verifies that parked objects are removed when libraries are +// unloaded. +TEST_F(HooksManagerTest, UnloadBeforeUnpark) { + // Load the same library twice. Both installed callouts will trigger + // asynchronous operation. + HookLibsCollection library_names; + library_names.push_back(make_pair(std::string(ASYNC_CALLOUT_LIBRARY), + data::ConstElementPtr())); + library_names.push_back(make_pair(std::string(ASYNC_CALLOUT_LIBRARY), + data::ConstElementPtr())); + // Load libraries. + EXPECT_TRUE(HooksManager::loadLibraries(library_names)); + + CalloutHandlePtr handle = HooksManager::createCalloutHandle(); + + // We could be parked any object. Typically it will be a pointer to the + // packet. In this case, however, it is simpler to just use a string. + std::string parked_object = "foo"; + handle->setArgument("parked_object", parked_object); + + // This boolean value will be set to true when the packet gets unparked. + bool unparked = false; + + // The callouts instruct us to park the object. We associated the callback + // function with the parked object, which sets "unparked" flag to true. We + // can later test the value of this flag to verify when exactly the packet + // got unparked. + HooksManager::park<std::string>("hookpt_one", "foo", + [&unparked] { + unparked = true; + }); + + // Call installed callout. + HooksManager::callCallouts(hookpt_one_index_, *handle); + + // Reset the handle to allow a reload. + handle.reset(); + + // Try reloading the libraries. + EXPECT_NO_THROW(HooksManager::prepareUnloadLibraries()); + bool status = false; + EXPECT_NO_THROW(status = HooksManager::unloadLibraries()); + EXPECT_TRUE(status); + EXPECT_TRUE(HooksManager::loadLibraries(library_names)); + + // Parked object should have been removed. + EXPECT_FALSE(HooksManager::unpark<std::string>("hookpt_one", "foo")); + + // Callback should not be called. + EXPECT_FALSE(unparked); +} + + +} // Anonymous namespace diff --git a/src/lib/hooks/tests/incorrect_version_library.cc b/src/lib/hooks/tests/incorrect_version_library.cc new file mode 100644 index 0000000..f4d7850 --- /dev/null +++ b/src/lib/hooks/tests/incorrect_version_library.cc @@ -0,0 +1,26 @@ +// Copyright (C) 2013-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +/// @file +/// @brief Incorrect version function test +/// +/// This is source of a test library for various test (LibraryManager and +/// HooksManager). The characteristics of the library produced from this +/// file are: +/// +/// - It contains the version() framework function only, which returns an +/// incorrect version number. + +#include <config.h> +#include <hooks/hooks.h> + +extern "C" { + +int version() { + return (KEA_HOOKS_VERSION + 1); +} + +}; diff --git a/src/lib/hooks/tests/library_manager_collection_unittest.cc b/src/lib/hooks/tests/library_manager_collection_unittest.cc new file mode 100644 index 0000000..9b30cb3 --- /dev/null +++ b/src/lib/hooks/tests/library_manager_collection_unittest.cc @@ -0,0 +1,314 @@ +// Copyright (C) 2013-2020 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <hooks/callout_handle.h> +#include <hooks/callout_manager.h> +#include <hooks/library_manager.h> +#include <hooks/library_manager_collection.h> +#include <hooks/libinfo.h> + +#include <hooks/tests/common_test_class.h> +#include <hooks/tests/test_libraries.h> + +#include <boost/shared_ptr.hpp> +#include <gtest/gtest.h> + +#include <algorithm> +#include <string> + + +using namespace isc; +using namespace isc::hooks; +using namespace std; + +namespace { + +/// @brief Library manager collection test class + +class LibraryManagerCollectionTest : public ::testing::Test, + public HooksCommonTestClass { +private: + + /// To avoid unused variable errors + std::string dummy(int i) { + if (i == 0) { + return (MARKER_FILE); + } else if (i > 0) { + return (LOAD_CALLOUT_LIBRARY); + } else { + return (LOAD_ERROR_CALLOUT_LIBRARY); + } + } +}; + +} // namespace + +namespace isc { +namespace hooks { +/// @brief Public library manager collection class +/// +/// This is an instance of the LibraryManagerCollection class but with the +/// protected methods made public for test purposes. + +class PublicLibraryManagerCollection : public LibraryManagerCollection { +public: + /// @brief Constructor + /// + /// @param List of libraries that this collection will manage. The order + /// of the libraries is important. + PublicLibraryManagerCollection(const HookLibsCollection& libraries) + : LibraryManagerCollection(libraries) { + } + + /// Public methods that call protected methods on the superclass. + using LibraryManagerCollection::unloadLibraries; +}; + +} // namespace hooks +} // namespace isc + +namespace { +// This is effectively the same test as for LibraryManager, but using the +// LibraryManagerCollection object. + +TEST_F(LibraryManagerCollectionTest, LoadLibraries) { + + // Set up the list of libraries to be loaded. + HookLibsCollection library_names; + library_names.push_back(make_pair(std::string(FULL_CALLOUT_LIBRARY), + data::ConstElementPtr())); + library_names.push_back(make_pair(std::string(BASIC_CALLOUT_LIBRARY), + data::ConstElementPtr())); + + // Set up the library manager collection and get the callout manager we'll + // be using. + PublicLibraryManagerCollection lm_collection(library_names); + + // Load the libraries. + EXPECT_TRUE(lm_collection.loadLibraries()); + EXPECT_EQ(2, lm_collection.getLoadedLibraryCount()); + + // Execute the callouts. The first library implements the calculation. + // + // r3 = (7 * d1 - d2) * d3 + // + // The last-loaded library implements the calculation + // + // r3 = (10 + d1) * d2 - d3 + // + // Putting the processing for each library together in the appropriate + // order, we get: + // + // r3 = ((10 * d1 + d1) - d2) * d2 * d3 - d3 + boost::shared_ptr<CalloutManager> manager = + lm_collection.getCalloutManager(); + { + SCOPED_TRACE("Doing calculation with libraries loaded"); + executeCallCallouts(manager, 10, 3, 33, 2, 62, 3, 183); + } + + // Try unloading the libraries. + EXPECT_NO_THROW(lm_collection.unloadLibraries()); + EXPECT_EQ(0, lm_collection.getLoadedLibraryCount()); + + // Re-execute the calculation - callouts can be called but as nothing + // happens, the result should always be -1. + { + SCOPED_TRACE("Doing calculation with libraries not loaded"); + executeCallCallouts(manager, -1, 3, -1, 22, -1, 83, -1); + } +} + +// This is effectively the same test as above, but with a library generating +// an error when loaded. It is expected that no libraries will be loaded. + +TEST_F(LibraryManagerCollectionTest, LoadLibrariesWithError) { + + // Set up the list of libraries to be loaded. + HookLibsCollection library_names; + library_names.push_back(make_pair(std::string(FULL_CALLOUT_LIBRARY), + data::ConstElementPtr())); + library_names.push_back(make_pair(std::string(INCORRECT_VERSION_LIBRARY), + data::ConstElementPtr())); + library_names.push_back(make_pair(std::string(BASIC_CALLOUT_LIBRARY), + data::ConstElementPtr())); + + // Set up the library manager collection and get the callout manager we'll + // be using. + PublicLibraryManagerCollection lm_collection(library_names); + + // Load the libraries. We expect a failure status to be returned as + // one of the libraries failed to load. + EXPECT_FALSE(lm_collection.loadLibraries()); + + // Expect no libraries were loaded. + EXPECT_EQ(0, lm_collection.getLoadedLibraryCount()); +} + +// Check that everything works even with no libraries loaded. + +TEST_F(LibraryManagerCollectionTest, NoLibrariesLoaded) { + // Set up the list of libraries to be loaded. + HookLibsCollection library_names; + + // Set up the library manager collection and get the callout manager we'll + // be using. + LibraryManagerCollection lm_collection(library_names); + EXPECT_TRUE(lm_collection.loadLibraries()); + EXPECT_EQ(0, lm_collection.getLoadedLibraryCount()); + boost::shared_ptr<CalloutManager> manager = + lm_collection.getCalloutManager(); + + // Execute the calculation - callouts can be called but as nothing + // happens, the result should always be -1. + executeCallCallouts(manager, -1, 3, -1, 22, -1, 83, -1); +} + +// Check that we can get the names of the libraries. + +TEST_F(LibraryManagerCollectionTest, LibraryNames) { + + // Set up the list of libraries to be loaded. + HookLibsCollection libraries; + libraries.push_back(make_pair(std::string(FULL_CALLOUT_LIBRARY), + data::ConstElementPtr())); + libraries.push_back(make_pair(std::string(BASIC_CALLOUT_LIBRARY), + data::ConstElementPtr())); + + // Set up the library manager collection and get the callout manager we'll + // be using. + PublicLibraryManagerCollection lm_collection(libraries); + + // Check the names before the libraries are loaded. + std::vector<std::string> collection_names = lm_collection.getLibraryNames(); + EXPECT_TRUE(extractNames(libraries) == collection_names); + + // Load the libraries and check the names again. + EXPECT_TRUE(lm_collection.loadLibraries()); + EXPECT_EQ(2, lm_collection.getLoadedLibraryCount()); + collection_names = lm_collection.getLibraryNames(); + EXPECT_TRUE(extractNames(libraries) == collection_names); +} + +// Test the library validation function. + +TEST_F(LibraryManagerCollectionTest, validateLibraries) { + // Vector of libraries that failed validation + std::vector<std::string> failed; + + // Test different vectors of libraries. + + // No libraries should return a success. + std::vector<std::string> libraries; + + failed = LibraryManagerCollection::validateLibraries(libraries); + EXPECT_TRUE(failed.empty()); + + // Single valid library should validate. + libraries.clear(); + libraries.push_back(BASIC_CALLOUT_LIBRARY); + + failed = LibraryManagerCollection::validateLibraries(libraries); + EXPECT_TRUE(failed.empty()); + + // Multiple valid libraries should succeed. + libraries.clear(); + libraries.push_back(BASIC_CALLOUT_LIBRARY); + libraries.push_back(FULL_CALLOUT_LIBRARY); + libraries.push_back(UNLOAD_CALLOUT_LIBRARY); + libraries.push_back(CALLOUT_PARAMS_LIBRARY); + + failed = LibraryManagerCollection::validateLibraries(libraries); + EXPECT_TRUE(failed.empty()); + + // Single invalid library should fail. + libraries.clear(); + libraries.push_back(NOT_PRESENT_LIBRARY); + + failed = LibraryManagerCollection::validateLibraries(libraries); + EXPECT_TRUE(failed == libraries); + + // Multiple invalid libraries should fail. + libraries.clear(); + libraries.push_back(INCORRECT_VERSION_LIBRARY); + libraries.push_back(NO_VERSION_LIBRARY); + libraries.push_back(FRAMEWORK_EXCEPTION_LIBRARY); + + failed = LibraryManagerCollection::validateLibraries(libraries); + EXPECT_TRUE(failed == libraries); + + // Combination of valid and invalid (first one valid) should fail. + libraries.clear(); + libraries.push_back(FULL_CALLOUT_LIBRARY); + libraries.push_back(INCORRECT_VERSION_LIBRARY); + libraries.push_back(NO_VERSION_LIBRARY); + + std::vector<std::string> expected_failures; + expected_failures.push_back(INCORRECT_VERSION_LIBRARY); + expected_failures.push_back(NO_VERSION_LIBRARY); + + failed = LibraryManagerCollection::validateLibraries(libraries); + EXPECT_TRUE(failed == expected_failures); + + // Combination of valid and invalid (first one invalid) should fail. + libraries.clear(); + libraries.push_back(NO_VERSION_LIBRARY); + libraries.push_back(FULL_CALLOUT_LIBRARY); + libraries.push_back(INCORRECT_VERSION_LIBRARY); + + expected_failures.clear(); + expected_failures.push_back(NO_VERSION_LIBRARY); + expected_failures.push_back(INCORRECT_VERSION_LIBRARY); + + failed = LibraryManagerCollection::validateLibraries(libraries); + EXPECT_TRUE(failed == expected_failures); +} + +// This test verifies if getLibraryNames and getLibraryInfo are returning +// expected values if there are no libraries configured. +TEST_F(LibraryManagerCollectionTest, libraryGetEmpty) { + + HookLibsCollection empty; + boost::shared_ptr<LibraryManagerCollection> mgr; + + // Instantiate library manager collection with no libraries + EXPECT_NO_THROW(mgr.reset(new LibraryManagerCollection(empty))); + + // Check that getLibraryInfo returns empty list properly. + HookLibsCollection returned = mgr->getLibraryInfo(); + EXPECT_TRUE(returned.empty()); + + // Check that getLibraryNames return empty list, too. + vector<string> names(3, "rubbish"); // just put something in it. + EXPECT_NO_THROW(names = mgr->getLibraryNames()); + EXPECT_TRUE(names.empty()); +} + +// This test verifies if getLibraryNames and getLibraryInfo are returning +// expected values when there are libraries configured. +TEST_F(LibraryManagerCollectionTest, libraryGet) { + using namespace data; + + HookLibsCollection libs; + ElementPtr param1(Element::fromJSON("{ \"param1\": \"foo\" }")); + ElementPtr param2(Element::fromJSON("{ \"param2\": \"bar\" }")); + libs.push_back(make_pair("libone", param1)); + libs.push_back(make_pair("libtwo", param2)); + + boost::shared_ptr<LibraryManagerCollection> mgr; + EXPECT_NO_THROW(mgr.reset(new LibraryManagerCollection(libs))); + EXPECT_TRUE(libs == mgr->getLibraryInfo()); + + vector<string> exp_names; + exp_names.push_back("libone"); + exp_names.push_back("libtwo"); + + EXPECT_TRUE(exp_names == mgr->getLibraryNames()); +} + +} // Anonymous namespace diff --git a/src/lib/hooks/tests/library_manager_unittest.cc b/src/lib/hooks/tests/library_manager_unittest.cc new file mode 100644 index 0000000..52dea20 --- /dev/null +++ b/src/lib/hooks/tests/library_manager_unittest.cc @@ -0,0 +1,735 @@ +// Copyright (C) 2013-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 <hooks/callout_handle.h> +#include <hooks/callout_manager.h> +#include <hooks/library_manager.h> +#include <hooks/server_hooks.h> + +#include <hooks/tests/common_test_class.h> +#include <hooks/tests/marker_file.h> +#include <hooks/tests/test_libraries.h> + +#include <log/message_dictionary.h> +#include <log/message_initializer.h> + +#include <util/multi_threading_mgr.h> + +#include <gtest/gtest.h> + +#include <algorithm> +#include <fstream> +#include <string> + +#include <unistd.h> + + +using namespace isc; +using namespace isc::hooks; +using namespace isc::log; +using namespace isc::util; +using namespace std; + +namespace { + +/// @brief Library manager test class + +class LibraryManagerTest : public ::testing::Test, + public HooksCommonTestClass { +public: + /// @brief Constructor + /// + /// Initializes the CalloutManager object used in the tests. It sets it + /// up with the hooks initialized in the HooksCommonTestClass object and + /// with four libraries. + LibraryManagerTest() { + callout_manager_.reset(new CalloutManager(4)); + + // Ensure the marker file is not present at the start of a test. + static_cast<void>(remove(MARKER_FILE)); + + // Disable multi-threading. + MultiThreadingMgr::instance().setMode(false); + } + + /// @brief Destructor + /// + /// Ensures a marker file is removed after each test. + ~LibraryManagerTest() { + static_cast<void>(remove(MARKER_FILE)); + + // Disable multi-threading. + MultiThreadingMgr::instance().setMode(false); + } + + /// @brief Marker file present + /// + /// Convenience function to check whether a marker file is present. It + /// does this by opening the file. + /// + /// @return true if the marker file is present. + bool markerFilePresent() const { + + // Try to open it. + std::fstream marker; + marker.open(MARKER_FILE, std::fstream::in); + + // Check if it is open and close it if so. + bool exists = marker.is_open(); + if (exists) { + marker.close(); + } + + return (exists); + } + + /// @brief Call callouts test + /// + /// A wrapper around the method of the same name in the HooksCommonTestClass + /// object, this passes this class's CalloutManager to that method. + /// + /// @param r0...r3, d1..d3 Values and intermediate values expected. They + /// are ordered so that the variables appear in the argument list in + /// the order they are used. See HooksCommonTestClass::execute for + /// a full description. (rN is used to indicate an expected result, + /// dN is data to be passed to the calculation.) + void executeCallCallouts(int r0, int d1, int r1, int d2, int r2, int d3, + int r3) { + HooksCommonTestClass::executeCallCallouts(callout_manager_, r0, d1, + r1, d2, r2, d3, r3); + } + + /// @brief Call command handlers test. + /// + /// A wrapper around the method of the same name in the HooksCommonTestClass + /// object, this passes this class's CalloutManager to that method. + /// + /// @param r1..r2, d1..d2 Values and intermediate values expected. + void executeCallCommandHandlers(int d1, int r1, int d2, int r2) { + HooksCommonTestClass::executeCallCommandHandlers(callout_manager_, + d1, r1, d2, r2); + } + + /// Callout manager used for the test. + boost::shared_ptr<CalloutManager> callout_manager_; +}; + +/// @brief Library manager class +/// +/// This is an instance of the LibraryManager class but with the protected +/// methods made public for test purposes. + +class PublicLibraryManager : public isc::hooks::LibraryManager { +public: + /// @brief Constructor + /// + /// Stores the library name. The actual loading is done in loadLibrary(). + /// + /// @param name Name of the library to load. This should be an absolute + /// path name. + /// @param index Index of this library. For all these tests, it will be + /// zero, as we are only using one library. + /// @param manager CalloutManager object + PublicLibraryManager(const std::string& name, int index, + const boost::shared_ptr<CalloutManager>& manager) + : LibraryManager(name, index, manager) + {} + + /// Public methods that call protected methods on the superclass. + using LibraryManager::unloadLibrary; + using LibraryManager::openLibrary; + using LibraryManager::closeLibrary; + using LibraryManager::checkVersion; + using LibraryManager::checkMultiThreadingCompatible; + using LibraryManager::registerStandardCallouts; + using LibraryManager::runLoad; + using LibraryManager::prepareUnloadLibrary; +}; + + +// Check that LibraryManager constructor requires a not null manager + +TEST_F(LibraryManagerTest, NullManager) { + boost::shared_ptr<CalloutManager> null_manager; + EXPECT_THROW(PublicLibraryManager(std::string("foo"), 0, null_manager), + NoCalloutManager); +} + +// Check that openLibrary() reports an error when it can't find the specified +// library. + +TEST_F(LibraryManagerTest, NoLibrary) { + PublicLibraryManager lib_manager(std::string(NOT_PRESENT_LIBRARY), + 0, callout_manager_); + EXPECT_FALSE(lib_manager.openLibrary()); +} + +// Check that the openLibrary() and closeLibrary() methods work. + +TEST_F(LibraryManagerTest, OpenClose) { + PublicLibraryManager lib_manager(std::string(BASIC_CALLOUT_LIBRARY), + 0, callout_manager_); + + // Open and close the library + EXPECT_TRUE(lib_manager.openLibrary()); + EXPECT_TRUE(lib_manager.closeLibrary()); + + // Check that a second close on an already closed library does not report + // an error. + EXPECT_TRUE(lib_manager.closeLibrary()); +} + +// Check that the code handles the case of a library with no version function. + +TEST_F(LibraryManagerTest, NoVersion) { + PublicLibraryManager lib_manager(std::string(NO_VERSION_LIBRARY), + 0, callout_manager_); + // Open should succeed. + EXPECT_TRUE(lib_manager.openLibrary()); + + // Version check should fail. + EXPECT_FALSE(lib_manager.checkVersion()); + + // Tidy up. + EXPECT_TRUE(lib_manager.closeLibrary()); +} + +// Check that the code handles the case of a library with a version function +// that returns an incorrect version number. + +TEST_F(LibraryManagerTest, WrongVersion) { + PublicLibraryManager lib_manager(std::string(INCORRECT_VERSION_LIBRARY), + 0, callout_manager_); + // Open should succeed. + EXPECT_TRUE(lib_manager.openLibrary()); + + // Version check should fail. + EXPECT_FALSE(lib_manager.checkVersion()); + + // Tidy up. + EXPECT_TRUE(lib_manager.closeLibrary()); +} + +// Check that the code handles the case of a library where the version function +// throws an exception. + +TEST_F(LibraryManagerTest, VersionException) { + PublicLibraryManager lib_manager(std::string(FRAMEWORK_EXCEPTION_LIBRARY), + 0, callout_manager_); + // Open should succeed. + EXPECT_TRUE(lib_manager.openLibrary()); + + // Version check should fail. + EXPECT_FALSE(lib_manager.checkVersion()); + + // Tidy up. + EXPECT_TRUE(lib_manager.closeLibrary()); +} + +// Tests that checkVersion() function succeeds in the case of a library with a +// version function that returns the correct version number. + +TEST_F(LibraryManagerTest, CorrectVersionReturned) { + PublicLibraryManager lib_manager(std::string(BASIC_CALLOUT_LIBRARY), + 0, callout_manager_); + // Open should succeed. + EXPECT_TRUE(lib_manager.openLibrary()); + + // Version check should succeed. + EXPECT_TRUE(lib_manager.checkVersion()); + + // Tidy up. + EXPECT_TRUE(lib_manager.closeLibrary()); +} + +// Checks that the code handles the case of a library with no +// multi_threading_compatible function. + +TEST_F(LibraryManagerTest, NoMultiThreadingCompatible) { + PublicLibraryManager lib_manager(std::string(BASIC_CALLOUT_LIBRARY), + 0, callout_manager_); + + // Open should succeed. + EXPECT_TRUE(lib_manager.openLibrary()); + + // Not multi-threading compatible: does not matter without MT. + EXPECT_TRUE(lib_manager.checkMultiThreadingCompatible(false)); + + // Not multi-threading compatible: does matter with MT. + EXPECT_FALSE(lib_manager.checkMultiThreadingCompatible(true)); + + // Tidy up. + EXPECT_TRUE(lib_manager.closeLibrary()); +} + +// Checks that the code handles the case of a library with a +// multi_threading_compatible function returning 0 (not compatible). + +TEST_F(LibraryManagerTest, multiThreadingNotCompatible) { + PublicLibraryManager lib_manager(std::string(LOAD_ERROR_CALLOUT_LIBRARY), + 0, callout_manager_); + + // Open should succeed. + EXPECT_TRUE(lib_manager.openLibrary()); + + // Not multi-threading compatible: does not matter without MT. + EXPECT_TRUE(lib_manager.checkMultiThreadingCompatible(false)); + + // Not multi-threading compatible: does matter with MT. + EXPECT_FALSE(lib_manager.checkMultiThreadingCompatible(true)); + + // Tidy up. + EXPECT_TRUE(lib_manager.closeLibrary()); +} + +// Checks that the code handles the case of a library with a +// multi_threading_compatible function returning 1 (compatible) + +TEST_F(LibraryManagerTest, multiThreadingCompatible) { + PublicLibraryManager lib_manager(std::string(FULL_CALLOUT_LIBRARY), + 0, callout_manager_); + + // Open should succeed. + EXPECT_TRUE(lib_manager.openLibrary()); + + // Multi-threading compatible: does not matter without MT. + EXPECT_TRUE(lib_manager.checkMultiThreadingCompatible(false)); + + // Multi-threading compatible: does matter with MT. + EXPECT_TRUE(lib_manager.checkMultiThreadingCompatible(true)); + + // Tidy up. + EXPECT_TRUE(lib_manager.closeLibrary()); +} + +// Checks that the code handles the case of a library with a +// multi_threading_compatible function returning 1 (compatible) + +TEST_F(LibraryManagerTest, multiThreadingCompatibleException) { + PublicLibraryManager lib_manager(std::string(FRAMEWORK_EXCEPTION_LIBRARY), + 0, callout_manager_); + + // Open should succeed. + EXPECT_TRUE(lib_manager.openLibrary()); + + // Throw exception: does not matter without MT. + EXPECT_TRUE(lib_manager.checkMultiThreadingCompatible(false)); + + // Throw exception: does matter with MT. + EXPECT_FALSE(lib_manager.checkMultiThreadingCompatible(true)); + + // Tidy up. + EXPECT_TRUE(lib_manager.closeLibrary()); +} + +// Checks the registration of standard callouts. + +TEST_F(LibraryManagerTest, RegisterStandardCallouts) { + + // Load the only library, specifying the index of 0 as it's the only + // library. This should load all callouts. + PublicLibraryManager lib_manager(std::string(BASIC_CALLOUT_LIBRARY), + 0, callout_manager_); + EXPECT_TRUE(lib_manager.openLibrary()); + + // Check the version of the library. + EXPECT_TRUE(lib_manager.checkVersion()); + + // Load the standard callouts + EXPECT_NO_THROW(lib_manager.registerStandardCallouts()); + + // Now execute the callouts in the order expected. The library performs + // the calculation: + // + // r3 = (10 + d1) * d2 - d3 + executeCallCallouts(10, 5, 15, 7, 105, 17, 88); + + // Tidy up + EXPECT_TRUE(lib_manager.closeLibrary()); +} + +// Test that the "load" function is called correctly. + +TEST_F(LibraryManagerTest, CheckLoadCalled) { + + // Load the only library, specifying the index of 0 as it's the only + // library. This should load all callouts. + PublicLibraryManager lib_manager(std::string(LOAD_CALLOUT_LIBRARY), + 0, callout_manager_); + EXPECT_TRUE(lib_manager.openLibrary()); + + // Check the version of the library. + EXPECT_TRUE(lib_manager.checkVersion()); + + // Load the standard callouts + EXPECT_NO_THROW(lib_manager.registerStandardCallouts()); + + // Check that only context_create and hookpt_one have callouts registered. + EXPECT_TRUE(callout_manager_->calloutsPresent( + ServerHooks::CONTEXT_CREATE)); + EXPECT_TRUE(callout_manager_->calloutsPresent(hookpt_one_index_)); + EXPECT_FALSE(callout_manager_->calloutsPresent(hookpt_two_index_)); + EXPECT_FALSE(callout_manager_->calloutsPresent(hookpt_three_index_)); + EXPECT_FALSE(callout_manager_->commandHandlersPresent("command-one")); + EXPECT_FALSE(callout_manager_->commandHandlersPresent("command-two")); + EXPECT_FALSE(callout_manager_->calloutsPresent( + ServerHooks::CONTEXT_DESTROY)); + + // Call the runLoad() method to run the load() function. + EXPECT_TRUE(lib_manager.runLoad()); + EXPECT_TRUE(callout_manager_->calloutsPresent( + ServerHooks::CONTEXT_CREATE)); + EXPECT_TRUE(callout_manager_->calloutsPresent(hookpt_one_index_)); + EXPECT_TRUE(callout_manager_->calloutsPresent(hookpt_two_index_)); + EXPECT_TRUE(callout_manager_->calloutsPresent(hookpt_three_index_)); + EXPECT_TRUE(callout_manager_->commandHandlersPresent("command-one")); + EXPECT_TRUE(callout_manager_->commandHandlersPresent("command-two")); + EXPECT_FALSE(callout_manager_->calloutsPresent( + ServerHooks::CONTEXT_DESTROY)); + + // Now execute the callouts in the order expected. The library performs + // the calculation: + // + // r3 = (5 * d1 + d2) * d3 + executeCallCallouts(5, 5, 25, 7, 32, 10, 320); + + // Execute command handlers for 'command-one' and 'command-two'. + // + // r2 = d1 * d2 * 10; + executeCallCommandHandlers(5, 5, 7, 350); + + // Tidy up + EXPECT_TRUE(lib_manager.closeLibrary()); +} + +// Check handling of a "load" function that throws an exception + +TEST_F(LibraryManagerTest, CheckLoadException) { + + // Load the only library, specifying the index of 0 as it's the only + // library. This should load all callouts. + PublicLibraryManager lib_manager(std::string(FRAMEWORK_EXCEPTION_LIBRARY), + 0, callout_manager_); + EXPECT_TRUE(lib_manager.openLibrary()); + + // Running the load function should fail. + EXPECT_FALSE(lib_manager.runLoad()); + + // Tidy up + EXPECT_TRUE(lib_manager.closeLibrary()); +} + +// Check handling of a "load" function that returns an error. + +TEST_F(LibraryManagerTest, CheckLoadError) { + + // Load the only library, specifying the index of 0 as it's the only + // library. This should load all callouts. + PublicLibraryManager lib_manager(std::string(LOAD_ERROR_CALLOUT_LIBRARY), + 0, callout_manager_); + EXPECT_TRUE(lib_manager.openLibrary()); + + // Check that we catch a load error + EXPECT_FALSE(lib_manager.runLoad()); + + // Tidy up + EXPECT_TRUE(lib_manager.closeLibrary()); +} + +// No unload function + +TEST_F(LibraryManagerTest, CheckNoUnload) { + + // Load the only library, specifying the index of 0 as it's the only + // library. This should load all callouts. + PublicLibraryManager lib_manager(std::string(BASIC_CALLOUT_LIBRARY), + 0, callout_manager_); + EXPECT_TRUE(lib_manager.openLibrary()); + + // Check that no unload function returns true. + EXPECT_TRUE(lib_manager.prepareUnloadLibrary()); + + // Tidy up + EXPECT_TRUE(lib_manager.closeLibrary()); +} + +// Unload function returns an error + +TEST_F(LibraryManagerTest, CheckUnloadError) { + + // Load the only library, specifying the index of 0 as it's the only + // library. This should load all callouts. + PublicLibraryManager lib_manager(std::string(LOAD_ERROR_CALLOUT_LIBRARY), + 0, callout_manager_); + EXPECT_TRUE(lib_manager.openLibrary()); + + // Check that unload function returning an error returns false. + EXPECT_FALSE(lib_manager.prepareUnloadLibrary()); + + // Tidy up + EXPECT_TRUE(lib_manager.closeLibrary()); +} + +// Unload function throws an exception. + +TEST_F(LibraryManagerTest, CheckUnloadException) { + + // Load the only library, specifying the index of 0 as it's the only + // library. This should load all callouts. + PublicLibraryManager lib_manager(std::string(FRAMEWORK_EXCEPTION_LIBRARY), + 0, callout_manager_); + EXPECT_TRUE(lib_manager.openLibrary()); + + // Check that we detect that the unload function throws an exception. + EXPECT_FALSE(lib_manager.prepareUnloadLibrary()); + + // Tidy up + EXPECT_TRUE(lib_manager.closeLibrary()); +} + +// Check that the case of the library's unload() function returning a +// success is handled correctly. + +TEST_F(LibraryManagerTest, CheckUnload) { + + // Load the only library, specifying the index of 0 as it's the only + // library. This should load all callouts. + PublicLibraryManager lib_manager(std::string(UNLOAD_CALLOUT_LIBRARY), + 0, callout_manager_); + EXPECT_TRUE(lib_manager.openLibrary()); + + + // Check that the marker file is not present (at least that the file + // open fails). + EXPECT_FALSE(markerFilePresent()); + + // Check that unload function runs and returns a success + EXPECT_TRUE(lib_manager.prepareUnloadLibrary()); + + // Check that the marker file was created. + EXPECT_TRUE(markerFilePresent()); + + // Tidy up + EXPECT_TRUE(lib_manager.closeLibrary()); +} + +// Test the operation of unloadLibrary(). We load a library with a set +// of callouts then unload it. We need to check that the callouts have been +// removed. We'll also check that the library's unload() function was called +// as well. + +TEST_F(LibraryManagerTest, LibUnload) { + + // Load the only library, specifying the index of 0 as it's the only + // library. This should load all callouts. + PublicLibraryManager lib_manager(std::string(LOAD_CALLOUT_LIBRARY), + 0, callout_manager_); + EXPECT_TRUE(lib_manager.openLibrary()); + + // Check the version of the library. + EXPECT_TRUE(lib_manager.checkVersion()); + + // No callouts should be registered at the moment. + EXPECT_FALSE(callout_manager_->calloutsPresent(hookpt_one_index_)); + EXPECT_FALSE(callout_manager_->calloutsPresent(hookpt_two_index_)); + EXPECT_FALSE(callout_manager_->calloutsPresent(hookpt_three_index_)); + EXPECT_FALSE(callout_manager_->commandHandlersPresent("command-one")); + EXPECT_FALSE(callout_manager_->commandHandlersPresent("command-two")); + + // Load the single standard callout and check it is registered correctly. + EXPECT_NO_THROW(lib_manager.registerStandardCallouts()); + EXPECT_TRUE(callout_manager_->calloutsPresent(hookpt_one_index_)); + EXPECT_FALSE(callout_manager_->calloutsPresent(hookpt_two_index_)); + EXPECT_FALSE(callout_manager_->calloutsPresent(hookpt_three_index_)); + EXPECT_FALSE(callout_manager_->commandHandlersPresent("command-one")); + EXPECT_FALSE(callout_manager_->commandHandlersPresent("command-two")); + + // Call the load function to load the other callouts. + EXPECT_TRUE(lib_manager.runLoad()); + EXPECT_TRUE(callout_manager_->calloutsPresent(hookpt_one_index_)); + EXPECT_TRUE(callout_manager_->calloutsPresent(hookpt_two_index_)); + EXPECT_TRUE(callout_manager_->calloutsPresent(hookpt_three_index_)); + EXPECT_TRUE(callout_manager_->commandHandlersPresent("command-one")); + EXPECT_TRUE(callout_manager_->commandHandlersPresent("command-two")); + + // Unload the library and check that the callouts have been removed from + // the CalloutManager. + lib_manager.unloadLibrary(); + EXPECT_FALSE(callout_manager_->calloutsPresent(hookpt_one_index_)); + EXPECT_FALSE(callout_manager_->calloutsPresent(hookpt_two_index_)); + EXPECT_FALSE(callout_manager_->calloutsPresent(hookpt_three_index_)); + EXPECT_FALSE(callout_manager_->commandHandlersPresent("command-one")); + EXPECT_FALSE(callout_manager_->commandHandlersPresent("command-two")); +} + +// Now come the loadLibrary() tests that make use of all the methods tested +// above. These tests are really to make sure that the methods have been +// tied together correctly. + +// First test the basic error cases - no library, no version function, version +// function returning an error. + +TEST_F(LibraryManagerTest, LoadLibraryNoLibrary) { + LibraryManager lib_manager(std::string(NOT_PRESENT_LIBRARY), 0, + callout_manager_); + EXPECT_FALSE(lib_manager.loadLibrary()); +} + +// Check that the code handles the case of a library with no version function. + +TEST_F(LibraryManagerTest, LoadLibraryNoVersion) { + LibraryManager lib_manager(std::string(NO_VERSION_LIBRARY), 0, + callout_manager_); + EXPECT_FALSE(lib_manager.loadLibrary()); +} + +// Check that the code handles the case of a library with a version function +// that returns an incorrect version number. + +TEST_F(LibraryManagerTest, LoadLibraryWrongVersion) { + LibraryManager lib_manager(std::string(INCORRECT_VERSION_LIBRARY), 0, + callout_manager_); + EXPECT_FALSE(lib_manager.loadLibrary()); +} + +// Check that the full loadLibrary call works. + +TEST_F(LibraryManagerTest, LoadLibrary) { + PublicLibraryManager lib_manager(std::string(FULL_CALLOUT_LIBRARY), 0, + callout_manager_); + EXPECT_TRUE(lib_manager.loadLibrary()); + + // Now execute the callouts in the order expected. The library performs + // the calculation: + // + // r3 = (7 * d1 - d2) * d3 + executeCallCallouts(7, 5, 35, 9, 26, 3, 78); + + EXPECT_TRUE(lib_manager.unloadLibrary()); + + // Check that the callouts have been removed from the callout manager. + EXPECT_FALSE(callout_manager_->calloutsPresent(hookpt_one_index_)); + EXPECT_FALSE(callout_manager_->calloutsPresent(hookpt_two_index_)); + EXPECT_FALSE(callout_manager_->calloutsPresent(hookpt_three_index_)); +} + +// Now test for multiple libraries. We'll load the full callout library +// first, then load some of the libraries with missing framework functions. +// This will check that when searching for framework functions, only the +// specified library is checked, not other loaded libraries. We will +// load a second library with suitable callouts and check that the callouts +// are added correctly. Finally, we'll unload one of the libraries and +// check that only the callouts belonging to that library were removed. + +TEST_F(LibraryManagerTest, LoadMultipleLibraries) { + // Load a library with all framework functions. + PublicLibraryManager lib_manager_1(std::string(FULL_CALLOUT_LIBRARY), + 0, callout_manager_); + EXPECT_TRUE(lib_manager_1.loadLibrary()); + + // Attempt to load a library with no version() function. We should detect + // this and not end up calling the function from the already loaded + // library. + PublicLibraryManager lib_manager_2(std::string(NO_VERSION_LIBRARY), + 1, callout_manager_); + EXPECT_FALSE(lib_manager_2.loadLibrary()); + + // Attempt to load the library with an incorrect version. This should + // be detected. + PublicLibraryManager lib_manager_3(std::string(INCORRECT_VERSION_LIBRARY), + 1, callout_manager_); + EXPECT_FALSE(lib_manager_3.loadLibrary()); + + // Load the basic callout library. This only has standard callouts so, + // if the first library's load() function gets called, some callouts + // will be registered twice and lead to incorrect results. + PublicLibraryManager lib_manager_4(std::string(BASIC_CALLOUT_LIBRARY), + 1, callout_manager_); + EXPECT_TRUE(lib_manager_4.loadLibrary()); + + // Execute the callouts. The first library implements the calculation. + // + // r3 = (7 * d1 - d2) * d3 + // + // The last-loaded library implements the calculation + // + // r3 = (10 + d1) * d2 - d3 + // + // Putting the processing for each library together in the appropriate + // order, we get: + // + // r3 = ((10 * d1 + d1) - d2) * d2 * d3 - d3 + executeCallCallouts(10, 3, 33, 2, 62, 3, 183); + + // All done, so unload the first library. + EXPECT_TRUE(lib_manager_1.unloadLibrary()); + + // Now execute the callouts again and check that the results are as + // expected for the new calculation. + executeCallCallouts(10, 5, 15, 7, 105, 17, 88); + + // ... and tidy up. + EXPECT_TRUE(lib_manager_4.unloadLibrary()); +} + +// Check that libraries can be validated. + +TEST_F(LibraryManagerTest, validateLibraries) { + EXPECT_TRUE(LibraryManager::validateLibrary(BASIC_CALLOUT_LIBRARY)); + EXPECT_TRUE(LibraryManager::validateLibrary(FULL_CALLOUT_LIBRARY)); + EXPECT_FALSE(LibraryManager::validateLibrary(FRAMEWORK_EXCEPTION_LIBRARY)); + EXPECT_FALSE(LibraryManager::validateLibrary(INCORRECT_VERSION_LIBRARY)); + EXPECT_TRUE(LibraryManager::validateLibrary(LOAD_CALLOUT_LIBRARY)); + EXPECT_TRUE(LibraryManager::validateLibrary(LOAD_ERROR_CALLOUT_LIBRARY)); + EXPECT_FALSE(LibraryManager::validateLibrary(NOT_PRESENT_LIBRARY)); + EXPECT_FALSE(LibraryManager::validateLibrary(NO_VERSION_LIBRARY)); + EXPECT_TRUE(LibraryManager::validateLibrary(UNLOAD_CALLOUT_LIBRARY)); + EXPECT_TRUE(LibraryManager::validateLibrary(CALLOUT_PARAMS_LIBRARY)); + + EXPECT_FALSE(LibraryManager::validateLibrary(BASIC_CALLOUT_LIBRARY, true)); + EXPECT_TRUE(LibraryManager::validateLibrary(FULL_CALLOUT_LIBRARY, true)); + EXPECT_FALSE(LibraryManager::validateLibrary(FRAMEWORK_EXCEPTION_LIBRARY, true)); + EXPECT_FALSE(LibraryManager::validateLibrary(INCORRECT_VERSION_LIBRARY, true)); + EXPECT_FALSE(LibraryManager::validateLibrary(LOAD_CALLOUT_LIBRARY, true)); + EXPECT_FALSE(LibraryManager::validateLibrary(LOAD_ERROR_CALLOUT_LIBRARY, true)); + EXPECT_FALSE(LibraryManager::validateLibrary(NOT_PRESENT_LIBRARY, true)); + EXPECT_FALSE(LibraryManager::validateLibrary(NO_VERSION_LIBRARY, true)); + EXPECT_FALSE(LibraryManager::validateLibrary(UNLOAD_CALLOUT_LIBRARY, true)); + EXPECT_FALSE(LibraryManager::validateLibrary(CALLOUT_PARAMS_LIBRARY, true)); +} + +// Check that log messages are properly registered and unregistered. + +TEST_F(LibraryManagerTest, libraryLoggerSetup) { + // Load a library with all framework functions. + PublicLibraryManager lib_manager(std::string(BASIC_CALLOUT_LIBRARY), + 0, callout_manager_); + EXPECT_TRUE(lib_manager.loadLibrary()); + + // After loading the library, the global logging dictionary should + // contain log messages registered for this library. + const MessageDictionaryPtr& dict = MessageDictionary::globalDictionary(); + EXPECT_EQ("basic callout load %1", dict->getText("BCL_LOAD_START")); + EXPECT_EQ("basic callout load end", dict->getText("BCL_LOAD_END")); + // Some of the messages defined by the hook library are duplicates. But, + // the loadLibrary function should have logged the duplicates and clear + // the duplicates list. By checking that the list of duplicates is empty + // we test that the LibraryManager handles the duplicates (logs and + // clears them). + EXPECT_TRUE(MessageInitializer::getDuplicates().empty()); + + // After unloading the library, the messages should be unregistered. + EXPECT_TRUE(lib_manager.unloadLibrary()); + // The musl libc does not implement dlclose +#ifndef LIBC_MUSL + EXPECT_TRUE(dict->getText("BCL_LOAD_START").empty()); + EXPECT_TRUE(dict->getText("BCL_LOAD_END").empty()); +#endif +} + +} // Anonymous namespace diff --git a/src/lib/hooks/tests/load_callout_library.cc b/src/lib/hooks/tests/load_callout_library.cc new file mode 100644 index 0000000..613ec2c --- /dev/null +++ b/src/lib/hooks/tests/load_callout_library.cc @@ -0,0 +1,152 @@ +// Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +/// @file +/// @brief Basic library with load() function +/// +/// This is source of a test library for various test (LibraryManager and +/// HooksManager). The characteristics of the library produced from this +/// file are: +/// +/// - The "version" and "load" framework functions are supplied. One "standard" +/// callout is supplied ("hookpt_one") and two non-standard ones which are +/// registered during the call to "load" on the hooks "hookpt_two" and +/// "hookpt_three". +/// +/// All callouts do trivial calculations, the result of all being called in +/// sequence being +/// +/// @f[ ((5 * data_1) + data_2) * data_3 @f] +/// +/// ...where data_1, data_2 and data_3 are the values passed in arguments of +/// the same name to the three callouts (data_1 passed to hookpt_one, data_2 +/// to hookpt_two etc.) and the result is returned in the argument "result". + +#include <config.h> +#include <hooks/hooks.h> + +using namespace isc::hooks; + +extern "C" { + +// Callouts + +int +context_create(CalloutHandle& handle) { + handle.setContext("result", static_cast<int>(5)); + handle.setArgument("result", static_cast<int>(5)); + return (0); +} + +// First callout adds the passed "data_1" argument to the initialized context +// value of 5. (Note that the value set by context_create is accessed through +// context and not the argument, so checking that context is correctly passed +// between callouts in the same library.) + +int +hookpt_one(CalloutHandle& handle) { + int data; + handle.getArgument("data_1", data); + + int result; + handle.getContext("result", result); + + result *= data; + handle.setArgument("result", result); + + return (0); +} + +// Second callout multiplies the current context value by the "data_2" +// argument. + +static int +hook_nonstandard_two(CalloutHandle& handle) { + int data; + handle.getArgument("data_2", data); + + int result; + handle.getArgument("result", result); + + result += data; + handle.setArgument("result", result); + + return (0); +} + +// Third callout adds "data_3" to the result. + +static int +hook_nonstandard_three(CalloutHandle& handle) { + int data; + handle.getArgument("data_3", data); + + int result; + handle.getArgument("result", result); + + result *= data; + handle.setArgument("result", result); + + return (0); +} + +// First command handler assigns data to a result. + +static int +command_handler_one(CalloutHandle& handle) { + int data; + handle.getArgument("data_1", data); + + int result; + handle.getArgument("result", result); + + result = data; + handle.setArgument("result", result); + + return (0); +} + +// Second command handler multiples the result by data by 10. + +static int +command_handler_two(CalloutHandle& handle) { + int data; + handle.getArgument("data_2", data); + + int result; + handle.getArgument("result", result); + + result *= data * 10; + handle.setArgument("result", result); + + return (0); +} + +// Framework functions + +int +version() { + return (KEA_HOOKS_VERSION); +} + +int load(LibraryHandle& handle) { + // Initialize the user library if the main image was statically linked +#ifdef USE_STATIC_LINK + hooksStaticLinkInit(); +#endif + // Register the non-standard functions + handle.registerCallout("hookpt_two", hook_nonstandard_two); + handle.registerCallout("hookpt_three", hook_nonstandard_three); + + // Register command_handler_one as control command handler. + handle.registerCommandCallout("command-one", command_handler_one); + handle.registerCommandCallout("command-two", command_handler_two); + + return (0); +} + +}; + diff --git a/src/lib/hooks/tests/load_error_callout_library.cc b/src/lib/hooks/tests/load_error_callout_library.cc new file mode 100644 index 0000000..66b1359 --- /dev/null +++ b/src/lib/hooks/tests/load_error_callout_library.cc @@ -0,0 +1,47 @@ +// Copyright (C) 2013-2020 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +/// @file +/// @brief Error load library +/// +/// This is source of a test library for various test (LibraryManager and +/// HooksManager). The characteristics of the library produced from this +/// file are: +/// +/// - All framework functions are supplied. "version" returns the correct +/// value, but "load" and unload return an error. + +#include <config.h> +#include <hooks/hooks.h> + +using namespace isc::hooks; + +extern "C" { + +// Framework functions + +int +version() { + return (KEA_HOOKS_VERSION); +} + +int +load(LibraryHandle&) { + return (1); +} + +int +unload() { + return (1); +} + +int +multi_threading_compatible() { + return (0); +} + +}; + diff --git a/src/lib/hooks/tests/marker_file.h.in b/src/lib/hooks/tests/marker_file.h.in new file mode 100644 index 0000000..368ad37 --- /dev/null +++ b/src/lib/hooks/tests/marker_file.h.in @@ -0,0 +1,19 @@ +// Copyright (C) 2013-2015 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 MARKER_FILE_H +#define MARKER_FILE_H + +/// @file +/// Define a marker file that is used in tests to prove that an "unload" +/// function has been called. + +namespace { +const char* MARKER_FILE = "@abs_builddir@/marker_file.dat"; +} + +#endif // MARKER_FILE_H + diff --git a/src/lib/hooks/tests/no_version_library.cc b/src/lib/hooks/tests/no_version_library.cc new file mode 100644 index 0000000..a4c4bb5 --- /dev/null +++ b/src/lib/hooks/tests/no_version_library.cc @@ -0,0 +1,24 @@ +// Copyright (C) 2013-2020 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> + +/// @file +/// @brief No version function library +/// +/// This is source of a test library for various test (LibraryManager and +/// HooksManager). The characteristics of the library produced from this +/// file are: +/// +/// - No version() function is present. + +extern "C" { + +int no_version() { + return (0); +} + +}; diff --git a/src/lib/hooks/tests/parking_lots_unittest.cc b/src/lib/hooks/tests/parking_lots_unittest.cc new file mode 100644 index 0000000..96f8814 --- /dev/null +++ b/src/lib/hooks/tests/parking_lots_unittest.cc @@ -0,0 +1,339 @@ +// Copyright (C) 2018-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 <exceptions/exceptions.h> +#include <hooks/parking_lots.h> +#include <boost/weak_ptr.hpp> +#include <testutils/gtest_utils.h> +#include <gtest/gtest.h> +#include <string> + +using namespace isc; +using namespace isc::hooks; + +namespace { + +// Defines a pointer to a string. The tests use shared pointers +// as parked objects to ensure key matching works correctly with +// them. We're doing this because real-world use parked objects +// are typically pointers to packets. +typedef boost::shared_ptr<std::string> StringPtr; + +// Test that it is possible to create and retrieve parking lots for +// specified hook points. +TEST(ParkingLotsTest, createGetParkingLot) { + ParkingLots parking_lots; + + ParkingLotPtr parking_lot0 = parking_lots.getParkingLotPtr(1); + ParkingLotPtr parking_lot1 = parking_lots.getParkingLotPtr(2); + ParkingLotPtr parking_lot2 = parking_lots.getParkingLotPtr(1); + + ASSERT_TRUE(parking_lot0); + ASSERT_TRUE(parking_lot1); + ASSERT_TRUE(parking_lot2); + + EXPECT_EQ(0, parking_lot0->size()); + EXPECT_EQ(0, parking_lot1->size()); + EXPECT_EQ(0, parking_lot2->size()); + + EXPECT_FALSE(parking_lot0 == parking_lot1); + EXPECT_TRUE(parking_lot0 == parking_lot2); + + ASSERT_NO_THROW(parking_lots.clear()); + + ParkingLotPtr parking_lot3 = parking_lots.getParkingLotPtr(1); + ASSERT_TRUE(parking_lot3); + + EXPECT_FALSE(parking_lot3 == parking_lot0); +} + +// Verify that an object can be parked. +TEST(ParkingLotsTest, park) { + ParkingLot parking_lot; + + // Create object to park. + StringPtr parked_object(new std::string("foo")); + + // Verify that we can park an object that has not been parked. + ASSERT_NO_THROW(parking_lot.park(parked_object, [] {})); + + EXPECT_EQ(1, parking_lot.size()); + + // Verify that we cannot park an object that has been parked + EXPECT_THROW(parking_lot.park(parked_object, [] {}), + InvalidOperation); +} + +// Verify that an object can be referenced. +TEST(ParkingLotsTest, reference) { + ParkingLotPtr parking_lot = boost::make_shared<ParkingLot>(); + ParkingLotHandlePtr parking_lot_handle = + boost::make_shared<ParkingLotHandle>(parking_lot); + + // Create an object. + StringPtr parked_object(new std::string("foo")); + + // Cannot reference an object that has not been parked. + ASSERT_THROW(parking_lot_handle->reference(parked_object), + InvalidOperation); + + // Park the object. + ASSERT_NO_THROW(parking_lot->park(parked_object, [] {})); + + EXPECT_EQ(1, parking_lot->size()); + + // Reference the object. Reference count should one. + int ref_count = 0; + ASSERT_NO_THROW(ref_count = parking_lot_handle->reference(parked_object)); + ASSERT_EQ(1, ref_count); + + // Reference the object again. Reference count should two. + ASSERT_NO_THROW(ref_count = parking_lot_handle->reference(parked_object)); + ASSERT_EQ(2, ref_count); + + EXPECT_EQ(1, parking_lot->size()); +} + +// Test that object can be parked and then unparked. +TEST(ParkingLotsTest, unpark) { + ParkingLotPtr parking_lot = boost::make_shared<ParkingLot>(); + ParkingLotHandlePtr parking_lot_handle = + boost::make_shared<ParkingLotHandle>(parking_lot); + + StringPtr parked_object(new std::string("foo")); + + // Unparking should return false if the object isn't parked. + EXPECT_FALSE(parking_lot->unpark(parked_object)); + + EXPECT_EQ(0, parking_lot->size()); + + // This flag will indicate if the callback has been called. + bool unparked = false; + + ASSERT_NO_THROW(parking_lot->park(parked_object, [&unparked] { + unparked = true; + })); + + EXPECT_EQ(1, parking_lot->size()); + + // Reference the parked object twice because we're going to test that + // reference counting works fine. + ASSERT_NO_THROW(parking_lot_handle->reference(parked_object)); + ASSERT_NO_THROW(parking_lot_handle->reference(parked_object)); + + EXPECT_EQ(1, parking_lot->size()); + + // Try to unpark the object. It should decrease the reference count, but not + // unpark the packet yet. + EXPECT_TRUE(parking_lot_handle->unpark(parked_object)); + EXPECT_FALSE(unparked); + + EXPECT_EQ(1, parking_lot->size()); + + // Try to unpark the object. This time it should be successful, because the + // reference count goes to 0. + EXPECT_TRUE(parking_lot_handle->unpark(parked_object)); + EXPECT_TRUE(unparked); + + EXPECT_EQ(0, parking_lot->size()); + + // Calling unpark again should return false to indicate that the object is + // not parked. + EXPECT_FALSE(parking_lot_handle->unpark(parked_object)); + + EXPECT_EQ(0, parking_lot->size()); +} + +// Test that parked object can be dropped. +TEST(ParkingLotsTest, drop) { + ParkingLotPtr parking_lot = boost::make_shared<ParkingLot>(); + ParkingLotHandlePtr parking_lot_handle = + boost::make_shared<ParkingLotHandle>(parking_lot); + + StringPtr parked_object(new std::string("foo")); + + // This flag will indicate if the callback has been called. + bool unparked = false; + ASSERT_NO_THROW(parking_lot->park(parked_object, [&unparked] { + unparked = true; + })); + + EXPECT_EQ(1, parking_lot->size()); + + // Reference object twice to test that dropping the packet ignores + // reference counting. + ASSERT_NO_THROW(parking_lot_handle->reference(parked_object)); + ASSERT_NO_THROW(parking_lot_handle->reference(parked_object)); + + // Drop parked object. The callback should not be invoked. + EXPECT_TRUE(parking_lot_handle->drop(parked_object)); + EXPECT_FALSE(unparked); + + EXPECT_EQ(0, parking_lot->size()); + + // Expect that an attempt to unpark return false, as the object + // has been dropped. + EXPECT_FALSE(parking_lot_handle->unpark(parked_object)); +} + +// Test that parked lots can be cleared. +TEST(ParkingLotsTest, clear) { + ParkingLotsPtr parking_lots = boost::make_shared<ParkingLots>(); + ParkingLotPtr parking_lot = parking_lots->getParkingLotPtr(1234); + ASSERT_TRUE(parking_lot); + ParkingLotHandlePtr parking_lot_handle = + boost::make_shared<ParkingLotHandle>(parking_lot); + + boost::shared_ptr<std::string> parked_object = + boost::make_shared<std::string>("foo"); + boost::weak_ptr<std::string> weak_parked_object(parked_object); + + // This flag will indicate if the callback has been called. + bool unparked = false; + ASSERT_NO_THROW(parking_lot->park(parked_object, [&unparked] { + unparked = true; + })); + + // Reference object twice to test that clearing the parking lots + // ignores reference counting. + ASSERT_NO_THROW(parking_lot_handle->reference(parked_object)); + ASSERT_NO_THROW(parking_lot_handle->reference(parked_object)); + + // Drop reference on objects. + parking_lot.reset(); + parking_lot_handle.reset(); + parked_object.reset(); + + // The parked object is still alive. + EXPECT_FALSE(weak_parked_object.expired()); + + // Clear the parking lots. + ASSERT_NO_THROW(parking_lots->clear()); + + // The callback should not be invoked. + EXPECT_FALSE(unparked); + + // The parked object was destroyed. + EXPECT_TRUE(weak_parked_object.expired()); +} + +// Verify that an object can be dereferenced. +TEST(ParkingLotsTest, dereference) { + ParkingLotPtr parking_lot = boost::make_shared<ParkingLot>(); + ParkingLotHandlePtr parking_lot_handle = + boost::make_shared<ParkingLotHandle>(parking_lot); + + // Create an object. + StringPtr parked_object(new std::string("foo")); + + // Verify that an object that hasn't been parked, cannot be + // dereferenced. + ASSERT_THROW(parking_lot_handle->dereference(parked_object), + InvalidOperation); + + // Park the object. + // This flag will indicate if the callback has been called. + bool unparked = false; + ASSERT_NO_THROW(parking_lot->park(parked_object, [&unparked] { + unparked = true; + })); + + EXPECT_EQ(1, parking_lot->size()); + + // Reference the parked object twice. + int ref_count = 0; + ASSERT_NO_THROW(ref_count = parking_lot_handle->reference(parked_object)); + ASSERT_EQ(1, ref_count); + ASSERT_NO_THROW(ref_count = parking_lot_handle->reference(parked_object)); + ASSERT_EQ(2, ref_count); + + EXPECT_EQ(1, parking_lot->size()); + + // Try to dereference the object. It should decrease the reference count, + // but not unpark the packet or invoke the callback. + ASSERT_NO_THROW(ref_count = parking_lot_handle->dereference(parked_object)); + ASSERT_EQ(1, ref_count); + EXPECT_FALSE(unparked); + + EXPECT_EQ(1, parking_lot->size()); + + // Try to dereference the object. It should decrease the reference count, + // but not unpark the packet or invoke the callback. + ASSERT_NO_THROW(ref_count = parking_lot_handle->dereference(parked_object)); + ASSERT_EQ(0, ref_count); + EXPECT_FALSE(unparked); + + EXPECT_EQ(1, parking_lot->size()); + + // Try to dereference the object. It should decrement to -1 + // but not unpark the packet or invoke the callback. + ASSERT_NO_THROW(ref_count = parking_lot_handle->dereference(parked_object)); + EXPECT_EQ(-1, ref_count); + EXPECT_FALSE(unparked); + + EXPECT_EQ(1, parking_lot->size()); + + // Calling unpark should invoke the callback. + ASSERT_TRUE(parking_lot_handle->unpark(parked_object)); + EXPECT_TRUE(unparked); + + EXPECT_EQ(0, parking_lot->size()); +} + +// Verify that parked objects are correctly distinguished from +// one another. +TEST(ParkingLotsTest, multipleObjects) { + ParkingLotPtr parking_lot = boost::make_shared<ParkingLot>(); + ParkingLotHandlePtr parking_lot_handle = + boost::make_shared<ParkingLotHandle>(parking_lot); + + // Create an object and park it. + StringPtr object_one(new std::string("one")); + int unparked_one = 0; + ASSERT_NO_THROW(parking_lot->park(object_one, [&unparked_one] { + ++unparked_one; + })); + + // Create a second object and park it. + StringPtr object_two(new std::string("two")); + int unparked_two = 0; + ASSERT_NO_THROW(parking_lot->park(object_two, [&unparked_two] { + ++unparked_two; + })); + + EXPECT_EQ(2, parking_lot->size()); + + // Create a third object but don't park it. + StringPtr object_three(new std::string("three")); + + // Try to unpark object_three. It should fail, and no callbacks + // should get invoked. + EXPECT_FALSE(parking_lot_handle->unpark(object_three)); + EXPECT_EQ(unparked_one, 0); + EXPECT_EQ(unparked_two, 0); + + EXPECT_EQ(2, parking_lot->size()); + + // Unpark object one. It should succeed and its callback should + // get invoked. + EXPECT_TRUE(parking_lot_handle->unpark(object_one)); + EXPECT_EQ(unparked_one, 1); + EXPECT_EQ(unparked_two, 0); + + EXPECT_EQ(1, parking_lot->size()); + + // Unpark object two. It should succeed and its callback should + // get invoked. + EXPECT_TRUE(parking_lot_handle->unpark(object_two)); + EXPECT_EQ(unparked_one, 1); + EXPECT_EQ(unparked_two, 1); + + EXPECT_EQ(0, parking_lot->size()); +} + +} diff --git a/src/lib/hooks/tests/run_unittests.cc b/src/lib/hooks/tests/run_unittests.cc new file mode 100644 index 0000000..cd6fc2b --- /dev/null +++ b/src/lib/hooks/tests/run_unittests.cc @@ -0,0 +1,19 @@ +// Copyright (C) 2009-2015 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 <util/unittests/run_all.h> + +#include <gtest/gtest.h> + +int +main(int argc, char* argv[]) { + ::testing::InitGoogleTest(&argc, argv); + isc::log::initLogger(); + return (isc::util::unittests::run_all()); +} diff --git a/src/lib/hooks/tests/server_hooks_unittest.cc b/src/lib/hooks/tests/server_hooks_unittest.cc new file mode 100644 index 0000000..f9b20cb --- /dev/null +++ b/src/lib/hooks/tests/server_hooks_unittest.cc @@ -0,0 +1,232 @@ +// Copyright (C) 2013-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 <hooks/server_hooks.h> + +#include <gtest/gtest.h> + +#include <algorithm> +#include <string> +#include <vector> + +using namespace isc; +using namespace isc::hooks; +using namespace std; + +namespace { + +// Checks the registration of hooks and the interrogation methods. As the +// constructor registers two hooks, this is also a test of the constructor. + +TEST(ServerHooksTest, RegisterHooks) { + ServerHooks& hooks = ServerHooks::getServerHooks(); + hooks.reset(); + + // There should be two hooks already registered, with indexes 0 and 1. + EXPECT_EQ(2, hooks.getCount()); + EXPECT_EQ(0, hooks.getIndex("context_create")); + EXPECT_EQ(0, hooks.findIndex("context_create")); + EXPECT_EQ(1, hooks.getIndex("context_destroy")); + EXPECT_EQ(1, hooks.findIndex("context_destroy")); + + // Check that the constants are as expected. (The intermediate variables + // are used because of problems with g++ 4.6.1/Ubuntu 11.10 when resolving + // the value of the ServerHooks constants when they appeared within the + // gtest macro.) + const int create_value = ServerHooks::CONTEXT_CREATE; + const int destroy_value = ServerHooks::CONTEXT_DESTROY; + EXPECT_EQ(0, create_value); + EXPECT_EQ(1, destroy_value); + + // Register another couple of hooks. The test on returned index is based + // on knowledge that the hook indexes are assigned in ascending order. + int alpha = hooks.registerHook("alpha"); + EXPECT_EQ(2, alpha); + EXPECT_EQ(2, hooks.getIndex("alpha")); + + int beta = hooks.registerHook("beta"); + EXPECT_EQ(3, beta); + EXPECT_EQ(3, hooks.getIndex("beta")); + + // Should be four hooks now + EXPECT_EQ(4, hooks.getCount()); +} + +// Check that duplicate names cannot be registered. +// This test has been updated. See #5251 for details. The old +// code is retained in case we decide to get back to it. +TEST(ServerHooksTest, DISABLED_OldDuplicateHooks) { + ServerHooks& hooks = ServerHooks::getServerHooks(); + hooks.reset(); + + // Ensure we can't duplicate one of the existing names. + EXPECT_THROW(hooks.registerHook("context_create"), DuplicateHook); + + // Check we can't duplicate a newly registered hook. + int gamma = hooks.registerHook("gamma"); + EXPECT_EQ(2, gamma); + EXPECT_THROW(hooks.registerHook("gamma"), DuplicateHook); +} + +// Check that duplicate names are handled properly. The code used to throw, +// but it now returns the existing index. See #5251 for details. +TEST(ServerHooksTest, NewDuplicateHooks) { + ServerHooks& hooks = ServerHooks::getServerHooks(); + hooks.reset(); + + int index = hooks.getIndex("context_create"); + + // Ensure we can duplicate one of the existing names. + // Instead of throwing, we just check that a reasonable + // index has been returned. + EXPECT_EQ(index, hooks.registerHook("context_create")); + + // Check that mutiple attempts to register the same hook will return + // existing index. + int gamma = hooks.registerHook("gamma"); + EXPECT_EQ(2, gamma); + EXPECT_EQ(gamma, hooks.registerHook("gamma")); + EXPECT_EQ(gamma, hooks.registerHook("gamma")); + EXPECT_EQ(gamma, hooks.registerHook("gamma")); + EXPECT_EQ(gamma, hooks.registerHook("gamma")); +} + +// Checks that we can get the name of the hooks. + +TEST(ServerHooksTest, GetHookNames) { + ServerHooks& hooks = ServerHooks::getServerHooks(); + hooks.reset(); + vector<string> expected_names; + + // Add names into the hooks object and to the set of expected names. + expected_names.push_back("alpha"); + expected_names.push_back("beta"); + expected_names.push_back("gamma"); + expected_names.push_back("delta"); + for (size_t i = 0; i < expected_names.size(); ++i) { + hooks.registerHook(expected_names[i].c_str()); + }; + + // Update the expected names to include the pre-defined hook names. + expected_names.push_back("context_create"); + expected_names.push_back("context_destroy"); + + // Get the actual hook names + vector<string> actual_names = hooks.getHookNames(); + + // For comparison, sort the names into alphabetical order and do a straight + // vector comparison. + sort(expected_names.begin(), expected_names.end()); + sort(actual_names.begin(), actual_names.end()); + + EXPECT_TRUE(expected_names == actual_names); +} + +// Test the inverse hooks functionality (i.e. given an index, get the name). + +TEST(ServerHooksTest, GetHookIndexes) { + ServerHooks& hooks = ServerHooks::getServerHooks(); + hooks.reset(); + + int alpha = hooks.registerHook("alpha"); + int beta = hooks.registerHook("beta"); + int gamma = hooks.registerHook("gamma"); + + EXPECT_EQ(std::string("context_create"), + hooks.getName(ServerHooks::CONTEXT_CREATE)); + EXPECT_EQ(std::string("context_destroy"), + hooks.getName(ServerHooks::CONTEXT_DESTROY)); + EXPECT_EQ(std::string("alpha"), hooks.getName(alpha)); + EXPECT_EQ(std::string("beta"), hooks.getName(beta)); + EXPECT_EQ(std::string("gamma"), hooks.getName(gamma)); + + // Check for an invalid index + EXPECT_THROW(hooks.getName(-1), NoSuchHook); + EXPECT_THROW(hooks.getName(42), NoSuchHook); +} + +// Test the reset functionality. + +TEST(ServerHooksTest, Reset) { + ServerHooks& hooks = ServerHooks::getServerHooks(); + hooks.reset(); + + int alpha = hooks.registerHook("alpha"); + int beta = hooks.registerHook("beta"); + int gamma = hooks.registerHook("gamma"); + + EXPECT_EQ(std::string("alpha"), hooks.getName(alpha)); + EXPECT_EQ(std::string("beta"), hooks.getName(beta)); + EXPECT_EQ(std::string("gamma"), hooks.getName(gamma)); + + // Check the counts before and after a reset. + EXPECT_EQ(5, hooks.getCount()); + hooks.reset(); + EXPECT_EQ(2, hooks.getCount()); + + // ... and check that the hooks are as expected. + EXPECT_EQ(0, hooks.getIndex("context_create")); + EXPECT_EQ(1, hooks.getIndex("context_destroy")); +} + +// Check that getting an unknown name throws an exception. + +TEST(ServerHooksTest, UnknownHookName) { + ServerHooks& hooks = ServerHooks::getServerHooks(); + hooks.reset(); + + EXPECT_THROW(static_cast<void>(hooks.getIndex("unknown")), NoSuchHook); + EXPECT_EQ(-1, hooks.findIndex("unknown")); +} + +// Check that the count of hooks is correct. + +TEST(ServerHooksTest, HookCount) { + ServerHooks& hooks = ServerHooks::getServerHooks(); + hooks.reset(); + + // Insert the names into the hooks object + hooks.registerHook("alpha"); + hooks.registerHook("beta"); + hooks.registerHook("gamma"); + hooks.registerHook("delta"); + + // Should be two more hooks that the number we have registered. + EXPECT_EQ(6, hooks.getCount()); +} + +// Check that the hook name is correctly generated for a control command name +// and vice versa. + +TEST(ServerHooksTest, CommandToHookName) { + EXPECT_EQ("$x_y_z", ServerHooks::commandToHookName("x-y-z")); + EXPECT_EQ("$foo_bar_foo", ServerHooks::commandToHookName("foo-bar_foo")); + EXPECT_EQ("$", ServerHooks::commandToHookName("")); +} + +TEST(ServerHooksTest, HookToCommandName) { + // Underscores replaced by hyphens. + EXPECT_EQ("x-y-z", ServerHooks::hookToCommandName("$x_y_z")); + EXPECT_EQ("foo-bar-foo", ServerHooks::hookToCommandName("$foo_bar-foo")); + // Single dollar is converted to empty string. + EXPECT_TRUE(ServerHooks::hookToCommandName("$").empty()); + // If no dollar, it is not a hook name. Return empty string. + EXPECT_TRUE(ServerHooks::hookToCommandName("abc").empty()); +} + +TEST(ServerHooksTest, getParkingLots) { + ServerHooks& hooks = ServerHooks::getServerHooks(); + hooks.reset(); + int alpha_hook = hooks.registerHook("alpha"); + + ASSERT_TRUE(hooks.getParkingLotsPtr()); + ASSERT_TRUE(hooks.getParkingLotPtr(alpha_hook)); + ASSERT_TRUE(hooks.getParkingLotPtr("alpha")); +} + +} // Anonymous namespace diff --git a/src/lib/hooks/tests/test_libraries.h.in b/src/lib/hooks/tests/test_libraries.h.in new file mode 100644 index 0000000..afad62f --- /dev/null +++ b/src/lib/hooks/tests/test_libraries.h.in @@ -0,0 +1,61 @@ +// Copyright (C) 2013-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/. + +#ifndef TEST_LIBRARIES_H +#define TEST_LIBRARIES_H + +#include <config.h> + +namespace { + +// Names of the libraries used in these tests. These libraries are built using +// libtool, so we need to look in the hidden ".libs" directory to locate the +// .so file. Note that we access the .so file - libtool creates this as a +// like to the real shared library. + +// Basic library with context_create and three "standard" callouts. +static const char* BASIC_CALLOUT_LIBRARY = "@abs_builddir@/.libs/libbcl.so"; + +// Library with context_create and three "standard" callouts, as well as +// load() and unload() functions. +static const char* FULL_CALLOUT_LIBRARY = "@abs_builddir@/.libs/libfcl.so"; + +// Library where the all framework functions throw an exception +static const char* FRAMEWORK_EXCEPTION_LIBRARY = "@abs_builddir@/.libs/libfxl.so"; + +// Library where the version() function returns an incorrect result. +static const char* INCORRECT_VERSION_LIBRARY = "@abs_builddir@/.libs/libivl.so"; + +// Library where some of the callout registration is done with the load() +// function. +static const char* LOAD_CALLOUT_LIBRARY = "@abs_builddir@/.libs/liblcl.so"; + +// Library where the load() function returns an error. +static const char* LOAD_ERROR_CALLOUT_LIBRARY = + "@abs_builddir@/.libs/liblecl.so"; + +// Name of a library which is not present. +static const char* NOT_PRESENT_LIBRARY = "@abs_builddir@/.libs/libnothere.so"; + +// Library that does not include a version function. +static const char* NO_VERSION_LIBRARY = "@abs_builddir@/.libs/libnvl.so"; + +// Library where there is an unload() function. +static const char* UNLOAD_CALLOUT_LIBRARY = "@abs_builddir@/.libs/libucl.so"; + +// Library where parameters are checked. +static const char* CALLOUT_PARAMS_LIBRARY = "@abs_builddir@/.libs/libpcl.so"; + +// Library which tests objects parking. +// Used only by hooks_manager_unittest.cc. +#ifdef TEST_ASYNC_CALLOUT +static const char* ASYNC_CALLOUT_LIBRARY = "@abs_builddir@/.libs/libacl.so"; +#endif + +} // anonymous namespace + + +#endif // TEST_LIBRARIES_H diff --git a/src/lib/hooks/tests/unload_callout_library.cc b/src/lib/hooks/tests/unload_callout_library.cc new file mode 100644 index 0000000..a15b870 --- /dev/null +++ b/src/lib/hooks/tests/unload_callout_library.cc @@ -0,0 +1,46 @@ +// Copyright (C) 2013-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +/// @file +/// @brief Basic unload library +/// +/// This is source of a test library for various test (LibraryManager and +/// HooksManager). The characteristics of the library produced from this +/// file are: +/// +/// - The "version" and "unload" framework functions are supplied. "version" +/// returns a valid value and "unload" creates a marker file and returns +/// success. + +#include <config.h> + +#include <hooks/hooks.h> +#include <hooks/tests/marker_file.h> + +#include <fstream> + +using namespace isc::hooks; + +extern "C" { + +// Framework functions + +int +version() { + return (KEA_HOOKS_VERSION); +} + +int +unload() { + // Create the marker file. + std::fstream marker; + marker.open(MARKER_FILE, std::fstream::out); + marker.close(); + + return (0); +} + +}; |